From 0a6c3d71fb9562c4e47fdf6878a705d8b775c2a0 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Fri, 24 Apr 2026 15:39:27 -0500 Subject: [PATCH 01/18] build: Add a 1ES Pipeline Templates version of Canary (#20127) This pipeline runs on our agents, rather than OneBranch's, and doesn't use all of the OneBranch machinery--which is only required for producing a vpack that we check into Windows. Since Canary will never be a vpack, we don't need to worry. It runs at about twice the speed _and_ we control the build images! This pull request also adds support for the "Terrapin Retrieval Tool," which will allow us to move away from having vcpkg contact remote servers directly to download source code (and which may become mandatory even in our OneBranch pipelines.) --- .github/actions/spelling/expect/expect.txt | 1 + build/config/tsa.json | 1 + build/pipelines/1espt-nightly.yml | 64 +++++ .../templates-v2/job-build-package-wpf.yml | 4 + .../templates-v2/job-build-project.yml | 4 + .../job-merge-msix-into-bundle.yml | 4 + .../templates-v2/job-package-conpty.yml | 4 + .../pipeline-1espt-full-release-build.yml | 233 ++++++++++++++++++ .../pipeline-full-release-build.yml | 5 +- .../pipeline-onebranch-full-release-build.yml | 5 +- .../templates-v2/steps-install-terrapin.yml | 6 + 11 files changed, 329 insertions(+), 2 deletions(-) create mode 100644 build/pipelines/1espt-nightly.yml create mode 100644 build/pipelines/templates-v2/pipeline-1espt-full-release-build.yml create mode 100644 build/pipelines/templates-v2/steps-install-terrapin.yml diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 6c226753b9..571abdbafb 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -541,6 +541,7 @@ EPres EQU ERASEBKGND ERRORONEXIT +espt esrp ESV ETW diff --git a/build/config/tsa.json b/build/config/tsa.json index 61924ef4bd..f6cb80d2ce 100644 --- a/build/config/tsa.json +++ b/build/config/tsa.json @@ -1,4 +1,5 @@ { + "codebaseName": "VSTS_Microsoft_OSGS_OpenConsole", "instanceUrl": "https://microsoft.visualstudio.com", "projectName": "OS", "areaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SHINE\\Terminal", diff --git a/build/pipelines/1espt-nightly.yml b/build/pipelines/1espt-nightly.yml new file mode 100644 index 0000000000..cbd6cfef72 --- /dev/null +++ b/build/pipelines/1espt-nightly.yml @@ -0,0 +1,64 @@ +trigger: none +pr: none +schedules: + - cron: "30 3 * * 2-6" # Run at 03:30 UTC Tuesday through Saturday (After the work day in Pacific, Mon-Fri) + displayName: "Nightly Terminal Build" + branches: + include: + - main + always: false # only run if there's code changes! + +parameters: + - name: publishToAzure + displayName: "Deploy to **PUBLIC** Azure Storage" + type: boolean + default: true + - name: official + displayName: "Run on Official 1ES Pipeline Templates" + type: boolean + default: true + +name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr) + +variables: + - template: templates-v2/variables-nuget-package-version.yml + parameters: + branding: Canary + +extends: + template: templates-v2/pipeline-1espt-full-release-build.yml + parameters: + official: ${{ parameters.official }} + branding: Canary + buildTerminal: true + pgoBuildMode: Optimize + codeSign: true + signingIdentity: + serviceName: $(SigningServiceName) + appId: $(SigningAppId) + tenantId: $(SigningTenantId) + akvName: $(SigningAKVName) + authCertName: $(SigningAuthCertName) + signCertName: $(SigningSignCertName) + useManagedIdentity: $(SigningUseManagedIdentity) + clientId: $(SigningOriginalClientId) + publishSymbolsToPublic: true + symbolExpiryTime: 15 + symbolPublishingSubscription: $(SymbolPublishingServiceConnection) + symbolPublishingProject: $(SymbolPublishingProject) + ${{ if eq(true, parameters.publishToAzure) }}: + extraPublishJobs: + - template: build/pipelines/templates-v2/job-deploy-to-azure-storage.yml@self + parameters: + pool: + name: SHINE-INT-S + os: windows + dependsOn: [PublishSymbols] + storagePublicRootURL: $(AppInstallerRootURL) + subscription: $(AzureSubscriptionName) + storageAccount: $(AzureStorageAccount) + storageContainer: $(AzureStorageContainer) + buildConfiguration: Release + buildPlatforms: [x64, x86, arm64] + environment: production-canary + diff --git a/build/pipelines/templates-v2/job-build-package-wpf.yml b/build/pipelines/templates-v2/job-build-package-wpf.yml index b71341bcac..d8d40a01f5 100644 --- a/build/pipelines/templates-v2/job-build-package-wpf.yml +++ b/build/pipelines/templates-v2/job-build-package-wpf.yml @@ -30,9 +30,13 @@ parameters: - name: signingIdentity type: object default: {} + - name: outerTemplateContext + type: object + default: {} jobs: - job: ${{ parameters.jobName }} + templateContext: ${{ parameters.outerTemplateContext }} ${{ if ne(length(parameters.pool), 0) }}: pool: ${{ parameters.pool }} ${{ if eq(parameters.codeSign, true) }}: diff --git a/build/pipelines/templates-v2/job-build-project.yml b/build/pipelines/templates-v2/job-build-project.yml index c6d84c4bad..659f95a126 100644 --- a/build/pipelines/templates-v2/job-build-project.yml +++ b/build/pipelines/templates-v2/job-build-project.yml @@ -74,9 +74,13 @@ parameters: - name: afterBuildSteps type: stepList default: [] + - name: outerTemplateContext + type: object + default: {} jobs: - job: ${{ parameters.jobName }} + templateContext: ${{ parameters.outerTemplateContext }} ${{ if ne(length(parameters.pool), 0) }}: pool: ${{ parameters.pool }} strategy: diff --git a/build/pipelines/templates-v2/job-merge-msix-into-bundle.yml b/build/pipelines/templates-v2/job-merge-msix-into-bundle.yml index 261750db8f..c4624a0d01 100644 --- a/build/pipelines/templates-v2/job-merge-msix-into-bundle.yml +++ b/build/pipelines/templates-v2/job-merge-msix-into-bundle.yml @@ -35,9 +35,13 @@ parameters: - name: signingIdentity type: object default: {} + - name: outerTemplateContext + type: object + default: {} jobs: - job: ${{ parameters.jobName }} + templateContext: ${{ parameters.outerTemplateContext }} ${{ if ne(length(parameters.pool), 0) }}: pool: ${{ parameters.pool }} ${{ if eq(parameters.codeSign, true) }}: diff --git a/build/pipelines/templates-v2/job-package-conpty.yml b/build/pipelines/templates-v2/job-package-conpty.yml index b91c2989f3..21455cd11f 100644 --- a/build/pipelines/templates-v2/job-package-conpty.yml +++ b/build/pipelines/templates-v2/job-package-conpty.yml @@ -30,9 +30,13 @@ parameters: - name: signingIdentity type: object default: {} + - name: outerTemplateContext + type: object + default: {} jobs: - job: ${{ parameters.jobName }} + templateContext: ${{ parameters.outerTemplateContext }} ${{ if ne(length(parameters.pool), 0) }}: pool: ${{ parameters.pool }} ${{ if eq(parameters.codeSign, true) }}: diff --git a/build/pipelines/templates-v2/pipeline-1espt-full-release-build.yml b/build/pipelines/templates-v2/pipeline-1espt-full-release-build.yml new file mode 100644 index 0000000000..62e541a2c1 --- /dev/null +++ b/build/pipelines/templates-v2/pipeline-1espt-full-release-build.yml @@ -0,0 +1,233 @@ +parameters: + - name: official + type: boolean + default: false + - name: branding + type: string + default: Release + values: + - Release + - Preview + - Canary + - Dev + - name: buildTerminal + type: boolean + default: true + - name: buildConPTY + type: boolean + default: false + - name: buildWPF + type: boolean + default: false + - name: pgoBuildMode + type: string + default: Optimize + values: + - Optimize + - Instrument + - None + - name: buildConfigurations + type: object + default: + - Release + - name: buildPlatforms + type: object + default: + - x64 + - x86 + - arm64 + - name: codeSign + type: boolean + default: true + - name: terminalInternalPackageVersion + type: string + default: '0.0.8' + + - name: publishSymbolsToPublic + type: boolean + default: true + - name: symbolExpiryTime + type: string + default: 36530 # This is the default from PublishSymbols@2 + - name: symbolPublishingSubscription + type: string + - name: symbolPublishingProject + type: string + + - name: extraPublishJobs + type: object + default: [] + - name: signingIdentity + type: object + default: {} + +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + ${{ if eq(parameters.official, true) }}: + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + ${{ else }}: + template: v1/1ES.Unofficial.PipelineTemplate.yml@1esPipelines + parameters: + customBuildTags: + - 1ES.PT.ViaStartRight + pool: + name: SHINE-INT-L + os: windows + sdl: + tsa: + enabled: true + configFile: '$(Build.SourcesDirectory)\build\config\tsa.json' + binskim: + enabled: true + policheck: + enabled: false + severity: Note + baseline: + baselineFile: '$(Build.SourcesDirectory)\build\config\release.gdnbaselines' + suppressionSet: default + + stages: + - stage: Build + displayName: Build + dependsOn: [] + jobs: + - template: ./build/pipelines/templates-v2/job-build-project.yml@self + parameters: + outerTemplateContext: + outputs: + - output: pipelineArtifact + targetPath: $(JobOutputDirectory) + artifactName: $(JobOutputArtifactName) + publishArtifacts: false # Handled by 1ESPT + branding: ${{ parameters.branding }} + buildTerminal: ${{ parameters.buildTerminal }} + buildConPTY: ${{ parameters.buildConPTY }} + buildWPF: ${{ parameters.buildWPF }} + pgoBuildMode: ${{ parameters.pgoBuildMode }} + buildConfigurations: ${{ parameters.buildConfigurations }} + buildPlatforms: ${{ parameters.buildPlatforms }} + generateSbom: false # this is handled by 1ESPT + removeAllNonSignedFiles: true # appease the overlords + codeSign: ${{ parameters.codeSign }} + signingIdentity: ${{ parameters.signingIdentity }} + beforeBuildSteps: + - template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self + + - template: ./build/pipelines/templates-v2/steps-install-terrapin.yml@self + + - task: UniversalPackages@0 + displayName: Download terminal-internal Universal Package + inputs: + feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48 + packageListDownload: e82d490c-af86-4733-9dc4-07b772033204 + versionListDownload: ${{ parameters.terminalInternalPackageVersion }} + + - ${{ if eq(parameters.buildWPF, true) }}: + # Add an Any CPU build flavor for the WPF control bits + - template: ./build/pipelines/templates-v2/job-build-project.yml@self + parameters: + outerTemplateContext: + outputs: + - output: pipelineArtifact + targetPath: $(JobOutputDirectory) + artifactName: $(JobOutputArtifactName) + publishArtifacts: false # Handled by 1ESPT + jobName: BuildWPF + branding: ${{ parameters.branding }} + buildTerminal: false + buildWPFDotNetComponents: true + buildConfigurations: ${{ parameters.buildConfigurations }} + buildPlatforms: + - Any CPU + generateSbom: false # this is handled by 1ESPT + removeAllNonSignedFiles: true # appease the overlords + codeSign: ${{ parameters.codeSign }} + signingIdentity: ${{ parameters.signingIdentity }} + beforeBuildSteps: + - template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self + # WPF doesn't need the localizations or the universal package, but if it does... put them here. + + - stage: Package + displayName: Package + dependsOn: [Build] + jobs: + - ${{ if eq(parameters.buildTerminal, true) }}: + - template: ./build/pipelines/templates-v2/job-merge-msix-into-bundle.yml@self + parameters: + pool: + name: SHINE-INT-S + os: windows + outerTemplateContext: + outputs: + - output: pipelineArtifact + targetPath: $(JobOutputDirectory) + artifactName: $(JobOutputArtifactName) + publishArtifacts: false # Handled by 1ESPT + jobName: Bundle + branding: ${{ parameters.branding }} + buildConfigurations: ${{ parameters.buildConfigurations }} + buildPlatforms: ${{ parameters.buildPlatforms }} + generateSbom: false # Handled by 1ESPT + codeSign: ${{ parameters.codeSign }} + signingIdentity: ${{ parameters.signingIdentity }} + + - ${{ if eq(parameters.buildConPTY, true) }}: + - template: ./build/pipelines/templates-v2/job-package-conpty.yml@self + parameters: + pool: + name: SHINE-INT-S + os: windows + outerTemplateContext: + outputs: + - output: pipelineArtifact + targetPath: $(JobOutputDirectory) + artifactName: $(JobOutputArtifactName) + publishArtifacts: false # Handled by 1ESPT + buildConfigurations: ${{ parameters.buildConfigurations }} + buildPlatforms: ${{ parameters.buildPlatforms }} + generateSbom: false # this is handled by 1ESPT + codeSign: ${{ parameters.codeSign }} + signingIdentity: ${{ parameters.signingIdentity }} + + - ${{ if eq(parameters.buildWPF, true) }}: + - template: ./build/pipelines/templates-v2/job-build-package-wpf.yml@self + parameters: + pool: + name: SHINE-INT-S + os: windows + outerTemplateContext: + outputs: + - output: pipelineArtifact + targetPath: $(JobOutputDirectory) + artifactName: $(JobOutputArtifactName) + publishArtifacts: false # Handled by 1ESPT + buildConfigurations: ${{ parameters.buildConfigurations }} + buildPlatforms: ${{ parameters.buildPlatforms }} + generateSbom: false # this is handled by 1ESPT + codeSign: ${{ parameters.codeSign }} + signingIdentity: ${{ parameters.signingIdentity }} + + - stage: Publish + displayName: Publish + dependsOn: + - Build + - ${{ if or(parameters.buildTerminal, parameters.buildConPTY, parameters.buildWPF) }}: + - Package + jobs: + - template: ./build/pipelines/templates-v2/job-publish-symbols-using-symbolrequestprod-api.yml@self + parameters: + pool: + name: SHINE-INT-S + os: windows + includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }} + symbolExpiryTime: ${{ parameters.symbolExpiryTime }} + subscription: ${{ parameters.symbolPublishingSubscription }} + symbolProject: ${{ parameters.symbolPublishingProject }} + + - ${{ parameters.extraPublishJobs }} diff --git a/build/pipelines/templates-v2/pipeline-full-release-build.yml b/build/pipelines/templates-v2/pipeline-full-release-build.yml index 8651f54568..9a65d6e08a 100644 --- a/build/pipelines/templates-v2/pipeline-full-release-build.yml +++ b/build/pipelines/templates-v2/pipeline-full-release-build.yml @@ -153,7 +153,10 @@ stages: - stage: Publish displayName: Publish pool: ${{ parameters.pool }} - dependsOn: [Build, Package] + dependsOn: + - Build + - ${{ if or(parameters.buildTerminal, parameters.buildConPTY, parameters.buildWPF) }}: + - Package jobs: # We only support the vpack for Release builds that include Terminal - ${{ if and(containsValue(parameters.buildConfigurations, 'Release'), parameters.buildTerminal, parameters.publishVpackToWindows) }}: diff --git a/build/pipelines/templates-v2/pipeline-onebranch-full-release-build.yml b/build/pipelines/templates-v2/pipeline-onebranch-full-release-build.yml index f2111de855..bd78a0d5f9 100644 --- a/build/pipelines/templates-v2/pipeline-onebranch-full-release-build.yml +++ b/build/pipelines/templates-v2/pipeline-onebranch-full-release-build.yml @@ -279,7 +279,10 @@ extends: - stage: Publish displayName: Publish - dependsOn: [Build] + dependsOn: + - Build + - ${{ if or(parameters.buildTerminal, parameters.buildConPTY, parameters.buildWPF) }}: + - Package jobs: - template: ./build/pipelines/templates-v2/job-publish-symbols-using-symbolrequestprod-api.yml@self parameters: diff --git a/build/pipelines/templates-v2/steps-install-terrapin.yml b/build/pipelines/templates-v2/steps-install-terrapin.yml new file mode 100644 index 0000000000..c8330c803d --- /dev/null +++ b/build/pipelines/templates-v2/steps-install-terrapin.yml @@ -0,0 +1,6 @@ +steps: +- pwsh: |- + nuget install -source "https://pkgs.dev.azure.com/microsoft/_packaging/WindowsTerminal/nuget/v3/index.json" TerrapinRetrievalTool -Prerelease -OutputDirectory _trt + $TerrapinRetrievalToolPath = (Get-Item _trt\TerrapinRetrievalTool.*\win-x64\TerrapinRetrievalTool.exe).FullName + Write-Host "##vso[task.setvariable variable=X_VCPKG_ASSET_SOURCES]x-script,${TerrapinRetrievalToolPath} -b https://vcpkg.storage.devpackages.microsoft.io/artifacts/ -a true -u None -p {url} -s {sha512} -d {dst};x-block-origin" + displayName: Set up the Terrapin Retrieval Tool (vcpkg cache) From c62bb193d326ef2d3828f382d61ead064222b896 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Fri, 24 Apr 2026 18:50:42 -0400 Subject: [PATCH 02/18] Refresh check-spelling metadata for v0.0.26 (#20141) This is a refresh of spell-check-this, more or less as of https://github.com/check-spelling/spell-check-this/tree/e089393b4e834a8b44d585e684f06d5642537818. ## References and Relevant Issues A number of changes take advantage of features from http://github.com/check-spelling/check-spelling/releases/v0.0.26 1. [`load-config-from`](https://docs.check-spelling.dev/Configuration#load-config-from) will allow future PRs to switch cleanly w/o the mess that this PR has -- once this merges, the `config.json` file will be used for the three dictionary configuration elements instead of the ones in the workflow. 2. `contents: read` is no longer needed by the comment jobs as the data is provided by the main job Contains fixes for the following specific issues: `without`, `with`, `with the`, `with the window`, `will be`, `whether or not`, `where the`, `using`, `uppercase or lowercase`, `unit testing`, `to`, `to which...`, `to which`, `to which the view refers`, `to which the pane was moved`, `to run a command/switch to a tab/...`, `to retrieve the user selected command`, `time,`, `the...that the`, `the session's initial directory`, `that`, `that will ask`, `that the`, `that opened the first flyout`, `same as terminal,`, `results,`, `queue,`, `please`, `pane,`, `out-of-date`, `our`, `one`, `on-screen`, `often`, `off-screen`, `of a`, `little-endian`, `left over`, `includes, at a minimum,`, `know of`, `its`, `if, after the calculation,`, `if`, `if we have an`, `if dragging`, `if commands`, `guard,`, `given process information in a list`, `from which`, `from creating`, `for which...`, `for the axis`, `for initializing the buffer`, `containing the cursor`, `console-wait`, `change`, `bytes`, `be`, `baseline,`, `aumid`, `at`, `ask me *again*`, `an`, `also need to`, `again`, `add`, `add event`, `about spelunking`, (rewrite `Appearances::_UpdateWithNewViewModel` comment), `'a'`, and ` (` Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/Bug_Report.yml | 2 +- .github/actions/spelling/README.md | 1 + .github/actions/spelling/advice.md | 1 + .github/actions/spelling/allow/allow.txt | 9 +- .../spelling/allow/remove-after-merging.txt | 2 + .github/actions/spelling/candidate.patterns | 84 ++- .github/actions/spelling/config.json | 111 ++++ .github/actions/spelling/excludes.txt | 5 +- ...d92373e136649071b3c04dc8773f18deaf5e04.txt | 1 - .github/actions/spelling/expect/alphabet.txt | 1 - .github/actions/spelling/expect/expect.txt | 140 +---- .../spelling/expect/remove-after-merging.txt | 40 ++ .../actions/spelling/line_forbidden.patterns | 572 +++++++++++++++++- .../actions/spelling/patterns/patterns.txt | 56 +- .github/actions/spelling/reject.txt | 49 +- .github/workflows/spelling2.yml | 62 +- .vscode/settings.json | 3 +- doc/ConsoleHostSettings.md | 2 +- doc/cascadia/profiles.schema.json | 4 +- .../spec.md | 4 +- .../#11000 - Marks/Shell-Integration-Marks.md | 2 +- doc/specs/#1142 - Keybinding Arguments.md | 2 +- .../#1337 - Per-Profile Tab Colors.md | 2 +- .../#1502 - Advanced Tab Switcher/spec.md | 2 +- .../#1564 - Settings UI/cascading-settings.md | 2 +- doc/specs/#1564 - Settings UI/spec.md | 2 +- .../#1571 - New Tab Menu Customization.md | 2 +- .../#1595 - Suggestions UI/Suggestions-UI.md | 4 +- .../#1790 - Font features and axes-spec.md | 2 +- doc/specs/#2046 - Command Palette.md | 6 +- doc/specs/#492 - Default Terminal/spec.md | 20 +- ... Elevation Quality of Life Improvements.md | 4 +- ...2 - Windows Terminal Session Management.md | 2 +- .../#5000 - Process Model 2.0.md | 8 +- doc/specs/#532 - Panes and Split Windows.md | 6 +- doc/specs/#605 - Search/spec.md | 4 +- ...line Arguments for the Windows Terminal.md | 4 +- .../#653 - Quake Mode/#653 - Quake Mode.md | 12 +- .../#754 - Cascading Default Settings.md | 6 +- doc/specs/#8324 - Application State (TSM).md | 2 +- doc/specs/Proto extensions-spec.md | 4 +- doc/specs/drafts/#1256 - Tab tearoff.md | 44 +- .../#3327 - Application Theming.md | 2 +- doc/specs/drafts/#997 Non-Terminal-Panes.md | 2 +- src/buffer/out/textBuffer.cpp | 6 +- .../CascadiaPackage/CascadiaPackage.wapproj | 2 +- .../LocalTests_TerminalApp/SettingsTests.cpp | 2 +- src/cascadia/TerminalApp/AppLogic.cpp | 4 +- src/cascadia/TerminalApp/CommandPalette.cpp | 10 +- src/cascadia/TerminalApp/Pane.cpp | 4 +- .../Resources/en-US/Resources.resw | 6 +- .../TerminalApp/SuggestionsControl.cpp | 4 +- src/cascadia/TerminalApp/Tab.cpp | 8 +- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- src/cascadia/TerminalApp/TerminalWindow.cpp | 2 +- .../TerminalConnection/AzureConnection.cpp | 4 +- .../TerminalConnection/CTerminalHandoff.cpp | 2 +- src/cascadia/TerminalControl/ControlCore.cpp | 4 +- .../HwndTerminalAutomationPeer.cpp | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 2 +- .../TermControlAutomationPeer.cpp | 2 +- src/cascadia/TerminalCore/Terminal.cpp | 2 +- .../TerminalSettingsEditor/Appearances.cpp | 8 +- .../Resources/en-US/Resources.resw | 12 +- .../IDynamicProfileGenerator.h | 2 +- src/cascadia/TerminalSettingsModel/Theme.cpp | 2 +- src/cascadia/UIHelpers/TextMenuFlyout.h | 2 +- src/cascadia/UIMarkdown/MarkdownToXaml.cpp | 2 +- .../UnitTests_Control/ControlCoreTests.cpp | 4 +- .../UnitTests_SettingsModel/ProfileTests.cpp | 2 +- .../UnitTests_TerminalCore/InputTest.cpp | 4 +- .../WindowsTerminal/NonClientIslandWindow.cpp | 2 +- src/host/ConsoleArguments.cpp | 2 +- src/host/PtySignalInputThread.cpp | 2 +- src/host/_stream.cpp | 2 +- src/host/ft_host/API_InputTests.cpp | 2 +- src/host/ft_host/API_RgbColorTests.cpp | 2 +- src/host/ft_host/CJK_DbcsTests.cpp | 2 +- src/host/ft_integrity/IntegrityTest.cpp | 2 +- src/host/getset.cpp | 2 +- src/host/inputBuffer.cpp | 2 +- src/host/inputKeyInfo.cpp | 2 +- src/host/output.cpp | 2 +- src/host/outputStream.cpp | 2 +- src/host/proxy/ITerminalHandoff.idl | 2 +- src/host/screenInfo.cpp | 4 +- src/host/selection.cpp | 4 +- src/host/selection.hpp | 4 +- src/host/selectionState.cpp | 2 +- src/host/srvinit.cpp | 2 +- src/host/ut_host/ConsoleArgumentsTests.cpp | 10 +- src/host/ut_host/TextBufferTests.cpp | 2 +- src/inc/TestUtils.h | 4 +- src/inc/til/mutex.h | 2 +- src/inc/til/spsc.h | 4 +- src/inc/til/u8u16convert.h | 4 +- .../base/HostSignalInputThread.cpp | 2 +- src/interactivity/win32/window.cpp | 2 +- src/propsheet/fontdlg.cpp | 6 +- src/renderer/base/renderer.cpp | 2 +- src/renderer/gdi/state.cpp | 2 +- src/server/ProcessList.cpp | 4 +- src/server/WaitBlock.cpp | 2 +- src/terminal/adapter/DispatchTypes.hpp | 2 +- src/terminal/adapter/SixelParser.cpp | 2 +- src/terminal/adapter/adaptDispatch.cpp | 4 +- .../adapter/ut_adapter/adapterTest.cpp | 6 +- src/terminal/parser/ft_fuzzer/fuzzing_logic.h | 4 +- src/terminal/parser/stateMachine.cpp | 4 +- .../parser/ut_parser/InputEngineTest.cpp | 6 +- .../parser/ut_parser/OutputEngineTest.cpp | 2 +- src/tools/ansi-color/ansi-color.cmd | 5 +- src/tools/ansi-color/sgr.def | 4 +- src/tools/vtapp/Program.cs | 2 +- src/types/ut_types/UuidTests.cpp | 2 +- src/types/utils.cpp | 4 +- src/types/viewport.cpp | 4 +- src/winconpty/winconpty.h | 2 +- 118 files changed, 1113 insertions(+), 431 deletions(-) create mode 100644 .github/actions/spelling/allow/remove-after-merging.txt create mode 100644 .github/actions/spelling/config.json delete mode 100644 .github/actions/spelling/expect/74d92373e136649071b3c04dc8773f18deaf5e04.txt create mode 100644 .github/actions/spelling/expect/remove-after-merging.txt diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.yml b/.github/ISSUE_TEMPLATE/Bug_Report.yml index 2a647a35d5..c8fe7cb570 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.yml +++ b/.github/ISSUE_TEMPLATE/Bug_Report.yml @@ -8,7 +8,7 @@ body: value: | Please make sure to [search for existing issues](https://github.com/microsoft/terminal/issues) and [check the FAQ](https://github.com/microsoft/terminal/wiki/Frequently-Asked-Questions-(FAQ)) before filing a new one! - If this is an application crash, please also provide a [Feedback Hub](https://aka.ms/terminal-feedback-hub) submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal" and choose "Share My Feedback" after submission to get the link. + If this is an application crash, please provide a [Feedback Hub](https://aka.ms/terminal-feedback-hub) submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal" and choose "Share My Feedback" after submission to get the link. - type: input attributes: diff --git a/.github/actions/spelling/README.md b/.github/actions/spelling/README.md index 4c40f7f02a..820182ba55 100644 --- a/.github/actions/spelling/README.md +++ b/.github/actions/spelling/README.md @@ -10,6 +10,7 @@ File | Purpose | Format | Info [line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns) [expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect) [advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice) +[config.json](config.json) | Action Configuration | JSON key (action configuration variable) value (action configuration value) | [config](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-config) Note: you can replace any of these files with a directory by the same name (minus the suffix) and then include multiple files inside that directory (with that suffix) to merge multiple files together. diff --git a/.github/actions/spelling/advice.md b/.github/actions/spelling/advice.md index 536c601aec..48c4345fc5 100644 --- a/.github/actions/spelling/advice.md +++ b/.github/actions/spelling/advice.md @@ -22,6 +22,7 @@ See the `README.md` in each directory for more information.
If the flagged items are :exploding_head: false positives If items relate to a ... + * binary file (or some other file you wouldn't want to check at all). Please add a file path to the `excludes.txt` file matching the containing file. diff --git a/.github/actions/spelling/allow/allow.txt b/.github/actions/spelling/allow/allow.txt index 68c5a275e8..0e9ddc717e 100644 --- a/.github/actions/spelling/allow/allow.txt +++ b/.github/actions/spelling/allow/allow.txt @@ -23,8 +23,10 @@ FTCS gantt gfm ghe +github godbolt hstrings +https hyperlinking hyperlinks Kbds @@ -44,6 +46,7 @@ mru notwrapped NTMTo overlined +passthrough perlw postmodern Powerline @@ -65,6 +68,7 @@ rubyw runtimes servicebus slnt +ssh stakeholders subpage subpages @@ -72,10 +76,11 @@ sustainability sxn Tencent toolset -Uids +ubuntu UEFI -UIDs uiatextrange +Uids +UIDs und vsdevcmd westus diff --git a/.github/actions/spelling/allow/remove-after-merging.txt b/.github/actions/spelling/allow/remove-after-merging.txt new file mode 100644 index 0000000000..ba4657da13 --- /dev/null +++ b/.github/actions/spelling/allow/remove-after-merging.txt @@ -0,0 +1,2 @@ +changelists +screenshots diff --git a/.github/actions/spelling/candidate.patterns b/.github/actions/spelling/candidate.patterns index d405383514..033119874d 100644 --- a/.github/actions/spelling/candidate.patterns +++ b/.github/actions/spelling/candidate.patterns @@ -1,5 +1,5 @@ # Repeated letters -\b([a-z])\g{-1}{2,}\b +\b([A-Za-z])\g{-1}{2,}\b # marker to ignore all code on line ^.*/\* #no-spell-check-line \*/.*$ @@ -11,7 +11,7 @@ ^.*\b[Cc][Ss][Pp][Ee][Ll]{2}:\s*[Dd][Ii][Ss][Aa][Bb][Ll][Ee]-[Ll][Ii][Nn][Ee]\b # copyright -Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+ +Copyright (?:\([Cc]\)|©|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+ # patch hunk comments ^@@ -\d+(?:,\d+|) \+\d+(?:,\d+|) @@ .* @@ -19,10 +19,10 @@ Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+ index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40} # file permissions -['"`\s][-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s] +(?:^|['"`\s])(?!-+\s)[-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s] # css fonts -\bfont(?:-family|):[^;}]+ +\bfont(?:-family(?:[-\w+]*)|):[^;}]+ # css url wrappings \burl\([^)]+\) @@ -36,10 +36,10 @@ index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40} # data url in quotes ([`'"])data:(?:[^ `'"].*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1} # data url -\bdata:[-a-zA-Z=;:/0-9+]*,\S* +\bdata:[-a-zA-Z=;:/0-9+_]*,\S* # https/http/file urls -(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/*%?=~_|!:,.;]+[-A-Za-z0-9+&@#/*%=~_|] +#(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/*%?=~_|!:,.;]+[-A-Za-z0-9+&@#/*%=~_|] # mailto urls mailto:[-a-zA-Z=;:/?%&0-9+@._]{3,} @@ -88,6 +88,9 @@ arn:aws:[-/:\w]+ # AWS VPC vpc-\w+ +# Azure AD +\baad\.\w{48}\b + # While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there # YouTube url \b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]* @@ -169,7 +172,7 @@ themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+. GHSA(?:-[0-9a-z]{4}){3} # GitHub actions -\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+ +\buses:\s+(['"]?)[-\w.]+/[-\w./]+@[-\w.]+\g{-1} # GitLab commit \bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b @@ -238,7 +241,7 @@ accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]* \bmedium\.com/@?[^/\s"]+/[-\w]+ # microsoft -\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%]* +\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%?#]* # powerbi \bapp\.powerbi\.com/reportEmbed/[^"' ]* # vs devops @@ -412,7 +415,7 @@ ipfs://[0-9a-zA-Z]{3,} \bgetopts\s+(?:"[^"]+"|'[^']+') # ANSI color codes -(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+)*m +#(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[(?:\d+(?:;\d+)*|)m # URL escaped characters %[0-9A-F][A-F](?=[A-Za-z]) @@ -430,7 +433,7 @@ sha\d+:[0-9a-f]*?[a-f]{3,}[0-9a-f]* # sha-... -- uses a fancy capture (\\?['"]|")[0-9a-f]{40,}\g{-1} # hex runs -\b[0-9a-fA-F]{16,}\b +\b(?=(?:[a-fA-F]{0,2}\d)*[a-fA-F]{3})[0-9a-fA-F]{16,}\b # hex in url queries =[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?& # ssh @@ -454,8 +457,12 @@ LS0tLS1CRUdJT.* # uuid: \b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b -# hex digits including css/html color classes: -(?:[\\0][xX]|\\u|[uU]\+|#x?|%23|&H)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b + +# unicode escaped characters (4) +\\u[0-9a-fA-F]{4} + +# hex digits including css/html color classes +(?:[\\0][xX]|\\u\{?|[uU]\+|#x?|%23|&H)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b # integrity integrity=(['"])(?:\s*sha\d+-[-a-zA-Z=;:/0-9+]{40,})+\g{-1} @@ -477,7 +484,7 @@ Name\[[^\]]+\]=.* (?:(?:\b|_|(?<=[a-z]))I|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b)) # python -\b(?i)py(?!gments|gmy|lon|ramid|ro|th)(?=[a-z]{2,}) +\b(?i)py(?!gment|gmy|lon|ramid|ro|th)(?=[a-z]{2,}) # crypt (['"])\$2[ayb]\$.{56}\g{-1} @@ -497,12 +504,21 @@ Name\[[^\]]+\]=.* # go.sum \bh1:\S+ +# golang print-f-style functions +#(?i)(?<=append|comma|debug|equal|err|error|exit|fatal|format|info|log|name|panic|print|skip|scan|string|trace|true|warn|warning|wrap|write)(?:f|ln)(?:[ (]|$) + +# golang regular expression +#(?[-a-zA-Z=;:/0-9+]{3,}== 0.0.22) +# LaTeX \\\w{2,}\{ # American Mathematical Society (AMS) / Doxygen @@ -719,7 +746,6 @@ nolint:\s*[\w,]+ # cygwin paths /cygdrive/[a-zA-Z]/(?:Program Files(?: \(.*?\)| ?)(?:/[-+.~\\/()\w ]+)*|[-+.~\\/()\w])+ -# in check-spelling@v0.0.22+, printf markers aren't automatically consumed # printf markers #(?"'`=(#])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}) +#(?:^|[\t ,>"'`=\[(#])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}) # Compiler flags (Windows / PowerShell) # This is a subset of the more general compiler flags pattern. # It avoids matching `-Path` to prevent it from being treated as `ath` -#(?:^|[\t ,"'`=(#])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})) +#(?:^|[\t ,"'`=\[(#])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})) # Compiler flags (linker) ,-B -# libraries -#(?:\b|_)[Ll]ib(?:re(?=office)|)(?!era[lt]|ero|erty|rar(?:i(?:an|es)|y))(?=[a-z]) +# Library prefix +# e.g., `lib`+`archive`, `lib`+`raw`, `lib`+`unwind` +# (ignores some words that happen to start with `lib`) +#(?:\b|_)[Ll]ib(?!era[lt])(?:re(?=office)|era|)(?!ero|erty|rar(?:i(?:an|es)|y))(?=[a-z]) # iSCSI iqn (approximate regex) \biqn\.[0-9]{4}-[0-9]{2}(?:[\.-][a-z][a-z0-9]*)*\b @@ -772,9 +800,9 @@ W/"[^"]+" # curl arguments \b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)* # set arguments -\b(?:bash|sh|set)(?:\s+[-+][abefimouxE]{1,2})*\s+[-+][abefimouxE]{3,}(?:\s+[-+][abefimouxE]+)* +\b(?:bash|(?]|depth|frame|page|project|select)\s[1-9] (?!byte|day|hour|meaning|minute|month|(?:new |)page|people|(?:more |)space|year)[a-z]+ [a-z]+\s + +# Write out numbers at the start of a sentence +# https://www.scribendi.com/academy/articles/when_to_spell_out_numbers_in_writing.en.html#:~:text=Beginning%20a%20Sentence%20with%20a%20Number,may%20be%2e +(?:\b[a-z]{4,}|\s(?:[a-eg-z][a-z]{2}|f[a-hj-z][a-z]|fi[a-fh][a-z]))[:.?!] [1-9] [a-z]{3,} [a-z]+\s\w+ + +# Don't write two numbers in a row +# https://www.scribendi.com/academy/articles/when_to_spell_out_numbers_in_writing.en.html#:~:text=Paired%20Numbers%20%28Two%20Numbers%20in,librarian%20to%20begin%20story%20time%2e +(?:[a-z]{4,}|\s(?!apr|aug|dec|feb|fri|jan|mar|mon|nov|oct|sat|sep|sun|thu|tue|wed)[a-z]{3})\s\d+\s\d+(?!--)[-\s](?:(?!--)[-A-Za-z]){2,}\s + +# This probably indicates Mojibake https://en.wikipedia.org/wiki/Mojibake +# You probably should try to unbake this content +Ã(?:Â[¤¶¥]|[£¢])|à + # Should be `HH:MM:SS` \bHH:SS:MM\b @@ -36,30 +85,103 @@ # Assuming that the time is being passed to https://go.dev/src/time/format.go \b2006-02-01\b +# Should probably have a trailing `.` +\s([a-z]\.){2,}[a-z]\s(?=\w) + +# Should probably end with `”` +# Likely bad OCR +“.+[^'‘\\\[]+’'(?!['"]) + +# Should probably end with `”` or with only one of `’`/`'` +\s\w+[^'‘\\\[]+’'(?!['"]) + +# Should probably be matching (smart)quotes or backticks (if Markdown) +# Unless the file format is TeX +^[^`]+(? + allow-hunspell: false + load-config-from: | { - "cspell": "https://raw.githubusercontent.com/check-spelling/cspell-dicts/v20241114/dictionaries/" + "pr-base-keys": [ + "" + ], + "pr-trusted-keys": [ + "check_extra_dictionaries", + "dictionary_source_prefixes", + "extra_dictionaries", + "" + ], + "": [] } - extra_dictionaries: | - cspell:software-terms/softwareTerms.txt - cspell:cpp/stdlib-cpp.txt - cspell:cpp/stdlib-c.txt - cspell:python/python/python-lib.txt - cspell:php/php.txt - cspell:node/node.txt - cspell:dart/dart.txt - cspell:filetypes/filetypes.txt - cspell:java/java.txt - cspell:css/css.txt - cspell:dotnet/dotnet.txt - cspell:npm/npm.txt - cspell:fullstack/fullstack.txt - cspell:java/java-terms.txt - cspell:r/r.txt - cspell:golang/go.txt - cspell:cpp/stdlib-cmath.txt - cspell:typescript/typescript.txt - cspell:html/html.txt - cspell:cpp/compiler-msvc.txt - cspell:django/django.txt - cspell:aws/aws.txt - cspell:python/common/extra.txt - cspell:cpp/ecosystem.txt - cspell:cpp/lang-keywords.txt - cspell:csharp/csharp.txt - cspell:cpp/compiler-clang-attributes.txt - cspell:python/python/python.txt - cspell:mnemonics/mnemonics.txt - cspell:powershell/powershell.txt comment-push: name: Report (Push) # If your workflow isn't running on push, you can remove this job - runs-on: ubuntu-latest + runs-on: ubuntu-slim needs: spelling permissions: actions: read @@ -161,11 +141,10 @@ jobs: comment-pr: name: Report (PR) # If you workflow isn't running on pull_request*, you can remove this job - runs-on: ubuntu-latest + runs-on: ubuntu-slim needs: spelling permissions: actions: read - contents: read pull-requests: write if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request') steps: @@ -182,12 +161,13 @@ jobs: contents: write pull-requests: write actions: read - runs-on: ubuntu-latest + runs-on: ubuntu-slim if: ${{ github.repository_owner != 'microsoft' && github.event_name == 'issue_comment' && github.event.issue.pull_request && - contains(github.event.comment.body, '@check-spelling-bot apply') && + contains(github.event.comment.body, '@check-spelling-bot') && + contains(github.event.comment.body, 'apply') && contains(github.event.comment.body, 'https://') }} concurrency: diff --git a/.vscode/settings.json b/.vscode/settings.json index 0dd3cf3794..4fbffe8663 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -127,4 +127,5 @@ "**/obj/**": true, "**/packages/**": true, }, -} \ No newline at end of file + "sarif-viewer.connectToGithubCodeScanning": "on", +} diff --git a/doc/ConsoleHostSettings.md b/doc/ConsoleHostSettings.md index 7eef405c2d..1b9864038b 100644 --- a/doc/ConsoleHostSettings.md +++ b/doc/ConsoleHostSettings.md @@ -63,7 +63,7 @@ When console applications are launched, the Windows Console Host determines whic 2. Overlay settings specified by the user's configured defaults 3. Overlay application-specific settings from either the registry or the shortcut file, depending on how the application was launched -Note that the registry settings are "sparse" settings repositories, meaning that if a setting isn't present, then whatever value that is already in use remains unchanged. This allows users to have some settings shared amongst all console applications and other settings be specific. Shortcut files, however, store each setting regardless of whether it was a default setting or not. +Note that the registry settings are "sparse" settings repositories, meaning that if a setting isn't present, then whatever value that is already in use remains unchanged. This allows users to have some settings shared amongst all console applications and other settings be specific. Shortcut files, however, store each setting regardless of whether or not it was a default setting. ## Known Issues diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 1756b7cc9d..11eb698965 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -1765,7 +1765,7 @@ ] }, "ExportBufferAction": { - "description": "Arguments corresponding to a exportBuffer Action", + "description": "Arguments corresponding to an exportBuffer Action", "allOf": [ { "$ref": "#/$defs/ShortcutAction" @@ -2242,7 +2242,7 @@ "$ref": "#/$defs/Icon" }, "name": { - "description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.\nIf name is a string, it will be the name of the command.\nIf name is a object, the key property of the object will be used to lookup a localized string resource for the command", + "description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.\nIf name is a string, it will be the name of the command.\nIf name is an object, the key property of the object will be used to lookup a localized string resource for the command", "type": [ "string", "object", diff --git a/doc/specs/#1043 - Set the initial position of the Terminal/spec.md b/doc/specs/#1043 - Set the initial position of the Terminal/spec.md index 9d7966a491..10b7b8dbc1 100644 --- a/doc/specs/#1043 - Set the initial position of the Terminal/spec.md +++ b/doc/specs/#1043 - Set the initial position of the Terminal/spec.md @@ -55,7 +55,7 @@ Edge cases: 1. Multiple monitors. The user should be able to set the initial position to any monitors attached. For the monitors on the left side of the major monitor, the initial position values are negative. 2. If the initial position is larger than the screen resolution and the window top left corner is off-screen, we should let user be able to see and drag the window back on screen. One solution is to set the initial position to the top left corner of the nearest monitor if the top left is off-screen. -3. If the user wants to launch maximized and provides an initial position, we should launch the maximized window on the top left corner of the monitor where the position is located. +3. If the user wants to launch maximized and provides an initial position, we should launch the maximized window at the top left corner of the monitor where the position is located. 4. Launch the Terminal on a monitor with custom dpi. Changing the dpi of the monitor will not affect the initial position of the top left corner. So we do not need to handle this case. 5. Launch the Terminal on a monitor with custom resolution. Changing the resolution will change the available point for the initial position. (2) already covers this case. @@ -73,7 +73,7 @@ The rest of the UI will be the same of the current Terminal experience, except t Users can only set the initial position and launch mode in the Json file with keyboard. Thus, this will not affect accessibility. ### Reliability -We need to make sure that whatever the initial position is set, the user can access the Terminal window. This is guaranteed because if the top left corner position of the Terminal Window is out of screen, we put it on the top left corner of the screen. +We need to make sure that whatever the initial position is set, the user can access the Terminal window. This is guaranteed because if the top left corner position of the Terminal Window is out of screen, we put it at the top left corner of the screen. ### Performance, Power, and Efficiency diff --git a/doc/specs/#11000 - Marks/Shell-Integration-Marks.md b/doc/specs/#11000 - Marks/Shell-Integration-Marks.md index 48e4112d93..e253614ade 100644 --- a/doc/specs/#11000 - Marks/Shell-Integration-Marks.md +++ b/doc/specs/#11000 - Marks/Shell-Integration-Marks.md @@ -68,7 +68,7 @@ allows the terminal to expose quick actions for: ### User Stories -This is a bit of a unusual section, as this feature was already partially +This is a bit of an unusual section, as this feature was already partially implemented when this spec was written. Story | Size | Description diff --git a/doc/specs/#1142 - Keybinding Arguments.md b/doc/specs/#1142 - Keybinding Arguments.md index 8073b9fa78..02ca2a6ddb 100644 --- a/doc/specs/#1142 - Keybinding Arguments.md +++ b/doc/specs/#1142 - Keybinding Arguments.md @@ -189,7 +189,7 @@ However, for actions that _do_ require args, we'll set up a global function that can be used to parse a json blob into an `IActionArgs`. Once the `IActionArgs` is built for the keybinding, we'll set it in -`AppKeyBindings` with a updated `AppKeyBindings::SetKeyBinding` call. +`AppKeyBindings` with an updated `AppKeyBindings::SetKeyBinding` call. `SetKeyBinding`'s signature will be updated to take a `ActionAndArgs` instead. Should an action not need arguments, the `Args` member can be left `null` in the `ActionAndArgs`. diff --git a/doc/specs/#1337 - Per-Profile Tab Colors/#1337 - Per-Profile Tab Colors.md b/doc/specs/#1337 - Per-Profile Tab Colors/#1337 - Per-Profile Tab Colors.md index e2830babbe..099ed0d9f6 100644 --- a/doc/specs/#1337 - Per-Profile Tab Colors/#1337 - Per-Profile Tab Colors.md +++ b/doc/specs/#1337 - Per-Profile Tab Colors/#1337 - Per-Profile Tab Colors.md @@ -100,7 +100,7 @@ No expected change Compatibility -This entire spec outlines how this feature is designed with a emphasis on future +This entire spec outlines how this feature is designed with an emphasis on future compatibility. As such, there are no expected regressions in the future when we do add support for themes. diff --git a/doc/specs/#1502 - Advanced Tab Switcher/spec.md b/doc/specs/#1502 - Advanced Tab Switcher/spec.md index c348ad5f52..39188b93e7 100644 --- a/doc/specs/#1502 - Advanced Tab Switcher/spec.md +++ b/doc/specs/#1502 - Advanced Tab Switcher/spec.md @@ -141,7 +141,7 @@ Pressing the `openTabSwitcher` keychord again will not close the switcher, it'll We'll provide a setting that will allow the list of tabs to be presented in either _in-order_ (how the tabs are ordered on the tab bar), or _Most Recently Used Order_ (MRU). MRU means that the tab that the terminal most recently visited will be on the top of the list, and the tab that the terminal has not visited for the longest time will be on the bottom. -There will be an argument for the `openTabSwitcher` action called `displayOrder`. This can be either `inOrder` or `mruOrder`. Making the setting an argument passed into `openTabSwitcher` would allow the user to have one keybinding to open an MRU Tab Switcher, and different one for the In-Order Tab Switcher. For example: +There will be an argument for the `openTabSwitcher` action called `displayOrder`. This can be either `inOrder` or `mruOrder`. Using an argument passed into `openTabSwitcher` would allow the user to have one keybinding to open an MRU Tab Switcher, and different one for the In-Order Tab Switcher. For example: ``` {"keys": ["ctrl+tab"], "command": {"action": "openTabSwitcher", "anchor":"ctrl", "displayOrder":"mruOrder"}} {"keys": ["ctrl+shift+p"], "command": {"action": "openTabSwitcher", "anchor":"ctrl", "displayOrder":"inOrder"}} diff --git a/doc/specs/#1564 - Settings UI/cascading-settings.md b/doc/specs/#1564 - Settings UI/cascading-settings.md index 0c358f945e..f2a96b8c90 100644 --- a/doc/specs/#1564 - Settings UI/cascading-settings.md +++ b/doc/specs/#1564 - Settings UI/cascading-settings.md @@ -103,7 +103,7 @@ This option was not chosen because it added too much overhead for changing a set ### 2: Lock Button -Every setting will have a lock button next to it. If the lock is locked, that means the setting is being inherited from Global, and the control is disabled. If the user wants to edit the setting, they can click the lock, which will changed it to the unlocked lock icon, and the control will become enabled. +Every setting will have a lock button next to it. If the lock is locked, that means the setting is being inherited from Global, and the control is disabled. If the user wants to edit the setting, they can click the lock, which will change it to the unlocked lock icon, and the control will become enabled. ![Locks inheritance](./inheritance-locks.png) diff --git a/doc/specs/#1564 - Settings UI/spec.md b/doc/specs/#1564 - Settings UI/spec.md index 77fe70d7df..50ccad6fd2 100644 --- a/doc/specs/#1564 - Settings UI/spec.md +++ b/doc/specs/#1564 - Settings UI/spec.md @@ -9,7 +9,7 @@ issue id: #1564 ## Abstract -This spec describes the basic functionality of the settings UI, including disabling it, the navigation items, launch methods, and editing of settings. The specific layout of each page will defined in later design reviews. +This spec describes the basic functionality of the settings UI, including disabling it, the navigation items, launch methods, and editing of settings. The specific layout of each page will be defined in later design reviews. ## Inspiration diff --git a/doc/specs/#1571 - New Tab Menu Customization/#1571 - New Tab Menu Customization.md b/doc/specs/#1571 - New Tab Menu Customization/#1571 - New Tab Menu Customization.md index 45bd669f84..98149ea106 100644 --- a/doc/specs/#1571 - New Tab Menu Customization/#1571 - New Tab Menu Customization.md +++ b/doc/specs/#1571 - New Tab Menu Customization/#1571 - New Tab Menu Customization.md @@ -71,7 +71,7 @@ There are five `type`s of objects in this menu: the user to visually space out entries. * `"type":"folder"`: This represents a nested menu of entries. - The `"name"` property provides a string of text to display for the group. - - The `"icon"` property provides a path to a image to use as the icon. This + - The `"icon"` property provides a path to an image to use as the icon. This property is optional. - The `"entries"` property specifies a list of menu entries that will appear nested under this entry. This can contain other `"type":"folder"` groups as diff --git a/doc/specs/#1595 - Suggestions UI/Suggestions-UI.md b/doc/specs/#1595 - Suggestions UI/Suggestions-UI.md index b4bf0409ad..f38cd766e6 100644 --- a/doc/specs/#1595 - Suggestions UI/Suggestions-UI.md +++ b/doc/specs/#1595 - Suggestions UI/Suggestions-UI.md @@ -377,7 +377,7 @@ spec's review. * [ ] Enable previewing `sendInput` actions in the Command Palette and `SuggestionsControl` * [ ] Enable the `SuggestionsControl` to open top-down (aligned to the bottom of the cursor row) or bottom-up (aligned to the top of the cursor row). * [ ] Disable sorting on the `SuggestionsControl` - elements should presumably be pre-sorted by the source. -* [ ] Expose the recent commands as a accessor on `TermControl` +* [ ] Expose the recent commands as an accessor on `TermControl` * [ ] Add a `suggestions` action which accepts a single option `recentCommands`. These should be fed in MRU order to the `SuggestionsControl`. * [ ] Expose the recent directories as an accessor on `TermControl`, and add a `recentDirectories` source. @@ -505,7 +505,7 @@ Here's a sample json schema for the settings discussed here. > committing any plans here._ It would be beneficial for the Suggestions UI to display additional context to -the user. Consider a extension that provides some commands for the user, like a +the user. Consider an extension that provides some commands for the user, like a hypothetical "Docker" extension. The extension author might be able to give the commands simplified names, but also want to expose a more detailed description of the commands to the user. diff --git a/doc/specs/#1790 - Font features and axes-spec.md b/doc/specs/#1790 - Font features and axes-spec.md index bc524a4099..d3736ea83f 100644 --- a/doc/specs/#1790 - Font features and axes-spec.md +++ b/doc/specs/#1790 - Font features and axes-spec.md @@ -36,7 +36,7 @@ We will do this by allowing users to define a dictionary in their settings.json ### Axes of variation -Specifying axes of variation is done in an extremely similar manner to the way font features are specified - a 4-character tag is used to specify which font axis is being modified and a numerical value is provided to specify the value the axis should be set to. For example, {'slnt', 20} specifies that the 'slant' axis should be set to 20. +Specifying axes of variation is done in an extremely similar manner to the way font features are specified - a 4-character tag is used to specify which font axis is being modified and a numerical value is provided to specify the value for the axis. For example, {'slnt', 20} specifies that the 'slant' axis should be set to 20. There is also a standard list of axes of variation, and each axis has its own default. We will approach this the same way we approached font features, by allowing users to specify additional features or omit features without needing to redefine the defaults. diff --git a/doc/specs/#2046 - Command Palette.md b/doc/specs/#2046 - Command Palette.md index 200b84a03e..91e46d01dc 100644 --- a/doc/specs/#2046 - Command Palette.md +++ b/doc/specs/#2046 - Command Palette.md @@ -229,7 +229,7 @@ with the default profile running `wsl` in it. We'll add another action that can be used to toggle the visibility of the command palette. Pressing that keybinding will bring up the command palette. We -should make sure to add a argument to this action that specifies whether the +should make sure to add an argument to this action that specifies whether the palette should be opened directly in Action Mode or Commandline Mode. When the command palette appears, we'll want it to appear as a single overlay @@ -525,7 +525,7 @@ default. These are largely the actions that are bound by default. ## Addenda This spec also has a follow-up spec which introduces further changes upon this -original draft. Please also refer to: +original draft. Please refer to: * June 2020: Unified keybindings and commands, and synthesized action names. @@ -578,7 +578,7 @@ original draft. Please also refer to: in commandline mode before we try to auto-parse their commandline, to check for errors. Might be useful to help sanity check users. We can always parse their `wt` commandlines safely without having to execute them. -* It would be cool if the commands the user typed in Commandline Mode could be +* It would be cool if commands the user typed in Commandline Mode could be saved to a history of some sort, so they could easily be re-entered. - It would be especially cool if it could do this across launches. - We don't really have any way of storing transient data like that in the diff --git a/doc/specs/#492 - Default Terminal/spec.md b/doc/specs/#492 - Default Terminal/spec.md index c85982c64f..31a232bc35 100644 --- a/doc/specs/#492 - Default Terminal/spec.md +++ b/doc/specs/#492 - Default Terminal/spec.md @@ -68,7 +68,7 @@ This workflow affords us several benefits: - This also makes it potentially possible to backport this portion of the code change to popular in-market versions of Windows 10. For instance, WSL2 has just backported to 1903 and 1909. The less churn and risk, the easier it is to sell a backport. *Potential future:* -- ~~If no updated console exists, potentially check for registration of a terminal UX that is willing to use the inbox ConPTY bits, start it, and transition to being a PTY instead.~~ +- ~~If no updated console exists, potentially check for registration of a terminal UX that is willing to use the inbox ConPTY bits, start it, and transition to being a PTY instead.~~ - **CUT FROM v1**: To simplify the story for end-users, we're offering this as a package deal in the first revision. Explaining the difference between consoles and terminals to end users is very difficult. The registration would operate as follows: @@ -80,7 +80,7 @@ The registration would operate as follows: - **V1 NOTE:** The subkey `%%Startup` was chosen to separate these keys (this one and the `DelegationTerminal` one below) in case we needed to ACL them or protect them in some way. We want a per-user choice of which Terminal/Console are used, but we might need to take action to prevent these keys from being slammed at some point in the future. Why `%%`? The subkeys are traditionally used to resolve paths to client binaries that have their own console preferences set. The `%%` should never be resolvable as it won't lead to a valid path or expanded path variable. The delegation process would operate as follows: -- A method contract is established between the existing inbox console and any updated console (an interface). +- A method contract is established between the existing inbox console and any updated console (an interface). - `HRESULT ConsoleEstablishHandoff(HANDLE server, HANDLE driverInputEvent, const PortableConnectMessage* const msg, HANDLE signalPipe, HANDLE inboxProcess, HANDLE* process)` - `HANDLE server`: This is the server side handle to the console driver, used with `DeviceIoControl` to receive/send messages with the client command-line application - `HANDLE driverInputEvent`: The input event is created and assigned to the driver immediately on first connection, before any messages are read from the driver, to ensure that it can track a blocking state should first message be an input request that we do not yet have data to fill. As such, the inbox console will have created this and assigned it to the driver before pulling off the connection packet and determining that it wants to delegate. Therefore, we will transfer ownership of this event to the updated console. @@ -88,7 +88,7 @@ The delegation process would operate as follows: - ~~The `ConsoleArguments` structure could technically change between versions, so we will make a version agnostic portable structure that just carries the communication from the old one to the new one.~~ - **CUT FROM V1**: The only arguments coming in from a default light-up are the server handle. Pretty much all the other arguments are related to the operation of the PTY. Since this feature is about "default application" launches where no arguments are specified, this was cut from the initial revision. - `const PortableConnectMessage* const msg`: - - The `CONSOLE_API_MSG` structure contains both the actual packet data from the driver as well as some overhead/administration data related to the packet state, ordering, completion, errors, and buffers. It's a broad scope structure for every type of message we process and it can change over time as we improve the way the `conserver.lib` handles packets. + - The `CONSOLE_API_MSG` structure contains both the actual packet data from the driver as well as some overhead/administration data related to the packet state, ordering, completion, errors, and buffers. It's a broad scope structure for every type of message we process and it can change over time as we improve the way that `conserver.lib` handles packets. - This represents a version agnostic variant for ONLY the connect message that can pass along the initial connect information structure, the packet sequencing information, and other relevant payload only to that one message type. It will purposefully discard references to things like a specific set of API servicing routines because the point of handing off is to get updated routines, if necessary. - **V1 NOTE:** This was named `CONSOLE_PORTABLE_ATTACH_MSG` - `HANDLE signalPipe`: During authoring, it was identified that Ctrl+C and other similar signals need to make it back to the original `conhost.exe` application as the Operating System grants it special privilege over the originally attached client application. This privilege cannot be transferred to the delegated console. So this channel remains for the delegated one to send its signals back through the original one for commanding the underlying client. (This also implies the original `conhost.exe` inbox cannot close and must remain a part of the process tree for the life of the session to maintain this control.) @@ -100,7 +100,7 @@ The delegation process would operate as follows: 1. ~~The issue of passing the server, event, and other handles into another process space. We're not entirely sure if the console driver will happily accept these things moving to a different process. It probably should, but unconfirmed.~~ 1. ~~Some command-line client applications rely on spelunking the process tree to figure out who is their servicing application. Maintaining the delegated/updated console inside the same process space maintains some level of continuity for these sorts of applications.~~ - **Alternative:** We may make this just be a COM server/client contract. ~~An in-proc COM server should operate in much the same fashion here (loading the DLL into the process and running particular method) while being significantly more formal and customizable (version revisions, moving to out-of-proc, not really needing to know the binary path because the catalog knows).~~ - - **V1 NOTE:** We landed on an out-of-proc COM server/client here. This maintains the isolation of the newly running code from the old code. Since we're maintaining the original `conhost.exe` for signaling purposes, we're no longer worried about the spelunking the process tree and not having the relationship for clients to find. + - **V1 NOTE:** We landed on an out-of-proc COM server/client here. This maintains the isolation of the newly running code from the old code. Since we're maintaining the original `conhost.exe` for signaling purposes, we're no longer worried about spelunking the process tree and not having the relationship for clients to find. - **Not considering:** ~~WinRT. `conhost.exe` has no WinRT. Adding WinRT to it would significantly increase the complexity of compilation in the inbox and out of box code base. It would also significantly increase the compilation time, binary size, library link list, etc... unless we use just the ABI to access it. But I don't see an advantage to that over just using classic COM at that point. This is only one handoff method and a rather simplistic one at that. Every benefit WinRT provides is outweighed by the extra effort that would be required over just a classic COM server in this case.~~ - After delegation is complete, the inbox console will have to clean up any threads, handles, and state related to the session. We do a fairly good job with this normally, but some portions of the `conhost.exe` codebase are reliant on the process exiting for final cleanup. There may be a bit of extra effort to do some explicit cleanup here. - **V1 NOTE:** The inbox one cleans up everything it can and sits in a state waiting for the child/delegated process handle to exit. It also maintains a thread listening for the signals to come through in case it needs to send a command to the client application using the privilege granted to it by the driver. @@ -177,7 +177,7 @@ The settings experience includes: - Inside Windows Terminal - Inside the new Settings UI, we will likely need a page that configures the delegation keys in `HKCU\Console\%%Startup` ~~or a link out to the Windows Settings panel, should we manage to get the settings configurable there~~. - Inside the console property sheet - - Same as for Terminal but with `comctl` controls over XAML +/- a link to the Windows Settings panel + - Same as Terminal, but with `comctl` controls over XAML +/- a link to the Windows Settings panel - Inside the Settings panel for Windows (probably on the developer settings page) - The ultimate location for this is likely a panel directly inside Windows. This is the hardest one to accomplish because of the timelines of the Windows product. We may not get this in an initial revision, but it should likely be our ultimate goal. **V1 NOTE:** We did it! - Operation: @@ -185,7 +185,7 @@ The settings experience includes: - Offer a list of registered servers or discovered manifests from the app catalog - This is the ideal scenario where we search the installed app catalog +/- the COM catalog and offer a list of apps that conform to the contract in a drop-down. - The final process was to use [App Extensions](https://docs.microsoft.com/windows/uwp/launch-resume/how-to-create-an-extension) inside the Terminal APPX package to declare the COM GUIDs that were available for the `DelegationConsole` and `DelegationTerminal` fields respectively. A configuration class `DelegationConfig` was added to `propslib.lib` that enables the lookup of these from the application state catalog and presents a list of them to choose from. It also manages reading and writing the registry keys. - **V1 NOTE:** Our configuration options currently allow pairings of replacement consoles and terminals to be adjusted in lock-step from the UI. That's not to say further combinations are not possible or even necessarily inhibited by the code. We just went for minimal confusion in our first round. - + - Configuration of the legacy console state: - ~~Since we could end up in an experience where the default launch experience gets you directly into Windows Terminal, we believe that the Terminal will likely need an additional setting or settings in the new Settings UI that will allow the toggling of some of the `HKCU\Console` values to do things like set/remove the legacy console state.~~ **V1 NOTE:** Cut as low priority. Switch back to console and configure it that way or use the existing property sheet or tamper with registry keys. - We have left the per-launch debugging and advanced access hole of calling something like `conhost.exe cmd.exe` which will use the inbox conhost to launch `cmd.exe` even if there is a default specified. @@ -209,9 +209,9 @@ The major players here that I am considering are NVDA, JAWS, and Narrator. As fa Let's hit the elephant in the room. "You plan on pulling a completely different binary inside the `conhost.exe` process and just... delegating all activity to it?" Yes. -(**V1 NOTE:** Well, it's out of proc now. But it is at the same privilege level as the original one thanks to the mechanics of COM.) +(**V1 NOTE:** Well, it's out of proc now. But it is at the same privilege level as the original one thanks to the mechanics of COM.) -As far as I'm concerned, the `conhost.exe` that is started to host the command-line client application is running at the same integrity level as the client binary that is partially started and waiting for its server to be ready. This is the long-standing existing protection that we have from the Windows operating system. Anything running in the same integrity level is already expected to be able to tamper with anything else at the same integrity level. The delegated binary that we would be loading into our process space will also be at the same integrity level. Nothing really stops a malicious actor from launching that binary in any other way in the same integrity level as a part of the command-line client application's startup. +As far as I'm concerned, the `conhost.exe` that is started to host the command-line client application is running at the same integrity level as the client binary that is partially started and waiting for its server to be ready. This is the long-standing existing protection that we have from the Windows operating system. Anything running in the same integrity level is already expected to be able to tamper with anything else at the same integrity level. The delegated binary that we would be loading into our process space will also be at the same integrity level. Nothing really stops a malicious actor from launching that binary in any other way in the same integrity level as a part of the command-line client application's startup. The mitigation here, if necessary, would be to use `WinVerifyTrust` to validate the certification path of the `OpenConsole.exe` binary to ensure that only one that is signed by Microsoft can be the substitute server host for the application. This doesn't stop third parties from redistributing our `OpenConsole.exe` off of GitHub if necessary with their products, but it would stop someone from introducing any random binary that met the signature interface of the delegation methods into `conhost.exe`. The only value I see this providing is stopping someone from being "tricked" into delegating their `conhost.exe` to another binary through the configuration methods we provide. It doesn't really stop someone (or an attacker) from taking ownership of the `conhost.exe` in System32 and replacing it directly. So this point might be moot. (It is expected that replacement of the System32 one is already protected, to some degree, by being owned by the SYSTEM account and requiring some measure of authority to replace.) @@ -242,8 +242,8 @@ I expect to take some degree of performance, power, and efficiency hit by implem The mitigations to these losses are as follows: -1. We will delay load any of the interface load and packaging data lookup libraries to only be pulled into process space should we determine that the application is non-interactive. - 1. That should save us some of the commit and power costs for the sorts of non-interactive scripts and applications that typically run early in OS startup (and leverage `conhost.exe` as their host environment). +1. We will delay load any of the interface load and packaging data lookup libraries to only be pulled into process space should we determine that the application is non-interactive. + 1. That should save us some of the commit and power costs for the sorts of non-interactive scripts and applications that typically run early in OS startup (and leverage `conhost.exe` as their host environment). 1. We will still likely get hit with the on-disk commit cost for the additional export libraries linked as well as additional code. That would be a by-design change. 1. We plan to begin Profile Guided Optimization across our `OpenConsole.exe` and `WindowsTerminal.exe` binaries. This should allow us to optimize the startup paths for this scenario and bias the `OpenConsole.exe` binary that we redistribute to focus its efforts and efficiency on the ConPTY role specifically, ignoring all of the interactive Win32/GDI portions that aren't typically used. diff --git a/doc/specs/#5000 - Process Model 2.0/#1032 - Elevation Quality of Life Improvements.md b/doc/specs/#5000 - Process Model 2.0/#1032 - Elevation Quality of Life Improvements.md index 4535ff304a..a239c4979e 100644 --- a/doc/specs/#5000 - Process Model 2.0/#1032 - Elevation Quality of Life Improvements.md +++ b/doc/specs/#5000 - Process Model 2.0/#1032 - Elevation Quality of Life Improvements.md @@ -109,7 +109,7 @@ each thing in the elevated window that they'd want to create it elevated. Or the Terminal would need to provide some setting like `"autoElevateEverythingInAnElevatedWindow"`. -We cannot support mixed elevation when starting in a unelevated window. +We cannot support mixed elevation when starting in an unelevated window. Therefore, it doesn't make a lot of UX sense to support it in the other direction. It's a cleaner UX story to just have everything in a single window at the same elevation level. @@ -141,7 +141,7 @@ We could also simplify this to only allow a boolean true/false for displaying the shield. As we do often with other enums, we could define `true` to be the same as the default appearance, and `false` to be the hidden option. As always, the development of the Terminal is an iterative process, where we can -incrementally improve from no setting, to a boolean setting, to a enum-backed +incrementally improve from no setting, to a boolean setting, to an enum-backed one. ### Configuring a profile to always run elevated diff --git a/doc/specs/#5000 - Process Model 2.0/#4472 - Windows Terminal Session Management.md b/doc/specs/#5000 - Process Model 2.0/#4472 - Windows Terminal Session Management.md index 625ef51e92..05ec6f3993 100644 --- a/doc/specs/#5000 - Process Model 2.0/#4472 - Windows Terminal Session Management.md +++ b/doc/specs/#5000 - Process Model 2.0/#4472 - Windows Terminal Session Management.md @@ -469,7 +469,7 @@ This is a list of actionable tasks generated as described by this spec: commandline * [ ] Add a `NameWindow` action, subcommand that allows the user to set the name for the window. -* [ ] Add an action that will cause all windows to briefly display a overlay +* [ ] Add an action that will cause all windows to briefly display an overlay with the current window ID and name. This would be something like the "identify" feature of the Windows "Display" settings. diff --git a/doc/specs/#5000 - Process Model 2.0/#5000 - Process Model 2.0.md b/doc/specs/#5000 - Process Model 2.0/#5000 - Process Model 2.0.md index 620e5c30a6..71e46339df 100644 --- a/doc/specs/#5000 - Process Model 2.0/#5000 - Process Model 2.0.md +++ b/doc/specs/#5000 - Process Model 2.0/#5000 - Process Model 2.0.md @@ -886,7 +886,7 @@ Here, we've got two tabs that have been serialized. - The second pane is also a `TermControl`, takes up 70% of the parent, and is attached to the content process `{2-2-2-2}` * The second tab has a single pane, with a SettingsPage. The settings page has - also specified in it's `payload` that its current page is the "globals" page. + also specified in its `payload` that its current page is the "globals" page. When we send this serialized state to another window, it can use the content GUIDs to initialize new `TermControl`s connected to the appropriate content @@ -983,7 +983,7 @@ of each other. all the logic concerning input. The core will expose these methods that the UI layer calls as projected methods -8. (Dependent on 7): Expose the methods the UI layer calls on the core as +8. (Dependent on 7): Expose the methods that the UI layer calls on the core as projected methods. The control is still fundamentally in-proc, and the UI layer calls directly into the implementation of the control core, but the methods _could_ be used x-proc. @@ -1132,7 +1132,7 @@ prompt the user for permission, but that's an acceptable user experience. ## TODOs -* [x] Experimentally prove that a elevated window can host an unelevated content +* [x] Experimentally prove that an elevated window can host an unelevated content - Research proved the opposite actually. * [ ] Experimentally prove that I can toss content process IDs from one window to another @@ -1155,7 +1155,7 @@ prompt the user for permission, but that's an acceptable user experience. ## Addenda This spec also has a follow-up spec which introduces further changes upon this -original draft. Please also refer to: +original draft. Please refer to: * November 2020: Windows Terminal Window Management diff --git a/doc/specs/#532 - Panes and Split Windows.md b/doc/specs/#532 - Panes and Split Windows.md index d6563c0a89..dacf00b527 100644 --- a/doc/specs/#532 - Panes and Split Windows.md +++ b/doc/specs/#532 - Panes and Split Windows.md @@ -156,7 +156,7 @@ then this is the pane with the currently focused terminal control. When the user brings the tab into focus, the last focused pane is the pane that should become focused again. -The tab's state will be updated to reflect the state of it's focused pane. The +The tab's state will be updated to reflect the state of its focused pane. The title text and icon of the tab will reflect that of the focused pane. Should the focus switch from one pane to another, the tab's text and icon should update to reflect the newly focused control. Any additional state that the tab would @@ -172,7 +172,7 @@ match. A pane can either be closed by the user manually, or when the terminal it's attached to raises its ConnectionClosed event. When this happens, we should remove this pane from the tree. The parent of the closing pane will have to -remove the pane as one of it's children. If the sibling of the closing pane is a +remove the pane as one of its children. If the sibling of the closing pane is a leaf, then the parent should just take all of the state from the remaining pane. This will cause the remaining pane's content to expand to take the entire boundaries of the parent's pane. If the remaining child was a parent itself, @@ -182,7 +182,7 @@ replaced by the remaining child. ## Future considerations -The Pane implementation isn't complete in it's current form. There are many +The Pane implementation isn't complete in its current form. There are many additional things that could be done to improve the user experience. This is by no means a comprehensive list. diff --git a/doc/specs/#605 - Search/spec.md b/doc/specs/#605 - Search/spec.md index e828cec0f8..eb42ed6145 100644 --- a/doc/specs/#605 - Search/spec.md +++ b/doc/specs/#605 - Search/spec.md @@ -30,7 +30,7 @@ Conhost already has a module for search. It implements case-sensitive or insensi We will create a `SearchBoxControl` Xaml `UserControl` element. When a search process begins, a `SearchBoxControl` object will be created and attached to `TermControl` root grid. In other words, one SearchBox is added for each `TermControl`. The reasons for this design is: -1. Each `TermControl` object is a Terminal Window and has a individual text buffer. In phase 1 we are going to search within the current terminal text buffer. +1. Each `TermControl` object is a Terminal Window and has an individual text buffer. In phase 1 we are going to search within the current terminal text buffer. 2. If we put the search box under TerminalApp, then the search can only happen on the current focused Terminal. 3. If the community does not like the current design, we can lift SearchBox to a higher level. @@ -55,7 +55,7 @@ Above is the `SearchBoxControl` in dark theme and light theme. ![SearchBox mockup, arrow button clicked](images/SearchBoxUpSelected.png) -The search box defaults to be on the top right corner of the Terminal window. If the current tab is split into panes, each pane will have a individual searchbox. +The search box defaults to the top right corner of the Terminal window. If the current tab is split into panes, each pane will have an individual searchbox. #### Search process 1. The user presses ctrl+shift+f (or user's custom key binding) to open the search box. Focus will move to the TextBox. diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index b2937011bf..b5e7f8f337 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -169,7 +169,7 @@ wt my-commandline.exe with some args # tab, and in another tab, run "another.exe running in a second tab" wt my-commandline.exe with some args and a \; literal semicolon ; new-tab another.exe running in a second tab -# Start cmd.exe, then split it vertically (with the first taking 70% of it's +# Start cmd.exe, then split it vertically (with the first taking 70% of its # space, and the new pane taking 30%), and run wsl.exe in that pane (user story 13) wt cmd.exe ; split-pane --target 0 -V -% 30 wsl.exe wt cmd.exe ; split-pane -% 30 wsl.exe @@ -551,7 +551,7 @@ this works as expected. Painfully, powershell uses `;` as a separator between commands as well. So, if someone wanted to call a `wt` commandline in powershell with multiple commands, -the user would need to also escape those semicolons for powershell first. That +the user would also need to escape those semicolons for powershell first. That means a command like ```wt new-tab ; split-pane``` would need to be ```wt new-tab `; split-pane``` in powershell, and ```wt new-tab ; split-pane commandline \; with \; semicolons``` would need to become ```wt new-tab `; split-pane commandline \`; diff --git a/doc/specs/#653 - Quake Mode/#653 - Quake Mode.md b/doc/specs/#653 - Quake Mode/#653 - Quake Mode.md index 9bf32e33d0..ebc117031c 100644 --- a/doc/specs/#653 - Quake Mode/#653 - Quake Mode.md +++ b/doc/specs/#653 - Quake Mode/#653 - Quake Mode.md @@ -69,7 +69,7 @@ To implement this feature, we'll add the following settings: ### `globalSummon` Action -The `globalSummon` action will be a keybinding the user can use to summon a +The `globalSummon` action will be a keybinding that the user can use to summon a Terminal window from anywhere in the OS. Various arguments to the action will specify which window is summoned, to where, and how the window should behave on summon. @@ -182,7 +182,7 @@ for pure markdown, sorry. --> "any"
Summon the MRU window -Go to the desktop the window is on (leave position alone) +Go to the desktop with the window (leave position alone) Move the window to this desktop (leave position alone) @@ -196,7 +196,7 @@ Else: "toCurrent"
Summon the MRU window TO the monitor with the foreground window -Go to the desktop the window is on, move to the monitor with the foreground window +Go to the desktop with the window, move to the monitor with the foreground window Move the window to this desktop, move to the monitor with the foreground window @@ -213,7 +213,7 @@ Else: "toMouse" [2]
Summon the MRU window TO the monitor with the mouse -Go to the desktop the window is on, move to the monitor with the mouse +Go to the desktop with the window, move to the monitor with the mouse Move the window to this desktop, move to the monitor with the mouse @@ -230,7 +230,7 @@ Else: If there is a window on this monitor on any desktop, -* Go to the desktop the window is on (leave position alone) +* Go to the desktop with the window (leave position alone) else * Create a new window on this monitor & desktop @@ -262,7 +262,7 @@ Else (one on this desktop & monitor) If there is a window on monitor N on any desktop, -* Go to the desktop the window is on (leave position alone) +* Go to the desktop with the window (leave position alone) else * Create a new window on this monitor & desktop diff --git a/doc/specs/#754 - Cascading Default Settings.md b/doc/specs/#754 - Cascading Default Settings.md index 5d43c2d0c0..158bfb77ee 100644 --- a/doc/specs/#754 - Cascading Default Settings.md +++ b/doc/specs/#754 - Cascading Default Settings.md @@ -273,7 +273,7 @@ with GUIDs set. After a dynamic profile generator runs, we will determine what new profiles need to be added to the user settings, so we can append those to the list of profiles. The deserializer will look at the list of generated profiles and check -if each and every one already has a entry in the user settings. The generator +if each and every one already has an entry in the user settings. The generator will just blind hand back a list of profiles, and the deserializer will figure out if any of them need to be added to the user settings. We'll store some sort of result indicating that we want a save operation to occur. After the rest of @@ -505,8 +505,8 @@ like so: // To view the default settings, open the defaults.json file in this directory ``` -The "Settings" button would then only open the file the user needs to edit, and -provide them instructions on how to open the defaults file. +The "Settings" button would then only open the file that the user needs to edit, +and provide them instructions on how to open the defaults file. There could alternatively be a hidden option for the "Open Settings" button, where holding Alt while clicking on the button would open the diff --git a/doc/specs/#8324 - Application State (TSM).md b/doc/specs/#8324 - Application State (TSM).md index 70582d3a21..a44a20564c 100644 --- a/doc/specs/#8324 - Application State (TSM).md +++ b/doc/specs/#8324 - Application State (TSM).md @@ -56,7 +56,7 @@ short duration after they're made. ## UI/UX Design This has no direct impact on the UI/UX; however, we may want to add a button to general settings page titled "reset all -dialogs" or "don't not ask me again about those things that, some time ago, I told you to not ask me about". +dialogs" or "ask me *again* about those things that, some time ago, I told you to not ask me about". We do not intend this file to be edited by hand, so it does not have to be user-friendly or serialized with indentation. diff --git a/doc/specs/Proto extensions-spec.md b/doc/specs/Proto extensions-spec.md index 039da21d53..473da1eb26 100644 --- a/doc/specs/Proto extensions-spec.md +++ b/doc/specs/Proto extensions-spec.md @@ -66,7 +66,7 @@ default profiles (cmd/powershell) or the dynamically generated profiles. For modifications to existing profiles, the json stub would need to indicate which profile it wishes to modify. It will do this by providing the corresponding guid in the `"updates"` field of the json stub. The reason we use an `"updates"` -field rather than a `"guid"` field (like the way the user settings are eventually layered onto profiles) is because we +field rather than a `"guid"` field (like the way that user settings are eventually layered onto profiles) is because we do not want to mistakenly create a new profile when the stub was meant to update a profile that did not exist. Note that currently, we generate a GUID for dynamic profiles using the "initial" name of the profile (i.e. before @@ -96,7 +96,7 @@ Here is an example of a json file that modifies an existing profile (specificall } ``` -**NOTE**: This will *not* change the way the profile looks in the user's settings file. The Azure cloud shell profile +**NOTE**: This will *not* change the way that profile looks in the user's settings file. The Azure cloud shell profile in their settings file (assuming they have made no changes) will still be as below. ```js diff --git a/doc/specs/drafts/#1256 - Tab tearoff.md b/doc/specs/drafts/#1256 - Tab tearoff.md index fa1b2e9a0d..fdf13bdf8d 100644 --- a/doc/specs/drafts/#1256 - Tab tearoff.md +++ b/doc/specs/drafts/#1256 - Tab tearoff.md @@ -31,7 +31,7 @@ There are several common pieces needed for both the tab tear-off scenario and th We need some sort of server/manager code that sits there waiting for connections from `wt.exe` processes and potentially `conhost.exe` processes such that it can broker a connection between the processes. It either needs to run in its own process or it needs to run in one of the existing `wt.exe`s that is chosen as the primary manager at the time. It should create communication channels and a global mutex at the time of creation. -All other `wt.exe` processes starting after the primary should detect the existence of the server manager process and wait on the mutex handle. When the primary disappears, the OS scheduler should choose one of the others to wake up first on the mutex. It can take the lock and then set up the primary management channel. +All other `wt.exe` processes starting after the primary should detect the existence of the server manager process and wait on the mutex handle. When the primary disappears, the OS scheduler should choose one of the others to wake up first on the mutex. It can take the lock and then set up the primary management channel. Alternatively, if the manager process is completely isolated and we expect all `wt.exe`s to have to remain connected at all times, we can make it such that when the connections are broken between the individual processes and the manager that they all shut down. I would prefer that it is resilient (the previous option) over this one, but browsers must have a good reason for preferring this way. @@ -85,7 +85,7 @@ If the registered handler fails to start the connection, there is no registered ##### Interactive vs. Not -We would have to be able to detect the difference between an interactive and non-interactive mode here. +We would have to be able to detect the difference between an interactive and non-interactive mode here. - Interactive is defined as the end-user is attempting to launch a command-line application with a visible window to see the output and enter input. - Non-interactive is defined as tools, utilities, and services attempting to launch a command-line application with no visible window (and possibly some redirected handles). @@ -120,7 +120,7 @@ There's a few areas to study here. 3. Updating conhost.exe to look up the launch preference and/or to launch another console host via a protocol handler - This would allow the `C:\windows\system32\conhost.exe` to effectively delegate the session to another `conhost.exe` that is hopefully newer than the inbox one. Given that the driver protocol in the box doesn't change and hasn't changed and we don't intend to change it, the forward/backward compatibility story is great here. Additionally, if for whatever reason the delegated `conhost.exe` fails to launch, we can just fall back and launch the old one like we would have prior to the change. It is significantly more likely, but still challenging, to argue for servicing `conhost.exe` back several versions in Windows to make this light up better for all folks. It might be especially more possible if it is a very targeted code snippet that can drop in to all the old versions of the `conhost.exe` code. We would still have the argument about spending resources developing for OS versions that are supposed to be dropped in favor of latest, but it's still a lesser argument than upending all of `kernelbase.dll`. -- A protocol handler is also well understood and relatively well handled/tested in Windows. Old apps can handle protocols. New apps can handle protocols. Protocol handlers can take arguments. We don't have to lean on any other team to get them to help change the way the rest of the OS works. +- A protocol handler is also well understood and relatively well handled/tested in Windows. Old apps can handle protocols. New apps can handle protocols. Protocol handlers can take arguments. We don't have to lean on any other team to get them to help change the way that the rest of the OS works. #### Communicating the launch For the parameters passing, I see a few options: @@ -149,7 +149,7 @@ To simplify this for a first iteration, we could just make it so the transfer do - If released onto anything that isn't a `wt.exe` instance, we create a new `wt.exe` instance and send in the connection as the default startup parameter. #### Component UI -It is also theoretically possible that if we could find a Component UI style solution (where the tab/panes live in their own process and just remote the UI/input into the shell) that it would be easy and even trivial to change out which shell/frame host is holding that element at any given time. +It is also theoretically possible that if we could find a Component UI style solution (where the tab/panes live in their own process and just remote the UI/input into the shell) that it would be easy and even trivial to change out which shell/frame host is holding that element at any given time. ### For Default Application The UX would make it look exactly like the user had started `wt.exe` from a shortcut or launch tile, but would launch the first tab differently than the defaults. @@ -173,7 +173,7 @@ I don't believe it changes anything for accessibility. The only concern I'd have This particular feature will have to go through a security review/audit. It is unclear what level of control we will need over the IPC communication channels. A few things come to mind: 1. We need to ensure that the mutexes/pipes/communications are restricted inside of one particular session to one particular user. If another user is also running WT in their session, it should involve a completely different manager process and system objects. -1. We MAY have to enforce a scenario where we inhibit cross-integrity-level connections from being passed around. Generally speaking, processes at a higher integrity level have the authority to perform actions on those with a lower integrity level. This means that an elevated `wt.exe` could theoretically send a tab to a standard level `wt.exe`. We may be required to inhibit/prohibit this. We may also need to have one manager per integrity level. +1. We MAY have to enforce a scenario where we inhibit cross-integrity-level connections from being passed around. Generally speaking, processes at a higher integrity level have the authority to perform actions on those with a lower integrity level. This means that an elevated `wt.exe` could theoretically send a tab to a standard level `wt.exe`. We may be required to inhibit/prohibit this. We may also need to have one manager per integrity level. 1. I'm not sure what sorts of ACL/DACL/SACLs we would need to apply to all the kernel objects involved. 1. My initial prototype here used message-passing type pipes with a custom rolled protocol. If I make my own protocol, it needs to be fuzzed. And I'm probably missing something. Many/most of these concerns for security are probably eliminated if we use a well-known mechanism for this sort of IPC. My thoughts go to a COM server. More complicated to implement than message pipes, but probably brings a lot of security benefits and eliminates the need to fuzz the protocol (probably). @@ -184,18 +184,18 @@ In the simple implementation, it will decrease reliability. We'll be shuffling c We might be able to mitigate some of the reliability concerns here or even improve reliability by going a step further with the process/containerization model like browsers do and standing up each individual tab as its own process host. ``` -wt.exe - Manager Mode -|- wt.exe - Frame Host Mode +wt.exe - Manager Mode +|- wt.exe - Frame Host Mode | |- wt.exe - Tab Host Mode | | |- conhost.exe - ConPTY mode -| | |- pwsh.exe - Client application +| | |- pwsh.exe - Client application | |- wt.exe - Tab Host Mode | |- conhost.exe - ConPTY mode -| |- cmd.exe - Client application -|- wt.exe - Frame Host Mode +| |- cmd.exe - Client application +|- wt.exe - Frame Host Mode |- wt.exe - Tab Host Mode |- conhost.exe - ConPTY mode - |- pwsh.exe - Client application + |- pwsh.exe - Client application ``` The current structure of `wt.exe` has everything hosted within the one process. To improve reliability, we would likely have to make `wt.exe` run in three modes. @@ -219,29 +219,29 @@ It is possible (but would need to be explored) that the APIs available to us to In the one instance, we have this process hierarchy. Two instances of Windows Terminal exist. In Terminal A, the user has started a `cmd.exe` and a `pwsh.exe` tab. In the second instance, the user has started just one `cmd.exe` tab. ``` -- wt.exe (Terminal Instance A) +- wt.exe (Terminal Instance A) |- conhost.exe (in PTY mode) - Hosted to A | |- cmd.exe |- conhost.exe (in PTY mode) - Hosted to A |- pwsh.exe <-- I will be dragged out - wt.exe (Terminal Instance B) - |- conhost.exe (in PTY mode) - Hosted to B - |- cmd.exe + |- conhost.exe (in PTY mode) - Hosted to B + |- cmd.exe ``` When the `pwsh.exe` tab is torn off from Instance A and is dropped onto Instance B, the process hierarchy doesn't actually change. The connection details, preferences, and session metadata are passed via the IPC management channels, but to an outside observer, nothing has actually changed. ``` -- wt.exe (Terminal Instance A) +- wt.exe (Terminal Instance A) |- conhost.exe (in PTY mode) - Hosted to A | |- cmd.exe |- conhost.exe (in PTY mode) - Hosted to B |- pwsh.exe <-- I am hosted in B but I'm parented to A - wt.exe (Terminal Instance B) - |- conhost.exe (in PTY mode) - Hosted to B - |- cmd.exe + |- conhost.exe (in PTY mode) - Hosted to B + |- cmd.exe ``` I don't believe there are provisions in the Windows OS to reparent applications to a different process. @@ -253,8 +253,8 @@ Additionally, this becomes more interesting when Terminal Instance A dies and B |- pwsh.exe <-- I am hosted in B but I'm parented to A - wt.exe (Terminal Instance B) - |- conhost.exe (in PTY mode) - Hosted to B - |- cmd.exe + |- conhost.exe (in PTY mode) - Hosted to B + |- cmd.exe ``` When instance A dies, the `conhost.exe` that was reparented keeps running and now just appears orphaned within the process hierarchy, reporting to the top level under utilities like Process Explorer. @@ -280,7 +280,7 @@ The `conhost.exe` was started in response to a `pwsh.exe` being started with no ``` - conhost.exe - idling - + - wt.exe (Terminal Instance A) |- conhost.exe (in PTY mode) |- pwsh.exe @@ -294,7 +294,7 @@ This is obviously less efficient than not doing it as we have to stand up server But as long as we're creating threads and services that sleep most of the time and are only awakened on some kernel/system event, we shouldn't be wasting too much in terms of power and background resources. -Additionally, `wt.exe` is worse than `conhost.exe` alone in all efficiency categories simply because it not only requires more resources to display in a "pretty" manner, but it also requires a `conhost.exe` under it in PTY mode to adapt the API calls. This is generally acceptable for end users who care more about the experience than the total performance. +Additionally, `wt.exe` is worse than `conhost.exe` alone in all efficiency categories simply because it not only requires more resources to display in a "pretty" manner, but it also requires a `conhost.exe` under it in PTY mode to adapt the API calls. This is generally acceptable for end users who care more about the experience than the total performance. It is, however, not likely to be much if any worse than just choosing to use `wt.exe` anyway over `conhost.exe`. @@ -304,7 +304,7 @@ I've listed most of the issues above in their individual sections. The primary h 1. Process tree layout - The processes in hierarchy may not make sense to someone inspecting them either visually with a tool or programmatically 1. Process and kernel object lifetime - Applications may be counting on a specific process or object lifetime in regards to their hosting window and we might be tampering with that in how we apply job objects or shuffle around ownership to make tabs happen 1. Default launch expectations - It is possible that test utilities or automation are counting on `conhost.exe` being the host application or that they're not ready to tolerate the potential for other applications to start. I think the interactive/non-interactive check mitigates this, but we'd have to remain concerned here. -1. `AttachConsole` and `DetachConsole` and `AllocConsole` - I don't have the slightest idea what happens for these APIs. We would have to explore. `AttachConsole` has restrictions based on the process hierarchy. It would likely behave in interesting ways with the strange parenting order and might be a driver to why we would have to adjust the parenting of the processes (or change the API under the hood). `DetachConsole` might create an issue where a tab disappears out of the terminal and the job object causes everything to die. `AttachConsole` wouldn't necessarily be guaranteed to go back into the same `wt.exe` or a `wt.exe` at all. +1. `AttachConsole` and `DetachConsole` and `AllocConsole` - I don't have the slightest idea what happens for these APIs. We would have to explore. `AttachConsole` has restrictions based on the process hierarchy. It would likely behave in interesting ways with the strange parenting order and might be a driver to why we would have to adjust the parenting of the processes (or change the API under the hood). `DetachConsole` might create an issue where a tab disappears out of the terminal and the job object causes everything to die. `AttachConsole` wouldn't necessarily be guaranteed to go back into the same `wt.exe` or a `wt.exe` at all. ## Future considerations diff --git a/doc/specs/drafts/#3327 - Application Theming/#3327 - Application Theming.md b/doc/specs/drafts/#3327 - Application Theming/#3327 - Application Theming.md index e956b33491..14df79f488 100644 --- a/doc/specs/drafts/#3327 - Application Theming/#3327 - Application Theming.md +++ b/doc/specs/drafts/#3327 - Application Theming/#3327 - Application Theming.md @@ -647,7 +647,7 @@ style admin vs regular windows? ## Addenda This spec also has a follow-up spec which elaborates on the complexities of Mica -in the Terminal. Please also refer to: +in the Terminal. Please refer to: * [Mica in the Terminal] diff --git a/doc/specs/drafts/#997 Non-Terminal-Panes.md b/doc/specs/drafts/#997 Non-Terminal-Panes.md index 7dc2060d28..f34b1dd86d 100644 --- a/doc/specs/drafts/#997 Non-Terminal-Panes.md +++ b/doc/specs/drafts/#997 Non-Terminal-Panes.md @@ -94,7 +94,7 @@ should the control provide some sort of accessibility pattern. if the hosted control wants to use Ctrl+T for its own shortcut? The current keybindings model has the `TermControl` call into the App layer to see if a keystroke should be handled by the app first. We may want to make sure that - for non-terminal controls, we add a event handler to try and have the + for non-terminal controls, we add an event handler to try and have the `AppKeyBindings` handle the keypress if the control doesn't. This won't solve the case where the control wants to use a keybinding that is mapped by the Terminal App. In that case, non-terminal controls will actually behave diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index 3a29409a82..482892e419 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -100,7 +100,7 @@ void TextBuffer::_reserve(til::size screenBufferSize, const TextAttribute& defau const auto rowStride = rowSize + charsBufferSize + charOffsetsBufferSize; assert(rowStride % alignof(ROW) == 0); - // 65535*65535 cells would result in a allocSize of 8GiB. + // 65535*65535 cells would result in an allocSize of 8GiB. // --> Use uint64_t so that we can safely do our calculations even on x86. // We allocate 1 additional row, which will be used for GetScratchpadRow(). const auto rowCount = ::base::strict_cast(h) + 1; @@ -2724,7 +2724,7 @@ void TextBuffer::Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const View til::point newCursorPos; // BODGY: We use oldCursorPos in two critical places below: - // * To compute an oldHeight that includes at a minimum the cursor row + // * To compute an oldHeight that includes, at a minimum, the cursor row // * For REFLOW_JANK_CURSOR_WRAP (see comment below) // Both of these would break the reflow algorithm, but the latter of the two in particular // would cause the main copy loop below to deadlock. In other words, these two lines @@ -2844,7 +2844,7 @@ void TextBuffer::Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const View // We don't need to be smart about this. Reset() is fast and shrinking doesn't occur often. if (newY >= newHeight && newX == 0) { - // We need to ensure not to overwrite the row the cursor is on. + // We need to ensure not to overwrite the row containing the cursor. if (newY >= newYLimit) { break; diff --git a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj index 465f41ca94..317109ed35 100644 --- a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj +++ b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj @@ -103,7 +103,7 @@ - + $(OCExecutionAliasName).exe diff --git a/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp b/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp index df5032ffdf..d3f2647bc8 100644 --- a/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp +++ b/src/cascadia/LocalTests_TerminalApp/SettingsTests.cpp @@ -741,7 +741,7 @@ namespace TerminalAppLocalTests void SettingsTests::TestNestedInIterableCommand() { - // This test checks a iterable command that includes a nested command. + // This test checks an iterable command that includes a nested command. // The commands should look like: // // diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index f601ec8cf1..1fc52d2632 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -294,7 +294,7 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Registers for changes to the settings folder and upon a updated settings + // - Registers for changes to the settings folder and upon an updated settings // profile calls ReloadSettings(). // Arguments: // - @@ -307,7 +307,7 @@ namespace winrt::TerminalApp::implementation settingsPath.parent_path().c_str(), false, // We want file modifications, AND when files are renamed to be - // settings.json. This second case will oftentimes happen with text + // settings.json. This second case will often happen with text // editors, who will write a temp file, then rename it to be the // actual file you wrote. So listen for that too. wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime, diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index acf888fa26..61607319f1 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -741,10 +741,10 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Helper method for retrieving the action from a command the user - // selected, and dispatching that command. Also fires a tracelogging event - // indicating that the user successfully found the action they were - // looking for. + // - Helper method to run a command, switch to a tab, or retrieve the + // action from a user selected command and dispatch that command. + // Also fires a tracelogging event indicating that the user successfully + // found the action they were looking for. // Arguments: // - command: the Command to dispatch. This might be null. // Return Value: @@ -791,7 +791,7 @@ namespace winrt::TerminalApp::implementation _close(); // But make an exception for the Toggle Command Palette action: we don't want the dispatch - // make the command palette - that was just closed - visible again. + // to make the command palette - that was just closed - visible again. // All other actions can just be dispatched. if (command.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette) { diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index ed02e5250e..85354101b6 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -136,7 +136,7 @@ Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t n ActionAndArgs actionAndArgs; actionAndArgs.Action(ShortcutAction::SplitPane); const auto terminalArgs{ newPane->GetTerminalArgsForPane(kind) }; - // When creating a pane the split size is the size of the new pane + // When creating a pane, the split size is the size of the new pane // and not position. const auto splitDirection = _splitState == SplitState::Horizontal ? SplitDirection::Down : SplitDirection::Right; const auto splitSize = (kind != BuildStartupKind::None && _IsLeaf() ? 0.5f : 1.0f - _desiredSplitPosition); @@ -2264,7 +2264,7 @@ SplitState Pane::_convertAutomaticOrDirectionalSplitState(const SplitDirection& // creates a new Pane to host the control, registers event handlers. // Arguments: // - splitType: what type of split we should create. -// - splitSize: what fraction of the pane the new pane should get +// - splitSize: the fraction of the pane that the new pane should get // - newPane: the pane to add as a child // Return Value: // - The two newly created Panes, with the original pane as the first pane. diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index d27ae8e6ab..eb1c317e18 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -851,11 +851,11 @@ Active pane moved to "{0}" tab - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. "{0}" tab moved to "{1}" window - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. "{0}" tab moved to new window @@ -867,7 +867,7 @@ Active pane moved to "{0}" window - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Active pane moved to new window diff --git a/src/cascadia/TerminalApp/SuggestionsControl.cpp b/src/cascadia/TerminalApp/SuggestionsControl.cpp index 048fb1968e..29f3215df6 100644 --- a/src/cascadia/TerminalApp/SuggestionsControl.cpp +++ b/src/cascadia/TerminalApp/SuggestionsControl.cpp @@ -686,8 +686,8 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Helper method for retrieving the action from a command the user - // selected, and dispatching that command. Also fires a tracelogging event + // - Helper method to retrieve the action from the user selected command, + // and dispatch that command. Also fires a tracelogging event // indicating that the user successfully found the action they were // looking for. // Arguments: diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 4bbf58e50a..42fb9ab624 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -654,7 +654,7 @@ namespace winrt::TerminalApp::implementation _activePane = original; - // Add a event handlers to the new panes' GotFocus event. When the pane + // Add event handlers to the new panes' GotFocus event. When the pane // gains focus, we'll mark it as the new active pane. _AttachEventHandlersToPane(original); @@ -2098,7 +2098,7 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Calculates if the tab is read-only. // The tab is considered read-only if one of the panes is read-only. - // If after the calculation the tab is read-only we hide the close button on the tab view item + // If, after the calculation, the tab is read-only we hide the close button on the tab view item void Tab::_RecalculateAndApplyReadOnly() { const auto control = GetActiveTerminalControl(); @@ -2125,7 +2125,7 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Creates a text for the title run in the tool tip by returning tab title - // or : in the case the profile name differs from the title + // or : if the profile name differs from the title // Arguments: // - // Return Value: @@ -2353,7 +2353,7 @@ namespace winrt::TerminalApp::implementation auto deselectedTabColor = color.with_alpha(77); // 255 * .3 = 77 // If we DON'T have a color set from the color picker, or the profile's - // tabColor, but we do have a unfocused color in the theme, use the + // tabColor, but if we have an unfocused color in the theme, use the // unfocused theme color here instead. if (!GetTabColor().has_value() && _unfocusedThemeColor != nullptr) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 2e752bc775..c715b0e2a1 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4727,7 +4727,7 @@ namespace winrt::TerminalApp::implementation // Function Description: // - Helper to launch a new WT instance elevated. It'll do this by spawning - // a helper process, who will asking the shell to elevate the process for + // a helper process, that will ask the shell to elevate the process for // us. This might cause a UAC prompt. The elevation is performed on a // background thread, as to not block the UI thread. // Arguments: diff --git a/src/cascadia/TerminalApp/TerminalWindow.cpp b/src/cascadia/TerminalApp/TerminalWindow.cpp index 266ece81db..b2fa349e40 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.cpp +++ b/src/cascadia/TerminalApp/TerminalWindow.cpp @@ -861,7 +861,7 @@ namespace winrt::TerminalApp::implementation // - Used to tell the app that the titlebar has been clicked. The App won't // actually receive any clicks in the titlebar area, so this is a helper // to clue the app in that a click has happened. The App will use this as - // a indicator that it needs to dismiss any open flyouts. + // an indicator that it needs to dismiss any open flyouts. // Arguments: // - // Return Value: diff --git a/src/cascadia/TerminalConnection/AzureConnection.cpp b/src/cascadia/TerminalConnection/AzureConnection.cpp index 72208af100..81f5940ebf 100644 --- a/src/cascadia/TerminalConnection/AzureConnection.cpp +++ b/src/cascadia/TerminalConnection/AzureConnection.cpp @@ -879,7 +879,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation // Arguments: // - the device code that would have been received when authentication was initiated // - the polling interval duration - // - the duration the code is still valid for + // - the duration for which the code is still valid // Return value: // - if authentication is done successfully, then return the response from the server // - else, throw an exception @@ -1018,7 +1018,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation _terminalID = terminalResponse.GetNamedString(L"id"); // we have to do some post-handling to get the proper socket endpoint - // the logic here is based on the way the cloud shell team itself does it + // the logic here is based on the way that the cloud shell team itself does it winrt::hstring finalSocketUri; const std::wstring_view wCloudShellUri{ _cloudShellUri }; diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index c132a74615..a3bef730a2 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -78,7 +78,7 @@ HRESULT CTerminalHandoff::s_StopListening() // - server - PTY process handle to track for lifetime/cleanup // - client - Process handle to client so we can track its lifetime and exit appropriately // Return Value: -// - E_NOT_VALID_STATE if a event handler is not registered before calling. `::DuplicateHandle` +// - E_NOT_VALID_STATE if an event handler is not registered before calling. `::DuplicateHandle` // error codes if we cannot manage to make our own copy of handles to retain. Or S_OK/error // from the registered handler event function. HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 7b9d05e5a3..6f4ed75321 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -2309,7 +2309,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // The absolute cursor coordinate. const auto cursor = _terminal->GetViewportRelativeCursorPosition(); - // GH#18732: Users want the row the cursor is on to be preserved across clears. + // GH#18732: Users want the row that the cursor is on to be preserved across clears. std::wstring sequence; if (clearType == ClearBufferType::Scrollback || clearType == ClearBufferType::All) @@ -2859,7 +2859,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (markStart <= pos && markEnd >= pos) { - // ... select the part of the mark the caller told us about. + // ... select the part of the mark that the caller told us about. _selectSpan(getSpan(m)); // And quick bail return; diff --git a/src/cascadia/TerminalControl/HwndTerminalAutomationPeer.cpp b/src/cascadia/TerminalControl/HwndTerminalAutomationPeer.cpp index 92724a2c67..ae3ccc5c04 100644 --- a/src/cascadia/TerminalControl/HwndTerminalAutomationPeer.cpp +++ b/src/cascadia/TerminalControl/HwndTerminalAutomationPeer.cpp @@ -140,7 +140,7 @@ void HwndTerminalAutomationPeer::NotifyNewOutput(std::wstring_view newOutput) } // Try to suppress any events (or event data) - // that is just the keypress the user made + // that is just the keypress that the user made auto sanitized{ Sanitize(newOutput) }; while (!_keyEvents.empty() && IsReadable(sanitized)) { diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 61690a723b..a616bec79a 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -586,7 +586,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto data = buffer.data(); const auto stride = scrollBarWidthInPx * sizeof(til::color); - // The bitmap has the size of the entire scrollbar, but we want the marks to only show in the range the "thumb" + // The bitmap has the size of the entire scrollbar, but we want the marks to only show in the range that the "thumb" // (the scroll indicator) can move. That's why we need to add an offset to the start of the drawable bitmap area // (to offset the decrease button) and subtract twice that (to offset the increase button as well). // diff --git a/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp b/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp index bf49dd2e85..4ed8fc524f 100644 --- a/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp +++ b/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp @@ -213,7 +213,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { auto sanitized{ Sanitize(newOutput) }; // Try to suppress any events (or event data) - // that are just the keypresses the user made + // that are just the keypresses that the user made { auto keyEvents = _keyEvents.lock(); while (!keyEvents->empty() && IsReadable(sanitized)) diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index afdb6b4f45..39a0406278 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -735,7 +735,7 @@ TerminalInput::OutputType Terminal::SendCharEvent(const wchar_t ch, const WORD s } // GH#1527: When the user has auto mark prompts enabled, we're going to try - // and heuristically detect if this was the line the prompt was on. + // and heuristically detect if this was the line with the prompt. // * If the key was an Enter keypress (Terminal.app also marks ^C keypresses // as prompts. That's omitted for now.) // * AND we're not in the alt buffer diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.cpp b/src/cascadia/TerminalSettingsEditor/Appearances.cpp index c7548e636b..ec66af8cd0 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.cpp +++ b/src/cascadia/TerminalSettingsEditor/Appearances.cpp @@ -59,7 +59,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation }; // Turns a DWRITE_MAKE_OPENTYPE_TAG into a string_view... - // (...buffer holder because someone needs to hold onto the data the view refers to.) + // (...buffer holder because someone needs to hold onto the data to which the view refers.) static TagToStringImpl tagToString(uint32_t tag) noexcept { return TagToStringImpl{ tag }; @@ -1425,9 +1425,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // button won't work right. }); - // make sure to send all the property changed events once here - // we do this in the case an old appearance was deleted and then a new one is created, - // the old settings need to be updated in xaml + // make sure to send all the property changed events once here. + // we do this so that if an old appearance was deleted and then a new one created, + // the old settings are updated in xaml PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentCursorShape" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"IsVintageCursor" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentColorScheme" }); diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index 29137c94f0..9eb703a6e2 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -293,7 +293,7 @@ Header for a control to set the query URL when using the "search web" action. - The placeholder "%s" will replaced with the search query. + The placeholder "%s" will be replaced with the search query. {Locked="%s"} Additional text presented near "Globals_SearchWebDefaultQueryUrl.Header". @@ -507,7 +507,7 @@ Hide the title bar (requires relaunch) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. When disabled, the title bar will appear above the tabs. @@ -1195,15 +1195,15 @@ Starting directory - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Starting directory - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Starting directory - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. The directory the profile starts in when it is loaded. @@ -2147,7 +2147,7 @@ Shortcut - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Text Formatting diff --git a/src/cascadia/TerminalSettingsModel/IDynamicProfileGenerator.h b/src/cascadia/TerminalSettingsModel/IDynamicProfileGenerator.h index 9144bcb325..95b18655a6 100644 --- a/src/cascadia/TerminalSettingsModel/IDynamicProfileGenerator.h +++ b/src/cascadia/TerminalSettingsModel/IDynamicProfileGenerator.h @@ -6,7 +6,7 @@ Module Name: - IDynamicProfileGenerator Abstract: -- The DynamicProfileGenerator interface. A dynamic profile generator is a object +- The DynamicProfileGenerator interface. A dynamic profile generator is an object that can synthesize a list of profiles based on some arbitrary, typically external criteria. Profiles from dynamic sources are only available in the user's profiles if the generator actually ran and created the profile. diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 3b79b5297d..e53c72a79e 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -162,7 +162,7 @@ winrt::WUX::Media::Brush ThemeColor::Evaluate(const winrt::WUX::ResourceDictiona // Method Description: // - This is not an actual property on a theme color setting, but rather // something derived from the value itself. This is "the opacity we should use -// for this ThemeColor should it be used as a unfocusedTab color". Basically, +// for this ThemeColor should it be used as an unfocusedTab color". Basically, // terminalBackground and accent use 30% opacity when set, to match the how // inactive tabs were colored before themes existed. // Arguments: diff --git a/src/cascadia/UIHelpers/TextMenuFlyout.h b/src/cascadia/UIHelpers/TextMenuFlyout.h index 87a6d9a3f9..c134577d51 100644 --- a/src/cascadia/UIHelpers/TextMenuFlyout.h +++ b/src/cascadia/UIHelpers/TextMenuFlyout.h @@ -9,7 +9,7 @@ namespace winrt::Microsoft::Terminal::UI::implementation { // This custom flyout exists because WinUI 2 only supports 1 text block flyout // *per thread* not per window. If you have >1 window per 1 thread, as we do, - // the focus will just be delegated to the window the flyout was first opened in. + // the focus will just be delegated to the window that opened the first flyout. // Once the first window is gone, WinUI will either do nothing or crash. // See: GH#18599 struct TextMenuFlyout : TextMenuFlyoutT diff --git a/src/cascadia/UIMarkdown/MarkdownToXaml.cpp b/src/cascadia/UIMarkdown/MarkdownToXaml.cpp index eb515898b2..ecdea1e88e 100644 --- a/src/cascadia/UIMarkdown/MarkdownToXaml.cpp +++ b/src/cascadia/UIMarkdown/MarkdownToXaml.cpp @@ -219,7 +219,7 @@ void MarkdownToXaml::_RenderNode(cmark_node* node, cmark_event_type ev_type) } case CMARK_NODE_ITEM: - // A list item, either for a ordered list or an unordered one. + // A list item, either for an ordered list or an unordered one. if (entering) { _EndParagraph(); diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 5b242b8235..7a0ef5134f 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -598,7 +598,7 @@ namespace ControlUnitTests } Log::Comment(L"then move the cursor to the left"); - // This emulates the state the buffer is in when pwsh does it's "ghost + // This emulates the state the buffer is in when pwsh does its "ghost // text" thing. We don't want to include all that ghost text in the // current commandline. conn->WriteInput(winrt_wstring_to_array_view(L"\x1b[D")); @@ -682,7 +682,7 @@ namespace ControlUnitTests void ControlCoreTests::TestSelectOutputExactWrap() { // Just like the TestSelectOutputScrolling test, but these lines will - // exactly wrap to the right edge of the buffer, to catch a edge case + // exactly wrap to the right edge of the buffer, to catch an edge case // present in `ControlCore::_selectSpan` auto [settings, conn] = _createSettingsAndConnection(); Log::Comment(L"Create ControlCore object"); diff --git a/src/cascadia/UnitTests_SettingsModel/ProfileTests.cpp b/src/cascadia/UnitTests_SettingsModel/ProfileTests.cpp index 7697715b8f..76ae58bba6 100644 --- a/src/cascadia/UnitTests_SettingsModel/ProfileTests.cpp +++ b/src/cascadia/UnitTests_SettingsModel/ProfileTests.cpp @@ -222,7 +222,7 @@ namespace SettingsModelUnitTests VERIFY_ARE_EQUAL(L"not-null.png", profile0->Icon().Path()); Log::Comment(NoThrowString().Format( - L"Verify that layering an object the key set to null will clear the key")); + L"Verify that layering an object with the key set to null will clear the key")); profile0->LayerJson(profile1Json); VERIFY_IS_TRUE(profile0->Icon().Path().empty()); diff --git a/src/cascadia/UnitTests_TerminalCore/InputTest.cpp b/src/cascadia/UnitTests_TerminalCore/InputTest.cpp index 01436fcddf..97a8b21890 100644 --- a/src/cascadia/UnitTests_TerminalCore/InputTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/InputTest.cpp @@ -38,10 +38,10 @@ namespace TerminalCoreUnitTests { // Tests GH:637 - // Verify that Alt+a generates a lowercase a on the input + // Verify that Alt+a generates a lowercase 'a' on the input VERIFY_ARE_EQUAL(escChar(L'a'), term.SendCharEvent(L'a', 0, ControlKeyStates::LeftAltPressed)); - // Verify that Alt+shift+a generates a uppercase a on the input + // Verify that Alt+shift+a generates an uppercase 'a' on the input VERIFY_ARE_EQUAL(escChar(L'A'), term.SendCharEvent(L'A', 0, ControlKeyStates::LeftAltPressed | ControlKeyStates::ShiftPressed)); } diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index 07eba616f1..5ab07ef760 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -673,7 +673,7 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept auto state = (UINT)SHAppBarMessage(ABM_GETSTATE, &autohide); if (WI_IsFlagSet(state, ABS_AUTOHIDE)) { - // This helper can be used to determine if there's a auto-hide + // This helper can be used to determine if there's an auto-hide // taskbar on the given edge of the monitor we're currently on. auto hasAutohideTaskbar = [&monInfo](const UINT edge) -> bool { APPBARDATA data{ 0 }; diff --git a/src/host/ConsoleArguments.cpp b/src/host/ConsoleArguments.cpp index a0c6fb1837..ec88e5e901 100644 --- a/src/host/ConsoleArguments.cpp +++ b/src/host/ConsoleArguments.cpp @@ -315,7 +315,7 @@ void ConsoleArguments::s_ConsumeArg(_Inout_ std::vector& args, _In } else { - // If we're trying to set the handle a second time, invalid. + // If we're trying to set the handle again, invalid. hr = E_INVALIDARG; } diff --git a/src/host/PtySignalInputThread.cpp b/src/host/PtySignalInputThread.cpp index 063d3d4c4d..a9bf8e2a11 100644 --- a/src/host/PtySignalInputThread.cpp +++ b/src/host/PtySignalInputThread.cpp @@ -30,7 +30,7 @@ PtySignalInputThread::PtySignalInputThread(wil::unique_hfile hPipe) : PtySignalInputThread::~PtySignalInputThread() { - // Manually terminate our thread during unittesting. Otherwise, the test + // Manually terminate our thread during unit testing. Otherwise, the test // will finish, but TAEF will not manually kill the test. #ifdef UNIT_TESTING TerminateThread(_hThread.get(), 0); diff --git a/src/host/_stream.cpp b/src/host/_stream.cpp index 235ba52b10..14d0bf91df 100644 --- a/src/host/_stream.cpp +++ b/src/host/_stream.cpp @@ -126,7 +126,7 @@ static void AdjustCursorPosition(SCREEN_INFORMATION& screenInfo, _In_ til::point buffer.IncrementCircularBuffer(buffer.GetCurrentAttributes()); // TODO: This is very bad for performance. - // Track the total scroll offset as a int64 in buffer --> No need to track it here anymore. + // Track the total scroll offset as an int64 in buffer --> No need to track it here anymore. if (buffer.IsActiveBuffer()) { auto& an = ServiceLocator::LocateGlobals().accessibilityNotifier; diff --git a/src/host/ft_host/API_InputTests.cpp b/src/host/ft_host/API_InputTests.cpp index 3bb9f39b66..2624044038 100644 --- a/src/host/ft_host/API_InputTests.cpp +++ b/src/host/ft_host/API_InputTests.cpp @@ -681,7 +681,7 @@ void InputTests::RawReadUnpacksCoalescedInputRecords() SetConsoleMode(hIn, mode); // flush input queue before attempting to add new events and check - // in case any are leftover from previous tests + // in case any are left over from previous tests VERIFY_WIN32_BOOL_SUCCEEDED(FlushConsoleInputBuffer(hIn)); INPUT_RECORD record; diff --git a/src/host/ft_host/API_RgbColorTests.cpp b/src/host/ft_host/API_RgbColorTests.cpp index 42f5334a6f..4d1304c1af 100644 --- a/src/host/ft_host/API_RgbColorTests.cpp +++ b/src/host/ft_host/API_RgbColorTests.cpp @@ -78,7 +78,7 @@ class RgbColorTests TEST_METHOD(TestVT256Grid); }; -// Takes windows 16 color table index, and returns a int for the equivalent SGR sequence +// Takes windows 16 color table index, and returns an int for the equivalent SGR sequence WORD WinToVTColor(int winColor, bool isForeground) { auto red = (winColor & FOREGROUND_RED) > 0; diff --git a/src/host/ft_host/CJK_DbcsTests.cpp b/src/host/ft_host/CJK_DbcsTests.cpp index a773a31486..dc4398230e 100644 --- a/src/host/ft_host/CJK_DbcsTests.cpp +++ b/src/host/ft_host/CJK_DbcsTests.cpp @@ -21,7 +21,7 @@ constexpr CHAR_INFO makeCharInfo(T ch, WORD attr) CHAR_INFO info{}; // If T is a char, it'll be a signed integer, whereas UnicodeChar is an unsigned one. // A negative char like -1 would then result in a wchar_t of 0xffff instead of the expected 0xff. - // Casting ch to a unsigned integer first prevents such "sign extension". + // Casting ch to an unsigned integer first prevents such "sign extension". info.Char.UnicodeChar = static_cast(til::as_unsigned(ch)); info.Attributes = attr; return info; diff --git a/src/host/ft_integrity/IntegrityTest.cpp b/src/host/ft_integrity/IntegrityTest.cpp index 0ca45b0b5d..a5a79ebbea 100644 --- a/src/host/ft_integrity/IntegrityTest.cpp +++ b/src/host/ft_integrity/IntegrityTest.cpp @@ -131,7 +131,7 @@ bool IntegrityTest::ClassSetup() VERIFY_IS_NOT_NULL(appAumids); VERIFY_ARE_EQUAL(appAumids->Size, 1u); - // save off aumid + // save off AUMID this->_appAumid = appAumids->GetAt(0); return true; diff --git a/src/host/getset.cpp b/src/host/getset.cpp index 73c4a7fded..13e49724a2 100644 --- a/src/host/getset.cpp +++ b/src/host/getset.cpp @@ -874,7 +874,7 @@ void ApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& cont NewWindowSize.height = CalcWindowSizeY(Window); // see MSFT:17415266 - // If we have a actual head, we care about the maximum size the window can be. + // If we have an actual head, we care about the maximum size the window can be. // if we're headless, not so much. However, GetMaxWindowSizeInCharacters // will only return the buffer size, so we can't use that to clip the arg here. // So only clip the requested size if we're not headless diff --git a/src/host/inputBuffer.cpp b/src/host/inputBuffer.cpp index 240b3ee329..ecc9f4633b 100644 --- a/src/host/inputBuffer.cpp +++ b/src/host/inputBuffer.cpp @@ -743,7 +743,7 @@ void InputBuffer::_WriteBuffer(const std::span& inEvents, _O // - Coalescing here means updating a record that already exists in // the buffer with updated values from an incoming event, instead of // storing the incoming event (which would make the original one -// redundant/out of date with the most current state). +// redundant/out-of-date with the most current state). bool InputBuffer::_CoalesceEvent(const INPUT_RECORD& inEvent) noexcept { auto& lastEvent = _storage.back(); diff --git a/src/host/inputKeyInfo.cpp b/src/host/inputKeyInfo.cpp index 01554c3ac4..40c7ad5e0e 100644 --- a/src/host/inputKeyInfo.cpp +++ b/src/host/inputKeyInfo.cpp @@ -92,7 +92,7 @@ const bool INPUT_KEY_INFO::IsShiftAndCtrlOnly() const } // Routine Description: -// - Helps determine if this key input represents a alt+KEY combo +// - Helps determine if this key input represents an alt+KEY combo // Arguments: // - // Return Value: diff --git a/src/host/output.cpp b/src/host/output.cpp index e0dd534ef0..74a0f42283 100644 --- a/src/host/output.cpp +++ b/src/host/output.cpp @@ -381,7 +381,7 @@ void ScrollRegion(SCREEN_INFORMATION& screenInfo, const auto originalTargetOrigin = target.Origin(); target = Viewport::Intersect(clip, target); - // OK, if the target became smaller than before, we need to also adjust the source accordingly + // OK, if the target became smaller than before, we also need to adjust the source accordingly // so we don't waste time loading up/copying things that have no place to go within the target. { const auto currentTargetOrigin = target.Origin(); diff --git a/src/host/outputStream.cpp b/src/host/outputStream.cpp index 3852f8a8f4..df07c620d6 100644 --- a/src/host/outputStream.cpp +++ b/src/host/outputStream.cpp @@ -192,7 +192,7 @@ void ConhostInternalGetSet::SetWindowTitle(std::wstring_view title) // screen buffer and an alternate. This creates a new alternate, and switches to it. // If there is an already existing alternate, it is discarded. // Arguments: -// - attrs - the attributes the buffer is initialized with. +// - attrs - the attributes for initializing the buffer. // Return Value: // - void ConhostInternalGetSet::UseAlternateScreenBuffer(const TextAttribute& attrs) diff --git a/src/host/proxy/ITerminalHandoff.idl b/src/host/proxy/ITerminalHandoff.idl index f48bc10f69..de2a153650 100644 --- a/src/host/proxy/ITerminalHandoff.idl +++ b/src/host/proxy/ITerminalHandoff.idl @@ -64,7 +64,7 @@ typedef struct _TERMINAL_STARTUP_INFO }; // Quite a while later, we realized that passing the in/out handles as [in] instead of [out] has always been flawed. -// It prevents the terminal from making choices over the pipe buffer size and whether to use overlapped IO or not. +// It prevents the terminal from making choices over the pipe buffer size and whether or not to use overlapped IO. // The other handles remain [in] parameters because they have always been created internally by ConPTY. // Additionally, passing TERMINAL_STARTUP_INFO by-value was unusual under COM as structs are usually given by-ref. [ diff --git a/src/host/screenInfo.cpp b/src/host/screenInfo.cpp index 51beb39822..b0372755d8 100644 --- a/src/host/screenInfo.cpp +++ b/src/host/screenInfo.cpp @@ -1764,7 +1764,7 @@ const SCREEN_INFORMATION* SCREEN_INFORMATION::GetAltBuffer() const noexcept // machine with the main buffer it belongs to. // TODO: MSFT:19817348 Don't create alt screenbuffer's via an out SCREEN_INFORMATION** // Parameters: -// - initAttributes - the attributes the buffer is initialized with. +// - initAttributes - the attributes for initializing the buffer. // - ppsiNewScreenBuffer - a pointer to receive the newly created buffer. // Return value: // - STATUS_SUCCESS if handled successfully. Otherwise, an appropriate status code indicating the error. @@ -1871,7 +1871,7 @@ void SCREEN_INFORMATION::_handleDeferredResize(SCREEN_INFORMATION& siMain) // screen buffer and an alternate. ASBSET creates a new alternate, and switches to it. If there is an already // existing alternate, it is discarded. This allows applications to retain one HANDLE, and switch which buffer it points to seamlessly. // Parameters: -// - initAttributes - the attributes the buffer is initialized with. +// - initAttributes - the attributes for initializing the buffer. // Return value: // - STATUS_SUCCESS if handled successfully. Otherwise, an appropriate status code indicating the error. [[nodiscard]] NTSTATUS SCREEN_INFORMATION::UseAlternateScreenBuffer(const TextAttribute& initAttributes) diff --git a/src/host/selection.cpp b/src/host/selection.cpp index 40e675d6b8..352b558d77 100644 --- a/src/host/selection.cpp +++ b/src/host/selection.cpp @@ -413,7 +413,7 @@ void Selection::ClearSelection(const bool fStartingNewSelection) // Routine Description: // - Colors all text in the given rectangle with the color attribute provided. -// - This does not validate whether there is a valid selection right now or not. +// - This does not validate whether or not there is a valid selection right now. // It is assumed to already be in a proper selecting state and the given rectangle should be highlighted with the given color unconditionally. // Arguments: // - psrRect - Rectangular area to fill with color (exclusive) @@ -433,7 +433,7 @@ void Selection::ColorSelection(const til::rect& srRect, const TextAttribute attr coordTarget.x = srRect.left; coordTarget.y = srRect.top; - // Now color the selection a line at a time. + // Now color the selection one line at a time. for (; (coordTarget.y < srRect.top + coordTargetSize.y); ++coordTarget.y) { const auto cchWrite = gsl::narrow(coordTargetSize.x); diff --git a/src/host/selection.hpp b/src/host/selection.hpp index 7006291cd0..e4c19c50fb 100644 --- a/src/host/selection.hpp +++ b/src/host/selection.hpp @@ -161,13 +161,13 @@ private: bool fLineSelection{ true }; // whether to use line selection or block selection bool fUseAlternateSelection{ false }; // whether the user has triggered the alternate selection method - bool allowMouseDragSelection{ true }; // true if the dragging the mouse should change the selection + bool allowMouseDragSelection{ true }; // true if dragging the mouse should change the selection // Flags for this DWORD are defined in wincon.h. Search for def:CONSOLE_SELECTION_IN_PROGRESS, etc. DWORD dwSelectionFlags{ 0 }; // -- Current Selection Data -- - // Anchor is the point the selection was started from (and will be one of the corners of the rectangle). + // Anchor is the point from which the selection was started (and will be one of the corners of the rectangle). til::point coordSelectionAnchor{}; // Rectangle is the area inscribing the selection. It is extended to screen edges in a particular way for line selection. til::inclusive_rect srSelectionRect{}; diff --git a/src/host/selectionState.cpp b/src/host/selectionState.cpp index b769c3dc25..3acaeaf0fb 100644 --- a/src/host/selectionState.cpp +++ b/src/host/selectionState.cpp @@ -110,7 +110,7 @@ bool Selection::IsKeyboardMarkSelection() const // Routine Description: // - Determines whether a mouse event was responsible for initiating this selection. // - This primarily refers to mouse drag in QuickEdit mode. -// - However, it refers to any non-mark-mode selection, whether the mouse actually started it or not. +// - However, it refers to any non-mark-mode selection, whether or not the mouse actually started it. // Arguments: // - // Return Value: diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index c42a8663d2..2ebf9d083f 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -395,7 +395,7 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, // all necessary callback information for all subsequent API calls. // Return Value: // - COM errors, registry errors, pipe errors, handle manipulation errors, -// errors from the creating the thread for the +// errors from creating the thread for the // standard IO thread loop for the server to process messages // from the driver... or an S_OK success. [[nodiscard]] HRESULT ConsoleEstablishHandoff([[maybe_unused]] _In_ HANDLE Server, diff --git a/src/host/ut_host/ConsoleArgumentsTests.cpp b/src/host/ut_host/ConsoleArgumentsTests.cpp index b03b9099db..6abefefe7b 100644 --- a/src/host/ut_host/ConsoleArgumentsTests.cpp +++ b/src/host/ut_host/ConsoleArgumentsTests.cpp @@ -280,7 +280,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true); // successful parse? commandline = L"conhost.exe foo -- bar"; - ArgTestsRunner(L"#3 Check that a implicit commandline with other expected args is treated as a whole client commandline (1)", + ArgTestsRunner(L"#3 Check that an implicit commandline with other expected args is treated as a whole client commandline (1)", commandline, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, @@ -301,7 +301,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true); // successful parse? commandline = L"conhost.exe foo -- bar"; - ArgTestsRunner(L"#4 Check that a implicit commandline with other expected args is treated as a whole client commandline (2)", + ArgTestsRunner(L"#4 Check that an implicit commandline with other expected args is treated as a whole client commandline (2)", commandline, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, @@ -322,7 +322,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true); // successful parse? commandline = L"conhost.exe console --vtmode foo foo -- bar"; - ArgTestsRunner(L"#5 Check that a implicit commandline with other expected args is treated as a whole client commandline (3)", + ArgTestsRunner(L"#5 Check that an implicit commandline with other expected args is treated as a whole client commandline (3)", commandline, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, @@ -343,7 +343,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true); // successful parse? commandline = L"conhost.exe console --vtmode foo --outpipe foo -- bar"; - ArgTestsRunner(L"#6 Check that a implicit commandline with other expected args is treated as a whole client commandline (4)", + ArgTestsRunner(L"#6 Check that an implicit commandline with other expected args is treated as a whole client commandline (4)", commandline, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, @@ -1149,7 +1149,7 @@ void ConsoleArgumentsTests::FeatureArgTests() false); // successful parse? commandline = L"conhost.exe --feature pty --feature --signal foo"; - ArgTestsRunner(L"#6 a invalid feature value that is otherwise a valid arg", + ArgTestsRunner(L"#6 an invalid feature value that is otherwise a valid arg", commandline, hInSample, hOutSample, diff --git a/src/host/ut_host/TextBufferTests.cpp b/src/host/ut_host/TextBufferTests.cpp index af9954fef1..0c48af7c25 100644 --- a/src/host/ut_host/TextBufferTests.cpp +++ b/src/host/ut_host/TextBufferTests.cpp @@ -1305,7 +1305,7 @@ void TextBufferTests::TestBackspaceRightSideVt() VERIFY_ARE_EQUAL(0, postCursorPosition.x); VERIFY_ARE_EQUAL(preCursorPosition.y, postCursorPosition.y - 1); - // make sure "yx" was written to the end of the line the cursor started on + // make sure "yx" was written to the end of the line where the cursor started const auto& row = tbi.GetRowByOffset(preCursorPosition.y); const auto rowText = row.GetText(); auto it = rowText.crbegin(); diff --git a/src/inc/TestUtils.h b/src/inc/TestUtils.h index 36743f62c4..42ee49baa2 100644 --- a/src/inc/TestUtils.h +++ b/src/inc/TestUtils.h @@ -32,7 +32,7 @@ public: // caller should ensure that `iter` starts where they would like to validate. // Arguments: // - expectedChar: The character (or characters) we're expecting - // - iter: a iterator pointing to the cell we'd like to start validating at. + // - iter: an iterator pointing to the cell we'd like to start validating at. // - start: the first index in the range we'd like to validate // - end: the last index in the range we'd like to validate // Return Value: @@ -62,7 +62,7 @@ public: // expectedString. // Arguments: // - expectedString: The characters we're expecting - // - iter: a iterator pointing to the cell we'd like to start validating at. + // - iter: an iterator pointing to the cell we'd like to start validating at. // Return Value: // - static void VerifyExpectedString(std::wstring_view expectedString, diff --git a/src/inc/til/mutex.h b/src/inc/til/mutex.h index b08dcd4b2b..e4299d31cf 100644 --- a/src/inc/til/mutex.h +++ b/src/inc/til/mutex.h @@ -71,7 +71,7 @@ namespace til { public: // An exclusive, read/write reference to a til::shared_mutex's underlying data. - // If you drop the guard the mutex is unlocked. + // If you drop the guard, the mutex is unlocked. using guard = details::shared_mutex_guard>; // A shared, read-only reference to a til::shared_mutex's underlying data. diff --git a/src/inc/til/spsc.h b/src/inc/til/spsc.h index 9732cd5796..6f4669b211 100644 --- a/src/inc/til/spsc.h +++ b/src/inc/til/spsc.h @@ -169,7 +169,7 @@ namespace til::spsc // https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem // // arc follows the classic spsc design and manages a ring buffer with two positions: _producer and _consumer. - // They contain the position the producer / consumer will next write to / read from respectively. + // They contain the position that the producer / consumer will next write to / read from respectively. // As usual with ring buffers, these positions are modulo to the _capacity of the underlying buffer. // The producer's writable range is [_producer, _consumer) and the consumer's readable is [_consumer, _producer). // @@ -183,7 +183,7 @@ namespace til::spsc // Wait, what? [7, 0)? How does that work? As all positions are modulo _capacity, 0 mod 10 is the same as 10 mod 10. // If we only want to read forward in the buffer [7, 0) is thus the same as [7, 10). // - // If we read 3 items from the queue the contents will be: + // If we read 3 items from the queue, the contents will be: // [ _ | _ | _ | 3 | 4 | 5 | 6 | _ | _ | _ | _ ] // ^ ^ // _consumer = 3 _producer = 7 diff --git a/src/inc/til/u8u16convert.h b/src/inc/til/u8u16convert.h index b026220414..30ee848993 100644 --- a/src/inc/til/u8u16convert.h +++ b/src/inc/til/u8u16convert.h @@ -9,10 +9,10 @@ Abstract: - Defines classes which hold the status of the current partials handling. - Defines functions for converting between UTF-8 and UTF-16 strings. -Tests have been made in order to investigate whether or not own algorithms +Tests have been made in order to investigate whether or not our algorithms could overcome disadvantages of syscalls. Test results can be read up in PR #4093 and the test algorithms are available in src\tools\U8U16Test. -Based on the results the decision was made to keep using the platform +Based on the results, the decision was made to keep using the platform functions MultiByteToWideChar and WideCharToMultiByte. Author(s): diff --git a/src/interactivity/base/HostSignalInputThread.cpp b/src/interactivity/base/HostSignalInputThread.cpp index c32e796c53..1eb5803129 100644 --- a/src/interactivity/base/HostSignalInputThread.cpp +++ b/src/interactivity/base/HostSignalInputThread.cpp @@ -26,7 +26,7 @@ HostSignalInputThread::HostSignalInputThread(wil::unique_hfile&& hPipe) : HostSignalInputThread::~HostSignalInputThread() { - // Manually terminate our thread during unittesting. Otherwise, the test + // Manually terminate our thread during unit testing. Otherwise, the test // will finish, but TAEF will not manually kill the test. #ifdef UNIT_TESTING TerminateThread(_hThread.get(), 0); diff --git a/src/interactivity/win32/window.cpp b/src/interactivity/win32/window.cpp index aa21904f6c..f7a72fb2ed 100644 --- a/src/interactivity/win32/window.cpp +++ b/src/interactivity/win32/window.cpp @@ -238,7 +238,7 @@ void Window::_UpdateSystemMetrics() const //if launched from a shortcut, ensure window is visible on screen if (pSettings->IsStartupTitleIsLinkNameSet()) { - // if window would be fully OFFscreen, change position so it is ON screen. + // if window would be fully OFF-screen, change position so it is ON-screen. // This doesn't change the actual coordinates // stored in the link, just the starting position // of the window. diff --git a/src/propsheet/fontdlg.cpp b/src/propsheet/fontdlg.cpp index c45e3e519f..5e92ef0af6 100644 --- a/src/propsheet/fontdlg.cpp +++ b/src/propsheet/fontdlg.cpp @@ -528,7 +528,7 @@ FontDlgProc( // Iterate through all of our fonts to find the font entries that match the desired family, charset, name (TT), and // boldness (TT). Each entry in FontInfo represents a specific combination of font states. We expect to encounter // numerous entries for each size/boldness/charset of TT fonts. If fAddBoldFonts is true, we'll add a font even if it's -// bold, regardless of whether the user has chosen bold fonts or not. +// bold, regardless of whether or not the user has chosen bold fonts. void AddFontSizesToList(PCWSTR pwszTTFace, PCWSTR pwszAltTTFace, const LONG_PTR dwExStyle, @@ -579,8 +579,8 @@ void AddFontSizesToList(PCWSTR pwszTTFace, continue; } - // if we're being asked to add bold fonts, add unconditionally according to weight. Otherwise, only this - // entry to the list of it's in line with user choice. Raster fonts aren't available in bold. + // if we're being asked to add bold fonts, add unconditionally according to weight. Otherwise, only add this + // entry to the list if it's in line with user choice. Raster fonts aren't available in bold. if (!fAddBoldFonts && gbBold != IS_BOLD(FontInfo[i].Weight)) { DBGFONTS((" Font %x has weight %d, but we wanted %sbold\n", diff --git a/src/renderer/base/renderer.cpp b/src/renderer/base/renderer.cpp index 4a98b757a3..3bf90c2904 100644 --- a/src/renderer/base/renderer.cpp +++ b/src/renderer/base/renderer.cpp @@ -504,7 +504,7 @@ void Renderer::SynchronizedOutputChanged() noexcept // essentially drop our renderer to 10 FPS, because `_isSynchronizingOutput` is always true. // // Obviously calling LockConsole/UnlockConsole here is an awful, ugly hack, - // since there's no guarantee that this is the same lock as the one the VT parser uses. + // since there's no guarantee that this is the same lock as the one that the VT parser uses. // But the alternative is Denial-Of-Service of the render thread. // // Note that this causes raw throughput of DECSET 2026 to be comparatively low, but that's fine. diff --git a/src/renderer/gdi/state.cpp b/src/renderer/gdi/state.cpp index 62a20591c5..b31478fc30 100644 --- a/src/renderer/gdi/state.cpp +++ b/src/renderer/gdi/state.cpp @@ -406,7 +406,7 @@ GdiEngine::~GdiEngine() // 1. The lines are half the width of an underline // 2. Ideally the bottom line is aligned with the bottom of the underline // 3. The top underline is vertically in the middle between baseline and ideal bottom underline - // 4. If the top line gets too close to the baseline the underlines are shifted downwards + // 4. If the top line gets too close to the baseline, the underlines are shifted downwards // 5. The minimum gap between the two lines appears to be similar to Tex (1.2pt) // (Additional notes below.) diff --git a/src/server/ProcessList.cpp b/src/server/ProcessList.cpp index c83879dacf..bab3beed24 100644 --- a/src/server/ProcessList.cpp +++ b/src/server/ProcessList.cpp @@ -11,7 +11,7 @@ using namespace Microsoft::Console::Interactivity; // Routine Description: -// - Allocates and stores in a list the process information given. +// - Allocates and stores the given process information in a list. // - Will not create a new entry in the list given information matches a known process. Will instead return existing entry. // Arguments: // - dwProcessId - Process ID of connecting client @@ -19,7 +19,7 @@ using namespace Microsoft::Console::Interactivity; // - ulProcessGroupId - Process Group ID from connecting client (sometimes referred to as parent) // - pParentProcessData - Used to specify parent while locating appropriate scope of sending control messages // - ppProcessData - Filled on exit with a pointer to the process handle information. Optional. -// - If not used, return code will specify whether this process is known to the list or not. +// - If not used, return code will specify whether or not this process is known to the list. // Return Value: // - S_OK if the process was recorded in the list successfully or already existed. // - S_FALSE if we're running into an LPC port conflict by nature of the process chain. diff --git a/src/server/WaitBlock.cpp b/src/server/WaitBlock.cpp index d1485f7068..aed40e10ed 100644 --- a/src/server/WaitBlock.cpp +++ b/src/server/WaitBlock.cpp @@ -65,7 +65,7 @@ ConsoleWaitBlock::ConsoleWaitBlock(_In_ ConsoleWaitQueue* const pProcessQueue, } // Routine Description: -// - Destroys a ConsolewaitBlock +// - Destroys a ConsoleWaitBlock // - On deletion, ConsoleWaitBlocks will erase themselves from the process and object queues in // constant time with the iterator acquired on construction. ConsoleWaitBlock::~ConsoleWaitBlock() diff --git a/src/terminal/adapter/DispatchTypes.hpp b/src/terminal/adapter/DispatchTypes.hpp index b99dd997dd..66ec6eb08f 100644 --- a/src/terminal/adapter/DispatchTypes.hpp +++ b/src/terminal/adapter/DispatchTypes.hpp @@ -57,7 +57,7 @@ namespace Microsoft::Console::VirtualTerminal } // In order for the _string to hold the correct representation of the - // ID stored in _value, we must be on a little endian architecture. + // ID stored in _value, we must be on a little-endian architecture. static_assert(std::endian::native == std::endian::little); uint64_t _value = 0; diff --git a/src/terminal/adapter/SixelParser.cpp b/src/terminal/adapter/SixelParser.cpp index e23c23d1e6..959c6f2f30 100644 --- a/src/terminal/adapter/SixelParser.cpp +++ b/src/terminal/adapter/SixelParser.cpp @@ -387,7 +387,7 @@ void SixelParser::_updateRasterAttributes(const VTParameters& rasterAttributes) // And while not documented, we know from testing on a VT330 that the raster // attributes command should also trigger a carriage return. This applies - // regardless of whether the requested aspect ratio is valid or not. + // regardless of whether or not the requested aspect ratio is valid. _executeCarriageReturn(); } diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index e454822d8b..e1fdb6a69c 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -3649,7 +3649,7 @@ void AdaptDispatch::DoConEmuAction(const std::wstring_view string) } // Method Description: -// - Performs a iTerm2 action +// - Performs an iTerm2 action // - Ascribes to the ITermDispatch interface // - Currently, the actions we support are: // * `OSC1337;SetMark`: mark a line as a prompt line @@ -3878,7 +3878,7 @@ void AdaptDispatch::DoWTAction(const std::wstring_view string) // - SIXEL - Defines an image transmitted in sixel format via the returned // StringHandler function. // Arguments: -// - macroParameter - Selects one a of set of predefined aspect ratios. +// - macroParameter - Selects one of a set of predefined aspect ratios. // - backgroundSelect - Whether the background should be transparent or opaque. // - backgroundColor - The color number used for the background (VT240). // Return Value: diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp index 7da1782fde..596c9ed1a2 100644 --- a/src/terminal/adapter/ut_adapter/adapterTest.cpp +++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp @@ -1648,7 +1648,7 @@ public: Log::Comment(L"Test 2: Verify space decrease"); _testGetSet->PrepData(); - // Define four 8-byte macros, i.e. 32 byes (2 macro blocks). + // Define four 8-byte macros, i.e. 32 bytes (2 macro blocks). _stateMachine->ProcessString(L"\033P1;0;0!z12345678\033\\"); _stateMachine->ProcessString(L"\033P2;0;0!z12345678\033\\"); _stateMachine->ProcessString(L"\033P3;0;0!z12345678\033\\"); @@ -3151,7 +3151,7 @@ public: _testGetSet->_expectedAttribute = _testGetSet->_textBuffer->GetCurrentAttributes(); - Log::Comment(L"Test 1: Change Indexed Foreground with missing index parameter"); + Log::Comment(L"Test 1: Change Indexed Foreground without index parameter"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; rgOptions[1] = DispatchTypes::GraphicsOptions::BlinkOrXterm256Index; _testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::DARK_BLACK); @@ -3226,7 +3226,7 @@ public: _testGetSet->_expectedAttribute = _testGetSet->_textBuffer->GetCurrentAttributes(); - Log::Comment(L"Test 1: Change Indexed Foreground with missing index sub parameter"); + Log::Comment(L"Test 1: Change Indexed Foreground without index sub parameter"); rgOptions[0] = DispatchTypes::GraphicsOptions::ForegroundExtended; _testGetSet->MakeSubParamsAndRanges({ { 5 } }, rgSubParamOpts, subParamRanges); _testGetSet->_expectedAttribute.SetIndexedForeground256(TextColor::DARK_BLACK); diff --git a/src/terminal/parser/ft_fuzzer/fuzzing_logic.h b/src/terminal/parser/ft_fuzzer/fuzzing_logic.h index 726ed89083..0ac574f611 100644 --- a/src/terminal/parser/ft_fuzzer/fuzzing_logic.h +++ b/src/terminal/parser/ft_fuzzer/fuzzing_logic.h @@ -346,9 +346,9 @@ namespace fuzz }; CFuzzString<__FUZZING_ALLOCATOR, CHAR> eval(FUZZ_MAP(fuzzMap), pszReallocTemp); - // Performance optimization: 95% of the time the buffer returned from eval will not be reallocated + // Performance optimization: 95% of the time, the buffer returned from eval will not be reallocated // and thus will still be pointing at pszReallocTemp. In this case, it is not necessary to duplicate - // the string a second time, just transfer ownership to the calling function. + // the string again, just transfer ownership to the calling function. if ((LPSTR)eval == pszReallocTemp) { pszRealloc = pszReallocTemp; diff --git a/src/terminal/parser/stateMachine.cpp b/src/terminal/parser/stateMachine.cpp index 23139fbdaf..f01b45fcb1 100644 --- a/src/terminal/parser/stateMachine.cpp +++ b/src/terminal/parser/stateMachine.cpp @@ -288,7 +288,7 @@ static constexpr bool _isOscDelimiter(const wchar_t wch) noexcept } // Routine Description: -// - Determines if a character should be ignored in a operating system control sequence +// - Determines if a character should be ignored in an operating system control sequence // Arguments: // - wch - Character to check. // Return Value: @@ -1968,7 +1968,7 @@ bool StateMachine::FlushToTerminal() // Routine Description: // - Helper for entry to the state machine. Will take an array of characters // and print as many as it can without encountering a character indicating -// a escape sequence, then feed characters into the state machine one at a +// an escape sequence, then feed characters into the state machine one at a // time until we return to the ground state. // Arguments: // - string - Characters to operate upon diff --git a/src/terminal/parser/ut_parser/InputEngineTest.cpp b/src/terminal/parser/ut_parser/InputEngineTest.cpp index 6c7baa9bdc..19aa93919e 100644 --- a/src/terminal/parser/ut_parser/InputEngineTest.cpp +++ b/src/terminal/parser/ut_parser/InputEngineTest.cpp @@ -896,7 +896,7 @@ void InputEngineTest::AltCtrlDTest() void InputEngineTest::AltIntermediateTest() { - // Tests GH#1209. When we process a alt+key combination where the key just + // Tests GH#1209. When we process an alt+key combination where the key just // so happens to be an intermediate character, we should make sure that an // immediately subsequent ctrl character is handled correctly. @@ -966,7 +966,7 @@ void InputEngineTest::AltBackspaceEnterTest() inputRec.Event.KeyEvent.wVirtualScanCode = static_cast(OneCoreSafeMapVirtualKeyW(VK_BACK, MAPVK_VK_TO_VSC)); inputRec.Event.KeyEvent.uChar.UnicodeChar = L'\x08'; - // First, expect a alt+backspace. + // First, expect an alt+backspace. testState.vExpectedInput.push_back(inputRec); std::wstring seq = L"\x1b\x7f"; @@ -981,7 +981,7 @@ void InputEngineTest::AltBackspaceEnterTest() inputRec.Event.KeyEvent.wVirtualScanCode = static_cast(OneCoreSafeMapVirtualKeyW(VK_RETURN, MAPVK_VK_TO_VSC)); inputRec.Event.KeyEvent.uChar.UnicodeChar = L'\x0d'; //maybe \xa - // Then, expect a enter + // Then, expect an enter testState.vExpectedInput.push_back(inputRec); seq = L"\x0d"; diff --git a/src/terminal/parser/ut_parser/OutputEngineTest.cpp b/src/terminal/parser/ut_parser/OutputEngineTest.cpp index f12dac966c..f4db87490f 100644 --- a/src/terminal/parser/ut_parser/OutputEngineTest.cpp +++ b/src/terminal/parser/ut_parser/OutputEngineTest.cpp @@ -3425,7 +3425,7 @@ class StateMachineExternalTest final pDispatch->ClearState(); pDispatch->_copyContent = L"UNCHANGED"; - // Passing a query character with missing `Pc` param is illegal, won't change the content. + // Passing a query character without `Pc` param is illegal, won't change the content. mach.ProcessString(L"\x1b]52;?\x07"); VERIFY_ARE_EQUAL(L"UNCHANGED", pDispatch->_copyContent); diff --git a/src/tools/ansi-color/ansi-color.cmd b/src/tools/ansi-color/ansi-color.cmd index a0169cf3b6..3b5462b71b 100644 --- a/src/tools/ansi-color/ansi-color.cmd +++ b/src/tools/ansi-color/ansi-color.cmd @@ -33,7 +33,7 @@ GOTO :END_DATA_SEGMENT :: Complete matrix of SGR parameters available :: This definition also demonstrates the various configuration changes -:: which are used to control the way the table is generated +:: which are used to control the way that the table is generated __DATA__ :: Select Graphic Rendition (SGR) parameters :: #NUL# is treated as a special case to provide cells in that column @@ -1496,10 +1496,11 @@ IF NOT EXIST !DATA_FILE! ( :: :USAGE SET "SCRIPT_NAME=%~nx0" +SET BLANK_TO_EOL= z :: The following ECHO intentionally has 80 spaces to clear the :: line any remaining on screen text on call. -ECHO. +ECHO.%BLANK_TO_EOL:z=% IF [%1] NEQ [] ( ECHO !%1! ECHO. diff --git a/src/tools/ansi-color/sgr.def b/src/tools/ansi-color/sgr.def index 3daed55962..a81582f329 100644 --- a/src/tools/ansi-color/sgr.def +++ b/src/tools/ansi-color/sgr.def @@ -1,6 +1,6 @@ :: Complete matrix of SGR parameters available :: This definition also demonstrates the various configuration changes -:: which are used to control the way the table is generated +:: which are used to control the way that the table is generated :: Requires 97 columns to display correctly __DATA__ :: Select Graphic Rendition (SGR) parameters @@ -345,4 +345,4 @@ REM 29m 21;96m 21;97m __ROWS:END__ -__DATA:END__ \ No newline at end of file +__DATA:END__ diff --git a/src/tools/vtapp/Program.cs b/src/tools/vtapp/Program.cs index 3751b6e421..12ec6ff93a 100644 --- a/src/tools/vtapp/Program.cs +++ b/src/tools/vtapp/Program.cs @@ -37,7 +37,7 @@ namespace VTApp keyInfo = Console.ReadKey(true); // 40-7E are the "dispatch" characters meaning the sequence is done. - // 0x5B '[' is expected after the escape. So ignore that. We don't know a of a sequence terminated with it, so it also continues the loop. + // 0x5B '[' is expected after the escape. So ignore that. We don't know of a sequence terminated with it, so it also continues the loop. // keep collecting characters as the "reply" until then while (keyInfo.KeyChar < 0x40 || keyInfo.KeyChar > 0x7E || keyInfo.KeyChar == '[') { diff --git a/src/types/ut_types/UuidTests.cpp b/src/types/ut_types/UuidTests.cpp index e0abbc6a6f..488293fb21 100644 --- a/src/types/ut_types/UuidTests.cpp +++ b/src/types/ut_types/UuidTests.cpp @@ -34,7 +34,7 @@ class UuidTests { const GUID uuidExpected{ 0xe04fb1f7, 0x739d, 0x5d63, { 0xbb, 0x18, 0xe0, 0xea, 0x00, 0xb1, 0x9e, 0xe8 } }; - // This'll come out in little endian; the reference GUID was generated as such. + // This'll come out in little-endian; the reference GUID was generated as such. std::wstring name{ L"testing" }; auto uuidActual = CreateV5Uuid(TEST_NAMESPACE_GUID, std::as_bytes(std::span{ name })); diff --git a/src/types/utils.cpp b/src/types/utils.cpp index 18af447d8b..1ff0ba7b10 100644 --- a/src/types/utils.cpp +++ b/src/types/utils.cpp @@ -172,7 +172,7 @@ std::optional Utils::ColorFromXTermColor(const std::wstring_view str // spec2: a color in the following format: // "#" // -// In both specs, is a value contains up to 4 hex digits, upper or lower case. +// In both specs, is a value contains up to 4 hex digits, uppercase or lowercase. // Arguments: // - string - The string containing the color spec string to parse. // Return Value: @@ -544,7 +544,7 @@ bool Utils::HexToUint(const wchar_t wch, // - wstr - String to convert. // - value - receives the int value of the string // Return Value: -// - true iff the string is a unsigned integer string. +// - true iff the string is an unsigned integer string. bool Utils::StringToUint(const std::wstring_view wstr, unsigned int& value) { diff --git a/src/types/viewport.cpp b/src/types/viewport.cpp index ce4b38565e..6be33107fb 100644 --- a/src/types/viewport.cpp +++ b/src/types/viewport.cpp @@ -440,7 +440,7 @@ void Viewport::ConvertToOrigin(_Inout_ til::inclusive_rect* const psr) const noe // - Translates the input coordinate out of our coordinate space, whose origin is // at (this.left, this.right) // Arguments: -// - pcoord: a pointer to a coordinate the translate into our coordinate space. +// - pcoord: a pointer to a coordinate to translate into our coordinate space. // Return Value: // - void Viewport::ConvertToOrigin(_Inout_ til::point* const pcoord) const noexcept @@ -470,7 +470,7 @@ void Viewport::ConvertFromOrigin(_Inout_ til::inclusive_rect* const psr) const n // - Translates the input coordinate to our coordinate space, whose origin is // at (this.left, this.right) // Arguments: -// - pcoord: a pointer to a coordinate the translate into our coordinate space. +// - pcoord: a pointer to a coordinate to translate into our coordinate space. // Return Value: // - void Viewport::ConvertFromOrigin(_Inout_ til::point* const pcoord) const noexcept diff --git a/src/winconpty/winconpty.h b/src/winconpty/winconpty.h index e917a18ad7..47968df294 100644 --- a/src/winconpty/winconpty.h +++ b/src/winconpty/winconpty.h @@ -10,7 +10,7 @@ extern "C" { // This structure is part of an ABI shared with the rest of the operating system. typedef struct _PseudoConsole { - // hSignal is a anonymous pipe used for out of band communication with conhost. + // hSignal is an anonymous pipe used for out of band communication with conhost. // It's used to send the various PTY_SIGNAL_* messages. HANDLE hSignal; // The "server handle" in conhost represents the console IPC "pipe" over which all console From c17029a7e902983f8d28a5e35e581bc14f59e337 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 26 Apr 2026 21:43:00 -0400 Subject: [PATCH 03/18] Update dictionaries (#20148) Follow up to #20141 --- .../spelling/allow/remove-after-merging.txt | 2 - .github/actions/spelling/config.json | 24 +++++------ .../spelling/expect/remove-after-merging.txt | 40 ------------------- 3 files changed, 9 insertions(+), 57 deletions(-) delete mode 100644 .github/actions/spelling/allow/remove-after-merging.txt delete mode 100644 .github/actions/spelling/expect/remove-after-merging.txt diff --git a/.github/actions/spelling/allow/remove-after-merging.txt b/.github/actions/spelling/allow/remove-after-merging.txt deleted file mode 100644 index ba4657da13..0000000000 --- a/.github/actions/spelling/allow/remove-after-merging.txt +++ /dev/null @@ -1,2 +0,0 @@ -changelists -screenshots diff --git a/.github/actions/spelling/config.json b/.github/actions/spelling/config.json index 654a59c1cd..f6c6f5cd71 100644 --- a/.github/actions/spelling/config.json +++ b/.github/actions/spelling/config.json @@ -6,35 +6,29 @@ }, "extra_dictionaries": [ "cspell:software-terms/softwareTerms.txt", - "cspell:cpp/stdlib-cpp.txt", "cspell:cpp/stdlib-c.txt", + "census:census-5.txt", + "cspell:cpp/stdlib-cpp.txt", "cspell:python/python/python-lib.txt", "cspell:php/php.txt", - "cspell:node/node.txt", "cspell:dart/dart.txt", - "cspell:filetypes/filetypes.txt", - "cspell:java/java.txt", "cspell:css/css.txt", - "cspell:dotnet/dotnet.txt", + "cspell:node/node.txt", + "cspell:filetypes/filetypes.txt", "cspell:npm/npm.txt", + "cspell:java/java.txt", + "cspell:dotnet/dotnet.txt", "cspell:fullstack/fullstack.txt", "cspell:java/java-terms.txt", - "cspell:r/r.txt", - "cspell:golang/go.txt", "cspell:cpp/stdlib-cmath.txt", "cspell:typescript/typescript.txt", - "cspell:html/html.txt", "cspell:cpp/compiler-msvc.txt", - "cspell:django/django.txt", - "cspell:aws/aws.txt", "cspell:python/common/extra.txt", + "cspell:html/html.txt", + "cspell:golang/go.txt", "cspell:cpp/ecosystem.txt", - "cspell:cpp/lang-keywords.txt", - "cspell:csharp/csharp.txt", - "cspell:cpp/compiler-clang-attributes.txt", - "cspell:python/python/python.txt", - "cspell:mnemonics/mnemonics.txt", "cspell:powershell/powershell.txt", + "cspell:mnemonics/mnemonics.txt", "" ], "check_extra_dictionaries": [ diff --git a/.github/actions/spelling/expect/remove-after-merging.txt b/.github/actions/spelling/expect/remove-after-merging.txt deleted file mode 100644 index 49693b53ac..0000000000 --- a/.github/actions/spelling/expect/remove-after-merging.txt +++ /dev/null @@ -1,40 +0,0 @@ -Ccc -changelists -cplusplus -ctl -Debian -dotnet -drv -endptr -evt -Fullwidth -gitlab -hdr -idl -ime -inbox -Ioctl -KVM -lbl -lld -lsb -NONINFRINGEMENT -oss -outdir -pri -prioritization -rcv -screenshots -segfault -sourced -SWP -Tbl -testname -transitioning -unk -unparseable -Virt -VMs -webpage -websites -xsi From eeb9f7a805420291c30b323e1c5187bcf392496e Mon Sep 17 00:00:00 2001 From: Windows Console Service Bot <14666831+consvc@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:41:39 -0500 Subject: [PATCH 04/18] Localization Updates - minor wording changes after spell check - 04/24/2026 03:05:26 (#20140) Co-authored-by: Console Service Bot --- .../TerminalApp/Resources/de-DE/Resources.resw | 6 +++--- .../TerminalApp/Resources/es-ES/Resources.resw | 6 +++--- .../TerminalApp/Resources/fr-FR/Resources.resw | 6 +++--- .../TerminalApp/Resources/it-IT/Resources.resw | 6 +++--- .../TerminalApp/Resources/ja-JP/Resources.resw | 6 +++--- .../TerminalApp/Resources/ko-KR/Resources.resw | 6 +++--- .../TerminalApp/Resources/pt-BR/Resources.resw | 6 +++--- .../Resources/qps-ploc/Resources.resw | 6 +++--- .../Resources/qps-ploca/Resources.resw | 6 +++--- .../Resources/qps-plocm/Resources.resw | 6 +++--- .../TerminalApp/Resources/ru-RU/Resources.resw | 6 +++--- .../TerminalApp/Resources/zh-CN/Resources.resw | 6 +++--- .../TerminalApp/Resources/zh-TW/Resources.resw | 6 +++--- .../Resources/de-DE/Resources.resw | 12 ++++++------ .../Resources/es-ES/Resources.resw | 14 +++++++------- .../Resources/fr-FR/Resources.resw | 14 +++++++------- .../Resources/it-IT/Resources.resw | 10 +++++----- .../Resources/ja-JP/Resources.resw | 14 +++++++------- .../Resources/ko-KR/Resources.resw | 16 ++++++++-------- .../Resources/pt-BR/Resources.resw | 18 +++++++++--------- .../Resources/qps-ploc/Resources.resw | 12 ++++++------ .../Resources/qps-ploca/Resources.resw | 12 ++++++------ .../Resources/qps-plocm/Resources.resw | 12 ++++++------ .../Resources/ru-RU/Resources.resw | 10 +++++----- .../Resources/zh-CN/Resources.resw | 10 +++++----- .../Resources/zh-TW/Resources.resw | 12 ++++++------ 26 files changed, 122 insertions(+), 122 deletions(-) diff --git a/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw b/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw index 81c005f027..47d5325d8b 100644 --- a/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw @@ -854,11 +854,11 @@ Der aktive Bereich wurde auf die Registerkarte „{0}“ verschoben - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. Registerkarte „{0}“ wurde in das Fenster „{1}“ verschoben - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. Registerkarte „{0}“ in neues Fenster verschoben @@ -870,7 +870,7 @@ Der aktive Bereich wurde in das Fenster "{0}" verschoben - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Aktiver Bereich in neues Fenster verschoben diff --git a/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw b/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw index 07f94a6870..415d263e3d 100644 --- a/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw @@ -851,11 +851,11 @@ Panel activo movido a la pestaña "{0}" - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. La pestaña "{0}" se ha movido a la ventana "{1}" - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. La pestaña "{0}" se ha movido a la nueva ventana @@ -867,7 +867,7 @@ Panel activo movido a la ventana "{0}" - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Panel activo movido a nueva ventana diff --git a/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw index 37e1a5ab13..ec79eccd20 100644 --- a/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw @@ -851,11 +851,11 @@ Volet actif déplacé vers l’onglet « {0} » - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. Onglet « {0} » déplacé vers la fenêtre « {1} » - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. Onglet « {0} » déplacé vers une nouvelle fenêtre @@ -867,7 +867,7 @@ Volet actif déplacé vers l’onglet « {0} » - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Volet actif déplacé vers une nouvelle fenêtre diff --git a/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw b/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw index 693ea767e1..bca470f807 100644 --- a/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw @@ -851,11 +851,11 @@ Riquadro attivo spostato nella scheda "{0}" - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. Scheda "{0}" spostata nella finestra "{1}" - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. Scheda "{0}" spostata in una nuova finestra @@ -867,7 +867,7 @@ Riquadro attivo spostato nella finestra "{0}" - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Riquadro attivo spostato in una nuova finestra diff --git a/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw index 2aa1e445f7..57c9ae65d0 100644 --- a/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw @@ -852,11 +852,11 @@ アクティブなペインを [{0}] タブに移動しました - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. [{0}] タブを "{1}" ウィンドウに移動しました - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. [{0}] タブを新しいウィンドウに移動しました @@ -868,7 +868,7 @@ アクティブなペインを "{0}" ウィンドウに移動しました - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. アクティブなペインを新しいウィンドウに移動しました diff --git a/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw index fc9e9fa2aa..6b7223e0ef 100644 --- a/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw @@ -851,11 +851,11 @@ 활성 창이 "{0}" 탭으로 이동됨 - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. "{0}" 탭이 "{1}" 창으로 이동됨 - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. "{0}" 탭이 새 창으로 이동됨 @@ -867,7 +867,7 @@ 활성 창이 "{0}" 창으로 이동됨 - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. 활성 창이 새 창으로 이동됨 diff --git a/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw index 1dbc42d68c..7a122e0a03 100644 --- a/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw @@ -851,11 +851,11 @@ Painel ativo movido para a guia "{0}" - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. Guia "{0}" movida para janela "{1}" - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. Guia "{0}" movida para nova janela @@ -867,7 +867,7 @@ Painel ativo movido para a janela "{0}" - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Painel ativo movido para nova janela diff --git a/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw index 0747a98aef..8c2c8a652a 100644 --- a/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw @@ -851,11 +851,11 @@ ∆çťíνĕ рåⁿэ мôνеð ťб "{0}" ţав !!! !!! !!! - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. "{0}" ťāъ мōνęđ τŏ "{1}" шΐπδŏẅ !!! !!! !!! - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. "{0}" тąь mǿνєđ ŧσ ήèώ ẅĩŋďøẃ !!! !!! !!! @@ -867,7 +867,7 @@ Λςťìνє рáиė mόνéð ťб "{0}" ŵîńđθω !!! !!! !!! - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Αĉťįνέ ρªņз mσνёđ τǿ ήёẃ ẃîпďǿω !!! !!! !!! diff --git a/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw index 0747a98aef..8c2c8a652a 100644 --- a/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw @@ -851,11 +851,11 @@ ∆çťíνĕ рåⁿэ мôνеð ťб "{0}" ţав !!! !!! !!! - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. "{0}" ťāъ мōνęđ τŏ "{1}" шΐπδŏẅ !!! !!! !!! - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. "{0}" тąь mǿνєđ ŧσ ήèώ ẅĩŋďøẃ !!! !!! !!! @@ -867,7 +867,7 @@ Λςťìνє рáиė mόνéð ťб "{0}" ŵîńđθω !!! !!! !!! - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Αĉťįνέ ρªņз mσνёđ τǿ ήёẃ ẃîпďǿω !!! !!! !!! diff --git a/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw index 0747a98aef..8c2c8a652a 100644 --- a/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw @@ -851,11 +851,11 @@ ∆çťíνĕ рåⁿэ мôνеð ťб "{0}" ţав !!! !!! !!! - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. "{0}" ťāъ мōνęđ τŏ "{1}" шΐπδŏẅ !!! !!! !!! - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. "{0}" тąь mǿνєđ ŧσ ήèώ ẅĩŋďøẃ !!! !!! !!! @@ -867,7 +867,7 @@ Λςťìνє рáиė mόνéð ťб "{0}" ŵîńđθω !!! !!! !!! - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Αĉťįνέ ρªņз mσνёđ τǿ ήёẃ ẃîпďǿω !!! !!! !!! diff --git a/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw index a4fe1bfeda..1cbc6cfeb6 100644 --- a/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw @@ -851,11 +851,11 @@ Активная область перемещена на вкладку "{0}" - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. Вкладка "{0}" перемещена в окно "{1}" - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. Вкладка "{0}" перемещена в новое окно @@ -867,7 +867,7 @@ Активная область перемещена в окно "{0}" - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. Активная область перемещена в новое окно diff --git a/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw index 2770f6bf8c..bd1fd3eb79 100644 --- a/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw @@ -851,11 +851,11 @@ 活动窗格已移动到“{0}”选项卡 - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. “{0}”选项卡已移动到“{1}”窗口 - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. “{0}”选项卡已移动到新窗口 @@ -867,7 +867,7 @@ 活动窗格已移动到“{0}”选项卡 - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. 活动窗格已移动到新窗口 diff --git a/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw index 40dfadb600..a296905eaa 100644 --- a/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw @@ -851,11 +851,11 @@ 活動窗格已移動至「{0}」索引標籤 - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab to which the pane was moved. 「{0}」索引標籤已移至「{1}」視窗 - {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window to which the tab was moved. 「{0}」索引標籤已移至新視窗 @@ -867,7 +867,7 @@ 活動窗格已移動至「{0}」視窗 - {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to. + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window to which the pane was moved. 活動窗格已移至新視窗 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw index e432d9a6f4..c513df1870 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw @@ -507,7 +507,7 @@ Titelleiste ausblenden (Neustart erforderlich) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Wenn diese Option deaktiviert ist, wird die Titelleiste über den Registerkarten angezeigt. @@ -1195,15 +1195,15 @@ Startverzeichnis - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Startverzeichnis - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Startverzeichnis - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Das Verzeichnis, in dem das Profil gestartet wird, wenn es geladen wird. @@ -1742,7 +1742,7 @@ A supplementary setting to the "font face" setting. Toggling this control updates the font face control to show all of the fonts installed. - Wenn diese Option aktiviert ist, werden alle installierten Schriftarten in der Liste oben angezeigt. Andernfalls wird nur die Liste der Festbreitenschriftarten angezeigt. + Wenn diese Option aktiviert ist, werden alle installierten Schriftarten in der Liste oben angezeigt. Andernfalls wird nur die Liste der Schriftarten mit fester Breite angezeigt. A description for what the supplementary "show all fonts" setting does. Presented near "Profile_FontFaceShowAllFonts". @@ -2147,7 +2147,7 @@ Verknüpfung - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Textformatierung diff --git a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw index 8f4c12ce5e..adee08e315 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw @@ -507,7 +507,7 @@ Ocultar la barra de título (requiere reiniciar) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Cuando está deshabilitada, la barra de título aparecerá encima de las pestañas. @@ -983,11 +983,11 @@ {Locked="‗"} An option to choose from for the "cursor shape" setting. When selected, the cursor will look like a stacked set of two underscores. The character in the parentheses is used to show what it looks like. - Tipo de fuente + Estilo tipográfico Header for a control to select the font for text in the app. - Tipo de fuente + Estilo tipográfico Name for a control to select the font for text in the app. @@ -1195,15 +1195,15 @@ Directorio de inicio - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Directorio de inicio - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Directorio de inicio - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. El directorio en el que se inicia el perfil cuando se carga. @@ -2147,7 +2147,7 @@ Acceso directo - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Formato de texto diff --git a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw index 9d84137128..de770bfa41 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw @@ -507,7 +507,7 @@ Masquer la barre de titre (redémarrage nécessaire) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Une fois désactivée, la barre de titre s’affiche au-dessus des onglets. @@ -983,11 +983,11 @@ {Locked="‗"} An option to choose from for the "cursor shape" setting. When selected, the cursor will look like a stacked set of two underscores. The character in the parentheses is used to show what it looks like. - Type de police + Style de police Header for a control to select the font for text in the app. - Type de police + Style de police Name for a control to select the font for text in the app. @@ -1195,15 +1195,15 @@ Répertoire de démarrage - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Répertoire de démarrage - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Répertoire de démarrage - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Répertoire dans lequel le shell démarre lorsqu’il est chargé. @@ -2147,7 +2147,7 @@ Raccourci - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Mise en forme du texte diff --git a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw index 111fcf1b8d..9a064008b5 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw @@ -507,7 +507,7 @@ Nascondi la barra del titolo (sarà necessario riavviare) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Se disabilitata, la barra del titolo verrà visualizzata sopra le schede. @@ -1195,15 +1195,15 @@ Directory iniziale - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Directory iniziale - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Directory iniziale - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. La directory che inizia il profilo durante il caricamento. @@ -2147,7 +2147,7 @@ Collegamento - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Formattazione testo diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw index ded5b41cc8..bbd0167a5d 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw @@ -507,7 +507,7 @@ タイトル バーを非表示にする (再起動が必要) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. 無効にすると、タイトル バーがタブの上に表示されます。 @@ -983,11 +983,11 @@ {Locked="‗"} An option to choose from for the "cursor shape" setting. When selected, the cursor will look like a stacked set of two underscores. The character in the parentheses is used to show what it looks like. - フォント フェイス + フォント スタイル Header for a control to select the font for text in the app. - フォント フェイス + フォント スタイル Name for a control to select the font for text in the app. @@ -1195,15 +1195,15 @@ 開始ディレクトリ - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 開始ディレクトリ - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 開始ディレクトリ - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. プロファイルが読み込まれたときに開始されるディレクトリです。 @@ -2147,7 +2147,7 @@ ショートカット - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. テキストの​​書式設定 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw index b2bad68bd6..aecd60527d 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw @@ -293,7 +293,7 @@ Header for a control to set the query URL when using the "search web" action. - 자리 표시자 "%s" 검색 쿼리로 대체됩니다. + 자리 표시자 "%s"가 검색 쿼리로 바뀝니다. {Locked="%s"} Additional text presented near "Globals_SearchWebDefaultQueryUrl.Header". @@ -507,7 +507,7 @@ 제목 표시줄 숨기기(다시 시작해야 함) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. 사용하지 않도록 설정하면 제목 표시줄이 탭 위에 표시됩니다. @@ -983,11 +983,11 @@ {Locked="‗"} An option to choose from for the "cursor shape" setting. When selected, the cursor will look like a stacked set of two underscores. The character in the parentheses is used to show what it looks like. - 글꼴 + 글꼴 스타일 Header for a control to select the font for text in the app. - 글꼴 + 글꼴 스타일 Name for a control to select the font for text in the app. @@ -1195,15 +1195,15 @@ 시작 디렉터리 - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 시작 디렉터리 - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 시작 디렉터리 - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 프로필이 로드될 때 시작됩니다. @@ -2147,7 +2147,7 @@ 바로 가기 - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. 텍스트 서식 지정 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw index bfa7859637..e22d0a14eb 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw @@ -507,7 +507,7 @@ Oculta a barra do título (requer reinicialização) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Quando desabilitada, a barra de título aparecerá acima das guias. @@ -983,15 +983,15 @@ {Locked="‗"} An option to choose from for the "cursor shape" setting. When selected, the cursor will look like a stacked set of two underscores. The character in the parentheses is used to show what it looks like. - Tipo de fonte + Variação Header for a control to select the font for text in the app. - Tipo de fonte + Variação Name for a control to select the font for text in the app. - Pode utilizar vários tipos de letra separando-os com uma vírgula ASCII. + Você pode usar várias fontes, separando-as com uma vírgula ASCII. Tamanho da fonte @@ -1195,15 +1195,15 @@ Diretório inicial - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Diretório inicial - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Diretório inicial - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. A pasta em que o perfil começa quando é carregado. @@ -1742,7 +1742,7 @@ A supplementary setting to the "font face" setting. Toggling this control updates the font face control to show all of the fonts installed. - Se habilitado, mostrar todas as fontes instaladas na lista acima. Caso contrário, mostrar apenas a lista de fontes com espaçamento mono. + Se ativado, mostra todas as fontes instaladas na lista acima. Caso contrário, mostra apenas as fontes monoespaçadas. A description for what the supplementary "show all fonts" setting does. Presented near "Profile_FontFaceShowAllFonts". @@ -2147,7 +2147,7 @@ Atalho - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Formatação de Texto diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw index 79637c4893..9a5bada6ae 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw @@ -293,7 +293,7 @@ Header for a control to set the query URL when using the "search web" action. - Ţђě рłд¢èнøĺđĕг "%s" щіłĺ ѓēφŀāćεđ ẃĩτђ τђе šέªґ¢ħ qύėгў. !!! !!! !!! !!! !!! !! + Ţђě рłд¢èнøĺđĕг "%s" щіłĺ ьē ŕěρļąč℮ď ẁїτђ τђέ śеªřсħ qцегỳ. !!! !!! !!! !!! !!! !!! {Locked="%s"} Additional text presented near "Globals_SearchWebDefaultQueryUrl.Header". @@ -507,7 +507,7 @@ Ĥìđε тħê τīţĺё ъªř (ŗėqūΐŗêś яеľаϋʼnčћ) !!! !!! !!! !! - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Ẃћèп ðϊŝαъłėð, тнė ťĭτłê вąѓ ẁιĺł ąφφёǻŕ äвöνė ŧħė ťãьś. !!! !!! !!! !!! !!! ! @@ -1195,15 +1195,15 @@ Ŝταяτìлĝ ðĩѓ℮ćτоŗỳ !!! !! - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Ѕťåřťіπġ đíгëĉţöґγ !!! !! - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Šтдřтíⁿģ đϊŕёςŧôŗў !!! !! - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Ţћé đĭŗéçťòŕу τħе рѓøƒĩŀе śťªřťş ïή ẅћĕл îţ ίѕ ŀбдδėď. !!! !!! !!! !!! !!! ! @@ -2147,7 +2147,7 @@ Şħōяŧ¢цτ !! - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Ťĕхτ ₣ôямåτţίʼnğ !!! ! diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw index 79637c4893..9a5bada6ae 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw @@ -293,7 +293,7 @@ Header for a control to set the query URL when using the "search web" action. - Ţђě рłд¢èнøĺđĕг "%s" щіłĺ ѓēφŀāćεđ ẃĩτђ τђе šέªґ¢ħ qύėгў. !!! !!! !!! !!! !!! !! + Ţђě рłд¢èнøĺđĕг "%s" щіłĺ ьē ŕěρļąč℮ď ẁїτђ τђέ śеªřсħ qцегỳ. !!! !!! !!! !!! !!! !!! {Locked="%s"} Additional text presented near "Globals_SearchWebDefaultQueryUrl.Header". @@ -507,7 +507,7 @@ Ĥìđε тħê τīţĺё ъªř (ŗėqūΐŗêś яеľаϋʼnčћ) !!! !!! !!! !! - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Ẃћèп ðϊŝαъłėð, тнė ťĭτłê вąѓ ẁιĺł ąφφёǻŕ äвöνė ŧħė ťãьś. !!! !!! !!! !!! !!! ! @@ -1195,15 +1195,15 @@ Ŝταяτìлĝ ðĩѓ℮ćτоŗỳ !!! !! - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Ѕťåřťіπġ đíгëĉţöґγ !!! !! - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Šтдřтíⁿģ đϊŕёςŧôŗў !!! !! - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Ţћé đĭŗéçťòŕу τħе рѓøƒĩŀе śťªřťş ïή ẅћĕл îţ ίѕ ŀбдδėď. !!! !!! !!! !!! !!! ! @@ -2147,7 +2147,7 @@ Şħōяŧ¢цτ !! - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Ťĕхτ ₣ôямåτţίʼnğ !!! ! diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw index 79637c4893..9a5bada6ae 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw @@ -293,7 +293,7 @@ Header for a control to set the query URL when using the "search web" action. - Ţђě рłд¢èнøĺđĕг "%s" щіłĺ ѓēφŀāćεđ ẃĩτђ τђе šέªґ¢ħ qύėгў. !!! !!! !!! !!! !!! !! + Ţђě рłд¢èнøĺđĕг "%s" щіłĺ ьē ŕěρļąč℮ď ẁїτђ τђέ śеªřсħ qцегỳ. !!! !!! !!! !!! !!! !!! {Locked="%s"} Additional text presented near "Globals_SearchWebDefaultQueryUrl.Header". @@ -507,7 +507,7 @@ Ĥìđε тħê τīţĺё ъªř (ŗėqūΐŗêś яеľаϋʼnčћ) !!! !!! !!! !! - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Ẃћèп ðϊŝαъłėð, тнė ťĭτłê вąѓ ẁιĺł ąφφёǻŕ äвöνė ŧħė ťãьś. !!! !!! !!! !!! !!! ! @@ -1195,15 +1195,15 @@ Ŝταяτìлĝ ðĩѓ℮ćτоŗỳ !!! !! - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Ѕťåřťіπġ đíгëĉţöґγ !!! !! - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Šтдřтíⁿģ đϊŕёςŧôŗў !!! !! - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Ţћé đĭŗéçťòŕу τħе рѓøƒĩŀе śťªřťş ïή ẅћĕл îţ ίѕ ŀбдδėď. !!! !!! !!! !!! !!! ! @@ -2147,7 +2147,7 @@ Şħōяŧ¢цτ !! - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Ťĕхτ ₣ôямåτţίʼnğ !!! ! diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw index c3df5a49bb..4407da146b 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw @@ -507,7 +507,7 @@ Скрыть заголовок окна (требуется перезапуск) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. Если этот параметр отключен, строка заголовка будет отображаться над вкладками. @@ -1195,15 +1195,15 @@ Начальный каталог - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Запуск каталога - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Начальный каталог - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. Каталог, запускаемый профилем при загрузке. @@ -2147,7 +2147,7 @@ Сочетание клавиш - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. Форматирование текста diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw index c68422083e..62180d38ef 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw @@ -507,7 +507,7 @@ 隐藏标题栏(需要重新启动) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. 禁用后,标题栏将显示在选项卡上方。 @@ -1195,15 +1195,15 @@ 启动目录 - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 启动目录 - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 正在启动目录 - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 加载配置文件时启动的目录。 @@ -2147,7 +2147,7 @@ 快捷方式 - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. 文本格式 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw index aef9bfe188..f7671ba670 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw @@ -293,7 +293,7 @@ Header for a control to set the query URL when using the "search web" action. - 佔位元 "%s" 將取代為搜尋查詢。 + 預留位置 "%s" 將以搜尋查詢取代。 {Locked="%s"} Additional text presented near "Globals_SearchWebDefaultQueryUrl.Header". @@ -507,7 +507,7 @@ 隱藏標題列 (需要重新啟動) - Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. + Header for a control to toggle whether or not the title bar should be shown. Changing this setting requires the user to relaunch the app. 停用時,標題列會出現在索引標籤上方。 @@ -1195,15 +1195,15 @@ 起始目錄 - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 啟動時載入的目錄 - Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Header for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 起始目錄 - Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths. + Name for a control to determine the session's initial directory. This is on a text box that accepts folder paths. 載入時,設定檔起始的目錄。 @@ -2147,7 +2147,7 @@ 捷徑 - The label for a "key chord listener" control that sets the keys a key binding is bound to. + The label for a "key chord listener" control that sets the keys to which a key binding is bound. 文字格式設定 From c72600dd4f7d4cce50cec9d64938fe2f408afc9d Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 29 Apr 2026 10:16:30 -0700 Subject: [PATCH 05/18] Add more settings model unit tests (#20117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Adds tests to `UnitTests_SettingsModel` to improve coverage. Tests include: - `SettingInheritanceFallback`: Settings inherit from user defaults; unset settings fall back to built-in defaults - `ClearSettingRestoresInheritance`: `ClearXxx()` removes the value at the current layer, causing fallback to the parent - `HasSettingAtSpecificLayer`: `HasXxx() `distinguishes explicitly set values from inherited ones - `ModifyProfileSettingAndRoundtrip`: Change a profile setting via setter and `ToJson()` reflects it - `ModifyGlobalSettingAndRoundtrip`: Change global settings via setter and `ToJson()` reflects them - `ModifyColorSchemeAndRoundtrip`: Change a color scheme property and the serialized JSON reflects it - `FixupUserSettingsDetectsChanges`: A clean roundtrip produces idempotent FixupUserSettings() (returns false) - `FixupCommandlinePatching`: 4 sub-cases: CMD/PowerShell short names get patched to full paths, no-op when already clean, custom profiles are untouched This also updates `TestCloneInheritanceTree` to verify that `HasXxx()` and settters that modify the clone don't modify the original. This is being done in preparation for auto-save to help ensure we don't have any regressions. ## Validation Steps Performed ✅ Tests pass ✅ Manually reviewed the new tests, they make sense and do add value (though some are less valuable than others, admittedly) ✅ Sent Copilot on a quest to ensure we're not adding redundant tests. It did catch a few and remove them fwiw. --- .../DeserializationTests.cpp | 9 + .../UnitTests_SettingsModel/ProfileTests.cpp | 130 ++++++++ .../SerializationTests.cpp | 290 ++++++++++++++++++ 3 files changed, 429 insertions(+) diff --git a/src/cascadia/UnitTests_SettingsModel/DeserializationTests.cpp b/src/cascadia/UnitTests_SettingsModel/DeserializationTests.cpp index c253a17493..a145db6d3a 100644 --- a/src/cascadia/UnitTests_SettingsModel/DeserializationTests.cpp +++ b/src/cascadia/UnitTests_SettingsModel/DeserializationTests.cpp @@ -1843,6 +1843,15 @@ namespace SettingsModelUnitTests VERIFY_ARE_EQUAL(settings->ProfileDefaults().HasTabTitle(), copyImpl->ProfileDefaults().HasTabTitle()); VERIFY_ARE_NOT_EQUAL(settings->ProfileDefaults().TabTitle(), copyImpl->ProfileDefaults().TabTitle()); + // Verify HasXxx independence: setting a previously-inherited value on the clone + // should make HasXxx true on the clone but remain false on the original. + // SnapOnInput is not set in the JSON, so both should inherit the default. + VERIFY_IS_FALSE(settings->AllProfiles().GetAt(0).HasSnapOnInput()); + VERIFY_IS_FALSE(copyImpl->AllProfiles().GetAt(0).HasSnapOnInput()); + copyImpl->AllProfiles().GetAt(0).SnapOnInput(false); + VERIFY_IS_FALSE(settings->AllProfiles().GetAt(0).HasSnapOnInput()); + VERIFY_IS_TRUE(copyImpl->AllProfiles().GetAt(0).HasSnapOnInput()); + Log::Comment(L"Test empty profiles.defaults"); static constexpr std::string_view emptyPDJson{ R"( { diff --git a/src/cascadia/UnitTests_SettingsModel/ProfileTests.cpp b/src/cascadia/UnitTests_SettingsModel/ProfileTests.cpp index 76ae58bba6..9264a4a441 100644 --- a/src/cascadia/UnitTests_SettingsModel/ProfileTests.cpp +++ b/src/cascadia/UnitTests_SettingsModel/ProfileTests.cpp @@ -31,6 +31,10 @@ namespace SettingsModelUnitTests TEST_METHOD(TestGenGuidsForProfiles); TEST_METHOD(TestCorrectOldDefaultShellPaths); TEST_METHOD(ProfileDefaultsProhibitedSettings); + + TEST_METHOD(SettingInheritanceFallback); + TEST_METHOD(ClearSettingRestoresInheritance); + TEST_METHOD(HasSettingAtSpecificLayer); }; void ProfileTests::ProfileGeneratesGuid() @@ -532,4 +536,130 @@ namespace SettingsModelUnitTests VERIFY_ARE_NOT_EQUAL(L"Default Profile Source", allProfiles.GetAt(2).Source()); VERIFY_ARE_NOT_EQUAL(L"foo.exe", allProfiles.GetAt(2).Commandline()); } + + void ProfileTests::SettingInheritanceFallback() + { + // Verify that when no layer defines a setting, the default value is used. + // Also verify that when only user defaults defines it, profiles inherit from there. + static constexpr std::string_view userSettings{ R"({ + "profiles": { + "defaults": { + "historySize": 5000 + }, + "list": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}" + }, + { + "name": "profile1", + "guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}", + "snapOnInput": false + } + ] + } + })" }; + + const auto settings = winrt::make_self(userSettings); + const auto allProfiles = settings->AllProfiles(); + + VERIFY_ARE_EQUAL(2u, allProfiles.Size()); + + // profile0: historySize inherited from defaults + VERIFY_ARE_EQUAL(5000, allProfiles.GetAt(0).HistorySize()); + // profile0: snapOnInput not set anywhere, falls back to default (true) + VERIFY_ARE_EQUAL(true, allProfiles.GetAt(0).SnapOnInput()); + + // profile1: historySize inherited from defaults + VERIFY_ARE_EQUAL(5000, allProfiles.GetAt(1).HistorySize()); + // profile1: snapOnInput explicitly set to false + VERIFY_ARE_EQUAL(false, allProfiles.GetAt(1).SnapOnInput()); + } + + void ProfileTests::ClearSettingRestoresInheritance() + { + // Verify that clearing a setting at the profile layer causes it to + // fall back to the parent's value. + static constexpr std::string_view parentString{ R"({ + "name": "parent", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "historySize": 1000, + "tabTitle": "ParentTitle" + })" }; + static constexpr std::string_view childString{ R"({ + "name": "child", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "historySize": 2000, + "tabTitle": "ChildTitle" + })" }; + + const auto parentJson = VerifyParseSucceeded(parentString); + const auto childJson = VerifyParseSucceeded(childString); + + auto parent = implementation::Profile::FromJson(parentJson); + auto child = parent->CreateChild(); + child->LayerJson(childJson); + + // Verify child has its own values + VERIFY_ARE_EQUAL(2000, child->HistorySize()); + VERIFY_ARE_EQUAL(L"ChildTitle", child->TabTitle()); + VERIFY_IS_TRUE(child->HasHistorySize()); + VERIFY_IS_TRUE(child->HasTabTitle()); + + // Clear historySize on child: should fall back to parent + child->ClearHistorySize(); + VERIFY_IS_FALSE(child->HasHistorySize()); + VERIFY_ARE_EQUAL(1000, child->HistorySize()); + + // Clear tabTitle on child: should fall back to parent + child->ClearTabTitle(); + VERIFY_IS_FALSE(child->HasTabTitle()); + VERIFY_ARE_EQUAL(L"ParentTitle", child->TabTitle()); + } + + void ProfileTests::HasSettingAtSpecificLayer() + { + // Verify that HasXxx() correctly reports whether a setting is defined + // at the current layer vs inherited from a parent. + static constexpr std::string_view userSettings{ R"({ + "profiles": { + "defaults": { + "historySize": 5000, + "tabTitle": "DefaultTitle" + }, + "list": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "historySize": 9001 + }, + { + "name": "profile1", + "guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" + } + ] + } + })" }; + + const auto settings = winrt::make_self(userSettings); + const auto allProfiles = settings->AllProfiles(); + + VERIFY_ARE_EQUAL(2u, allProfiles.Size()); + + // profile0: historySize is explicitly set + VERIFY_IS_TRUE(allProfiles.GetAt(0).HasHistorySize()); + VERIFY_ARE_EQUAL(9001, allProfiles.GetAt(0).HistorySize()); + + // profile0: tabTitle is NOT set at this layer (inherited from defaults) + VERIFY_IS_FALSE(allProfiles.GetAt(0).HasTabTitle()); + VERIFY_ARE_EQUAL(L"DefaultTitle", allProfiles.GetAt(0).TabTitle()); + + // profile1: historySize is NOT set at this layer (inherited from defaults) + VERIFY_IS_FALSE(allProfiles.GetAt(1).HasHistorySize()); + VERIFY_ARE_EQUAL(5000, allProfiles.GetAt(1).HistorySize()); + + // ProfileDefaults: historySize is set + VERIFY_IS_TRUE(settings->ProfileDefaults().HasHistorySize()); + VERIFY_ARE_EQUAL(5000, settings->ProfileDefaults().HistorySize()); + } } diff --git a/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp b/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp index 3112f83939..7b0ac2c6ec 100644 --- a/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp +++ b/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp @@ -60,6 +60,12 @@ namespace SettingsModelUnitTests TEST_METHOD(ProfileWithInvalidIcon); + TEST_METHOD(ModifyProfileSettingAndRoundtrip); + TEST_METHOD(ModifyGlobalSettingAndRoundtrip); + TEST_METHOD(ModifyColorSchemeAndRoundtrip); + TEST_METHOD(FixupUserSettingsDetectsChanges); + TEST_METHOD(FixupCommandlinePatching); + private: // Method Description: // - deserializes and reserializes a json string representing a settings object model of type T @@ -1325,4 +1331,288 @@ namespace SettingsModelUnitTests // what was written in the settings file. VERIFY_ARE_EQUAL(R"(c:\this_icon_had_better_not_exist.tiff)", newResult["profiles"]["list"][0]["icon"].asString()); } + + void SerializationTests::ModifyProfileSettingAndRoundtrip() + { + // Load settings, modify a profile setting via setter, serialize, + // and verify the JSON output reflects the change. + static constexpr std::string_view settingsJson{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "profiles": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "historySize": 1000, + "commandline": "cmd.exe" + } + ] + })" }; + + const auto settings{ winrt::make_self(settingsJson) }; + + // Verify initial value + VERIFY_ARE_EQUAL(1000, settings->AllProfiles().GetAt(0).HistorySize()); + + // Modify the setting + settings->AllProfiles().GetAt(0).HistorySize(5000); + VERIFY_ARE_EQUAL(5000, settings->AllProfiles().GetAt(0).HistorySize()); + + // Serialize and verify the change is reflected in JSON + const auto result{ settings->ToJson() }; + VERIFY_ARE_EQUAL(5000, result["profiles"]["list"][0]["historySize"].asInt()); + + // Verify other settings are preserved + VERIFY_ARE_EQUAL("cmd.exe", result["profiles"]["list"][0]["commandline"].asString()); + + // Also verify: modify a setting that wasn't previously set + settings->AllProfiles().GetAt(0).TabTitle(L"NewTitle"); + const auto result2{ settings->ToJson() }; + VERIFY_ARE_EQUAL("NewTitle", result2["profiles"]["list"][0]["tabTitle"].asString()); + } + + void SerializationTests::ModifyGlobalSettingAndRoundtrip() + { + // Load settings, modify a global setting, serialize, verify JSON. + static constexpr std::string_view settingsJson{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "initialRows": 30, + "alwaysOnTop": false, + "profiles": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}" + } + ] + })" }; + + const auto settings{ winrt::make_self(settingsJson) }; + + // Verify initial values + VERIFY_ARE_EQUAL(30, settings->GlobalSettings().InitialRows()); + VERIFY_ARE_EQUAL(false, settings->GlobalSettings().AlwaysOnTop()); + + // Modify global settings + settings->GlobalSettings().InitialRows(50); + settings->GlobalSettings().AlwaysOnTop(true); + + // Verify in-memory changes + VERIFY_ARE_EQUAL(50, settings->GlobalSettings().InitialRows()); + VERIFY_ARE_EQUAL(true, settings->GlobalSettings().AlwaysOnTop()); + + // Serialize and verify + const auto result{ settings->ToJson() }; + VERIFY_ARE_EQUAL(50, result["initialRows"].asInt()); + VERIFY_ARE_EQUAL(true, result["alwaysOnTop"].asBool()); + } + + void SerializationTests::ModifyColorSchemeAndRoundtrip() + { + // Load settings with a user color scheme, modify it, serialize, verify. + static constexpr std::string_view settingsJson{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "profiles": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}" + } + ], + "schemes": [ + { + "name": "MyScheme", + "foreground": "#CCCCCC", + "background": "#0C0C0C", + "cursorColor": "#FFFFFF", + "black": "#0C0C0C", + "red": "#C50F1F", + "green": "#13A10E", + "yellow": "#C19C00", + "blue": "#0037DA", + "purple": "#881798", + "cyan": "#3A96DD", + "white": "#CCCCCC", + "brightBlack": "#767676", + "brightRed": "#E74856", + "brightGreen": "#16C60C", + "brightYellow": "#F9F1A5", + "brightBlue": "#3B78FF", + "brightPurple": "#B4009E", + "brightCyan": "#61D6D6", + "brightWhite": "#F2F2F2" + } + ] + })" }; + + const auto settings{ winrt::make_self(settingsJson) }; + + // Find and modify the color scheme + const auto schemes = settings->GlobalSettings().ColorSchemes(); + VERIFY_IS_TRUE(schemes.HasKey(L"MyScheme")); + auto myScheme = schemes.Lookup(L"MyScheme"); + + const auto origForeground = myScheme.Foreground(); + myScheme.Foreground(til::color{ 0xAA, 0xBB, 0xCC }); + + // Serialize and verify the change persists + const auto result{ settings->ToJson() }; + const auto& schemesJson = result["schemes"]; + bool found = false; + for (const auto& scheme : schemesJson) + { + if (scheme["name"].asString() == "MyScheme") + { + VERIFY_ARE_EQUAL("#AABBCC", scheme["foreground"].asString()); + found = true; + break; + } + } + VERIFY_IS_TRUE(found, L"MyScheme should be present in serialized output"); + } + + void SerializationTests::FixupUserSettingsDetectsChanges() + { + // Verify that FixupUserSettings returns true when settings need + // to be written back (e.g., migration), and false when clean. + static constexpr std::string_view cleanSettingsJson{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "profiles": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "commandline": "cmd.exe" + } + ] + })" }; + + // Load, fixup, serialize. Reload and verify fixup returns false. + implementation::SettingsLoader loader1{ cleanSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) }; + loader1.MergeInboxIntoUserSettings(); + loader1.FinalizeLayering(); + loader1.FixupUserSettings(); + const auto settings1 = winrt::make_self(std::move(loader1)); + const auto result1{ settings1->ToJson() }; + + // Reload from the serialized output (should be stable) + implementation::SettingsLoader loader2{ toString(result1), implementation::LoadStringResource(IDR_DEFAULTS) }; + loader2.MergeInboxIntoUserSettings(); + loader2.FinalizeLayering(); + const auto fixupNeeded = loader2.FixupUserSettings(); + + // After a clean roundtrip, no further fixups should be needed + VERIFY_IS_FALSE(fixupNeeded, L"A clean roundtrip should not require further fixups"); + } + + void SerializationTests::FixupCommandlinePatching() + { + // Verify that FixupUserSettings patches "cmd.exe" to the full path + // for the Command Prompt profile, and "powershell.exe" for the + // Windows PowerShell profile, and returns true to indicate changes. + + // Case 1: CMD profile with short commandline should be patched + static constexpr std::string_view cmdSettingsJson{ R"( + { + "defaultProfile": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", + "profiles": [ + { + "name": "Command Prompt", + "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", + "commandline": "cmd.exe" + } + ] + })" }; + + { + implementation::SettingsLoader loader{ cmdSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) }; + loader.MergeInboxIntoUserSettings(); + loader.FinalizeLayering(); + const auto fixupNeeded = loader.FixupUserSettings(); + VERIFY_IS_TRUE(fixupNeeded, L"FixupUserSettings should return true when cmd.exe is patched"); + + const auto settings = winrt::make_self(std::move(loader)); + const auto cmdProfile = settings->FindProfile(Utils::GuidFromString(L"{0caa0dad-35be-5f56-a8ff-afceeeaa6101}")); + VERIFY_IS_NOT_NULL(cmdProfile); + VERIFY_ARE_EQUAL(L"%SystemRoot%\\System32\\cmd.exe", cmdProfile.Commandline()); + } + + // Case 2: PowerShell profile with short commandline should be patched + static constexpr std::string_view psSettingsJson{ R"( + { + "defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", + "profiles": [ + { + "name": "Windows PowerShell", + "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", + "commandline": "powershell.exe" + } + ] + })" }; + + { + implementation::SettingsLoader loader{ psSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) }; + loader.MergeInboxIntoUserSettings(); + loader.FinalizeLayering(); + const auto fixupNeeded = loader.FixupUserSettings(); + VERIFY_IS_TRUE(fixupNeeded, L"FixupUserSettings should return true when powershell.exe is patched"); + + const auto settings = winrt::make_self(std::move(loader)); + const auto psProfile = settings->FindProfile(Utils::GuidFromString(L"{61c54bbd-c2c6-5271-96e7-009a87ff44bf}")); + VERIFY_IS_NOT_NULL(psProfile); + VERIFY_ARE_EQUAL(L"%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", psProfile.Commandline()); + } + + // Case 3: CMD profile with the full path should NOT trigger fixup + static constexpr std::string_view cleanCmdSettingsJson{ R"( + { + "defaultProfile": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", + "profiles": [ + { + "name": "Command Prompt", + "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}" + } + ] + })" }; + + { + implementation::SettingsLoader loader{ cleanCmdSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) }; + loader.MergeInboxIntoUserSettings(); + loader.FinalizeLayering(); + const auto fixupNeeded = loader.FixupUserSettings(); + VERIFY_IS_FALSE(fixupNeeded, L"FixupUserSettings should return false when no patching is needed"); + + const auto settings = winrt::make_self(std::move(loader)); + const auto cmdProfile = settings->FindProfile(Utils::GuidFromString(L"{0caa0dad-35be-5f56-a8ff-afceeeaa6101}")); + VERIFY_IS_NOT_NULL(cmdProfile); + // Should still resolve to the full path via inbox defaults + VERIFY_ARE_EQUAL(L"%SystemRoot%\\System32\\cmd.exe", cmdProfile.Commandline()); + } + + // Case 4: A non-builtin profile with "cmd.exe" should NOT be patched + static constexpr std::string_view customCmdSettingsJson{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "profiles": [ + { + "name": "My Custom CMD", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "commandline": "cmd.exe" + } + ] + })" }; + + { + implementation::SettingsLoader loader{ customCmdSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) }; + loader.MergeInboxIntoUserSettings(); + loader.FinalizeLayering(); + loader.FixupUserSettings(); + + const auto settings = winrt::make_self(std::move(loader)); + const auto customProfile = settings->FindProfile(Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}")); + VERIFY_IS_NOT_NULL(customProfile); + // Custom profile should keep "cmd.exe" unchanged + VERIFY_ARE_EQUAL(L"cmd.exe", customProfile.Commandline()); + } + } } From 3362651659dda87e294c56242d306d51f919ae12 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 29 Apr 2026 11:54:43 -0700 Subject: [PATCH 06/18] Tab menu: show "restart" + maintain items' enable state (#19972) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Changes how/when we display the "restart connection" item in the tab's context menu. Now, we always display it, but it's disabled if we're not in a terminal tab. Applies similar enable/disable logic to the rest of the menu items. Previous to this, they just wouldn't do anything (which is fair, they didn't make any sense). ## Validation Steps Performed Check tab's menu in following scenarios: ✅ terminal pane ✅ settings tab ✅ snippets pane Closes #18891 --- .../Resources/en-US/Resources.resw | 4 +- src/cascadia/TerminalApp/Tab.cpp | 105 +++++++++--------- src/cascadia/TerminalApp/Tab.h | 16 +-- .../Resources/en-US/Resources.resw | 2 +- 4 files changed, 66 insertions(+), 61 deletions(-) diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index eb1c317e18..9de52e45c3 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -881,10 +881,10 @@ If set, the command will be appended to the profile's default command instead of replacing it. - Restart connection + Restart session - Restart the active pane connection + Restart the session in the active pane Snippets diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 42fb9ab624..3d3db9a425 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -35,7 +35,6 @@ namespace winrt::TerminalApp::implementation _activePane = nullptr; _closePaneMenuItem.Visibility(WUX::Visibility::Collapsed); - _restartConnectionMenuItem.Visibility(WUX::Visibility::Collapsed); auto firstId = _nextPaneId; @@ -86,6 +85,7 @@ namespace winrt::TerminalApp::implementation _MakeTabViewItem(); _CreateContextMenu(); + _UpdateMenuItemStates(); _headerControl.TabStatus(_tabStatus); @@ -1254,7 +1254,7 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Set an indicator on the tab if any pane is in a closed connection state. - // - Show/hide the Restart Connection context menu entry depending on active pane's state. + // - Show/hide the Restart Session context menu entry depending on active pane's state. // Arguments: // - // Return Value: @@ -1271,13 +1271,6 @@ namespace winrt::TerminalApp::implementation _tabStatus.IsConnectionClosed(isClosed); } - - if (_activePane) - { - _restartConnectionMenuItem.Visibility(_activePane->IsConnectionClosed() ? - WUX::Visibility::Visible : - WUX::Visibility::Collapsed); - } } void Tab::_RestartActivePaneConnection() @@ -1348,6 +1341,22 @@ namespace winrt::TerminalApp::implementation } }); } + + _UpdateMenuItemStates(); + } + + void Tab::_UpdateMenuItemStates() + { + // Terminal-specific menu items + const auto content = _activePane ? _activePane->GetContent() : nullptr; + const auto isTerm = content && content.try_as() != nullptr; + _duplicateTabMenuItem.IsEnabled(isTerm); + _exportTabMenuItem.IsEnabled(isTerm); + _findMenuItem.IsEnabled(isTerm); + _restartConnectionMenuItem.IsEnabled(isTerm); + + // Snippets Pane can technically be split + _splitTabMenuItem.IsEnabled(isTerm || (content && content.try_as() != nullptr)); } // Method Description: @@ -1652,106 +1661,100 @@ namespace winrt::TerminalApp::implementation Automation::AutomationProperties::SetHelpText(renameTabMenuItem, renameTabToolTip); } - Controls::MenuFlyoutItem duplicateTabMenuItem; { // "Duplicate tab" Controls::FontIcon duplicateTabSymbol; duplicateTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); duplicateTabSymbol.Glyph(L"\xF5ED"); - duplicateTabMenuItem.Click({ get_weak(), &Tab::_duplicateTabClicked }); - duplicateTabMenuItem.Text(RS_(L"DuplicateTabText")); - duplicateTabMenuItem.Icon(duplicateTabSymbol); + _duplicateTabMenuItem.Click({ get_weak(), &Tab::_duplicateTabClicked }); + _duplicateTabMenuItem.Text(RS_(L"DuplicateTabText")); + _duplicateTabMenuItem.Icon(duplicateTabSymbol); const auto duplicateTabToolTip = RS_(L"DuplicateTabToolTip"); - WUX::Controls::ToolTipService::SetToolTip(duplicateTabMenuItem, box_value(duplicateTabToolTip)); - Automation::AutomationProperties::SetHelpText(duplicateTabMenuItem, duplicateTabToolTip); + WUX::Controls::ToolTipService::SetToolTip(_duplicateTabMenuItem, box_value(duplicateTabToolTip)); + Automation::AutomationProperties::SetHelpText(_duplicateTabMenuItem, duplicateTabToolTip); } - Controls::MenuFlyoutItem splitTabMenuItem; { // "Split tab" Controls::FontIcon splitTabSymbol; splitTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); splitTabSymbol.Glyph(L"\xF246"); // ViewDashboard - splitTabMenuItem.Click({ get_weak(), &Tab::_splitTabClicked }); - splitTabMenuItem.Text(RS_(L"SplitTabText")); - splitTabMenuItem.Icon(splitTabSymbol); + _splitTabMenuItem.Click({ get_weak(), &Tab::_splitTabClicked }); + _splitTabMenuItem.Text(RS_(L"SplitTabText")); + _splitTabMenuItem.Icon(splitTabSymbol); const auto splitTabToolTip = RS_(L"SplitTabToolTip"); - WUX::Controls::ToolTipService::SetToolTip(splitTabMenuItem, box_value(splitTabToolTip)); - Automation::AutomationProperties::SetHelpText(splitTabMenuItem, splitTabToolTip); + WUX::Controls::ToolTipService::SetToolTip(_splitTabMenuItem, box_value(splitTabToolTip)); + Automation::AutomationProperties::SetHelpText(_splitTabMenuItem, splitTabToolTip); } - Controls::MenuFlyoutItem closePaneMenuItem = _closePaneMenuItem; { // "Close pane" - closePaneMenuItem.Click({ get_weak(), &Tab::_closePaneClicked }); - closePaneMenuItem.Text(RS_(L"ClosePaneText")); + _closePaneMenuItem.Click({ get_weak(), &Tab::_closePaneClicked }); + _closePaneMenuItem.Text(RS_(L"ClosePaneText")); const auto closePaneToolTip = RS_(L"ClosePaneToolTip"); - WUX::Controls::ToolTipService::SetToolTip(closePaneMenuItem, box_value(closePaneToolTip)); - Automation::AutomationProperties::SetHelpText(closePaneMenuItem, closePaneToolTip); + WUX::Controls::ToolTipService::SetToolTip(_closePaneMenuItem, box_value(closePaneToolTip)); + Automation::AutomationProperties::SetHelpText(_closePaneMenuItem, closePaneToolTip); } - Controls::MenuFlyoutItem exportTabMenuItem; { // "Export tab" Controls::FontIcon exportTabSymbol; exportTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); exportTabSymbol.Glyph(L"\xE74E"); // Save - exportTabMenuItem.Click({ get_weak(), &Tab::_exportTextClicked }); - exportTabMenuItem.Text(RS_(L"ExportTabText")); - exportTabMenuItem.Icon(exportTabSymbol); + _exportTabMenuItem.Click({ get_weak(), &Tab::_exportTextClicked }); + _exportTabMenuItem.Text(RS_(L"ExportTabText")); + _exportTabMenuItem.Icon(exportTabSymbol); const auto exportTabToolTip = RS_(L"ExportTabToolTip"); - WUX::Controls::ToolTipService::SetToolTip(exportTabMenuItem, box_value(exportTabToolTip)); - Automation::AutomationProperties::SetHelpText(exportTabMenuItem, exportTabToolTip); + WUX::Controls::ToolTipService::SetToolTip(_exportTabMenuItem, box_value(exportTabToolTip)); + Automation::AutomationProperties::SetHelpText(_exportTabMenuItem, exportTabToolTip); } - Controls::MenuFlyoutItem findMenuItem; { // "Find" Controls::FontIcon findSymbol; findSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); findSymbol.Glyph(L"\xF78B"); // SearchMedium - findMenuItem.Click({ get_weak(), &Tab::_findClicked }); - findMenuItem.Text(RS_(L"FindText")); - findMenuItem.Icon(findSymbol); + _findMenuItem.Click({ get_weak(), &Tab::_findClicked }); + _findMenuItem.Text(RS_(L"FindText")); + _findMenuItem.Icon(findSymbol); const auto findToolTip = RS_(L"FindToolTip"); - WUX::Controls::ToolTipService::SetToolTip(findMenuItem, box_value(findToolTip)); - Automation::AutomationProperties::SetHelpText(findMenuItem, findToolTip); + WUX::Controls::ToolTipService::SetToolTip(_findMenuItem, box_value(findToolTip)); + Automation::AutomationProperties::SetHelpText(_findMenuItem, findToolTip); } - Controls::MenuFlyoutItem restartConnectionMenuItem = _restartConnectionMenuItem; { - // "Restart connection" + // "Restart session" Controls::FontIcon restartConnectionSymbol; restartConnectionSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); restartConnectionSymbol.Glyph(L"\xE72C"); - restartConnectionMenuItem.Click([weakThis](auto&&, auto&&) { + _restartConnectionMenuItem.Click([weakThis](auto&&, auto&&) { if (auto tab{ weakThis.get() }) { tab->_RestartActivePaneConnection(); } }); - restartConnectionMenuItem.Text(RS_(L"RestartConnectionText")); - restartConnectionMenuItem.Icon(restartConnectionSymbol); + _restartConnectionMenuItem.Text(RS_(L"RestartConnectionText")); + _restartConnectionMenuItem.Icon(restartConnectionSymbol); const auto restartConnectionToolTip = RS_(L"RestartConnectionToolTip"); - WUX::Controls::ToolTipService::SetToolTip(restartConnectionMenuItem, box_value(restartConnectionToolTip)); - Automation::AutomationProperties::SetHelpText(restartConnectionMenuItem, restartConnectionToolTip); + WUX::Controls::ToolTipService::SetToolTip(_restartConnectionMenuItem, box_value(restartConnectionToolTip)); + Automation::AutomationProperties::SetHelpText(_restartConnectionMenuItem, restartConnectionToolTip); } // Build the menu @@ -1759,16 +1762,16 @@ namespace winrt::TerminalApp::implementation Controls::MenuFlyoutSeparator menuSeparator; contextMenuFlyout.Items().Append(chooseColorMenuItem); contextMenuFlyout.Items().Append(renameTabMenuItem); - contextMenuFlyout.Items().Append(duplicateTabMenuItem); - contextMenuFlyout.Items().Append(splitTabMenuItem); + contextMenuFlyout.Items().Append(_duplicateTabMenuItem); + contextMenuFlyout.Items().Append(_splitTabMenuItem); _AppendMoveMenuItems(contextMenuFlyout); - contextMenuFlyout.Items().Append(exportTabMenuItem); - contextMenuFlyout.Items().Append(findMenuItem); - contextMenuFlyout.Items().Append(restartConnectionMenuItem); + contextMenuFlyout.Items().Append(_exportTabMenuItem); + contextMenuFlyout.Items().Append(_findMenuItem); + contextMenuFlyout.Items().Append(_restartConnectionMenuItem); contextMenuFlyout.Items().Append(menuSeparator); auto closeSubMenu = _AppendCloseMenuItems(contextMenuFlyout); - closeSubMenu.Items().Append(closePaneMenuItem); + closeSubMenu.Items().Append(_closePaneMenuItem); // GH#5750 - When the context menu is dismissed with ESC, toss the focus // back to our control. diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h index 65d4e574ed..70dec43426 100644 --- a/src/cascadia/TerminalApp/Tab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -140,11 +140,17 @@ namespace winrt::TerminalApp::implementation static constexpr double HeaderRenameBoxWidthTitleLength{ std::numeric_limits::infinity() }; winrt::Windows::UI::Xaml::FocusState _focusState{ winrt::Windows::UI::Xaml::FocusState::Unfocused }; - winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{}; - winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _duplicateTabMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _splitTabMenuItem{}; winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveToNewWindowMenuItem{}; winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveRightMenuItem{}; winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveLeftMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _exportTabMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _findMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _restartConnectionMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closePaneMenuItem{}; winrt::TerminalApp::ShortcutActionDispatch _dispatch; Microsoft::Terminal::Settings::Model::IActionMapView _actionMap{ nullptr }; winrt::hstring _keyChord{}; @@ -159,9 +165,6 @@ namespace winrt::TerminalApp::implementation std::shared_ptr _activePane{ nullptr }; std::shared_ptr _zoomedPane{ nullptr }; - Windows::UI::Xaml::Controls::MenuFlyoutItem _closePaneMenuItem; - Windows::UI::Xaml::Controls::MenuFlyoutItem _restartConnectionMenuItem; - winrt::Microsoft::Terminal::Settings::Model::IconStyle _lastIconStyle; winrt::hstring _lastIconPath{}; std::optional _runtimeTabColor{}; @@ -220,6 +223,7 @@ namespace winrt::TerminalApp::implementation void _AttachEventHandlersToPane(std::shared_ptr pane); void _UpdateActivePane(std::shared_ptr pane); + void _UpdateMenuItemStates(); winrt::hstring _GetActiveTitle() const; @@ -230,8 +234,6 @@ namespace winrt::TerminalApp::implementation void _UpdateConnectionClosedState(); void _RestartActivePaneConnection(); - void _DuplicateTab(); - winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush(); void _MakeTabViewItem(); diff --git a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw index 7e20657981..a21afe9e88 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Restart connection + Restart session Open scratchpad From 115ec2cbb990f56b553a1c1dcc8de96e86d4f8f9 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 29 Apr 2026 15:01:43 -0700 Subject: [PATCH 07/18] Fix rounding error for word selection (#20084) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Dustin reported this bug to me. Thankfully it was an easy fix. ## References and Relevant Issues Bug from implementing #5099 ## Validation Steps Performed Double-click ____ of right-most cell of a word selects the current word ✅ right-half ✅ left-half --- src/cascadia/TerminalControl/ControlInteractivity.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 06ce1e17f3..bd30911797 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -309,8 +309,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto isOnOriginalPosition = _lastMouseClickPosNoSelection == pixelPosition; // Rounded coordinates for text selection. - // Don't round in VT mouse mode; cell-level precision matters more - const auto round = !_core->IsVtMouseModeEnabled(); + // Don't round in VT mouse mode; cell-level precision matters more. + // Only round for single-click: for double/triple-click, rounding + // can push the position to the next cell, selecting the wrong word. + const auto round = multiClickMapper == 1 && !_core->IsVtMouseModeEnabled(); _core->LeftClickOnTerminal(_getTerminalPosition(til::point{ pixelPosition }, round), multiClickMapper, altEnabled, From 84e807cbeb5f8e4ba76fe5ab12803b934536bf29 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Wed, 29 Apr 2026 17:04:16 -0500 Subject: [PATCH 08/18] appx: add appLicensing to Preview and Stable manifests (#20163) This should prevent an outage like the one from #19764 --- src/cascadia/CascadiaPackage/Package-Pre.appxmanifest | 1 + src/cascadia/CascadiaPackage/Package.appxmanifest | 1 + 2 files changed, 2 insertions(+) diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 18d195efb1..497923da40 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -237,6 +237,7 @@ + diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index c679a959bc..679f3b9a52 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -237,6 +237,7 @@ + From e4e3f08efca9d0ffba330eee12edbcb16897ddcb Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 29 Apr 2026 17:24:45 -0700 Subject: [PATCH 09/18] Add toast notification infrastructure (#20010) ## Summary of the Pull Request Adds the infrastructure for toast notifications. Breakdown: - `DesktopNotification`: - `DesktopNotificationArgs` includes the struct to group all notification-related data together. - `SendNotification()` actually sends it - `AppCommandlineArgs.cpp`: added a check for the `--from-toast` no-op sentinel; ensures no new window is created - Most of the other changes are just bubbling up the notification from the `TerminalPaneContent` to `TerminalPage` - `TabManagement.cpp`: `_SendDesktopNotification()` does the final packaging of the notification before calling the `DesktopNotification` API This supports finding the right tab when it's been reordered or even moved to a new window! This also has expanded to support finding the right pane, which is resilient to pane swaps/closing too. When the pane can't be found, we just fallback to the tab. If the pane is already focused, we don't send a notification. This simply adds the infrastructure! Looks like nothing can actually take advantage of it yet, but it's been tested with the changes in #20011. Heavily based on #19935 Co-authored by @zadjii-msft --- .github/actions/spelling/expect/expect.txt | 1 + .../TerminalApp/AppCommandlineArgs.cpp | 9 ++ src/cascadia/TerminalApp/BasicPaneEvents.h | 1 + .../TerminalApp/DesktopNotification.cpp | 129 +++++++++++++++++ .../TerminalApp/DesktopNotification.h | 37 +++++ src/cascadia/TerminalApp/IPaneContent.idl | 7 + .../Resources/en-US/Resources.resw | 8 + src/cascadia/TerminalApp/Tab.cpp | 12 ++ src/cascadia/TerminalApp/Tab.h | 2 + src/cascadia/TerminalApp/TabManagement.cpp | 137 ++++++++++++++++++ .../TerminalApp/TerminalAppLib.vcxproj | 2 + src/cascadia/TerminalApp/TerminalPage.h | 4 + .../TerminalApp/TerminalPaneContent.h | 11 ++ src/cascadia/TerminalApp/TerminalWindow.cpp | 9 ++ src/cascadia/TerminalApp/TerminalWindow.h | 2 + src/cascadia/TerminalApp/TerminalWindow.idl | 3 + src/cascadia/TerminalApp/pch.h | 3 + src/cascadia/WindowsTerminal/AppHost.cpp | 9 ++ src/cascadia/WindowsTerminal/AppHost.h | 4 + .../WindowsTerminal/WindowEmperor.cpp | 28 +++- src/cascadia/WindowsTerminal/WindowEmperor.h | 1 + 21 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 src/cascadia/TerminalApp/DesktopNotification.cpp create mode 100644 src/cascadia/TerminalApp/DesktopNotification.h diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 29d56325c5..102af4d88f 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -1104,6 +1104,7 @@ NOSIZE NOSNAPSHOT NOTHOUSANDS NOTICKS +notif NOTIMEOUTIFNOTHUNG NOTIMPL NOTOPMOST diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index c41eea5431..950984019b 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -1068,6 +1068,15 @@ int AppCommandlineArgs::ParseArgs(winrt::array_view args) return 0; } + // When a toast notification is clicked, Windows may launch a new instance + // with "--from-toast" as the argument. This is a no-op sentinel — the + // in-process Activated handler on the toast already handled activation. + // See DesktopNotification.cpp for more details. + if (args.size() == 2 && args[1] == L"--from-toast") + { + return 0; + } + auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args); for (auto& cmdBlob : commands) diff --git a/src/cascadia/TerminalApp/BasicPaneEvents.h b/src/cascadia/TerminalApp/BasicPaneEvents.h index e82ff0f49b..bd9bfb3916 100644 --- a/src/cascadia/TerminalApp/BasicPaneEvents.h +++ b/src/cascadia/TerminalApp/BasicPaneEvents.h @@ -15,6 +15,7 @@ namespace winrt::TerminalApp::implementation til::typed_event TaskbarProgressChanged; til::typed_event ReadOnlyChanged; til::typed_event FocusRequested; + til::typed_event NotificationRequested; til::typed_event DispatchCommandRequested; }; diff --git a/src/cascadia/TerminalApp/DesktopNotification.cpp b/src/cascadia/TerminalApp/DesktopNotification.cpp new file mode 100644 index 0000000000..d1e8a198c7 --- /dev/null +++ b/src/cascadia/TerminalApp/DesktopNotification.cpp @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "DesktopNotification.h" + +#include + +using namespace winrt::Windows::UI::Notifications; +using namespace winrt::Windows::Data::Xml::Dom; + +namespace winrt::TerminalApp::implementation +{ + std::atomic DesktopNotification::_lastNotificationTime{ 0 }; + + // Method Description: + // - Rate-limits toast notifications so we don't spam the user. + // Return Value: + // - Returns true if a notification is allowed, false if too recent. + bool DesktopNotification::ShouldSendNotification() + { + const auto now = GetTickCount64(); + auto last = _lastNotificationTime.load(std::memory_order_relaxed); + + // Subtraction wraps cleanly modulo 2^64, so the delta is correct even + // across the (~584 million year) GetTickCount64 rollover. + if (now - last < MinNotificationIntervalMs) + { + return false; + } + + // Attempt to update; if another thread beat us, that's fine — we'll skip this one. + return _lastNotificationTime.compare_exchange_strong(last, now, std::memory_order_relaxed); + } + + // Method Description: + // - Sends a toast notification with the given title and message. + // - When the user clicks the toast, the `Activated` callback fires + // with the tabIndex that was passed in, so the caller can switch + // to the correct tab and summon the window. + // Arguments: + // - args: The title, message, and tab index to include in the notification. + // - activated: A callback invoked on the background thread when the + // toast is clicked. The uint32_t parameter is the tab index. + void DesktopNotification::SendNotification(const DesktopNotificationArgs& args, std::function activatedFunc) + { + try + { + if (!ShouldSendNotification()) + { + return; + } + + // Build the toast XML. We use a simple template with a title and body text. + // + // + // + // + // Title + // Message + // + // + // + auto toastXml = ToastNotificationManager::GetTemplateContent(ToastTemplateType::ToastText02); + auto textNodes = toastXml.GetElementsByTagName(L"text"); + + // First is the title + textNodes.Item(0).InnerText(args.Title); + // Second is the body + textNodes.Item(1).InnerText(args.Message); + + auto toastElement = toastXml.DocumentElement(); + + // When a toast is clicked, Windows launches a new instance of the app + // with the "launch" attribute as command-line arguments. We handle + // toast activation in-process via the Activated event below, so the + // new instance should do nothing. "--from-toast" is recognized by + // AppCommandlineArgs::ParseArgs as a no-op sentinel. + toastElement.SetAttribute(L"launch", L"--from-toast"); + + toastElement.SetAttribute(L"scenario", L"default"); + + auto toast = ToastNotification{ toastXml }; + + // Set the tag and group to enable notification replacement. + // Repeated notifications with the same tag replace the previous one + // rather than stacking in the notification center. + toast.Tag(args.Tag); + toast.Group(L"WindowsTerminal"); + + // When the user activates (clicks) the toast, fire the callback. + if (activatedFunc) + { + toast.Activated([activatedFunc](const auto& /*sender*/, const auto& /*eventArgs*/) { + activatedFunc(); + }); + } + + // For packaged apps, CreateToastNotifier() uses the package identity automatically. + // For unpackaged apps, we must pass the explicit AUMID that was registered + // at startup via SetCurrentProcessExplicitAppUserModelID. + winrt::Windows::UI::Notifications::ToastNotifier notifier{ nullptr }; + if (IsPackaged()) + { + notifier = ToastNotificationManager::CreateToastNotifier(); + } + else + { + // Retrieve the AUMID that was set by WindowEmperor at startup. + wil::unique_cotaskmem_string aumid; + if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&aumid))) + { + notifier = ToastNotificationManager::CreateToastNotifier(aumid.get()); + } + } + if (notifier) + { + notifier.Show(toast); + } + } + catch (...) + { + // Toast notification is a best-effort feature. If it fails (e.g., notifications + // are disabled, or the app is unpackaged without proper AUMID setup), we silently + // ignore the error. + LOG_CAUGHT_EXCEPTION(); + } + } +} diff --git a/src/cascadia/TerminalApp/DesktopNotification.h b/src/cascadia/TerminalApp/DesktopNotification.h new file mode 100644 index 0000000000..a3bab6dddd --- /dev/null +++ b/src/cascadia/TerminalApp/DesktopNotification.h @@ -0,0 +1,37 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- DesktopNotification.h + +Module Description: +- Helper for sending Windows desktop toast notifications. Used to surface + terminal activity events to the user via the Windows notification center. +--*/ + +#pragma once +#include "pch.h" + +namespace winrt::TerminalApp::implementation +{ + struct DesktopNotificationArgs + { + winrt::hstring Title; + winrt::hstring Message; + winrt::hstring Tag; + }; + + class DesktopNotification + { + public: + static bool ShouldSendNotification(); + static void SendNotification(const DesktopNotificationArgs& args, std::function activatedFunc); + + private: + static std::atomic _lastNotificationTime; + + // Minimum interval between notifications, in milliseconds (GetTickCount64 units). + static constexpr uint64_t MinNotificationIntervalMs = 5'000; + }; +} diff --git a/src/cascadia/TerminalApp/IPaneContent.idl b/src/cascadia/TerminalApp/IPaneContent.idl index f4c6ce1395..8128776247 100644 --- a/src/cascadia/TerminalApp/IPaneContent.idl +++ b/src/cascadia/TerminalApp/IPaneContent.idl @@ -16,6 +16,12 @@ namespace TerminalApp Boolean FlashTaskbar { get; }; }; + runtimeclass NotificationEventArgs + { + String Title { get; }; + String Body { get; }; + }; + interface IPaneContent { Windows.UI.Xaml.FrameworkElement GetRoot(); @@ -46,6 +52,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler TaskbarProgressChanged; event Windows.Foundation.TypedEventHandler ReadOnlyChanged; event Windows.Foundation.TypedEventHandler FocusRequested; + event Windows.Foundation.TypedEventHandler NotificationRequested; }; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 9de52e45c3..3e0a711711 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -745,6 +745,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + Activity in tab "{0}" + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Activity in tab "{0}" (window "{1}") + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Open a new tab in given starting directory diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 3d3db9a425..236ab16382 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -1166,6 +1166,18 @@ namespace winrt::TerminalApp::implementation events.RestartTerminalRequested = terminal.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &Tab::_bubbleRestartTerminalRequested }); } + events.NotificationRequested = content.NotificationRequested( + winrt::auto_revoke, + [dispatcher, weakThis](TerminalApp::IPaneContent sender, auto notifArgs) -> safe_void_coroutine { + const auto weakThisCopy = weakThis; + co_await wil::resume_foreground(dispatcher); + if (const auto tab{ weakThisCopy.get() }) + { + const auto title = notifArgs.Title().empty() ? tab->Title() : notifArgs.Title(); + tab->TabToastNotificationRequested.raise(title, notifArgs.Body(), sender); + } + }); + if (_tabStatus.IsInputBroadcastActive()) { if (const auto& termContent{ content.try_as() }) diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h index 70dec43426..1a9d43dd7b 100644 --- a/src/cascadia/TerminalApp/Tab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -121,6 +121,7 @@ namespace winrt::TerminalApp::implementation til::typed_event ActivePaneChanged; til::event> TabRaiseVisualBell; + til::event> TabToastNotificationRequested; til::typed_event TaskbarProgressChanged; // The TabViewIndex is the index this Tab object resides in TerminalPage's _tabs vector. @@ -185,6 +186,7 @@ namespace winrt::TerminalApp::implementation winrt::TerminalApp::IPaneContent::ConnectionStateChanged_revoker ConnectionStateChanged; winrt::TerminalApp::IPaneContent::ReadOnlyChanged_revoker ReadOnlyChanged; winrt::TerminalApp::IPaneContent::FocusRequested_revoker FocusRequested; + winrt::TerminalApp::IPaneContent::NotificationRequested_revoker NotificationRequested; // These events literally only apply if the content is a TermControl. winrt::Microsoft::Terminal::Control::TermControl::KeySent_revoker KeySent; diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index 21e31fb6dd..9c2621f712 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -17,6 +17,7 @@ #include "TabRowControl.h" #include "DebugTapConnection.h" +#include "DesktopNotification.h" #include "..\TerminalSettingsModel\FileUtils.h" #include "../TerminalSettingsAppAdapterLib/TerminalSettings.h" @@ -150,6 +151,18 @@ namespace winrt::TerminalApp::implementation } }); + // When a tab requests a desktop toast notification, send the toast + // and handle activation by summoning this window and switching to the tab. + newTabImpl->TabToastNotificationRequested([weakThis{ get_weak() }, weakTab{ newTabImpl->get_weak() }](const winrt::hstring& title, const winrt::hstring& body, const winrt::TerminalApp::IPaneContent& content) { + if (const auto page{ weakThis.get() }) + { + if (const auto tab{ weakTab.get() }) + { + page->_SendDesktopNotification(title, body, tab, content); + } + } + }); + auto tabViewItem = newTabImpl->TabViewItem(); _tabView.TabItems().InsertAt(insertPosition, tabViewItem); @@ -1185,4 +1198,128 @@ namespace winrt::TerminalApp::implementation { return _tabs.Size() > 1; } + + // Method Description: + // - Attempts to find and focus the given tab in this window. + // Arguments: + // - tab: The tab to focus. + // Return Value: + // - true if the tab was found and focused, false otherwise. + bool TerminalPage::FocusTab(const winrt::TerminalApp::Tab& tab) + { + if (const auto tabIndex{ _GetTabIndex(tab) }) + { + _SelectTab(tabIndex.value()); + return true; + } + return false; + } + + // Method Description: + // - Sends a desktop toast notification with the given title and body. + // When the toast is activated (clicked), the window is summoned and + // the originating tab is focused. + // Arguments: + // - tabTitle: The title to display in the notification. + // - body: The body text. If empty, a standard tab-activity message is built. + // - tab: The tab to switch to when the toast is activated. + void TerminalPage::_SendDesktopNotification(const winrt::hstring& tabTitle, const winrt::hstring& body, const winrt::com_ptr& tab, const winrt::TerminalApp::IPaneContent& content) + { + // Don't send a notification if the window is focused and the requesting + // pane is the active pane. The user is already looking at it. + if (_activated && tab == _GetFocusedTabImpl()) + { + if (const auto activePane{ tab->GetActivePane() }) + { + if (activePane->GetContent() == content) + { + return; + } + } + } + + // Build the notification message. + // If a custom body is provided (e.g. from OSC 777), use the title/body directly. + // Otherwise, build the standard tab-activity notification message. + winrt::hstring notificationTitle; + winrt::hstring message; + if (!body.empty()) + { + notificationTitle = tabTitle; + message = body; + } + else + { + // Use the window name if available for context; otherwise just use the tab title. + // Use the raw WindowName (not WindowNameForDisplay) so we don't include + // the "" placeholder in the notification body. + const auto windowName = _WindowProperties ? _WindowProperties.WindowName() : winrt::hstring{}; + if (!windowName.empty()) + { + message = RS_fmt(L"NotificationMessage_TabActivityInWindow", std::wstring_view{ tabTitle }, std::wstring_view{ windowName }); + } + else + { + message = RS_fmt(L"NotificationMessage_TabActivity", std::wstring_view{ tabTitle }); + } + notificationTitle = CascadiaSettings::ApplicationDisplayName(); + } + + // Use the Tab object's identity hash as a stable toast tag. + // This survives tab reordering and cross-window moves. + const auto tabHash = std::hash{}(*tab); + const hstring tabTag{ fmt::format(FMT_COMPILE(L"wt-tab-{:016x}"), tabHash) }; + + const implementation::DesktopNotificationArgs args{ + .Title = notificationTitle, + .Message = message, + .Tag = tabTag + }; + + implementation::DesktopNotification::SendNotification(args, [weakThis{ get_weak() }, weakTab{ tab->get_weak() }, weakContent{ winrt::make_weak(content) }]() { + if (const auto page{ weakThis.get() }) + { + // The toast Activated callback runs on a background thread. + // Marshal to the UI thread for tab focus and window summon. + page->Dispatcher().RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [weakPage{ page->get_weak() }, weakTab, weakContent]() { + if (const auto p{ weakPage.get() }) + { + if (const auto t{ weakTab.get() }) + { + // Try to find and focus the tab in this window first. + if (const auto tabIndex{ p->_GetTabIndex(*t) }) + { + p->SummonWindowRequested.raise(nullptr, nullptr); + p->_SelectTab(tabIndex.value()); + + // Focus the specific pane that raised the notification. + if (const auto paneContent{ weakContent.get() }) + { + const auto rootPane = t->GetRootPane(); + rootPane->WalkTree([&](const auto& pane) { + if (pane->GetContent() == paneContent) + { + rootPane->FocusPane(pane); + } + }); + } + } + else + { + // The tab may have moved to another window. + // Raise FocusTabRequested so the emperor can + // search all windows for it. + p->FocusTabRequested.raise(nullptr, *t); + } + } + else + { + // Tab was closed. Just summon this window. + p->SummonWindowRequested.raise(nullptr, nullptr); + } + } + }); + } + }); + } } diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj index fe141dfa64..371dbd1746 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj @@ -174,6 +174,7 @@ TerminalPaneContent.idl + SuggestionsControl.xaml @@ -287,6 +288,7 @@ + SuggestionsControl.xaml diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index b1d26ee69d..29f0cd23e1 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -168,6 +168,7 @@ namespace winrt::TerminalApp::implementation void OpenSettingsUI(); void WindowActivated(const bool activated); + bool FocusTab(const winrt::TerminalApp::Tab& tab); bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down); @@ -192,6 +193,7 @@ namespace winrt::TerminalApp::implementation til::typed_event IdentifyWindowsRequested; til::typed_event RenameWindowRequested; til::typed_event SummonWindowRequested; + til::typed_event FocusTabRequested; til::typed_event WindowSizeChanged; til::typed_event OpenSystemMenu; @@ -571,6 +573,8 @@ namespace winrt::TerminalApp::implementation void _activePaneChanged(winrt::TerminalApp::Tab tab, Windows::Foundation::IInspectable args); safe_void_coroutine _doHandleSuggestions(Microsoft::Terminal::Settings::Model::SuggestionsArgs realArgs); + void _SendDesktopNotification(const winrt::hstring& tabTitle, const winrt::hstring& body, const winrt::com_ptr& tab, const winrt::TerminalApp::IPaneContent& content); + #pragma region ActionHandlers // These are all defined in AppActionHandlers.cpp #define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action); diff --git a/src/cascadia/TerminalApp/TerminalPaneContent.h b/src/cascadia/TerminalApp/TerminalPaneContent.h index 0e828cdc1b..b2f38ba249 100644 --- a/src/cascadia/TerminalApp/TerminalPaneContent.h +++ b/src/cascadia/TerminalApp/TerminalPaneContent.h @@ -4,6 +4,7 @@ #pragma once #include "TerminalPaneContent.g.h" #include "BellEventArgs.g.h" +#include "NotificationEventArgs.g.h" #include "BasicPaneEvents.h" namespace winrt::TerminalApp::implementation @@ -19,6 +20,16 @@ namespace winrt::TerminalApp::implementation til::property FlashTaskbar; }; + struct NotificationEventArgs : public NotificationEventArgsT + { + public: + NotificationEventArgs(const winrt::hstring& title = {}, const winrt::hstring& body = {}) : + Title(title), Body(body) {} + + til::property Title; + til::property Body; + }; + struct TerminalPaneContent : TerminalPaneContentT, BasicPaneEvents { TerminalPaneContent(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile, diff --git a/src/cascadia/TerminalApp/TerminalWindow.cpp b/src/cascadia/TerminalApp/TerminalWindow.cpp index b2fa349e40..0fafac603c 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.cpp +++ b/src/cascadia/TerminalApp/TerminalWindow.cpp @@ -1205,6 +1205,15 @@ namespace winrt::TerminalApp::implementation } } + bool TerminalWindow::FocusTab(const winrt::TerminalApp::Tab& tab) + { + if (_root) + { + return _root->FocusTab(tab); + } + return false; + } + void TerminalWindow::WindowName(const winrt::hstring& name) { const auto oldIsQuakeMode = _WindowProperties->IsQuakeWindow(); diff --git a/src/cascadia/TerminalApp/TerminalWindow.h b/src/cascadia/TerminalApp/TerminalWindow.h index 2f1aad5a7a..08ddeabafc 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.h +++ b/src/cascadia/TerminalApp/TerminalWindow.h @@ -92,6 +92,7 @@ namespace winrt::TerminalApp::implementation bool ShowTabsFullscreen() const; bool AutoHideWindow(); void IdentifyWindow(); + bool FocusTab(const winrt::TerminalApp::Tab& tab); std::optional LoadPersistedLayoutIdx() const; winrt::Microsoft::Terminal::Settings::Model::WindowLayout LoadPersistedLayout(); @@ -221,6 +222,7 @@ namespace winrt::TerminalApp::implementation FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress); FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested); FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested); + FORWARDED_TYPED_EVENT(FocusTabRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::Tab, _root, FocusTabRequested); FORWARDED_TYPED_EVENT(OpenSystemMenu, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, OpenSystemMenu); FORWARDED_TYPED_EVENT(QuitRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, QuitRequested); FORWARDED_TYPED_EVENT(ShowWindowChanged, Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Control::ShowWindowArgs, _root, ShowWindowChanged); diff --git a/src/cascadia/TerminalApp/TerminalWindow.idl b/src/cascadia/TerminalApp/TerminalWindow.idl index b900522cbf..c12f73e137 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.idl +++ b/src/cascadia/TerminalApp/TerminalWindow.idl @@ -4,6 +4,7 @@ import "IPaneContent.idl"; import "TerminalPage.idl"; import "ShortcutActionDispatch.idl"; +import "Tab.idl"; namespace TerminalApp { @@ -74,6 +75,7 @@ namespace TerminalApp Boolean ShowTabsFullscreen { get; }; void IdentifyWindow(); + Boolean FocusTab(TerminalApp.Tab tab); void SetPersistedLayoutIdx(UInt32 idx); void RequestExitFullscreen(); @@ -126,6 +128,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler IdentifyWindowsRequested; event Windows.Foundation.TypedEventHandler IsQuakeWindowChanged; event Windows.Foundation.TypedEventHandler SummonWindowRequested; + event Windows.Foundation.TypedEventHandler FocusTabRequested; event Windows.Foundation.TypedEventHandler OpenSystemMenu; event Windows.Foundation.TypedEventHandler QuitRequested; event Windows.Foundation.TypedEventHandler SystemMenuChangeRequested; diff --git a/src/cascadia/TerminalApp/pch.h b/src/cascadia/TerminalApp/pch.h index ee36db25e3..ba0dcfda26 100644 --- a/src/cascadia/TerminalApp/pch.h +++ b/src/cascadia/TerminalApp/pch.h @@ -54,6 +54,9 @@ #include #include +#include +#include + #include #include #include diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 522e90c7d2..0fa2f61ae4 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -265,6 +265,7 @@ void AppHost::Initialize() _revokers.IsQuakeWindowChanged = _windowLogic.IsQuakeWindowChanged(winrt::auto_revoke, { this, &AppHost::_IsQuakeWindowChanged }); _revokers.SummonWindowRequested = _windowLogic.SummonWindowRequested(winrt::auto_revoke, { this, &AppHost::_SummonWindowRequested }); + _revokers.FocusTabRequested = _windowLogic.FocusTabRequested(winrt::auto_revoke, { this, &AppHost::_FocusTabRequested }); _revokers.OpenSystemMenu = _windowLogic.OpenSystemMenu(winrt::auto_revoke, { this, &AppHost::_OpenSystemMenu }); _revokers.QuitRequested = _windowLogic.QuitRequested(winrt::auto_revoke, { this, &AppHost::_RequestQuitAll }); _revokers.ShowWindowChanged = _windowLogic.ShowWindowChanged(winrt::auto_revoke, { this, &AppHost::_ShowWindowChanged }); @@ -1064,6 +1065,14 @@ void AppHost::_SummonWindowRequested(const winrt::Windows::Foundation::IInspecta HandleSummon(std::move(summonArgs)); } +void AppHost::_FocusTabRequested(const winrt::Windows::Foundation::IInspectable&, + const winrt::TerminalApp::Tab& tab) +{ + // The tab may have moved to another window. Ask the emperor to + // search all windows and focus the tab wherever it currently lives. + _windowManager->FocusTabInAnyWindow(tab); +} + void AppHost::_OpenSystemMenu(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&) { diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 379f876b94..ffc16d916b 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -91,6 +91,9 @@ private: void _SummonWindowRequested(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args); + void _FocusTabRequested(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::TerminalApp::Tab& tab); + void _OpenSystemMenu(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args); @@ -151,6 +154,7 @@ private: winrt::TerminalApp::TerminalWindow::IdentifyWindowsRequested_revoker IdentifyWindowsRequested; winrt::TerminalApp::TerminalWindow::IsQuakeWindowChanged_revoker IsQuakeWindowChanged; winrt::TerminalApp::TerminalWindow::SummonWindowRequested_revoker SummonWindowRequested; + winrt::TerminalApp::TerminalWindow::FocusTabRequested_revoker FocusTabRequested; winrt::TerminalApp::TerminalWindow::OpenSystemMenu_revoker OpenSystemMenu; winrt::TerminalApp::TerminalWindow::QuitRequested_revoker QuitRequested; winrt::TerminalApp::TerminalWindow::ShowWindowChanged_revoker ShowWindowChanged; diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp index 55244118c9..917f492be9 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp +++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp @@ -775,6 +775,25 @@ bool WindowEmperor::_summonWindow(const SummonWindowSelectionArgs& args) const return true; } +void WindowEmperor::FocusTabInAnyWindow(const winrt::TerminalApp::Tab& tab) const +{ + _assertIsMainThread(); + + for (const auto& w : _windows) + { + if (w->Logic().FocusTab(tab)) + { + winrt::TerminalApp::SummonWindowBehavior summonArgs; + summonArgs.MoveToCurrentDesktop(false); + summonArgs.DropdownDuration(0); + summonArgs.ToMonitor(winrt::TerminalApp::MonitorBehavior::InPlace); + summonArgs.ToggleVisibility(false); + w->HandleSummon(std::move(summonArgs)); + return; + } + } +} + void WindowEmperor::_summonAllWindows() const { _assertIsMainThread(); @@ -1033,7 +1052,14 @@ LRESULT WindowEmperor::_messageHandler(HWND window, UINT const message, WPARAM c { const auto handoff = deserializeHandoffPayload(static_cast(cds->lpData), static_cast(cds->lpData) + cds->cbData); const auto argv = commandlineToArgArray(handoff.args.c_str()); - _dispatchCommandlineCommon(argv, handoff.cwd, handoff.env, handoff.show); + // When a toast notification is clicked, Windows launches a new + // wt.exe with "--from-toast". That instance hands off here via + // WM_COPYDATA. We already handle activation in-process via the + // toast's Activated event, so just ignore this handoff. + if (argv.size() != 2 || argv[1] != L"--from-toast") + { + _dispatchCommandlineCommon(argv, handoff.cwd, handoff.env, handoff.show); + } } return 0; case WM_HOTKEY: diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.h b/src/cascadia/WindowsTerminal/WindowEmperor.h index 5e2801276c..42c84c38c9 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.h +++ b/src/cascadia/WindowsTerminal/WindowEmperor.h @@ -35,6 +35,7 @@ public: AppHost* GetWindowByName(std::wstring_view name) const noexcept; void CreateNewWindow(winrt::TerminalApp::WindowRequestedArgs args); void HandleCommandlineArgs(int nCmdShow); + void FocusTabInAnyWindow(const winrt::TerminalApp::Tab& tab) const; private: struct SummonWindowSelectionArgs From 059986ebce4900a7f8e46802aed903f3a0526579 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Fri, 1 May 2026 14:56:19 -0700 Subject: [PATCH 10/18] [Unpackaged] Fix taskbar glomming due to AUMID (#20064) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bug was caused by an AUMID mismatch between the Taskbar's .lnk file and Windows Terminal. Since no AUMID was associated with the .exe, the OS automatically creates one for us. However, #20018 added an AUMID for unpackaged scenarios, so now there was a mismatch, resulting in a new taskbar entry being created. To fix this, we check if a .lnk points to our .exe in the taskbar. There's 3 cases here: 1. no .lnk of interest exists --> set the AUMID normally 2. the .lnk carries our AUMID --> set the AUMID normally 3. the .lnk doesn't have an AUMID (aka uses the auto-resolved one) --> - for this launch: don't set the AUMID so that we both use the auto-resolved one - on next launch: set the AUMID on the .lnk and process so that they all agree ## Validation Steps Performed In unpackaged folder, move WindowsTerminal.exe to the taskbar (creates .lnk)... ✅ Double-click the .exe --> Same taskbar entry is used ✅ Double-click the .exe _again_ --> second window goes to same taskbar entry The first window doesn't have to close for this to work. It just * works *! Bug introduced in #20018 Closes #20053 --- .../WindowsTerminal/WindowEmperor.cpp | 128 +++++++++++++++++- src/cascadia/WindowsTerminal/WindowEmperor.h | 3 + 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp index 917f492be9..82d3c82620 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp +++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "AppHost.h" #include "resource.h" @@ -313,6 +315,107 @@ AppHost* WindowEmperor::_mostRecentWindow() const noexcept return mostRecent; } +// GH#20053: The shell resolves taskbar grouping identity as: per-window AUMID > +// per-process AUMID > auto-derived from exe path. Before we started setting a +// process AUMID, both the pinned .lnk and the process used auto-derived +// identity, so they matched. Now that we set an explicit AUMID, a pinned .lnk +// that predates the AUMID change has no AUMID and still uses auto-derived +// identity, causing a mismatch and a duplicate taskbar button. +// +// To fix this, we check if a pinned taskbar shortcut (.lnk) points to our exe. +// If it already carries our AUMID (or no pin exists), we set the process AUMID +// normally. If a pin exists WITHOUT our AUMID, we skip setting the process +// AUMID for THIS launch (both sides use auto-derived identity, so they match) +// and defer stamping the shortcut to process exit. On the next launch, the pin +// has our AUMID, so we set the process AUMID to match, and both agree. +// +// NOTE: On the first launch after pinning, the process AUMID is not set. If +// toast notifications are needed in the future, use +// ToastNotificationManager::CreateToastNotifier(aumid) with the AUMID string +// directly. That API does not depend on SetCurrentProcessExplicitAppUserModelID. +// A Start Menu shortcut with the AUMID (separate from the taskbar pin) is also +// required for toast routing; see +// https://learn.microsoft.com/windows/apps/develop/notifications/app-notifications/send-local-toast-other-apps +void WindowEmperor::_setupAumid(const std::wstring& aumid) +{ + const auto ourExePath = wil::GetModuleFileNameW(nullptr); + + bool needsDeferredStamping = false; + std::wstring pinnedLnkPath; + + const auto taskbarGlob = wil::ExpandEnvironmentStringsW( + LR"(%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\*.lnk)"); + + WIN32_FIND_DATAW findData{}; + const wil::unique_hfind findHandle{ FindFirstFileExW(taskbarGlob.c_str(), FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH) }; + if (findHandle) + { + const auto lastSlash = taskbarGlob.rfind(L'\\'); + const auto taskbarDir = taskbarGlob.substr(0, lastSlash + 1); + + do + { + const auto lnkPath = taskbarDir + findData.cFileName; + + wil::com_ptr shellLink; + if (FAILED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)))) + { + continue; + } + + const auto persistFile = shellLink.try_query(); + if (!persistFile || FAILED(persistFile->Load(lnkPath.c_str(), STGM_READ))) + { + continue; + } + + wchar_t targetPath[MAX_PATH]{}; + if (FAILED(shellLink->GetPath(targetPath, MAX_PATH, nullptr, SLGP_RAWPATH))) + { + continue; + } + + if (til::compare_ordinal_insensitive(targetPath, ourExePath) != 0) + { + continue; + } + + // Found a pin pointing to us. Assume it needs stamping unless + // we confirm it already has our AUMID. + pinnedLnkPath = lnkPath; + needsDeferredStamping = true; + + if (const auto propertyStore = shellLink.try_query()) + { + wil::unique_prop_variant pv; + if (SUCCEEDED(propertyStore->GetValue(PKEY_AppUserModel_ID, &pv)) && + pv.vt == VT_LPWSTR && pv.pwszVal && + aumid == pv.pwszVal) + { + needsDeferredStamping = false; + } + } + + break; + } while (FindNextFileW(findHandle.get(), &findData)); + } + + if (needsDeferredStamping) + { + // The pin exists but doesn't have our AUMID yet. Don't set the process + // AUMID or stamp the shortcut now. Writing the shortcut causes the + // shell to re-read it immediately, changing the pin's cached identity + // mid-launch and creating a mismatch in the opposite direction. Instead, + // stamp it at shutdown when the taskbar association no longer matters. + _pendingAumidLnkPath = std::move(pinnedLnkPath); + _pendingAumid = aumid; + } + else + { + LOG_IF_FAILED(SetCurrentProcessExplicitAppUserModelID(aumid.c_str())); + } +} + void WindowEmperor::HandleCommandlineArgs(int nCmdShow) { // When running without package identity, set an explicit AppUserModelID so @@ -373,7 +476,7 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow) #else fmt::format_to(std::back_inserter(unpackagedAumid), FMT_COMPILE(L".{:08x}"), hash); #endif - LOG_IF_FAILED(SetCurrentProcessExplicitAppUserModelID(unpackagedAumid.c_str())); + _setupAumid(unpackagedAumid); } } @@ -553,6 +656,29 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow) Shell_NotifyIconW(NIM_DELETE, &_notificationIcon); } + // GH#20053: Deferred shortcut stamping. See _setupAumid() for context. + if (!_pendingAumidLnkPath.empty()) + { + wil::com_ptr shellLink; + if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)))) + { + if (const auto persistFile = shellLink.try_query(); + persistFile && SUCCEEDED(persistFile->Load(_pendingAumidLnkPath.c_str(), STGM_READWRITE))) + { + if (const auto propertyStore = shellLink.try_query()) + { + wil::unique_prop_variant pv; + if (SUCCEEDED(InitPropVariantFromString(_pendingAumid.c_str(), &pv)) && + SUCCEEDED(propertyStore->SetValue(PKEY_AppUserModel_ID, pv)) && + SUCCEEDED(propertyStore->Commit())) + { + persistFile->Save(_pendingAumidLnkPath.c_str(), TRUE); + } + } + } + } + } + // There's a mysterious crash in XAML on Windows 10 if you just let _app get destroyed (GH#15410). // We also need to ensure that all UI threads exit before WindowEmperor leaves the scope on the main thread (MSFT:46744208). // Both problems can be solved and the shutdown accelerated by using TerminateProcess. diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.h b/src/cascadia/WindowsTerminal/WindowEmperor.h index 42c84c38c9..80d87023d7 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.h +++ b/src/cascadia/WindowsTerminal/WindowEmperor.h @@ -69,6 +69,7 @@ private: void _persistState(const winrt::Microsoft::Terminal::Settings::Model::ApplicationState& state) const; void _finalizeSessionPersistence() const; void _checkWindowsForNotificationIcon(); + void _setupAumid(const std::wstring& aumid); wil::unique_hwnd _window; winrt::TerminalApp::App _app{ nullptr }; @@ -84,6 +85,8 @@ private: std::optional _currentSystemThemeIsDark; int32_t _windowCount = 0; int32_t _messageBoxCount = 0; + std::wstring _pendingAumidLnkPath; + std::wstring _pendingAumid; #if 0 // #ifdef NDEBUG static constexpr void _assertIsMainThread() noexcept From a834313fb7899456cddfbfdc453f06b3d0dc9925 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Mon, 4 May 2026 10:38:17 -0700 Subject: [PATCH 11/18] Add a setting for sending a notification on BEL (#20011) ## Summary of the Pull Request Targets #20010 Adds another `bellStyle` flag option. This sends a windows toast notification to the user when a BEL is encountered - [X] Closes #18605 - [ ] Documentation updated Heavily based on #19936 Co-authored by @zadjii-msft --- doc/cascadia/profiles.schema.json | 4 +++- src/cascadia/TerminalApp/IPaneContent.idl | 1 + src/cascadia/TerminalApp/Tab.cpp | 8 ++++++++ src/cascadia/TerminalApp/TerminalPaneContent.cpp | 6 ++++-- src/cascadia/TerminalApp/TerminalPaneContent.h | 5 +++-- .../TerminalSettingsEditor/ProfileViewModel.cpp | 15 +++++++++++++-- .../TerminalSettingsEditor/ProfileViewModel.h | 1 + .../TerminalSettingsEditor/ProfileViewModel.idl | 1 + .../TerminalSettingsEditor/Profiles_Advanced.xaml | 2 ++ .../Resources/en-US/Resources.resw | 4 ++++ src/cascadia/TerminalSettingsModel/Profile.idl | 1 + .../TerminalSettingsSerializationHelpers.h | 3 ++- 12 files changed, 43 insertions(+), 8 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 11eb698965..e51c358bdf 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -60,7 +60,8 @@ "enum": [ "audible", "window", - "taskbar" + "taskbar", + "notification" ] } }, @@ -70,6 +71,7 @@ "audible", "taskbar", "window", + "notification", "all", "none" ] diff --git a/src/cascadia/TerminalApp/IPaneContent.idl b/src/cascadia/TerminalApp/IPaneContent.idl index 8128776247..2f5da33efe 100644 --- a/src/cascadia/TerminalApp/IPaneContent.idl +++ b/src/cascadia/TerminalApp/IPaneContent.idl @@ -14,6 +14,7 @@ namespace TerminalApp runtimeclass BellEventArgs { Boolean FlashTaskbar { get; }; + Boolean SendNotification { get; }; }; runtimeclass NotificationEventArgs diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 236ab16382..ed58f8e460 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -1148,6 +1148,14 @@ namespace winrt::TerminalApp::implementation tab->TabRaiseVisualBell.raise(); } + // Send a desktop toast notification if requested, but only if + // the pane isn't already in the belled state. This prevents + // sending repeated toasts for repeated BEL characters. + if (bellArgs.SendNotification() && !tab->_tabStatus.BellIndicator()) + { + tab->TabToastNotificationRequested.raise(tab->Title(), L"", sender); + } + // Show the bell indicator in the tab header tab->ShowBellIndicator(true); diff --git a/src/cascadia/TerminalApp/TerminalPaneContent.cpp b/src/cascadia/TerminalApp/TerminalPaneContent.cpp index 3a2c487db9..a14e0c326f 100644 --- a/src/cascadia/TerminalApp/TerminalPaneContent.cpp +++ b/src/cascadia/TerminalApp/TerminalPaneContent.cpp @@ -291,9 +291,11 @@ namespace winrt::TerminalApp::implementation _control.BellLightOn(); } - // raise the event with the bool value corresponding to the taskbar flag + // raise the event with the bool values corresponding to the taskbar and notification flags BellRequested.raise(*this, - *winrt::make_self(WI_IsFlagSet(_profile.BellStyle(), BellStyle::Taskbar))); + *winrt::make_self( + WI_IsFlagSet(_profile.BellStyle(), BellStyle::Taskbar), + WI_IsFlagSet(_profile.BellStyle(), BellStyle::Notification))); } } } diff --git a/src/cascadia/TerminalApp/TerminalPaneContent.h b/src/cascadia/TerminalApp/TerminalPaneContent.h index b2f38ba249..0388aae935 100644 --- a/src/cascadia/TerminalApp/TerminalPaneContent.h +++ b/src/cascadia/TerminalApp/TerminalPaneContent.h @@ -14,10 +14,11 @@ namespace winrt::TerminalApp::implementation struct BellEventArgs : public BellEventArgsT { public: - BellEventArgs(bool flashTaskbar) : - FlashTaskbar(flashTaskbar) {} + BellEventArgs(bool flashTaskbar, bool sendNotification) : + FlashTaskbar(flashTaskbar), SendNotification(sendNotification) {} til::property FlashTaskbar; + til::property SendNotification; }; struct NotificationEventArgs : public NotificationEventArgsT diff --git a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp index 661d077b7e..d7e1df4a83 100644 --- a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp +++ b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp @@ -574,7 +574,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation hstring ProfileViewModel::BellStylePreview() const { const auto bellStyle = BellStyle(); - if (WI_AreAllFlagsSet(bellStyle, BellStyle::Audible | BellStyle::Window | BellStyle::Taskbar)) + if (WI_AreAllFlagsSet(bellStyle, BellStyle::Audible | BellStyle::Window | BellStyle::Taskbar | BellStyle::Notification)) { return RS_(L"Profile_BellStyleAll/Content"); } @@ -584,7 +584,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } std::vector resultList; - resultList.reserve(3); + resultList.reserve(4); if (WI_IsFlagSet(bellStyle, BellStyle::Audible)) { resultList.emplace_back(RS_(L"Profile_BellStyleAudible/Content")); @@ -597,6 +597,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { resultList.emplace_back(RS_(L"Profile_BellStyleTaskbar/Content")); } + if (WI_IsFlagSet(bellStyle, BellStyle::Notification)) + { + resultList.emplace_back(RS_(L"Profile_BellStyleNotification/Content")); + } // add in the commas hstring result{}; @@ -640,6 +644,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation BellStyle(currentStyle); } + void ProfileViewModel::SetBellStyleNotification(winrt::Windows::Foundation::IReference on) + { + auto currentStyle = BellStyle(); + WI_UpdateFlag(currentStyle, Model::BellStyle::Notification, winrt::unbox_value(on)); + BellStyle(currentStyle); + } + // Method Description: // - Construct _CurrentBellSounds by importing the _inherited_ value from the model // - Adds a PropertyChanged handler to each BellSoundViewModel to propagate changes to the model diff --git a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h index 1112a2f8ef..fa403952e5 100644 --- a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h +++ b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h @@ -46,6 +46,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation void SetBellStyleAudible(winrt::Windows::Foundation::IReference on); void SetBellStyleWindow(winrt::Windows::Foundation::IReference on); void SetBellStyleTaskbar(winrt::Windows::Foundation::IReference on); + void SetBellStyleNotification(winrt::Windows::Foundation::IReference on); hstring BellSoundPreview(); void RequestAddBellSound(hstring path); diff --git a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl index 8b1aeba792..c2d99246d0 100644 --- a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl +++ b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl @@ -49,6 +49,7 @@ namespace Microsoft.Terminal.Settings.Editor void SetBellStyleAudible(Windows.Foundation.IReference on); void SetBellStyleWindow(Windows.Foundation.IReference on); void SetBellStyleTaskbar(Windows.Foundation.IReference on); + void SetBellStyleNotification(Windows.Foundation.IReference on); String BellSoundPreview { get; }; Windows.Foundation.Collections.IObservableVector CurrentBellSounds { get; }; diff --git a/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml b/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml index 941f410e97..b00c1753bb 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml +++ b/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml @@ -111,6 +111,8 @@ IsChecked="{x:Bind Profile.IsBellStyleFlagSet(2), BindBack=Profile.SetBellStyleWindow, Mode=TwoWay}" /> + diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index 9eb703a6e2..74967fc61d 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -1553,6 +1553,10 @@ Flash window An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Desktop notification + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Add new Button label that creates a new color scheme. diff --git a/src/cascadia/TerminalSettingsModel/Profile.idl b/src/cascadia/TerminalSettingsModel/Profile.idl index 96bc79ad19..874b37235a 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.idl +++ b/src/cascadia/TerminalSettingsModel/Profile.idl @@ -29,6 +29,7 @@ namespace Microsoft.Terminal.Settings.Model Audible = 0x1, Window = 0x2, Taskbar = 0x4, + Notification = 0x8, All = 0xffffffff }; diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index 9c071945a2..d5bfaf6f07 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -90,12 +90,13 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::MatchMode) JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::BellStyle) { - static constexpr std::array mappings = { + static constexpr std::array mappings = { pair_type{ "none", AllClear }, pair_type{ "audible", ValueType::Audible }, pair_type{ "visual", ValueType::Window | ValueType::Taskbar }, pair_type{ "window", ValueType::Window }, pair_type{ "taskbar", ValueType::Taskbar }, + pair_type{ "notification", ValueType::Notification }, pair_type{ "all", AllSet }, }; From b753e3dee3b28d4f3cd7d882b5d289c35e2e2f6c Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Mon, 4 May 2026 10:43:34 -0700 Subject: [PATCH 12/18] Replace `confirmCloseAllTabs` with `confirmOnClose` (#20055) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Replaces the `warning.confirmCloseAllTabs` setting with a `warning.confirmOnClose` enum setting that accepts the following: - `never`: don't present a warning dialog when closing a session - `automatic`: present a warning dialog when closing multiple tabs/panes at once - `always`: present a warning dialog when closing any session The confirmation dialog contains a "don't ask me again" checkbox. When checked, we update the setting to `never`. This setting also affects the following actions: - "close other tabs" - "close tabs after" - "close other panes" - "quit" The appropriate confirmation dialog is shown in these scenarios. We also present an aggregate dialog instead of prompting the user once per tab/pane. If there are no other tabs/panes, we don't present a dialog and treat the key binding as unhandled (passing the key through). ## References and Relevant Issues Iteration of #19944 ## Validation Steps Performed - closing a tab: - ✅ 1 pane --> no dialog - ✅ 2 panes --> dialog - ✅ action and middle clicking tab trigger same flow - close all other tabs: - ✅ no other tabs --> no dialog - ✅ 1 other tab --> dialog - close all other panes: - ✅ 1 pane --> no dialog - ✅ 2 panes --> dialog - close all tabs after the current tab: - ✅ no tabs after --> no dialog (even if tabs before) - ✅ 1 tab after --> dialog - close window: - ✅ 2 tabs --> dialog - ✅ 2 panes --> dialog - ✅ 1 tab with one pane --> no dialog - Quit the Terminal: - ✅ 3 windows --> dialog - ✅1 window --> dialog - ✅ "don't ask me again" checkbox checked --> setting changed to "never" - ✅ "never" --> no dialog for scenarios above - ✅ "always" --> dialog always appears, even when closing a single pane ## PR Checklist Closes #5301 Closes #6641 "don't ask me again" checkbox is also mentioned in #10000 Co-authored by @zadjii-msft --- doc/cascadia/profiles.schema.json | 13 +- .../TerminalApp/AppActionHandlers.cpp | 4 +- .../Resources/en-US/Resources.resw | 44 +++-- src/cascadia/TerminalApp/TabManagement.cpp | 97 ++++++++++- src/cascadia/TerminalApp/TerminalPage.cpp | 160 +++++++++++++++--- src/cascadia/TerminalApp/TerminalPage.h | 20 ++- src/cascadia/TerminalApp/TerminalPage.xaml | 13 +- .../TerminalSettingsEditor/Interaction.xaml | 13 +- .../InteractionViewModel.cpp | 1 + .../InteractionViewModel.h | 2 +- .../InteractionViewModel.idl | 8 +- .../Resources/en-US/Resources.resw | 20 +++ .../TerminalSettingsModel/EnumMappings.cpp | 1 + .../TerminalSettingsModel/EnumMappings.h | 1 + .../TerminalSettingsModel/EnumMappings.idl | 1 + .../GlobalAppSettings.cpp | 11 +- .../GlobalAppSettings.idl | 9 +- .../TerminalSettingsModel/MTSMSettings.h | 2 +- .../TerminalSettingsSerializationHelpers.h | 19 +++ .../TerminalSettingsModel/defaults.json | 2 +- .../SerializationTests.cpp | 2 +- 21 files changed, 372 insertions(+), 71 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index e51c358bdf..d8d2a684db 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -2656,10 +2656,21 @@ "type": "string" }, "warning.confirmCloseAllTabs": { + "deprecated": true, + "description": "[Deprecated] Use \"warning.confirmOnClose\" instead.", "default": true, - "description": "When set to \"true\" closing a window with multiple tabs open will require confirmation. When set to \"false\", the confirmation dialog will not appear.", "type": "boolean" }, + "warning.confirmOnClose": { + "default": "automatic", + "description": "Controls when a confirmation dialog appears before closing tabs or windows.", + "enum": [ + "never", + "automatic", + "always" + ], + "type": "string" + }, "useTabSwitcher": { "description": "[Deprecated] Replaced with the \"tabSwitcherMode\" setting.", "default": true, diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 66372a3e9e..bb5d859c85 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -801,7 +801,7 @@ namespace winrt::TerminalApp::implementation _RemoveTabs(tabsToRemove); - actionArgs.Handled(true); + actionArgs.Handled(!tabsToRemove.empty()); } } @@ -837,7 +837,7 @@ namespace winrt::TerminalApp::implementation // tab row, until you mouse over them. Probably has something to do // with tabs not resizing down until there's a mouse exit event. - actionArgs.Handled(true); + actionArgs.Handled(!tabsToRemove.empty()); } } diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 3e0a711711..2fe41f21a0 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -496,24 +496,48 @@ Third-Party notices A hyperlink name for the Terminal's third-party notices - + Cancel - - Close all - - + Do you want to close all windows? - - Cancel - - + Close all - + Do you want to close all tabs? + + Close all + + + Do you want to close this tab? + + + Close tab + + + Do you want to close this pane? + + + Close pane + + + Do you want to close these tabs? + + + Close tabs + + + Do you want to close these panes? + + + Close panes + + + Don't ask me again + Cancel diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index 9c2621f712..74b6c73693 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -407,7 +407,9 @@ namespace winrt::TerminalApp::implementation // - Removes the tab (both TerminalControl and XAML) after prompting for approval // Arguments: // - tab: the tab to remove - winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::Tab tab) + // - skipConfirmClose: if true, skip the confirmOnClose check. Used when + // an aggregate confirmation has already been shown (i.e. close other tabs) + winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::Tab tab, bool skipConfirmClose) { winrt::com_ptr strong; @@ -426,6 +428,24 @@ namespace winrt::TerminalApp::implementation } } + // Skip the per-tab confirmOnClose check when the caller has already + // shown an aggregate confirmation dialog (e.g. _RemoveTabs). + if (!skipConfirmClose) + { + const auto tabImpl = _GetTabImpl(tab); + if (tabImpl && _ShouldWarnOnCloseTab(tabImpl)) + { + const auto weak = get_weak(); + + auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::Tab); + strong = weak.get(); + if (!strong || warningResult != ContentDialogResult::Primary) + { + co_return; + } + } + } + auto t = winrt::get_self(tab); auto actions = t->BuildStartupActions(BuildStartupKind::None); _AddPreviouslyClosedPaneOrTab(std::move(actions)); @@ -795,6 +815,26 @@ namespace winrt::TerminalApp::implementation if (const auto pane{ activeTab->GetActivePane() }) { const auto weak = get_weak(); + + // Check if we should warn before closing a single pane + // (only triggers on Always — Automatic doesn't warn for single pane) + const auto setting = _settings.GlobalSettings().ConfirmOnClose(); + if (setting == ConfirmOnClose::Always) + { + // If this is the last pane, closing it closes the tab, + // so use the tab dialog text instead. + const auto kind = activeTab->GetLeafPaneCount() == 1 ? ConfirmCloseDialogKind::Tab : ConfirmCloseDialogKind::Pane; + auto warningResult = co_await _ShowConfirmCloseDialog(kind); + + // Hold a strong reference to `this` for the rest of the + // method; we may be the last holder after `co_await`. + auto strong = weak.get(); + if (!strong || warningResult != ContentDialogResult::Primary) + { + co_return; + } + } + if (co_await _PaneConfirmCloseReadOnly(pane)) { if (const auto strong = weak.get()) @@ -808,10 +848,37 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Close all panes with the given IDs sequentially. + // - Shows a single aggregate confirmation dialog upfront if the confirmOnClose setting warrants it. // Arguments: - // - weakTab: weak reference to the tab that the pane belongs to. + // - weakTab: weak reference to the tab that the panes belong to. // - paneIds: collection of the IDs of the panes that are marked for removal. - void TerminalPage::_ClosePanes(weak_ref weakTab, std::vector paneIds) + safe_void_coroutine TerminalPage::_ClosePanes(weak_ref weakTab, std::vector paneIds) + { + // Show a single aggregate confirmation for closing multiple panes. + if (_settings.GlobalSettings().ConfirmOnClose() != ConfirmOnClose::Never) + { + const auto weak = get_weak(); + auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::MultiplePanes); + + // Hold a strong reference to `this` after the co_await; we may + // be the last holder if the page was being torn down. + auto strong = weak.get(); + if (!strong || warningResult != ContentDialogResult::Primary) + { + co_return; + } + } + _CloseRemainingPanes(weakTab, std::move(paneIds)); + } + + // Method Description: + // - Recursively closes panes by ID, chaining each close via the + // ClosedByParent callback. Called after confirmation has already + // been handled by _ClosePanes. + // Arguments: + // - weakTab: weak reference to the tab that the panes belong to + // - paneIds: remaining pane IDs to close + void TerminalPage::_CloseRemainingPanes(weak_ref weakTab, std::vector paneIds) { if (auto strongTab{ weakTab.get() }) { @@ -826,10 +893,9 @@ namespace winrt::TerminalApp::implementation pane->ClosedByParent([ids{ std::move(paneIds) }, weakThis{ get_weak() }, weakTab]() { if (auto strongThis{ weakThis.get() }) { - strongThis->_ClosePanes(weakTab, std::move(ids)); + strongThis->_CloseRemainingPanes(weakTab, std::move(ids)); } }); - // Close the pane which will eventually trigger the closed by parent event _HandleClosePaneRequested(pane); break; @@ -854,18 +920,37 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Closes provided tabs one by one + // - Shows a single aggregate confirmation dialog upfront if the confirmOnClose setting warrants it. // Arguments: // - tabs - tabs to remove safe_void_coroutine TerminalPage::_RemoveTabs(const std::vector tabs) { + if (tabs.empty()) + { + co_return; + } + + // Show a single aggregate confirmation instead of per-tab dialogs. const auto weak = get_weak(); + if (_settings.GlobalSettings().ConfirmOnClose() != ConfirmOnClose::Never) + { + auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::MultipleTabs); + + // Hold a strong reference to `this` after the co_await so that + // the for-loop below can safely dispatch on us. + auto strong = weak.get(); + if (!strong || warningResult != ContentDialogResult::Primary) + { + co_return; + } + } for (auto& tab : tabs) { winrt::Windows::Foundation::IAsyncAction action{ nullptr }; if (const auto strong = weak.get()) { - action = _HandleCloseTabRequested(tab); + action = _HandleCloseTabRequested(tab, /*skipConfirmClose*/ true); } if (!action) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index c715b0e2a1..5655a9c9f1 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -884,26 +884,78 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Displays a dialog to warn the user that they are about to close all open windows. - // Once the user clicks the OK button, shut down the application. - // If cancel is clicked, the dialog will close. + // - Displays the unified close confirmation dialog configured for the + // given scenario. Resets the "don't ask me again" checkbox before showing. + // If the user confirms and checked "don't ask me again", sets + // confirmOnClose to Never and writes settings to disk. // - Only one dialog can be visible at a time. If another dialog is visible // when this is called, nothing happens. See _ShowDialog for details - winrt::Windows::Foundation::IAsyncOperation TerminalPage::_ShowQuitDialog() + winrt::Windows::Foundation::IAsyncOperation TerminalPage::_ShowConfirmCloseDialog(ConfirmCloseDialogKind kind) { - return _ShowDialogHelper(L"QuitDialog"); - } + // Load the dialog (triggers x:Load) and configure its strings. + const auto dialog = FindName(L"ConfirmCloseDialog").as(); - // Method Description: - // - Displays a dialog for warnings found while closing the terminal app using - // key binding with multiple tabs opened. Display messages to warn user - // that more than 1 tab is opened, and once the user clicks the OK button, remove - // all the tabs and shut down and app. If cancel is clicked, the dialog will close - // - Only one dialog can be visible at a time. If another dialog is visible - // when this is called, nothing happens. See _ShowDialog for details - winrt::Windows::Foundation::IAsyncOperation TerminalPage::_ShowCloseWarningDialog() - { - return _ShowDialogHelper(L"CloseAllDialog"); + winrt::hstring title; + winrt::hstring primary; + switch (kind) + { + case ConfirmCloseDialogKind::CloseAll: + title = RS_(L"ConfirmCloseDialog_CloseAllTitle"); + primary = RS_(L"ConfirmCloseDialog_CloseAllPrimary"); + break; + case ConfirmCloseDialogKind::Window: + title = RS_(L"ConfirmCloseDialog_WindowTitle"); + primary = RS_(L"ConfirmCloseDialog_WindowPrimary"); + break; + case ConfirmCloseDialogKind::Tab: + title = RS_(L"ConfirmCloseDialog_TabTitle"); + primary = RS_(L"ConfirmCloseDialog_TabPrimary"); + break; + case ConfirmCloseDialogKind::MultiplePanes: + title = RS_(L"ConfirmCloseDialog_MultiplePanesTitle"); + primary = RS_(L"ConfirmCloseDialog_MultiplePanesPrimary"); + break; + case ConfirmCloseDialogKind::MultipleTabs: + title = RS_(L"ConfirmCloseDialog_MultipleTabsTitle"); + primary = RS_(L"ConfirmCloseDialog_MultipleTabsPrimary"); + break; + case ConfirmCloseDialogKind::Pane: + title = RS_(L"ConfirmCloseDialog_PaneTitle"); + primary = RS_(L"ConfirmCloseDialog_PanePrimary"); + break; + } + dialog.Title(winrt::box_value(title)); + dialog.PrimaryButtonText(primary); + dialog.CloseButtonText(RS_(L"ConfirmCloseDialog_Cancel")); + + // BODGY: After a ContentDialog is dismissed, FindName() can no longer + // resolve children inside it. Use Content() to get the checkbox directly. + const auto checkbox = dialog.Content().as(); + checkbox.IsChecked(false); + + auto result = ContentDialogResult::None; + if (auto presenter{ _dialogPresenter.get() }) + { + const auto weak = get_weak(); + result = co_await presenter.ShowDialog(dialog); + + // ShowDialog blocks until the dialog is dismissed, so it is + // possible for `this` to be torn down while we wait. Re-acquire + // a strong reference before touching any of our state. + const auto strong = weak.get(); + if (!strong) + { + co_return ContentDialogResult::None; + } + + if (result == ContentDialogResult::Primary && checkbox.IsChecked().Value()) + { + _settings.GlobalSettings().ConfirmOnClose(ConfirmOnClose::Never); + _settings.WriteSettingsToDisk(); + } + } + + co_return result; } // Method Description: @@ -2209,12 +2261,13 @@ namespace winrt::TerminalApp::implementation // signal that we want to close everything. safe_void_coroutine TerminalPage::RequestQuit() { - if (!_displayingCloseDialog) + const auto setting = _settings.GlobalSettings().ConfirmOnClose(); + if (setting != ConfirmOnClose::Never && !_displayingCloseDialog) { _displayingCloseDialog = true; const auto weak = get_weak(); - auto warningResult = co_await _ShowQuitDialog(); + auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::CloseAll); const auto strong = weak.get(); if (!strong) { @@ -2227,9 +2280,9 @@ namespace winrt::TerminalApp::implementation { co_return; } - - QuitRequested.raise(nullptr, nullptr); } + + QuitRequested.raise(nullptr, nullptr); } void TerminalPage::PersistState() @@ -2307,12 +2360,59 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Close the terminal app. If there is more - // than one tab opened, show a warning dialog. + // - Determines whether a close-window action should show a confirmation + // dialog, based on the confirmOnClose setting and the current window state. + // Arguments: + // - + // Return Value: + // - true, if a warning dialog should be shown before closing the window + bool TerminalPage::_ShouldWarnOnClose() const + { + const auto setting = _settings.GlobalSettings().ConfirmOnClose(); + switch (setting) + { + case ConfirmOnClose::Always: + return true; + case ConfirmOnClose::Automatic: + { + // Warn if there's more than one tab, or the one tab has more than one pane. + return _HasMultipleTabs() || _GetTabImpl(_tabs.GetAt(0))->GetLeafPaneCount() > 1; + } + case ConfirmOnClose::Never: + default: + return false; + } + } + + // Method Description: + // - Determines whether closing a specific tab should show a confirmation + // dialog, based on the confirmOnClose setting and the tab's state. + // Arguments: + // - tab: The tab being closed + // Return Value: + // - true, if a warning dialog should be shown before closing the tab + bool TerminalPage::_ShouldWarnOnCloseTab(const winrt::com_ptr& tab) const + { + const auto setting = _settings.GlobalSettings().ConfirmOnClose(); + switch (setting) + { + case ConfirmOnClose::Always: + return true; + case ConfirmOnClose::Automatic: + // Warn if this tab has more than one pane. + return tab->GetLeafPaneCount() > 1; + case ConfirmOnClose::Never: + default: + return false; + } + } + + // Method Description: + // - Close the terminal app. If the confirmOnClose setting indicates we should + // warn for the current window state, show a warning dialog. safe_void_coroutine TerminalPage::CloseWindow() { - if (_HasMultipleTabs() && - _settings.GlobalSettings().ConfirmCloseAllTabs() && + if (_ShouldWarnOnClose() && !_displayingCloseDialog) { if (_newTabButton && _newTabButton.Flyout()) @@ -2321,7 +2421,17 @@ namespace winrt::TerminalApp::implementation } _DismissTabContextMenus(); _displayingCloseDialog = true; - auto warningResult = co_await _ShowCloseWarningDialog(); + + const auto weak = get_weak(); + auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::Window); + // Hold a strong reference to `this` after the co_await; we may + // be the last holder if the window was already being torn down. + auto strong = weak.get(); + if (!strong) + { + co_return; + } + _displayingCloseDialog = false; if (warningResult != ContentDialogResult::Primary) diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 29f0cd23e1..f70041f8b6 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -54,6 +54,16 @@ namespace winrt::TerminalApp::implementation ScrollDown = 1 }; + enum class ConfirmCloseDialogKind + { + Pane, + Tab, + MultiplePanes, + MultipleTabs, + Window, + CloseAll + }; + struct RenameWindowRequestedArgs : RenameWindowRequestedArgsT { WINRT_PROPERTY(winrt::hstring, ProposedName); @@ -303,8 +313,7 @@ namespace winrt::TerminalApp::implementation winrt::Windows::Foundation::IAsyncOperation _ShowDialogHelper(const std::wstring_view& name); void _ShowAboutDialog(); - winrt::Windows::Foundation::IAsyncOperation _ShowQuitDialog(); - winrt::Windows::Foundation::IAsyncOperation _ShowCloseWarningDialog(); + winrt::Windows::Foundation::IAsyncOperation _ShowConfirmCloseDialog(ConfirmCloseDialogKind kind); winrt::Windows::Foundation::IAsyncOperation _ShowCloseReadOnlyDialog(); winrt::Windows::Foundation::IAsyncOperation _ShowMultiLinePasteWarningDialog(); winrt::Windows::Foundation::IAsyncOperation _ShowLargePasteWarningDialog(); @@ -351,7 +360,7 @@ namespace winrt::TerminalApp::implementation safe_void_coroutine _ExportTab(const Tab& tab, winrt::hstring filepath); - winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::Tab tab); + winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::Tab tab, bool skipConfirmClose = false); void _CloseTabAtIndex(uint32_t index); void _RemoveTab(const winrt::TerminalApp::Tab& tab); safe_void_coroutine _RemoveTabs(const std::vector tabs); @@ -402,9 +411,12 @@ namespace winrt::TerminalApp::implementation TerminalApp::Tab _GetTabByTabViewItem(const IInspectable& tabViewItem) const noexcept; void _HandleClosePaneRequested(std::shared_ptr pane); + bool _ShouldWarnOnClose() const; + bool _ShouldWarnOnCloseTab(const winrt::com_ptr& tab) const; safe_void_coroutine _SetFocusedTab(const winrt::TerminalApp::Tab tab); safe_void_coroutine _CloseFocusedPane(); - void _ClosePanes(weak_ref weakTab, std::vector paneIds); + safe_void_coroutine _ClosePanes(weak_ref weakTab, std::vector paneIds); + void _CloseRemainingPanes(weak_ref weakTab, std::vector paneIds); winrt::Windows::Foundation::IAsyncOperation _PaneConfirmCloseReadOnly(std::shared_ptr pane); void _AddPreviouslyClosedPaneOrTab(std::vector&& args); diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml index 68396d01d5..cb4b2a4463 100644 --- a/src/cascadia/TerminalApp/TerminalPage.xaml +++ b/src/cascadia/TerminalApp/TerminalPage.xaml @@ -86,17 +86,12 @@ Grid.Row="2" x:Load="False" /> - - - + DefaultButton="Primary"> + + - - - + + + diff --git a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.cpp b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.cpp index 55a239e8e5..f069fec12d 100644 --- a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.cpp +++ b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.cpp @@ -17,5 +17,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { INITIALIZE_BINDABLE_ENUM_SETTING(TabSwitcherMode, TabSwitcherMode, TabSwitcherMode, L"Globals_TabSwitcherMode", L"Content"); INITIALIZE_BINDABLE_ENUM_SETTING(CopyFormat, CopyFormat, winrt::Microsoft::Terminal::Control::CopyFormat, L"Globals_CopyFormat", L"Content"); + INITIALIZE_BINDABLE_ENUM_SETTING(ConfirmOnClose, ConfirmOnClose, Model::ConfirmOnClose, L"Globals_ConfirmOnClose", L"Content"); } } diff --git a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.h b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.h index c3e48715f7..47cb331892 100644 --- a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.h +++ b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.h @@ -19,6 +19,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation GETSET_BINDABLE_ENUM_SETTING(TabSwitcherMode, Model::TabSwitcherMode, _GlobalSettings.TabSwitcherMode); GETSET_BINDABLE_ENUM_SETTING(CopyFormat, winrt::Microsoft::Terminal::Control::CopyFormat, _GlobalSettings.CopyFormatting); + GETSET_BINDABLE_ENUM_SETTING(ConfirmOnClose, Model::ConfirmOnClose, _GlobalSettings.ConfirmOnClose); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, CopyOnSelect); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, TrimBlockSelection); @@ -30,7 +31,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, DetectURLs); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, SearchWebDefaultQueryUrl); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WordDelimiters); - PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, ConfirmCloseAllTabs); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, InputServiceWarning); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WarnAboutLargePaste); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WarnAboutMultiLinePaste); diff --git a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.idl b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.idl index ba77aec55f..69b53b1b24 100644 --- a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.idl +++ b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.idl @@ -12,10 +12,13 @@ namespace Microsoft.Terminal.Settings.Editor InteractionViewModel(Microsoft.Terminal.Settings.Model.GlobalAppSettings globalSettings); IInspectable CurrentTabSwitcherMode; - Windows.Foundation.Collections.IObservableVector TabSwitcherModeList { get; }; + Windows.Foundation.Collections.IObservableVector TabSwitcherModeList { get; }; IInspectable CurrentCopyFormat; - Windows.Foundation.Collections.IObservableVector CopyFormatList { get; }; + Windows.Foundation.Collections.IObservableVector CopyFormatList { get; }; + + IInspectable CurrentConfirmOnClose; + Windows.Foundation.Collections.IObservableVector ConfirmOnCloseList { get; }; PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, CopyOnSelect); PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, TrimBlockSelection); @@ -27,7 +30,6 @@ namespace Microsoft.Terminal.Settings.Editor PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, DetectURLs); PERMANENT_OBSERVABLE_PROJECTED_SETTING(String, SearchWebDefaultQueryUrl); PERMANENT_OBSERVABLE_PROJECTED_SETTING(String, WordDelimiters); - PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ConfirmCloseAllTabs); PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, InputServiceWarning); PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, WarnAboutLargePaste); PERMANENT_OBSERVABLE_PROJECTED_SETTING(Microsoft.Terminal.Control.WarnAboutMultiLinePaste, WarnAboutMultiLinePaste); diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index 74967fc61d..ba6631deaa 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -2201,6 +2201,26 @@ Warn when closing more than one tab Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Warn when closing + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Controls when a confirmation dialog appears before closing tabs or windows. "Always" presents the dialog when closing any pane. + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Never + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Always + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Multiple tabs or panes + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Warn when "Touch Keyboard and Handwriting Panel Service" is disabled diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp index de1bf5185d..b92994c2d6 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp @@ -43,6 +43,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation DEFINE_ENUM_MAP(Microsoft::Terminal::Control::TextMeasurement, TextMeasurement); DEFINE_ENUM_MAP(Microsoft::Terminal::Control::AmbiguousWidth, AmbiguousWidth); DEFINE_ENUM_MAP(Microsoft::Terminal::Control::WarnAboutMultiLinePaste, WarnAboutMultiLinePaste); + DEFINE_ENUM_MAP(Model::ConfirmOnClose, ConfirmOnClose); // Profile Settings DEFINE_ENUM_MAP(Model::CloseOnExitMode, CloseOnExitMode); diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.h b/src/cascadia/TerminalSettingsModel/EnumMappings.h index 160c9a11b1..e858670450 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.h +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.h @@ -40,6 +40,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static winrt::Windows::Foundation::Collections::IMap TextMeasurement(); static winrt::Windows::Foundation::Collections::IMap AmbiguousWidth(); static winrt::Windows::Foundation::Collections::IMap WarnAboutMultiLinePaste(); + static winrt::Windows::Foundation::Collections::IMap ConfirmOnClose(); // Profile Settings static winrt::Windows::Foundation::Collections::IMap CloseOnExitMode(); diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.idl b/src/cascadia/TerminalSettingsModel/EnumMappings.idl index 128260a507..7f52aace49 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.idl +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.idl @@ -22,6 +22,7 @@ namespace Microsoft.Terminal.Settings.Model static Windows.Foundation.Collections.IMap TextMeasurement { get; }; static Windows.Foundation.Collections.IMap AmbiguousWidth { get; }; static Windows.Foundation.Collections.IMap WarnAboutMultiLinePaste { get; }; + static Windows.Foundation.Collections.IMap ConfirmOnClose { get; }; // Profile Settings static Windows.Foundation.Collections.IMap CloseOnExitMode { get; }; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index 254e52bdbc..3a5cd8cb1d 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -160,7 +160,16 @@ void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origi _fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyInputServiceWarningKey, _InputServiceWarning) || _fixupsAppliedDuringLoad; _fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyWarnAboutLargePasteKey, _WarnAboutLargePaste) || _fixupsAppliedDuringLoad; _fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyWarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste) || _fixupsAppliedDuringLoad; - _fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyConfirmCloseAllTabsKey, _ConfirmCloseAllTabs) || _fixupsAppliedDuringLoad; + // GH#6549 - Migrate legacy "confirmCloseAllTabs" boolean to the new + // "confirmOnClose" enum. true -> Automatic, false -> Never. + { + std::optional legacyConfirmClose; + if (JsonUtils::GetValueForKey(json, LegacyConfirmCloseAllTabsKey, legacyConfirmClose)) + { + _ConfirmOnClose = legacyConfirmClose.value() ? ConfirmOnClose::Automatic : ConfirmOnClose::Never; + _fixupsAppliedDuringLoad = true; + } + } #define GLOBAL_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ JsonUtils::GetValueForKey(json, jsonKey, _##name); \ diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl index 77bcfc494d..adb29b3395 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl @@ -50,6 +50,13 @@ namespace Microsoft.Terminal.Settings.Model AfterCurrentTab, }; + enum ConfirmOnClose + { + Never = 0, + Automatic = 1, + Always = 2, + }; + [default_interface] runtimeclass GlobalAppSettings { Guid DefaultProfile; @@ -61,7 +68,7 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_SETTING(Boolean, ShowTabsFullscreen); INHERITABLE_SETTING(NewTabPosition, NewTabPosition); INHERITABLE_SETTING(Boolean, ShowTitleInTitlebar); - INHERITABLE_SETTING(Boolean, ConfirmCloseAllTabs); + INHERITABLE_SETTING(ConfirmOnClose, ConfirmOnClose); INHERITABLE_SETTING(String, Language); INHERITABLE_SETTING(Microsoft.UI.Xaml.Controls.TabViewWidthMode, TabWidthMode); INHERITABLE_SETTING(Boolean, UseAcrylicInTabRow); diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index b95aad938e..ca147c707d 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -38,7 +38,7 @@ Author(s): X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \ X(Model::NewTabPosition, NewTabPosition, "newTabPosition", Model::NewTabPosition::AfterLastTab) \ X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \ - X(bool, ConfirmCloseAllTabs, "warning.confirmCloseAllTabs", true) \ + X(Model::ConfirmOnClose, ConfirmOnClose, "warning.confirmOnClose", Model::ConfirmOnClose::Automatic) \ X(Model::ThemePair, Theme, "theme") \ X(hstring, Language, "language") \ X(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, "tabWidthMode", winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal) \ diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index d5bfaf6f07..878b09f89c 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -88,6 +88,25 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::MatchMode) }; }; +JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::ConfirmOnClose) +{ + JSON_MAPPINGS(3) = { + pair_type{ "never", ValueType::Never }, + pair_type{ "automatic", ValueType::Automatic }, + pair_type{ "always", ValueType::Always }, + }; + + auto FromJson(const Json::Value& json) + { + return BaseEnumMapper::FromJson(json); + } + + bool CanConvert(const Json::Value& json) + { + return BaseEnumMapper::CanConvert(json); + } +}; + JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::BellStyle) { static constexpr std::array mappings = { diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index 9d9474cd9c..44efab04ca 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -24,7 +24,7 @@ "showAdminShield": true, // Miscellaneous - "confirmCloseAllTabs": true, + "warning.confirmOnClose": "automatic", "theme": "dark", "snapToGridOnResize": true, "disableAnimations": false, diff --git a/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp b/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp index 7b0ac2c6ec..98ad8cfcbf 100644 --- a/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp +++ b/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp @@ -131,7 +131,7 @@ namespace SettingsModelUnitTests "trimPaste": true, - "warning.confirmCloseAllTabs" : true, + "warning.confirmOnClose": "automatic", "warning.inputService" : true, "warning.largePaste" : true, "warning.multiLinePaste" : "automatic", From dbc5177f7f82608a888cb24b24ed917aa2aecfab Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Mon, 4 May 2026 19:34:13 -0500 Subject: [PATCH 13/18] Migrate some pull requests from OS (#20181) Some work was required to ensure conhost builds. --------- Co-authored-by: Dragos Sambotin Co-authored-by: Daniel Paoliello (HE HIM) --- .github/actions/spelling/expect/expect.txt | 1 + src/inc/LibraryIncludes.h | 10 ++++++++++ src/project.inc | 3 ++- src/renderer/atlas/pch.h | 10 ++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 102af4d88f..3d3eff382f 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -241,6 +241,7 @@ consoletaeftemplates consoleuwp CONSOLEWINDOWOWNER consrv +consteval constexprable contentfiles conterm diff --git a/src/inc/LibraryIncludes.h b/src/inc/LibraryIncludes.h index b9df47f957..728246e1c9 100644 --- a/src/inc/LibraryIncludes.h +++ b/src/inc/LibraryIncludes.h @@ -84,8 +84,18 @@ // {fmt}, a C++20-compatible formatting library #pragma warning(push) #pragma warning(disable: 4702) // unreachable code +// Workaround: clang-cl advertises consteval support but fmt's use of it in +// color.h triggers "call to consteval function is not a constant expression". +// Hide __cpp_lib_is_constant_evaluated so fmt falls back to the non-consteval path. +#ifdef __clang__ +#pragma push_macro("__cpp_lib_is_constant_evaluated") +#undef __cpp_lib_is_constant_evaluated +#endif #include #include +#ifdef __clang__ +#pragma pop_macro("__cpp_lib_is_constant_evaluated") +#endif #pragma warning(pop) #define USE_INTERVAL_TREE_NAMESPACE diff --git a/src/project.inc b/src/project.inc index 152aca2717..cf4a2e048c 100644 --- a/src/project.inc +++ b/src/project.inc @@ -35,7 +35,8 @@ USE_NATIVE_EH = 1 USE_STD_CPP20 = 1 MSC_WARNING_LEVEL = /W4 /WX -USER_C_FLAGS = $(USER_C_FLAGS) /Zc:preprocessor /fp:contract /utf-8 +USER_C_FLAGS = $(USER_C_FLAGS) /fp:contract /utf-8 +ZC_PREPROCESSOR = 1 # ------------------------------------- # Common Console Includes and Libraries diff --git a/src/renderer/atlas/pch.h b/src/renderer/atlas/pch.h index 952d0fb2d7..9d5bc66515 100644 --- a/src/renderer/atlas/pch.h +++ b/src/renderer/atlas/pch.h @@ -46,8 +46,18 @@ // {fmt}, a C++20-compatible formatting library #pragma warning(push) #pragma warning(disable : 4702) // unreachable code +// Workaround: clang-cl advertises consteval support but fmt's use of it in +// color.h triggers "call to consteval function is not a constant expression". +// Hide __cpp_lib_is_constant_evaluated so fmt falls back to the non-consteval path. +#ifdef __clang__ +#pragma push_macro("__cpp_lib_is_constant_evaluated") +#undef __cpp_lib_is_constant_evaluated +#endif #include #include +#ifdef __clang__ +#pragma pop_macro("__cpp_lib_is_constant_evaluated") +#endif #pragma warning(pop) #include From 8edac5fb12f9e7c21a88cf3d1617817ad0fdecc6 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Tue, 5 May 2026 14:19:25 -0500 Subject: [PATCH 14/18] Don't allow overflowing lengths in WM_COPYDATA (#20185) It is possible to craft a packet whose `len` is `0x80000001`. We should not produce values that do not fit in size_t (on e.g. x86). Reject them summarily. --- src/cascadia/WindowsTerminal/WindowEmperor.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp index 82d3c82620..9fa13c1b1c 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp +++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp @@ -99,9 +99,8 @@ static const uint8_t* deserializeString(const uint8_t* it, const uint8_t* end, w uint32_t len; it = deserializeUint32(it, end, len); - const auto bytes = static_cast(len) * sizeof(wchar_t); - - if (bytes == 0 || static_cast(end - it) < bytes) + size_t bytes{}; + if (!SUCCEEDED(SizeTMult(static_cast(len), sizeof(wchar_t), &bytes)) || bytes == 0 || static_cast(end - it) < bytes) { throw std::out_of_range("Not enough data for string content"); } From dadde2fb111371ca864c8331ff6583bdd693be1a Mon Sep 17 00:00:00 2001 From: nmurrell07 Date: Tue, 5 May 2026 14:42:48 -0500 Subject: [PATCH 15/18] fix(resizePane): Mark as handled only when resize succeeds (#20001) This fix addresses issue #19983 where resizePane actions unconditionally consume keystrokes even when no resize can occur. The fix follows the same pattern used for moveFocus and swapPane fixes: - Changed Tab::ResizePane to return bool indicating success - Changed TerminalPage::_ResizePane to return bool from ResizePane - Updated _HandleResizePane to set args.Handled() based on whether resize succeeded This allows the keychord to propagate to the terminal when no resize can occur, matching the behavior of moveFocus and swapPane (#6129). Closes #19983 --------- Co-authored-by: nmurrell07 Co-authored-by: Dustin L. Howett --- src/cascadia/TerminalApp/AppActionHandlers.cpp | 4 ++-- src/cascadia/TerminalApp/Tab.cpp | 6 +++--- src/cascadia/TerminalApp/Tab.h | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 7 ++++--- src/cascadia/TerminalApp/TerminalPage.h | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index bb5d859c85..7e0edef7bd 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -499,8 +499,8 @@ namespace winrt::TerminalApp::implementation } else { - _ResizePane(realArgs.ResizeDirection()); - args.Handled(true); + const auto resizeSucceeded = _ResizePane(realArgs.ResizeDirection()); + args.Handled(resizeSucceeded); } } } diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index ed58f8e460..da4d0896ae 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -844,14 +844,14 @@ namespace winrt::TerminalApp::implementation // Arguments: // - direction: The direction to move the separator in. // Return Value: - // - - void Tab::ResizePane(const ResizeDirection& direction) + // - whether a pane was resized + bool Tab::ResizePane(const ResizeDirection& direction) { ASSERT_UI_THREAD(); // NOTE: This _must_ be called on the root pane, so that it can propagate // throughout the entire tree. - _rootPane->ResizePane(direction); + return _rootPane->ResizePane(direction); } // Method Description: diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h index 1a9d43dd7b..5f7b18c901 100644 --- a/src/cascadia/TerminalApp/Tab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -53,7 +53,7 @@ namespace winrt::TerminalApp::implementation const float splitSize, winrt::Windows::Foundation::Size availableSpace) const; - void ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction); + bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction); bool NavigateFocus(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction); bool SwapPane(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction); bool FocusPane(const uint32_t id); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 5655a9c9f1..cfffdf9a38 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2900,14 +2900,15 @@ namespace winrt::TerminalApp::implementation // Arguments: // - direction: The direction to move the separator in. // Return Value: - // - - void TerminalPage::_ResizePane(const ResizeDirection& direction) + // - whether a pane was resized + bool TerminalPage::_ResizePane(const ResizeDirection& direction) { if (const auto tabImpl{ _GetFocusedTabImpl() }) { _UnZoomIfNeeded(); - tabImpl->ResizePane(direction); + return tabImpl->ResizePane(direction); } + return false; } // Method Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index f70041f8b6..67ff3f2564 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -426,7 +426,7 @@ namespace winrt::TerminalApp::implementation const Microsoft::Terminal::Settings::Model::SplitDirection splitType, const float splitSize, std::shared_ptr newPane); - void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction); + bool _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction); void _ToggleSplitOrientation(); void _ScrollPage(ScrollDirection scrollDirection); From a325a2fa5a1cee7e46c23934fa6f82bc1922af3c Mon Sep 17 00:00:00 2001 From: Sushaanth Srinivasan <80441330+SushaanthSrinivasan@users.noreply.github.com> Date: Tue, 5 May 2026 19:35:16 -0700 Subject: [PATCH 16/18] Fix settings error text legibility in High Contrast mode (#20098) Closes #18147 `SystemErrorTextColor` doesn't adapt to High Contrast themes, so the error details in the "Failed to reload settings" dialog are illegible (yellow on cream in HC White, for example). Fix: skip the `ErrorTextBrush` foreground override when High Contrast is active, letting the text inherit the system HC text color from its parent element. This matches the existing HC detection pattern used in `TermControl.cpp` and `MainPage.cpp`. Validated manually on High Contrast White and Night sky themes. Co-authored-by: SushaanthSrinivasan Co-authored-by: Claude Opus 4.6 (1M context) --- src/cascadia/TerminalApp/TerminalWindow.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalWindow.cpp b/src/cascadia/TerminalApp/TerminalWindow.cpp index 0fafac603c..67110a1667 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.cpp +++ b/src/cascadia/TerminalApp/TerminalWindow.cpp @@ -108,13 +108,19 @@ static Documents::Run _BuildErrorRun(const winrt::hstring& text, const ResourceD Documents::Run textRun; textRun.Text(text); - // Color the text red (light theme) or yellow (dark theme) based on the system theme - auto key = winrt::box_value(L"ErrorTextBrush"); - if (resources.HasKey(key)) + // GH #18147 - In High Contrast mode, don't override the foreground. + // Let the text inherit the system HC text color from its parent element, + // since SystemErrorTextColor doesn't adapt to High Contrast themes. + if (!winrt::Windows::UI::ViewManagement::AccessibilitySettings{}.HighContrast()) { - auto g = resources.Lookup(key); - auto brush = g.try_as(); - textRun.Foreground(brush); + // Color the text red (light theme) or yellow (dark theme) based on the system theme + auto key = winrt::box_value(L"ErrorTextBrush"); + if (resources.HasKey(key)) + { + auto g = resources.Lookup(key); + auto brush = g.try_as(); + textRun.Foreground(brush); + } } return textRun; From ea4cb8145f768c49e5b91229eb77f5ad1135f9ad Mon Sep 17 00:00:00 2001 From: Windows Console Service Bot <14666831+consvc@users.noreply.github.com> Date: Wed, 6 May 2026 16:36:17 -0500 Subject: [PATCH 17/18] Localization Updates - main - 04/30/2026 03:04:35 (#20168) Co-authored-by: Console Service Bot --- .../Resources/de-DE/Resources.resw | 56 +++++++++++++---- .../Resources/es-ES/Resources.resw | 56 +++++++++++++---- .../Resources/fr-FR/Resources.resw | 56 +++++++++++++---- .../Resources/it-IT/Resources.resw | 56 +++++++++++++---- .../Resources/ja-JP/Resources.resw | 56 +++++++++++++---- .../Resources/ko-KR/Resources.resw | 56 +++++++++++++---- .../Resources/pt-BR/Resources.resw | 56 +++++++++++++---- .../Resources/qps-ploc/Resources.resw | 60 ++++++++++++++----- .../Resources/qps-ploca/Resources.resw | 60 ++++++++++++++----- .../Resources/qps-plocm/Resources.resw | 60 ++++++++++++++----- .../Resources/ru-RU/Resources.resw | 56 +++++++++++++---- .../Resources/zh-CN/Resources.resw | 28 ++++----- .../Resources/zh-TW/Resources.resw | 56 +++++++++++++---- .../Resources/de-DE/Resources.resw | 24 ++++++++ .../Resources/es-ES/Resources.resw | 24 ++++++++ .../Resources/fr-FR/Resources.resw | 24 ++++++++ .../Resources/it-IT/Resources.resw | 24 ++++++++ .../Resources/ja-JP/Resources.resw | 24 ++++++++ .../Resources/ko-KR/Resources.resw | 24 ++++++++ .../Resources/pt-BR/Resources.resw | 24 ++++++++ .../Resources/qps-ploc/Resources.resw | 24 ++++++++ .../Resources/qps-ploca/Resources.resw | 24 ++++++++ .../Resources/qps-plocm/Resources.resw | 24 ++++++++ .../Resources/ru-RU/Resources.resw | 24 ++++++++ .../Resources/zh-CN/Resources.resw | 8 +++ .../Resources/zh-TW/Resources.resw | 24 ++++++++ .../Resources/de-DE/Resources.resw | 2 +- .../Resources/es-ES/Resources.resw | 2 +- .../Resources/fr-FR/Resources.resw | 2 +- .../Resources/it-IT/Resources.resw | 2 +- .../Resources/ja-JP/Resources.resw | 2 +- .../Resources/ko-KR/Resources.resw | 2 +- .../Resources/pt-BR/Resources.resw | 2 +- .../Resources/qps-ploc/Resources.resw | 2 +- .../Resources/qps-ploca/Resources.resw | 2 +- .../Resources/qps-plocm/Resources.resw | 2 +- .../Resources/ru-RU/Resources.resw | 2 +- .../Resources/zh-CN/Resources.resw | 2 +- .../Resources/zh-TW/Resources.resw | 2 +- 39 files changed, 855 insertions(+), 179 deletions(-) diff --git a/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw b/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw index 47d5325d8b..108f2eda49 100644 --- a/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw @@ -499,24 +499,48 @@ Hinweise von Drittanbietern A hyperlink name for the Terminal's third-party notices - + Abbrechen - - Alle schließen - - + Möchten Sie alle Fenster schließen? - - Abbrechen - - + Alle schließen - + Möchten Sie alle Registerkarten schließen? + + Alle schließen + + + Möchten Sie diese Registerkarte schließen? + + + Registerkarte schließen + + + Möchten Sie diesen Bereich schließen? + + + Bereich schließen + + + Möchten Sie diese Registerkarten schließen? + + + Registerkarten schließen + + + Möchten Sie diese Bereiche schließen? + + + Bereiche schließen + + + Nicht mehr fragen + Abbrechen @@ -748,6 +772,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + Aktivität auf der Registerkarte „{0}“ + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Aktivität auf der Registerkarte „{0}“ (Fenster „{1}“) + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Eine neue Registerkarte im angegebenen Startverzeichnis öffnen @@ -884,10 +916,10 @@ Wenn diese Option festgelegt ist, wird der Befehl an den Standardbefehl des Profils angefügt, anstatt ihn zu ersetzen. - Verbindung neu starten + Sitzung neu starten - Verbindung mit aktivem Bereich neu starten + Sitzung im aktiven Bereich neu starten Schnipsel diff --git a/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw b/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw index 415d263e3d..ff5dc65670 100644 --- a/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw @@ -496,24 +496,48 @@ Avisos de terceros A hyperlink name for the Terminal's third-party notices - + Cancelar - - Cerrar todo - - + ¿Quiere cerrar todas las ventanas? - - Cancelar - - + Cerrar todo - + ¿Quieres cerrar todas las pestañas? + + Cerrar todo + + + ¿Desea cerrar esta pestaña? + + + Cerrar pestaña + + + ¿Desea cerrar este panel? + + + Cerrar panel + + + ¿Desea cerrar estas pestañas? + + + Cerrar pestañas + + + ¿Desea cerrar estos paneles? + + + Cerrar paneles + + + No volver a preguntarme + Cancelar @@ -745,6 +769,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + Actividad en la pestaña "{0}" + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Actividad en la pestaña "{0}" (ventana "{1}") + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Abrir una nueva pestaña en un directorio de inicio determinado @@ -881,10 +913,10 @@ Si se establece, el comando se anexará al comando predeterminado del perfil en lugar de reemplazarlo. - Reiniciar conexión + Reiniciar sesión - Reiniciar la conexión del panel activo + Reiniciar la sesión en el panel activo Fragmentos diff --git a/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw index ec79eccd20..9c4ed030a4 100644 --- a/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw @@ -496,24 +496,48 @@ Mentions tierces A hyperlink name for the Terminal's third-party notices - + Annuler - - Fermer tout - - + Voulez-vous fermer toutes les fenêtres ? - - Annuler - - + Fermer tout - + Voulez-vous fermer tous les onglets ? + + Fermer tout + + + Voulez-vous fermer cet onglet ? + + + Fermer l'onglet + + + Voulez-vous fermer ce volet ? + + + Fermer le volet + + + Voulez-vous fermer ces onglets ? + + + Fermer les onglets + + + Voulez-vous fermer ces volets ? + + + Fermer les panneaux + + + Ne plus me le demander + Annuler @@ -745,6 +769,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + Activité sous l’onglet « {0} » + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Activité sous l’onglet « {0} » (fenêtre « {1} ») + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Ouvrez un nouvel onglet dans le répertoire correspondant @@ -881,10 +913,10 @@ Si elle est définie, la commande sera ajoutée à la commande par défaut du profil au lieu de la remplacer. - Redémarrer la connexion + Redémarrer la session - Redémarrer la connexion du volet actif + Redémarrez la session dans le volet actif Extraits diff --git a/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw b/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw index bca470f807..dce13d5ef1 100644 --- a/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw @@ -496,24 +496,48 @@ Comunicazioni di terze parti A hyperlink name for the Terminal's third-party notices - + Annulla - - Chiudi tutto - - + Vuoi chiudere tutte le finestre? - - Annulla - - + Chiudi tutto - + Vuoi chiudere tutte le schede? + + Chiudi tutto + + + Vuoi chiudere questa scheda? + + + Chiudi scheda + + + Vuoi chiudere questo riquadro? + + + Chiudi riquadro + + + Vuoi chiudere queste schede? + + + Chiudi schede + + + Vuoi chiudere questi riquadri? + + + Chiudi riquadri + + + Non chiedermelo più + Annulla @@ -745,6 +769,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + Attività nella scheda "{0}" + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Attività nella scheda "{0}" (finestra "{1}") + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Apri una nuova scheda nella directory di avvio specificata @@ -881,10 +913,10 @@ Se impostato, il comando verrà aggiunto al comando predefinito del profilo invece di sostituirlo. - Riavvia connessione + Riavvia la sessione - Riavvia la connessione al riquadro attivo + Riavvia la sessione nel riquadro attivo Frammenti diff --git a/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw index 57c9ae65d0..4b8e6146f2 100644 --- a/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw @@ -497,24 +497,48 @@ サード パーティ通知 A hyperlink name for the Terminal's third-party notices - + キャンセル - - すべて閉じる - - + すべてのウィンドウを閉じますか? - - キャンセル - - + すべて閉じる - + すべてのタブを閉じますか? + + すべて閉じる + + + このタブを閉じますか? + + + タブを閉じる + + + このウィンドウを閉じますか? + + + ウィンドウを閉じる + + + これらのタブを閉じますか? + + + タブを閉じる + + + これらのウィンドウを閉じますか? + + + ウィンドウを閉じる + + + 今後、このメッセージを表示しない + キャンセル @@ -746,6 +770,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + タブ "{0}" のアクティビティ + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + タブ "{0}" のアクティビティ (ウィンドウ "{1}") + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + 指定された開始ディレクトリで新しいタブを開きます @@ -882,10 +914,10 @@ 設定されている場合、コマンドはプロファイルの既定のコマンドを置き換えるのではなく、追加されます。 - 接続の再起動 + セッションの再開 - アクティブ ペイン接続を再起動します + アクティブなウィンドウでセッションを再起動します 抜粋 diff --git a/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw index 6b7223e0ef..969f4be72c 100644 --- a/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw @@ -496,24 +496,48 @@ 타사 통지 A hyperlink name for the Terminal's third-party notices - + 취소 - - 모두 닫기 - - + 모든 창을 닫으시겠습니까? - - 취소 - - + 모두 닫기 - + 모든 탭을 닫으시겠습니까? + + 모두 닫기 + + + 이 탭을 닫으시겠습니까? + + + 탭 닫기 + + + 이 창을 닫으시겠습니까? + + + 창 닫기 + + + 이러한 탭을 닫으시겠습니까? + + + 탭 닫기 + + + 이 창을 닫으시겠습니까? + + + 창 닫기 + + + 다시 묻지 않기 + 취소 @@ -745,6 +769,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + "{0}" 탭의 활동 + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + "{0}" 탭의 활동(창 "{1}") + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + 지정된 시작 디렉터리에서 새 탭 열기 @@ -881,10 +913,10 @@ 설정하면 이 명령은 프로필의 기본 명령 대신 프로필의 기본 명령에 추가됩니다. - 연결 다시 시작 + 세션 다시 시작 - 활성 창 연결 다시 시작 + 활성 창에서 세션을 다시 시작하세요. 짧은 요약 diff --git a/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw index 7a122e0a03..1342e0eed3 100644 --- a/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw @@ -496,24 +496,48 @@ Avisos de Terceiros A hyperlink name for the Terminal's third-party notices - + Cancelar - - Fechar tudo - - + Deseja fechar todas as janelas? - - Cancelar - - + Fechar tudo - + Deseja fechar todas as guias? + + Fechar tudo + + + Deseja fechar esta guia? + + + Fechar guia + + + Deseja fechar este painel? + + + Fechar painel + + + Deseja fechar estas guias? + + + Fechar guias + + + Deseja fechar estes painéis? + + + Fechar painéis + + + Não me pergunte novamente + Cancelar @@ -745,6 +769,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + Atividade na aba "{0}" + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Atividade na aba "{0}" (janela "{1}") + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Abrir uma nova guia no diretório inicial fornecido @@ -881,10 +913,10 @@ Se definido, o comando será acrescentado ao comando padrão do perfil em vez de substituí-lo. - Reiniciar conexão + Reiniciar sessão - Reiniciar a conexão do painel ativo + Reinicie a sessão no painel ativo Trechos diff --git a/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw index 8c2c8a652a..db987ba292 100644 --- a/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw @@ -496,23 +496,47 @@ Ţћĩřð-Ρářŧγ ñοŧīĉęŝ !!! !!! A hyperlink name for the Terminal's third-party notices - - Ċдйĉέł ! + + Ĉάйçэļ ! - - €ļőşε áļľ !!! + + Ďő убυ ẅåήт ţø ¢ľöѕē äľľ ẃιⁿðŏŵş? !!! !!! !!! - - Ďõ γбű ẁāŋţ ťó ςℓσśĕ äℓℓ шîйđбẁś? !!! !!! !!! + + Ċľóѕε ªĺĺ !!! - - Ćăʼnċęℓ ! + + Ďō γőű шдπŧ ŧò ςłοѕз āĺℓ ţäьš? !!! !!! !!! - - Ćļõѕέ аłℓ !!! + + Ĉŀõśê āłĺ !!! - - Đσ ŷőū шдиŧ тò čļòŝз αŀľ ţâвŝ? !!! !!! !!! + + Đó уøυ ẅāńť тο çŀǿśę ŧĥíš τάъ? !!! !!! !!! + + + Ċℓοѕē ţαъ !!! + + + Đò γθũ ώăńт ťǿ ¢ℓσŝę ŧħîŝ ρаńе? !!! !!! !!! + + + Ĉŀбśз φдŋё !!! + + + Đó ўоú ŵąňτ ŧò çŀσѕė ŧћěśé ţдьş? !!! !!! !!! + + + Ćŀöśé ŧãвś !!! + + + Ðǿ ỳбū ŵáήť ŧо ćļόśě τнέšê φăñєš? !!! !!! !!! + + + €łǿśē рāⁿęѕ !!! + + + Đòñ'ť ªѕķ мë àĝáîⁿ !!! !! Čǻñčėŀ ! @@ -745,6 +769,14 @@ Ẃϊйδοŵš !! This is displayed as a label for the context menu item that holds the submenu of available windows. + + Δćţíνïŧý īй τаь "{0}" !!! !!! + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Δсŧìνιŧý įņ ţªь "{0}" (ŵϊņδόώ "{1}") !!! !!! !!! ! + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Фφĕń ª пёẅ ţâь ίи ğīνęņ ѕŧāятĩлğ δįŗęćтŏяγ !!! !!! !!! !!! @@ -881,10 +913,10 @@ Ĩƒ šęţ, ŧнĕ ¢ömmдлδ ŵîĺł ьέ åφрєйδĕđ τσ ŧђė рřŏƒїłє'ş đзƒªūľţ ¢οmмăńδ іñѕţέáđ øƒ ѓēρļąċĭлĝ їţ. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! - Γēѕŧâяŧ ćǿńńēčťїöл !!! !! + Γēѕŧâяŧ ŝєѕѕïσⁿ !!! ! - Γėşťáгţ ŧħ℮ ãčтĩνέ ρăйё сǿηńëςтιóņ !!! !!! !!! ! + Γėşťáгţ ŧħ℮ ŝёšŝīőń įй τђ℮ ăċţΐνе φǻñē !!! !!! !!! !! Šņíрρēťş !! diff --git a/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw index 8c2c8a652a..db987ba292 100644 --- a/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw @@ -496,23 +496,47 @@ Ţћĩřð-Ρářŧγ ñοŧīĉęŝ !!! !!! A hyperlink name for the Terminal's third-party notices - - Ċдйĉέł ! + + Ĉάйçэļ ! - - €ļőşε áļľ !!! + + Ďő убυ ẅåήт ţø ¢ľöѕē äľľ ẃιⁿðŏŵş? !!! !!! !!! - - Ďõ γбű ẁāŋţ ťó ςℓσśĕ äℓℓ шîйđбẁś? !!! !!! !!! + + Ċľóѕε ªĺĺ !!! - - Ćăʼnċęℓ ! + + Ďō γőű шдπŧ ŧò ςłοѕз āĺℓ ţäьš? !!! !!! !!! - - Ćļõѕέ аłℓ !!! + + Ĉŀõśê āłĺ !!! - - Đσ ŷőū шдиŧ тò čļòŝз αŀľ ţâвŝ? !!! !!! !!! + + Đó уøυ ẅāńť тο çŀǿśę ŧĥíš τάъ? !!! !!! !!! + + + Ċℓοѕē ţαъ !!! + + + Đò γθũ ώăńт ťǿ ¢ℓσŝę ŧħîŝ ρаńе? !!! !!! !!! + + + Ĉŀбśз φдŋё !!! + + + Đó ўоú ŵąňτ ŧò çŀσѕė ŧћěśé ţдьş? !!! !!! !!! + + + Ćŀöśé ŧãвś !!! + + + Ðǿ ỳбū ŵáήť ŧо ćļόśě τнέšê φăñєš? !!! !!! !!! + + + €łǿśē рāⁿęѕ !!! + + + Đòñ'ť ªѕķ мë àĝáîⁿ !!! !! Čǻñčėŀ ! @@ -745,6 +769,14 @@ Ẃϊйδοŵš !! This is displayed as a label for the context menu item that holds the submenu of available windows. + + Δćţíνïŧý īй τаь "{0}" !!! !!! + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Δсŧìνιŧý įņ ţªь "{0}" (ŵϊņδόώ "{1}") !!! !!! !!! ! + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Фφĕń ª пёẅ ţâь ίи ğīνęņ ѕŧāятĩлğ δįŗęćтŏяγ !!! !!! !!! !!! @@ -881,10 +913,10 @@ Ĩƒ šęţ, ŧнĕ ¢ömmдлδ ŵîĺł ьέ åφрєйδĕđ τσ ŧђė рřŏƒїłє'ş đзƒªūľţ ¢οmмăńδ іñѕţέáđ øƒ ѓēρļąċĭлĝ їţ. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! - Γēѕŧâяŧ ćǿńńēčťїöл !!! !! + Γēѕŧâяŧ ŝєѕѕïσⁿ !!! ! - Γėşťáгţ ŧħ℮ ãčтĩνέ ρăйё сǿηńëςтιóņ !!! !!! !!! ! + Γėşťáгţ ŧħ℮ ŝёšŝīőń įй τђ℮ ăċţΐνе φǻñē !!! !!! !!! !! Šņíрρēťş !! diff --git a/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw index 8c2c8a652a..db987ba292 100644 --- a/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw @@ -496,23 +496,47 @@ Ţћĩřð-Ρářŧγ ñοŧīĉęŝ !!! !!! A hyperlink name for the Terminal's third-party notices - - Ċдйĉέł ! + + Ĉάйçэļ ! - - €ļőşε áļľ !!! + + Ďő убυ ẅåήт ţø ¢ľöѕē äľľ ẃιⁿðŏŵş? !!! !!! !!! - - Ďõ γбű ẁāŋţ ťó ςℓσśĕ äℓℓ шîйđбẁś? !!! !!! !!! + + Ċľóѕε ªĺĺ !!! - - Ćăʼnċęℓ ! + + Ďō γőű шдπŧ ŧò ςłοѕз āĺℓ ţäьš? !!! !!! !!! - - Ćļõѕέ аłℓ !!! + + Ĉŀõśê āłĺ !!! - - Đσ ŷőū шдиŧ тò čļòŝз αŀľ ţâвŝ? !!! !!! !!! + + Đó уøυ ẅāńť тο çŀǿśę ŧĥíš τάъ? !!! !!! !!! + + + Ċℓοѕē ţαъ !!! + + + Đò γθũ ώăńт ťǿ ¢ℓσŝę ŧħîŝ ρаńе? !!! !!! !!! + + + Ĉŀбśз φдŋё !!! + + + Đó ўоú ŵąňτ ŧò çŀσѕė ŧћěśé ţдьş? !!! !!! !!! + + + Ćŀöśé ŧãвś !!! + + + Ðǿ ỳбū ŵáήť ŧо ćļόśě τнέšê φăñєš? !!! !!! !!! + + + €łǿśē рāⁿęѕ !!! + + + Đòñ'ť ªѕķ мë àĝáîⁿ !!! !! Čǻñčėŀ ! @@ -745,6 +769,14 @@ Ẃϊйδοŵš !! This is displayed as a label for the context menu item that holds the submenu of available windows. + + Δćţíνïŧý īй τаь "{0}" !!! !!! + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Δсŧìνιŧý įņ ţªь "{0}" (ŵϊņδόώ "{1}") !!! !!! !!! ! + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Фφĕń ª пёẅ ţâь ίи ğīνęņ ѕŧāятĩлğ δįŗęćтŏяγ !!! !!! !!! !!! @@ -881,10 +913,10 @@ Ĩƒ šęţ, ŧнĕ ¢ömmдлδ ŵîĺł ьέ åφрєйδĕđ τσ ŧђė рřŏƒїłє'ş đзƒªūľţ ¢οmмăńδ іñѕţέáđ øƒ ѓēρļąċĭлĝ їţ. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! - Γēѕŧâяŧ ćǿńńēčťїöл !!! !! + Γēѕŧâяŧ ŝєѕѕïσⁿ !!! ! - Γėşťáгţ ŧħ℮ ãčтĩνέ ρăйё сǿηńëςтιóņ !!! !!! !!! ! + Γėşťáгţ ŧħ℮ ŝёšŝīőń įй τђ℮ ăċţΐνе φǻñē !!! !!! !!! !! Šņíрρēťş !! diff --git a/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw index 1cbc6cfeb6..0ade0378de 100644 --- a/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw @@ -496,24 +496,48 @@ Уведомления третьих лиц A hyperlink name for the Terminal's third-party notices - + Отмена - - Закрыть все - - + Закрыть все окна? - - Отмена - - + Закрыть все - + Закрыть все вкладки? + + Закрыть все + + + Закрыть эту вкладку? + + + Закрыть вкладку + + + Закрыть эту панель? + + + Закрыть область + + + Закрыть эти вкладки? + + + Закрыть вкладки + + + Закрыть эти панели? + + + Закрыть панели + + + Больше не спрашивать + Отмена @@ -745,6 +769,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + Активность на вкладке "{0}" + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + Активность на вкладке "{0}" (окно "{1}") + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + Открыть новую вкладку в указанном начальном каталоге @@ -881,10 +913,10 @@ Если этот параметр настроен, команда будет добавлена к стандартной команде профиля, а не заменит ее. - Перезапустить подключение + Перезапустить сеанс - Перезапустить соединение с активной панелью. + Перезапустите сеанс в активной панели Фрагменты diff --git a/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw index bd1fd3eb79..2d02620a93 100644 --- a/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw @@ -496,22 +496,10 @@ 第三方通知 A hyperlink name for the Terminal's third-party notices - - 取消 - - - 全部关闭 - - + 是否要关闭所有窗口? - - 取消 - - - 全部关闭 - - + 是否要关闭所有标签页? @@ -745,6 +733,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + 选项卡“{0}”中的活动 + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + 选项卡“{0}”(窗口“{1}”)中的活动 + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + 在给定的起始目录中打开新选项卡 @@ -881,10 +877,10 @@ 如果设置,该命令将追加到配置文件的默认命令,而不是替换它。 - 重新启动连接 + 重启会话 - 重新启动活动窗格连接 + 重启活动窗格中的会话 片段 diff --git a/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw index a296905eaa..096a0ad7f9 100644 --- a/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw @@ -496,24 +496,48 @@ 第三方注意事項 A hyperlink name for the Terminal's third-party notices - + 取消 - - 全部關閉 - - + 您要關閉所有視窗嗎? - - 取消 - - + 全部關閉 - + 您要關閉所有索引標籤嗎? + + 全部關閉 + + + 是否要關閉此索引標籤? + + + 關閉索引標籤 + + + 是否要關閉此窗格? + + + 關閉窗格 + + + 是否要關閉這些索引標籤? + + + 關閉索引標籤 + + + 是否要關閉這些窗格? + + + 關閉窗格 + + + 不要再問我 + 取消 @@ -745,6 +769,14 @@ Windows This is displayed as a label for the context menu item that holds the submenu of available windows. + + 索引標籤「{0}」中的活動 + {0} is the tab title. Shown as the body of a desktop notification when tab activity is detected. + + + 索引標籤「{0}」(視窗「{1}」) 中的活動 + {0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name. + 開啟指定起始目錄中的新索引標籤 @@ -881,10 +913,10 @@ 如果設定,命令會附加到設定檔的預設命令,而不是取代命令。 - 重新啟動連線 + 重新啟動工作模式 - 重新啟動使用中的窗格連線 + 在使用中窗格重新啟動工作階段 片斷 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw index c513df1870..3b20dcb8ee 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw @@ -1553,6 +1553,10 @@ Blinkendes Fenster An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Desktopbenachrichtigung + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Neu hinzufügen Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ Warnen, wenn mehrere Registerkarten geschlossen werden Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Beim Schließen warnen + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Steuert, wann ein Bestätigungsdialogfeld angezeigt wird, bevor Registerkarten oder Fenster geschlossen werden. "Immer" zeigt das Dialogfeld beim Schließen eines Fensters an. + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Nie + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Immer + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Mehrere Registerkarten oder Bereiche + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Warnen, wenn „Dienst für Bildschirmtastatur und Handschrifteingabefeld“ deaktiviert ist diff --git a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw index adee08e315..28fc273118 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw @@ -1553,6 +1553,10 @@ Ventana Flash An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Notificaciones de escritorio + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Agregar nuevo Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ Advertir al cerrar más de una pestaña Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Advertir al cerrar + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Controla cuándo aparece un cuadro de diálogo de confirmación antes de cerrar pestañas o ventanas. "Siempre" presenta el cuadro de diálogo al cerrar cualquier panel. + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Nunca + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Siempre + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Varias pestañas o paneles + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Advertir cuando el servicio "Panel de escritura a mano y teclado táctil" está deshabilitado diff --git a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw index de770bfa41..6dbe23803b 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw @@ -1553,6 +1553,10 @@ Fenêtre Flash An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Notification de bureau + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Ajouter nouveau Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ M'avertir lorsque je ferme plusieurs onglets Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Avertir lors de la fermeture + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Contrôle l’apparition d’une boîte de dialogue de confirmation avant la fermeture des onglets ou des fenêtres. « Toujours » affiche la boîte de dialogue lors de la fermeture de n’importe quel volet. + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Jamais + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Toujours + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Plusieurs onglets ou volets + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Avertir lorsque le « service clavier tactile et volet d’écriture manuscrite » est désactivé diff --git a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw index 9a064008b5..72778d4534 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw @@ -1553,6 +1553,10 @@ Finestra di Flash An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Notifica desktop + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Aggiungi nuovo Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ Avvisa in caso di chiusura di più schede Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Avvisa in caso di chiusura + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Controlla quando viene visualizzata una finestra di dialogo di conferma prima di chiudere schede o finestre. "Sempre" visualizza la finestra di dialogo quando si chiude un riquadro. + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Mai + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Sempre + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Più schede o pannelli + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Avvisa quando il servizio "Tastiera virtuale e pannello per la grafia" è disabilitato diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw index bbd0167a5d..7ac0c6cc8e 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw @@ -1553,6 +1553,10 @@ フラッシュ ウィンドウ An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + デスクトップ通知 + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + 新規追加 Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ 複数のタブを閉じるときに警告する Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + 閉じるときに警告する + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + タブまたはウィンドウを閉じる前に確認ダイアログを表示するタイミングを制御します。[常に] を選択すると、ウィンドウを閉じるときにダイアログが表示されます。 + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + しない + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + 常に + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + 複数のタブまたはウィンドウ + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + [タッチ キーボードと手書きパネル サービス] が無効になっている場合に警告する diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw index aecd60527d..cd4e601694 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw @@ -1553,6 +1553,10 @@ 플래시 창 An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + 데스크톱 알림 + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + 새로 추가 Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ 두 개 이상의 탭을 닫을 때 경고 Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + 닫을 때 경고 표시 + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + 탭이나 창을 닫기 전에 확인 대화 상자가 나타나는 시기를 제어합니다. "항상"은 창을 닫을 때 대화 상자를 표시합니다. + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + 사용 안 함 + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + 항상 + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + 여러 탭 또는 창 + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + "터치 키보드 및 필기 패널 서비스"를 사용할 수 없는 경우 경고 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw index e22d0a14eb..7d52d28450 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw @@ -1553,6 +1553,10 @@ Piscar janela An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Notificação da área de trabalho + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Adicionar novo Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ Avisar ao fechar mais de uma guia Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Avisar ao fechar + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Controla quando uma caixa de diálogo de confirmação aparece antes de fechar guias ou janelas. "Sempre" apresenta a caixa de diálogo ao fechar qualquer painel. + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Nunca + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Sempre + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Múltiplas guias ou painéis + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Avisar quando o "Serviço de Teclado Virtual e Painel de Manuscrito" estiver desabilitado diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw index 9a5bada6ae..cdf6c6bf63 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw @@ -1553,6 +1553,10 @@ ₣łāŝћ ẅїňďŏщ !!! An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Ðëśкťõρ ʼnσţíƒΐçâτĭõη !!! !!! + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Äδď ⁿĕш !! Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ Ẃářй ẅђëπ ĉľôśĩήĝ mǿѓĕ тĥąπ òπё τάь !!! !!! !!! ! Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Ŵǻřπ ωћеŋ ςĺõşϊйĝ !!! !! + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Ĉбńţřòłѕ шĥεπ à čоņƒϊřmąτīóп ďíдłбġ ªррéǻŕѕ ъеƒбѓě ςłôśîпğ ţавś оѓ шϊńδǿẅş. "Άŀшãўś" ргзŝêņţš ťнê ðіāľŏĝ ẃћĕй ċℓöѕíñĝ αпŷ рāйε. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Ņèνέѓ ! + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Δŀώǻỳş ! + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Μύłтîрĺё ťдьś óя φąŋéŝ !!! !!! + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Ẃǻґņ ώћĕπ "Ŧõũčђ Κзγьοдгď ąʼnð Нáлđẅŕīťίńģ Ρàňεℓ Śεŕνîçé" íš đìşāъŀêδ !!! !!! !!! !!! !!! !!! !! diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw index 9a5bada6ae..cdf6c6bf63 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw @@ -1553,6 +1553,10 @@ ₣łāŝћ ẅїňďŏщ !!! An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Ðëśкťõρ ʼnσţíƒΐçâτĭõη !!! !!! + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Äδď ⁿĕш !! Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ Ẃářй ẅђëπ ĉľôśĩήĝ mǿѓĕ тĥąπ òπё τάь !!! !!! !!! ! Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Ŵǻřπ ωћеŋ ςĺõşϊйĝ !!! !! + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Ĉбńţřòłѕ шĥεπ à čоņƒϊřmąτīóп ďíдłбġ ªррéǻŕѕ ъеƒбѓě ςłôśîпğ ţавś оѓ шϊńδǿẅş. "Άŀшãўś" ргзŝêņţš ťнê ðіāľŏĝ ẃћĕй ċℓöѕíñĝ αпŷ рāйε. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Ņèνέѓ ! + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Δŀώǻỳş ! + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Μύłтîрĺё ťдьś óя φąŋéŝ !!! !!! + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Ẃǻґņ ώћĕπ "Ŧõũčђ Κзγьοдгď ąʼnð Нáлđẅŕīťίńģ Ρàňεℓ Śεŕνîçé" íš đìşāъŀêδ !!! !!! !!! !!! !!! !!! !! diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw index 9a5bada6ae..cdf6c6bf63 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw @@ -1553,6 +1553,10 @@ ₣łāŝћ ẅїňďŏщ !!! An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Ðëśкťõρ ʼnσţíƒΐçâτĭõη !!! !!! + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Äδď ⁿĕш !! Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ Ẃářй ẅђëπ ĉľôśĩήĝ mǿѓĕ тĥąπ òπё τάь !!! !!! !!! ! Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Ŵǻřπ ωћеŋ ςĺõşϊйĝ !!! !! + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Ĉбńţřòłѕ шĥεπ à čоņƒϊřmąτīóп ďíдłбġ ªррéǻŕѕ ъеƒбѓě ςłôśîпğ ţавś оѓ шϊńδǿẅş. "Άŀшãўś" ргзŝêņţš ťнê ðіāľŏĝ ẃћĕй ċℓöѕíñĝ αпŷ рāйε. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Ņèνέѓ ! + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Δŀώǻỳş ! + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Μύłтîрĺё ťдьś óя φąŋéŝ !!! !!! + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Ẃǻґņ ώћĕπ "Ŧõũčђ Κзγьοдгď ąʼnð Нáлđẅŕīťίńģ Ρàňεℓ Śεŕνîçé" íš đìşāъŀêδ !!! !!! !!! !!! !!! !!! !! diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw index 4407da146b..2ed9ed275d 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw @@ -1553,6 +1553,10 @@ Мигающее окно An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + Уведомления на рабочем столе + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + Добавить новую Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ Предупреждать при закрытии нескольких вкладок Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + Предупреждать при закрытии + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + Определяет, когда появляется диалоговое окно подтверждения перед закрытием вкладок или окон. "Всегда" — диалог отображается при закрытии любой панели. + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + Никогда + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + Всегда + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + Несколько вкладок или панелей + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + Предупреждать, если параметр "Служба сенсорной клавиатуры и панели рукописного ввода" отключен diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw index 62180d38ef..efa2a3736c 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw @@ -1553,6 +1553,10 @@ 闪烁窗口 An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + 桌面通知 + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + 新增 Button label that creates a new color scheme. @@ -2197,6 +2201,10 @@ 关闭多个选项卡时发出警告 Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + 控制在关闭选项卡或窗口之前何时显示确认对话框。“始终”在关闭任何窗格时显示对话框。 + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + 禁用“触摸键盘和手写面板服务”时发出警告 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw index f7671ba670..ed47981d0e 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw @@ -1553,6 +1553,10 @@ 快閃視窗 An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed. + + 桌面通知 + An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user. + 新增 Button label that creates a new color scheme. @@ -2197,6 +2201,26 @@ 關閉多個索引標籤時發出警告 Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + 關閉時警告 + Header for a dropdown controlling when to show a confirmation dialog before closing. + + + 控制在關閉索引標籤或視窗之前出現確認對話方塊的時間。[永遠] 會在關閉任何窗格時顯示對話方塊。 + Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + + 一律不要 + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + 一律 + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + 多個索引標籤或窗格 + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + 停用「觸控式鍵盤和手寫面板服務」時發出警告 diff --git a/src/cascadia/TerminalSettingsModel/Resources/de-DE/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/de-DE/Resources.resw index 28fde2c635..facba2a8bd 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/de-DE/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Verbindung neu starten + Sitzung neu starten Notizblock öffnen diff --git a/src/cascadia/TerminalSettingsModel/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/es-ES/Resources.resw index b3a530a7ad..0380fe3a32 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/es-ES/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Reiniciar conexión + Reiniciar sesión Abrir el bloc de notas diff --git a/src/cascadia/TerminalSettingsModel/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/fr-FR/Resources.resw index def18e6251..1bcf1c598d 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/fr-FR/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Redémarrer la connexion + Redémarrer la session Ouvrir le bloc-notes diff --git a/src/cascadia/TerminalSettingsModel/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/it-IT/Resources.resw index 1d59e4b8fd..fa31357b52 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/it-IT/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Riavvia connessione + Riavvia la sessione Aprire scratchpad diff --git a/src/cascadia/TerminalSettingsModel/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/ja-JP/Resources.resw index c72bd80bdf..755d5d5d62 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/ja-JP/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - 接続の再起動 + セッションの再開 スクラッチパッドを開く diff --git a/src/cascadia/TerminalSettingsModel/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/ko-KR/Resources.resw index 7f3a820c0b..57fe72b9d9 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/ko-KR/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - 연결 다시 시작 + 세션 다시 시작 스크래치 패드 열기 diff --git a/src/cascadia/TerminalSettingsModel/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/pt-BR/Resources.resw index dc6d7c2c0b..5cc5f45248 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/pt-BR/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Reiniciar conexão + Reiniciar sessão Abrir o scratchpad diff --git a/src/cascadia/TerminalSettingsModel/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/qps-ploc/Resources.resw index 27a124e407..bfe4714838 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/qps-ploc/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Ŗ℮ŝţāґт čõʼnлęčŧįоή !!! !! + Ŗ℮ŝţāґт ѕēšŝĭσή !!! ! Θφěп ŝĉґαŧςђρąδ !!! ! diff --git a/src/cascadia/TerminalSettingsModel/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/qps-ploca/Resources.resw index 27a124e407..bfe4714838 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/qps-ploca/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Ŗ℮ŝţāґт čõʼnлęčŧįоή !!! !! + Ŗ℮ŝţāґт ѕēšŝĭσή !!! ! Θφěп ŝĉґαŧςђρąδ !!! ! diff --git a/src/cascadia/TerminalSettingsModel/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/qps-plocm/Resources.resw index 27a124e407..bfe4714838 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/qps-plocm/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Ŗ℮ŝţāґт čõʼnлęčŧįоή !!! !! + Ŗ℮ŝţāґт ѕēšŝĭσή !!! ! Θφěп ŝĉґαŧςђρąδ !!! ! diff --git a/src/cascadia/TerminalSettingsModel/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/ru-RU/Resources.resw index fbae0922e2..8b6534ce84 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/ru-RU/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - Перезапустить подключение + Перезапустить сеанс Открыть временную память diff --git a/src/cascadia/TerminalSettingsModel/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/zh-CN/Resources.resw index ca30f12637..450405e58f 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/zh-CN/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - 重新启动连接 + 重启会话 打开便笺本 diff --git a/src/cascadia/TerminalSettingsModel/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/zh-TW/Resources.resw index 890b4c1c75..2b4d858dc9 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/zh-TW/Resources.resw @@ -702,7 +702,7 @@ When enabled, input will go to all panes in this tab simultaneously - 重新啟動連線 + 重新啟動工作模式 開啟聽寫面板 From d3f76e7acf88436497850ce36ca4fa5c8bb61be0 Mon Sep 17 00:00:00 2001 From: Windows Console Service Bot <14666831+consvc@users.noreply.github.com> Date: Thu, 7 May 2026 14:03:13 -0500 Subject: [PATCH 18/18] Localization Updates - main - 05/07/2026 03:04:15 (#20196) Co-authored-by: Console Service Bot --- .../Resources/zh-CN/Resources.resw | 36 +++++++++++++++++++ .../Resources/zh-CN/Resources.resw | 16 +++++++++ 2 files changed, 52 insertions(+) diff --git a/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw index 2d02620a93..7420369e14 100644 --- a/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw @@ -496,12 +496,48 @@ 第三方通知 A hyperlink name for the Terminal's third-party notices + + 取消 + 是否要关闭所有窗口? + + 全部关闭 + 是否要关闭所有标签页? + + 全部关闭 + + + 是否要关闭此选项卡? + + + 关闭选项卡 + + + 是否要关闭此窗格? + + + 关闭窗格 + + + 是否要关闭这些选项卡? + + + 关闭选项卡 + + + 是否要关闭这些窗格? + + + 关闭窗格 + + + 不再询问 + 取消 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw index efa2a3736c..9b5a5fab20 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw @@ -2201,10 +2201,26 @@ 关闭多个选项卡时发出警告 Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open. + + 关闭时发出警告 + Header for a dropdown controlling when to show a confirmation dialog before closing. + 控制在关闭选项卡或窗口之前何时显示确认对话框。“始终”在关闭任何窗格时显示对话框。 Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content. + + 从不 + Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing. + + + 始终 + Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing. + + + 多个选项卡或窗格 + Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present. + 禁用“触摸键盘和手写面板服务”时发出警告