mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-06 14:19:45 +00:00
Compare commits
190 Commits
dev/migrie
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e301b010d | ||
|
|
27887603b4 | ||
|
|
87c840b381 | ||
|
|
91616885db | ||
|
|
089c015347 | ||
|
|
dea94d51ad | ||
|
|
83649075a7 | ||
|
|
e9375d67f1 | ||
|
|
4b4e057a75 | ||
|
|
35c82d37f0 | ||
|
|
4acbffb0e3 | ||
|
|
aaefdf4408 | ||
|
|
1f2bb760eb | ||
|
|
5cb4ab1a9e | ||
|
|
cfe879da96 | ||
|
|
ac62de78a2 | ||
|
|
9870eb1d39 | ||
|
|
e06ce39811 | ||
|
|
997212f9c5 | ||
|
|
2ab0a50a11 | ||
|
|
376939cef8 | ||
|
|
15a7d49f4d | ||
|
|
ef595b497a | ||
|
|
97676cedd8 | ||
|
|
91bf709ca6 | ||
|
|
7abed9f6fb | ||
|
|
b4a52c847f | ||
|
|
3f21996589 | ||
|
|
fd74d59c6c | ||
|
|
04478d1df0 | ||
|
|
589286a357 | ||
|
|
d74b66a0a7 | ||
|
|
ae5b04f7b2 | ||
|
|
3434208947 | ||
|
|
32379c29f0 | ||
|
|
cd2166aedf | ||
|
|
66f4f9d9ea | ||
|
|
bbc570d107 | ||
|
|
238b5c2e22 | ||
|
|
55dd4af9cb | ||
|
|
2970017243 | ||
|
|
1faf67fba3 | ||
|
|
024b9fc0f4 | ||
|
|
aa4e9f5414 | ||
|
|
76b00e3b31 | ||
|
|
07d58a800c | ||
|
|
f893f7516a | ||
|
|
702e15ce5a | ||
|
|
ff23726b7c | ||
|
|
7675354b2d | ||
|
|
16028dee8b | ||
|
|
c6b67aad4b | ||
|
|
bd403dc8e7 | ||
|
|
f025c53dba | ||
|
|
66ecb0bd63 | ||
|
|
95a19624a4 | ||
|
|
86dfefa690 | ||
|
|
478c2c3613 | ||
|
|
a579566a1d | ||
|
|
f1b6b17c58 | ||
|
|
7b8a53c030 | ||
|
|
d6a9e9ffb6 | ||
|
|
eb1d6b599e | ||
|
|
2cd2351deb | ||
|
|
843e61aa8a | ||
|
|
f785168aac | ||
|
|
8fba292bd7 | ||
|
|
9e8427d81e | ||
|
|
059b53bf94 | ||
|
|
4d48f305a1 | ||
|
|
06e2317012 | ||
|
|
4071df73ba | ||
|
|
19605bf75b | ||
|
|
8962f88f90 | ||
|
|
eb4b2a7534 | ||
|
|
72a4e936cc | ||
|
|
1f083cbd89 | ||
|
|
1ac7fe16ae | ||
|
|
ff7a632f0f | ||
|
|
797ebae6e1 | ||
|
|
4f7e99123a | ||
|
|
b8cd2b239f | ||
|
|
24a53d4968 | ||
|
|
023eb75550 | ||
|
|
0b97c7b5ca | ||
|
|
f7d93849a8 | ||
|
|
7707716b08 | ||
|
|
6436e712e7 | ||
|
|
08c2f350e6 | ||
|
|
a5fb91dd4c | ||
|
|
848314ef17 | ||
|
|
deffbbc7f5 | ||
|
|
f12ee745ef | ||
|
|
9eb191d545 | ||
|
|
d866908eaf | ||
|
|
2e7a95ddb5 | ||
|
|
75e462441d | ||
|
|
c754f4d22d | ||
|
|
b22684e697 | ||
|
|
1b630ab6f6 | ||
|
|
cac52a9e30 | ||
|
|
94e1697a48 | ||
|
|
1de1325cd1 | ||
|
|
dc8183a525 | ||
|
|
2a7dd8b730 | ||
|
|
f685720cac | ||
|
|
205c09ccb8 | ||
|
|
799b5d4add | ||
|
|
730eb5fafd | ||
|
|
cd35bc5989 | ||
|
|
4e20a8631c | ||
|
|
bfd910c4ca | ||
|
|
715844b01c | ||
|
|
1b81c6540f | ||
|
|
f4c4efc7f0 | ||
|
|
d76c70c470 | ||
|
|
ed27737233 | ||
|
|
c157f6346a | ||
|
|
9dca6c27ee | ||
|
|
7dbe741e1a | ||
|
|
fb1491a4af | ||
|
|
11b810e403 | ||
|
|
6439b4d807 | ||
|
|
dfd345405a | ||
|
|
daa2ef139f | ||
|
|
44ac527f31 | ||
|
|
78852e04ec | ||
|
|
52f7664d01 | ||
|
|
223e270778 | ||
|
|
c5fad74c54 | ||
|
|
bb03b00ebf | ||
|
|
4c333536b4 | ||
|
|
bf41a90ad8 | ||
|
|
d82af9367f | ||
|
|
77215d9d77 | ||
|
|
0154da5d33 | ||
|
|
eac5cebbc6 | ||
|
|
7d4ee45e4e | ||
|
|
02fa24cb12 | ||
|
|
f898855c82 | ||
|
|
a38fe5f1a6 | ||
|
|
bbe32f80e5 | ||
|
|
446d07e79f | ||
|
|
a74b45aa2c | ||
|
|
c588a9c75d | ||
|
|
082c63bde5 | ||
|
|
91977bec5a | ||
|
|
07a1a07e47 | ||
|
|
ce8f8fb618 | ||
|
|
538285cc45 | ||
|
|
b1ee82ae18 | ||
|
|
358edd520a | ||
|
|
bf0f516634 | ||
|
|
99308b43e2 | ||
|
|
2a9eefc2d9 | ||
|
|
33b1ab9e79 | ||
|
|
7b3ca83329 | ||
|
|
76d8fa7b7e | ||
|
|
9141f0419a | ||
|
|
857fb399e1 | ||
|
|
b3129192ad | ||
|
|
b253440cf5 | ||
|
|
5429fca422 | ||
|
|
46e299d2b6 | ||
|
|
34601f7e05 | ||
|
|
cf70797083 | ||
|
|
07ba33b893 | ||
|
|
f818885636 | ||
|
|
738d1910da | ||
|
|
651efe248b | ||
|
|
768d4c0df3 | ||
|
|
8ceb9baf9a | ||
|
|
35ca313b48 | ||
|
|
1a78557b61 | ||
|
|
dafb627278 | ||
|
|
eeb01a139d | ||
|
|
4a8f0e9562 | ||
|
|
ea9d3cb5f7 | ||
|
|
3d15b097b7 | ||
|
|
5a07282d19 | ||
|
|
7e792b2b5e | ||
|
|
c3a94454e0 | ||
|
|
2f23e1fc0c | ||
|
|
996c71a933 | ||
|
|
7731f5943a | ||
|
|
bb49d5086c | ||
|
|
e168413e9f | ||
|
|
a59e3d0c57 | ||
|
|
f73da456fa | ||
|
|
9ccd6ecd74 |
3156
.github/fabricbot.json
vendored
Normal file
3156
.github/fabricbot.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -410,6 +410,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InteractivityOneCore", "src
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererWddmCon", "src\renderer\wddmcon\lib\wddmcon.vcxproj", "{75C6F576-18E9-4566-978A-F0A301CAC090}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Audio", "Audio", "{40BD8415-DD93-4200-8D82-498DDDC08CC8}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MidiAudio", "src\audio\midi\lib\midi.vcxproj", "{3C67784E-1453-49C2-9660-483E2CC7F7AD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
AuditMode|Any CPU = AuditMode|Any CPU
|
||||
@@ -3449,6 +3453,46 @@ Global
|
||||
{75C6F576-18E9-4566-978A-F0A301CAC090}.Release|x64.Build.0 = Release|x64
|
||||
{75C6F576-18E9-4566-978A-F0A301CAC090}.Release|x86.ActiveCfg = Release|Win32
|
||||
{75C6F576-18E9-4566-978A-F0A301CAC090}.Release|x86.Build.0 = Release|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|x64.Build.0 = Debug|x64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Debug|x86.Build.0 = Debug|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|x64.ActiveCfg = Release|x64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|x64.Build.0 = Release|x64
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|x86.ActiveCfg = Release|Win32
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -3552,6 +3596,8 @@ Global
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
|
||||
{06EC74CB-9A12-428C-B551-8537EC964726} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
{75C6F576-18E9-4566-978A-F0A301CAC090} = {05500DEF-2294-41E3-AF9A-24E580B82836}
|
||||
{40BD8415-DD93-4200-8D82-498DDDC08CC8} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
|
||||
{3C67784E-1453-49C2-9660-483E2CC7F7AD} = {40BD8415-DD93-4200-8D82-498DDDC08CC8}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
|
||||
|
||||
@@ -111,10 +111,10 @@ repository.
|
||||
|
||||
---
|
||||
|
||||
## Windows Terminal 2.0 Roadmap
|
||||
## Windows Terminal Roadmap
|
||||
|
||||
The plan for delivering Windows Terminal 2.0 [is described
|
||||
here](/doc/terminal-v2-roadmap.md) and will be updated as the project proceeds.
|
||||
The plan for the Windows Terminal [is described here](/doc/roadmap-2022.md) and
|
||||
will be updated as the project proceeds.
|
||||
|
||||
## Project Build Status
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
pool:
|
||||
pool:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
parameters:
|
||||
- name: branding
|
||||
@@ -195,7 +195,6 @@ jobs:
|
||||
condition: true
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /t:Terminal\CascadiaPackage /p:WindowsTerminalReleaseBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
@@ -222,7 +221,6 @@ jobs:
|
||||
displayName: Build solution **\OpenConsole.sln for PublicTerminalCore
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /p:WindowsTerminalReleaseBuild=true /t:Terminal\wpf\PublicTerminalCore
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
@@ -231,7 +229,6 @@ jobs:
|
||||
displayName: Build solution **\OpenConsole.sln for ConPTY
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /p:WindowsTerminalReleaseBuild=true /t:Conhost\Host_EXE;Conhost\winconpty_DLL
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
@@ -327,7 +324,7 @@ jobs:
|
||||
|
||||
- ${{ if eq(parameters.runCompliance, true) }}:
|
||||
- template: ./templates/build-console-compliance-job.yml
|
||||
|
||||
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- job: BundleAndSign
|
||||
strategy:
|
||||
@@ -546,7 +543,6 @@ jobs:
|
||||
displayName: Build solution **\OpenConsole.sln for WPF Control
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:WindowsTerminalReleaseBuild=$(UseReleaseBranding);Version=$(XES_PACKAGEVERSIONNUMBER) /t:Pack
|
||||
platform: Any CPU
|
||||
configuration: $(BuildConfiguration)
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -27,7 +27,6 @@ jobs:
|
||||
displayName: 'Build solution **\OpenConsole.sln'
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
platform: '$(BuildPlatform)'
|
||||
configuration: '$(BuildConfiguration)'
|
||||
msbuildArgs: ${{ parameters.additionalBuildArguments }}
|
||||
|
||||
@@ -12,12 +12,12 @@ jobs:
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
WindowsTerminalBranding: ${{ parameters.branding }}
|
||||
EnableRichCodeNavigation: true
|
||||
pool:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
- steps: restore-nuget-steps.yml
|
||||
- template: restore-nuget-steps.yml
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
|
||||
@@ -9,12 +9,12 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -32,12 +32,11 @@ jobs:
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 'Build solution **\OpenConsole.sln'
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
platform: '$(BuildPlatform)'
|
||||
configuration: '$(BuildConfiguration)'
|
||||
msbuildArgs: "${{ parameters.additionalBuildArguments }}"
|
||||
@@ -88,4 +87,4 @@ jobs:
|
||||
displayName: 'Publish All Build Artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'fuzzingBuildOutput'
|
||||
ArtifactName: 'fuzzingBuildOutput'
|
||||
|
||||
@@ -12,12 +12,12 @@ jobs:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Instrument'
|
||||
pool:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
configuration: ${{ parameters.configuration }}
|
||||
platform: ${{ parameters.platform }}
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
|
||||
|
||||
- template: helix-processtestresults-job.yml
|
||||
parameters:
|
||||
name: 'ProcessTestResults'
|
||||
|
||||
@@ -28,7 +28,6 @@ steps:
|
||||
displayName: 'Build solution **\OpenConsole.sln'
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
platform: '$(BuildPlatform)'
|
||||
configuration: '$(BuildConfiguration)'
|
||||
msbuildArgs: "${{ parameters.additionalBuildArguments }} /p:PGOBuildMode=$(PGOBuildMode) /bl:$(Build.SourcesDirectory)\\msbuild.binlog"
|
||||
|
||||
@@ -11,12 +11,12 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2022</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>15</VersionMinor>
|
||||
<VersionMinor>16</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<!-- Managed packages -->
|
||||
<package id="Appium.WebDriver" version="3.0.0.2" targetFramework="net45" />
|
||||
<package id="Castle.Core" version="4.1.1" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net45" />
|
||||
<package id="Selenium.Support" version="3.5.0" targetFramework="net45" />
|
||||
<package id="Selenium.WebDriver" version="3.5.0" targetFramework="net45" />
|
||||
</packages>
|
||||
|
||||
@@ -110,7 +110,7 @@ This takes quite some time, and only generates an `msix`. It does not install th
|
||||
|
||||
```powershell
|
||||
# If you haven't already:
|
||||
Import-Module tools\OpenConsole.psm1;
|
||||
Import-Module .\tools\OpenConsole.psm1;
|
||||
Set-MsBuildDevEnvironment;
|
||||
|
||||
# The Set-MsBuildDevEnvironment call is needed for finding the path to
|
||||
@@ -121,7 +121,7 @@ if ((Get-AppxPackage -Name 'WindowsTerminalDev*') -ne $null) {
|
||||
Remove-AppxPackage 'WindowsTerminalDev_0.0.1.0_x64__8wekyb3d8bbwe'
|
||||
};
|
||||
New-Item ..\loose -Type Directory -Force;
|
||||
makeappx unpack /v /o /p .\CascadiaPackage_0.0.1.0_x64_Debug.msix /d ..\Loose\;
|
||||
makeappx unpack /v /o /p .\CascadiaPackage_0.0.1.0_x64_Debug.msix /d ..\loose\;
|
||||
Add-AppxPackage -Path ..\loose\AppxManifest.xml -Register -ForceUpdateFromAnyVersion -ForceApplicationShutdown
|
||||
```
|
||||
|
||||
|
||||
@@ -318,6 +318,7 @@
|
||||
"moveFocus",
|
||||
"movePane",
|
||||
"swapPane",
|
||||
"markMode",
|
||||
"moveTab",
|
||||
"multipleActions",
|
||||
"newTab",
|
||||
@@ -349,9 +350,11 @@
|
||||
"switchToTab",
|
||||
"tabSearch",
|
||||
"toggleAlwaysOnTop",
|
||||
"toggleBlockSelection",
|
||||
"toggleFocusMode",
|
||||
"selectAll",
|
||||
"setFocusMode",
|
||||
"switchSelectionEndpoint",
|
||||
"toggleFullscreen",
|
||||
"setFullScreen",
|
||||
"setMaximized",
|
||||
@@ -363,6 +366,10 @@
|
||||
"quit",
|
||||
"adjustOpacity",
|
||||
"restoreLastClosed",
|
||||
"addMark",
|
||||
"scrollToMark",
|
||||
"clearMark",
|
||||
"clearAllMarks",
|
||||
"unbound"
|
||||
],
|
||||
"type": "string"
|
||||
@@ -382,6 +389,15 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ScrollToMarkDirection": {
|
||||
"enum": [
|
||||
"previous",
|
||||
"next",
|
||||
"first",
|
||||
"last"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ResizeDirection": {
|
||||
"enum": [
|
||||
"left",
|
||||
@@ -731,6 +747,30 @@
|
||||
"direction"
|
||||
]
|
||||
},
|
||||
"ScrollToMarkAction": {
|
||||
"description": "Arguments corresponding to a Scroll to Mark Action",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/ShortcutAction"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"const": "scrollToMark"
|
||||
},
|
||||
"direction": {
|
||||
"$ref": "#/$defs/ScrollToMarkDirection",
|
||||
"default": "previous",
|
||||
"description": "The direction to scroll to a mark."
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": [
|
||||
"direction"
|
||||
]
|
||||
},
|
||||
"SendInputAction": {
|
||||
"description": "Arguments corresponding to a Send Input Action",
|
||||
"allOf": [
|
||||
@@ -838,6 +878,27 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"AddMarkAction": {
|
||||
"description": "Arguments corresponding to an Add Mark Action",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/ShortcutAction"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"const": "addMark"
|
||||
},
|
||||
"color": {
|
||||
"$ref": "#/$defs/Color",
|
||||
"default": null,
|
||||
"description": "If provided, will set the mark's color to the given value."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"SetColorSchemeAction": {
|
||||
"description": "Arguments corresponding to a Set Color Scheme Action",
|
||||
"allOf": [
|
||||
@@ -1666,6 +1727,16 @@
|
||||
"description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.autoMarkPrompts": {
|
||||
"default": false,
|
||||
"description": "When set to true, prompts will automatically be marked.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.showMarksOnScrollbar": {
|
||||
"default": false,
|
||||
"description": "When set to true, marks added to the buffer via the addMark action will appear on the scrollbar.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"disableAnimations": {
|
||||
"default": false,
|
||||
"description": "When set to `true`, visual animations will be disabled across the application.",
|
||||
@@ -2010,6 +2081,10 @@
|
||||
"description": "Controls what happens when the application emits a BEL character. When set to \"all\", the Terminal will play a sound, flash the taskbar icon (if the terminal window is not in focus) and flash the window. An array of specific behaviors can also be used. Supported array values include `audible`, `window` and `taskbar`. When set to \"none\", nothing will happen.",
|
||||
"$ref": "#/$defs/BellStyle"
|
||||
},
|
||||
"bellSound": {
|
||||
"description": "Sets the sound played when the application emits a BEL. When set to an array, the terminal will pick one of those sounds at random.",
|
||||
"$ref": "#/$defs/BellSound"
|
||||
},
|
||||
"closeOnExit": {
|
||||
"default": "graceful",
|
||||
"description": "Sets how the profile reacts to termination or failure to launch. Possible values:\n -\"graceful\" (close when exit is typed or the process exits normally)\n -\"always\" (always close)\n -\"never\" (never close).\ntrue and false are accepted as synonyms for \"graceful\" and \"never\" respectively.",
|
||||
|
||||
@@ -22,21 +22,61 @@ Below is the schedule for when milestones will be included in release builds of
|
||||
| Milestone End Date | Milestone Name | Preview Release Blog Post |
|
||||
| ------------------ | -------------- | ------------------------- |
|
||||
| 2020-06-18 | [1.1] in Windows Terminal Preview | [Windows Terminal Preview 1.1 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-1-release/) |
|
||||
| 2020-07-31 | [1.2] in Windows Terminal Preview<br>[1.1] in Windows Terminal | [Windows Terminal Preview 1.2 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-2-release/) |
|
||||
| 2020-08-31 | [1.3] in Windows Terminal Preview<br>[1.2] in Windows Terminal | [Windows Terminal Preview 1.3 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-3-release/) |
|
||||
| 2020-09-30 | [1.4] in Windows Terminal Preview<br>[1.3] in Windows Terminal | [Windows Terminal Preview 1.4 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-4-release/) |
|
||||
| 2020-11-30 | [1.5] in Windows Terminal Preview<br>[1.4] in Windows Terminal | [Windows Terminal Preview 1.5 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-5-release/) |
|
||||
| 2021-01-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | [Windows Terminal Preview 1.6 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-6-release/) |
|
||||
| 2021-03-01 | [1.7] in Windows Terminal Preview<br>[1.6] in Windows Terminal | [Windows Terminal Preview 1.7 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-7-release/) |
|
||||
| 2021-04-14 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | [Windows Terminal Preview 1.8 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-8-release/) |
|
||||
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | [Windows Terminal Preview 1.9 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-9-release/) |
|
||||
| 2021-07-14 | [1.10] in Windows Terminal Preview<br>[1.9] in Windows Terminal | [Windows Terminal Preview 1.10 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-10-release/) |
|
||||
| 2021-08-31 | [1.11] in Windows Terminal Preview<br>[1.10] in Windows Terminal | [Windows Terminal Preview 1.11 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-11-release/) |
|
||||
| 2021-10-20 | [1.12] in Windows Terminal Preview<br>[1.11] in Windows Terminal | [Windows Terminal Preview 1.12 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-12-release/) |
|
||||
| | [1.13] in Windows Terminal Preview<br>[1.12] in Windows Terminal | |
|
||||
| | [1.14] in Windows Terminal Preview<br>[1.13] in Windows Terminal | |
|
||||
| 2020-07-31 | [1.2] in Windows Terminal Preview<br>[1.1] in Windows Terminal | [Windows Terminal Preview 1.2 Release] |
|
||||
| 2020-08-31 | [1.3] in Windows Terminal Preview<br>[1.2] in Windows Terminal | [Windows Terminal Preview 1.3 Release] |
|
||||
| 2020-09-30 | [1.4] in Windows Terminal Preview<br>[1.3] in Windows Terminal | [Windows Terminal Preview 1.4 Release] |
|
||||
| 2020-11-30 | [1.5] in Windows Terminal Preview<br>[1.4] in Windows Terminal | [Windows Terminal Preview 1.5 Release] |
|
||||
| 2021-01-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | [Windows Terminal Preview 1.6 Release] |
|
||||
| 2021-03-01 | [1.7] in Windows Terminal Preview<br>[1.6] in Windows Terminal | [Windows Terminal Preview 1.7 Release] |
|
||||
| 2021-04-14 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | [Windows Terminal Preview 1.8 Release] |
|
||||
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | [Windows Terminal Preview 1.9 Release] |
|
||||
| 2021-07-14 | [1.10] in Windows Terminal Preview<br>[1.9] in Windows Terminal | [Windows Terminal Preview 1.10 Release] |
|
||||
| 2021-08-31 | [1.11] in Windows Terminal Preview<br>[1.10] in Windows Terminal | [Windows Terminal Preview 1.11 Release] |
|
||||
| 2021-10-20 | [1.12] in Windows Terminal Preview<br>[1.11] in Windows Terminal | [Windows Terminal Preview 1.12 Release] |
|
||||
| 2022-02-03 | [1.13] in Windows Terminal Preview<br>[1.12] in Windows Terminal | [Windows Terminal Preview 1.13 Release] |
|
||||
| 2022-05-24 | [1.14] in Windows Terminal Preview<br>[1.13] in Windows Terminal | [Windows Terminal Preview 1.14 Release] |
|
||||
| | [1.15] in Windows Terminal Preview<br>[1.14] in Windows Terminal | |
|
||||
| | [1.16] in Windows Terminal Preview<br>[1.15] in Windows Terminal | |
|
||||
| | [1.17] in Windows Terminal Preview<br>[1.16] in Windows Terminal | |
|
||||
|
||||
|
||||
### Release outline
|
||||
|
||||
Below is a VERY vague outline of the remaining calendar year that was drafted late May 2022. This was drafted for internal planning purposes, as a guide. It is not meant to represent official dates. More often than not, releases are synced to official features landing, rather than arbitrary dates. Drift from this initial draft is entirely expected.
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title Proposed Terminal Releases 1.14-1.18
|
||||
dateFormat YYYY-MM-DD
|
||||
axisFormat %d %b
|
||||
section Terminal 1.14
|
||||
Lock down & bake :done, 2022-05-06, 2w
|
||||
Release 1.14 :milestone, 2022-05-24
|
||||
section Terminal 1.15
|
||||
Features :done, a1, 2022-05-06, 4w
|
||||
Bugfix :active, a2, after a1 , 1w
|
||||
Lock down & bake :after a2 , 1w
|
||||
Release 1.15 :milestone, 2022-06-21, 0
|
||||
1.15 becomes Stable :milestone, after b3, 0
|
||||
section Terminal 1.16
|
||||
Features :b1, after a2, 4w
|
||||
Bugfix :b2, after b1 , 2w
|
||||
Lock down & bake :b3, after b2 , 2w
|
||||
Release 1.16 :milestone, after b3, 0
|
||||
1.16 becomes Stable :milestone, after c3, 0
|
||||
section Terminal 1.17
|
||||
Features :c1, after b2, 4w
|
||||
Bugfix :c2, after c1 , 2w
|
||||
Lock down & bake :c3, after c2 , 2w
|
||||
Release 1.17 :milestone, after c3, 0
|
||||
1.17 becomes Stable :milestone, after d3, 0
|
||||
section Terminal 1.18
|
||||
Features :d1, after c2, 4w
|
||||
Bugfix :d2, after d1 , 2w
|
||||
Lock down & bake :d3, after d2 , 2w
|
||||
Release 1.18 :milestone, after d3, 0
|
||||
```
|
||||
|
||||
## Issue Triage & Prioritization
|
||||
|
||||
Incoming issues/asks/etc. are triaged several times a week, labeled appropriately, and assigned to a milestone in priority order:
|
||||
@@ -62,7 +102,9 @@ Incoming issues/asks/etc. are triaged several times a week, labeled appropriatel
|
||||
[1.12]: https://github.com/microsoft/terminal/milestone/38
|
||||
[1.13]: https://github.com/microsoft/terminal/milestone/39
|
||||
[1.14]: https://github.com/microsoft/terminal/milestone/41
|
||||
|
||||
[1.15]: https://github.com/microsoft/terminal/milestone/47
|
||||
[1.16]: https://github.com/microsoft/terminal/milestone/48
|
||||
[1.17]: https://github.com/microsoft/terminal/milestone/49
|
||||
|
||||
[22H1]: https://github.com/microsoft/terminal/milestone/43
|
||||
[22H2]: https://github.com/microsoft/terminal/milestone/44
|
||||
@@ -70,3 +112,17 @@ Incoming issues/asks/etc. are triaged several times a week, labeled appropriatel
|
||||
[Backlog]: https://github.com/microsoft/terminal/milestone/45
|
||||
|
||||
[Terminal v2 Roadmap]: https://github.com/microsoft/terminal/tree/main/doc/terminal-v2-roadmap.md
|
||||
|
||||
[Windows Terminal Preview 1.2 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-2-release/
|
||||
[Windows Terminal Preview 1.3 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-3-release/
|
||||
[Windows Terminal Preview 1.4 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-4-release/
|
||||
[Windows Terminal Preview 1.5 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-5-release/
|
||||
[Windows Terminal Preview 1.6 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-6-release/
|
||||
[Windows Terminal Preview 1.7 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-7-release/
|
||||
[Windows Terminal Preview 1.8 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-8-release/
|
||||
[Windows Terminal Preview 1.9 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-9-release/
|
||||
[Windows Terminal Preview 1.10 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-10-release/
|
||||
[Windows Terminal Preview 1.11 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-11-release/
|
||||
[Windows Terminal Preview 1.12 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-12-release/
|
||||
[Windows Terminal Preview 1.13 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-13-release/
|
||||
[Windows Terminal Preview 1.14 Release]: https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-14-release/
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 45 KiB |
@@ -1,274 +0,0 @@
|
||||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2022-05-18
|
||||
last updated: 2022-10-28
|
||||
issue id: n/a
|
||||
---
|
||||
|
||||
# Markdown Notebooks in the Terminal
|
||||
|
||||
## Abstract
|
||||
|
||||
Notebooks have risen to popularity in recent years as a way of combining both
|
||||
code and documentation in a single experience. They enable users to seamlessly
|
||||
write code, and execute it to see the output, write documentation on the code,
|
||||
and share that with others. However, there's not really anything like notebooks
|
||||
for generic commandline experiences.
|
||||
|
||||
There are, however, markdown files. Markdown has become a bit of a lingua franca
|
||||
of the developer experience. It's used prominently on GitHub - the "homepage" of
|
||||
any repo on GitHub is now typically a markdown file. This file will have all
|
||||
sorts of documentation, and notably these READMEs are often filled with commands
|
||||
that one can execute for this project. Downloading, installing its dependencies,
|
||||
building and running the project, etc, all commands that are already listed
|
||||
todcay in READMEs across the world.
|
||||
|
||||
It would be a major convenience for users to be able to just load a pre-rendered
|
||||
markdown file directly into their terminal windows. These files already include
|
||||
marked blocks of code which identify sets of commands for the command line. It
|
||||
should be as simple as clicking a button to run these commands in the Terminal,
|
||||
or even to run a whole file worth of commands automatically.
|
||||
|
||||
## Background
|
||||
|
||||
### Inspiration
|
||||
|
||||
[Jupyter notebooks] ([a Jupyter example]) served as the primary inspiration for
|
||||
this feature. Another shoutout to [this comment on HackerNews], which inspired a
|
||||
lot of brainstorming on this topic over the last year since it was posted.
|
||||
|
||||
Many initial brainstorms were focused on more notebook-like features in the
|
||||
Terminal. For example, finding ways to create individual terminal blocks inline
|
||||
with commands, where each input command and its output would be separated from
|
||||
one another, possibly separated by some sort of text/rich markup. This seemed to
|
||||
precipitate the need for a new file syntax to be authored, where we could save
|
||||
commands as they were run. The Terminal would then open this new file type as a
|
||||
set of terminal blocks each pre-populated with these saved commands. Hoever,
|
||||
this came with the drawback that projects which would like to leverage this
|
||||
feature would have to author entirely new files, in a new syntax, just to make
|
||||
use of this functionality. It seemed as though it was a niche enough UX that it
|
||||
would be unlikely to broadly catch on.
|
||||
|
||||
The real inspiration here was that there's already a file type with broad
|
||||
adoption that's already filled with commands like this. Markdown files. Take a
|
||||
look at something like [building.md](../../../building.md). That file _already_
|
||||
has a long set of commands for building the Terminal, running tests, deploying,
|
||||
and various other helper scripts. Being able to immediately leverage this
|
||||
existing ecosystem would undobtably lead to quicker adoption.
|
||||
|
||||
|
||||
### User Stories
|
||||
|
||||
* **A**: The user can perform some commandline action (like `wt open
|
||||
README.md`), which opens a new pane in the Terminal, with the markdown file
|
||||
rendered into that pane.
|
||||
* **B**: Markdown panes have buttons next to code blocks that allow the text of
|
||||
that block to be sent directly to the adjacent terminal as input.
|
||||
* **C**: The user can press different buttons to run some subset of all the
|
||||
commands in the file
|
||||
- **C.1**: Run all the commands in this file
|
||||
- **C.2**: Run all the commands from (the currently selected block) to the end
|
||||
of the file
|
||||
- **C.1**: Run all the commands from (the currently selected block) to the
|
||||
next header. (e.g., run all the commands in this section of the doc.)
|
||||
* **D**: The user can edit the contents of the markdown file directly in the
|
||||
Terminal.
|
||||
* **E**: The Terminal could be configured to automatically open a markdown file
|
||||
when `cd`ing to a directory
|
||||
* **F**: The command for opening a markdown file also supports opening files
|
||||
from the web (e.g. directly from GitHub)
|
||||
* **G**: Code blocks in the markdown file are automatically assigned
|
||||
autoincrementing IDs. The user can perform an action (via keybinding, command
|
||||
palette, whatever) to execute a command block from the file, based on it's
|
||||
assigned ID.
|
||||
* **H**: ...
|
||||
|
||||
|
||||
## Solution Design
|
||||
|
||||
The Terminal will allow for non-terminal content in a pane. This is something
|
||||
that's been prototyped before, just needs a stronger justification for
|
||||
finishing.
|
||||
|
||||
We'll leverage the Terminal's existing `sendInput` command to handle a lot of
|
||||
this. That can be used to send keystrokes to the Terminal. Figuring out which
|
||||
pane to send the `sendInput` command to might be a bit tricky. We'll need to
|
||||
figure out what an action like that does when the active pane is not a terminal
|
||||
pane.
|
||||
|
||||
Below are two different structures that could be used for imlpementing notebooks
|
||||
in the Terminal. These are **Side-by-side** notebooks, and **Inline** notebooks.
|
||||
Side-by-side notebooks consist of two panes - a standard terminal control in
|
||||
one, and rendered markdown in the other. Inline notebooks are more like
|
||||
traditional notebooks, with the terminal output rendered as a block within the
|
||||
rendered markdown content.
|
||||
|
||||
### Side-by-side notebooks
|
||||
|
||||
Opening Markdown side-by-side with the Terminal output is certainly a little
|
||||
different than the way a notebook traditionally works. Notebooks typically have
|
||||
the code in a block, with output inline, below the block. Blocks could also just
|
||||
be dedicated to text, for documentation mixed between the code. The feature
|
||||
proposed here is different from that, for sure. For this proposal, the Terminal
|
||||
still exists side-by-side from the source markdown. Running commands from the
|
||||
markdown text would then send the command as a string of input to the connected
|
||||
terminal. This approach was elected over attempting to create artificial
|
||||
boundaries between different blocks.
|
||||
|
||||
Oftentimes, the command line is a very stateful experience. Set some environment
|
||||
variables, run some script, use the errorlevel from the previous command, etc.
|
||||
Running each block in wholly separate console instances would likely not be
|
||||
useful.
|
||||
|
||||
Additionally, finding the separation between command line input and its output,
|
||||
and the separation between individual commands is not an entirely trivial
|
||||
process. Should we try to separate out the command input line into one buffer,
|
||||
then the output into another buffer sounds great on paper. Consider, however,
|
||||
something like `cmd.exe`, which does not provide any sort of distinction between
|
||||
its input line and its output. Or `python.exe`, as an interactive REPL, which
|
||||
certainly doesn't tell the terminal the difference. How would we be able to
|
||||
detect something like a multi-line command at the REPL?
|
||||
|
||||
By keeing the command blocks out-of-band from the terminal output, we keep the
|
||||
familiar terminal experience. It acts just as you'd expect, with no additional
|
||||
configuration on the user's side. The commands are something that are already
|
||||
written down, just waiting for the user to run them. They could even be sent to
|
||||
something that isn't necessarily a shell - like pasting a bit of configuration
|
||||
into a text editor like `vim` or `emacs`. The commands in the markdown side are
|
||||
just strings of text to send to the terminal side - nothing more.
|
||||
|
||||
### Inline notebooks
|
||||
|
||||
Is there a way to have a more traditional notebook experience, where the
|
||||
terminal output is rendered as blocks within the markdown itself? I believe
|
||||
there is, by making agressive use of the FTCS mark VT sequences. These are
|
||||
sequences that enable identifying the parts of the buffer as a prompt, the
|
||||
commandline, or the output. We can use these to pull out individual rows of the
|
||||
buffer, and display them as miniature terminal controls within the notebook.
|
||||
|
||||
This involves a single terminal insance backing the entire notebook. When the
|
||||
user runs a code block in the notebook, we'll `sendInput` the text to the
|
||||
backing terminal the same as before. We'll then use the `FTCS_COMMAND_EXECUTED`
|
||||
sequence to know where the actual start of the output of the command is. We'll
|
||||
gather all output from that moment on, and tee that to a separate "front"
|
||||
control, which we use as the display for the output of the command. We'll render
|
||||
that "front" control inline with the rest of the markdown content, immediately
|
||||
below the code block for that command.
|
||||
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
### Side-by-side
|
||||

|
||||
|
||||
|
||||
### Inline
|
||||
|
||||

|
||||
|
||||
## Tenents
|
||||
|
||||
<table>
|
||||
|
||||
<tr><td><strong>Accessibility</strong></td><td>
|
||||
|
||||
[comment]: # How will the proposed change impact accessibility for users of screen readers, assistive input devices, etc.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Security</strong></td><td>
|
||||
|
||||
[comment]: # How will the proposed change impact security?
|
||||
|
||||
Opening a file like this will _never_ auto-run commands. Commands must always be
|
||||
intentionally interacted with, to provide a positive confirmation from the user
|
||||
"yes, I intended to run `curl some.website.com/foo.txt`".
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Reliability</strong></td><td>
|
||||
|
||||
[comment]: # Will the proposed change improve reliability? If not, why make the change?
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Compatibility</strong></td><td>
|
||||
|
||||
[comment]: # Will the proposed change break existing code/behaviors? If so, how, and is the breaking change "worth it"?
|
||||
|
||||
It's critically important that nothing about this feature be necessarily Windows
|
||||
Terminal-dependent. These features shouldn't be powered by some new undocumented
|
||||
escape sequence that only we support. They should NOT be powered by new Windows
|
||||
APIs, especially not any extensions to the Console API. There's no reason other
|
||||
terminals couldn't also implement similar functionality.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr><td><strong>Performance, Power, and Efficiency</strong></td><td>
|
||||
|
||||
[comment]: # Will the proposed change break existing code/behaviors? If so, how, and is the breaking change "worth it"?
|
||||
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
## Potential Issues
|
||||
|
||||
For rendering markdown, we'll either need:
|
||||
* A way to display a WebView in a WinUI2 XAML Island
|
||||
- This is something that's on the backlog currently for MUX 2.x. Theoretically
|
||||
not too hard to add an `IInitializeWithWindow` to `WebView2` which should
|
||||
enable XAML Islands, but needs more research.
|
||||
* To migrate to WinUI 3
|
||||
- In WinUI 3 I believe we should be able to get WebViews for free.
|
||||
- We might still be a XAML Island in WinUI 3, which may complicate that.
|
||||
* A C++ based method of rendering Markdown to UWP XAML
|
||||
- There's a Windows Community Toolkit control for rendering to XAML currently,
|
||||
but that is backed by C#, so we can't use that.
|
||||
|
||||
We'll also need the markdown rendering to be extensible, so that we can insert
|
||||
"play" buttons alongside the blocks.
|
||||
|
||||
## Future considerations
|
||||
|
||||
### Tighter GitHub integration
|
||||
|
||||
GitHub already has the helpful "Open In GitHub" button for opening a repo in the
|
||||
GitHub desktop client, or in Visual Studio.
|
||||
|
||||

|
||||
|
||||
It'd be cool if there was a similar button for opening it up in the Terminal. It
|
||||
could open the README immediately as a new tab, and then provide some sort of
|
||||
InfoBar with a button that would allow the user to immediately clone the repo to
|
||||
some location on their PC. This would likely need a protocol handler installed
|
||||
by the Terminal to help connect the browser to the Terminal.
|
||||
|
||||
### Collapsible Blocks
|
||||
|
||||
One of the key features of notebooks is the ability to easily collapse regions
|
||||
of the notebook. With the command output being out of band from the input of the
|
||||
command, not as independent blocks, this becomes a bit trickier. To try and
|
||||
reproduce a similar ability to collapse regions of the buffer, we'll look to
|
||||
[Marks] in the terminal as a potential solution. The FinalTerm sequences allow a
|
||||
client to mark up the region of the buffer that's the prompt, the command line,
|
||||
and the output. Using those marks would provide an easy heuristic to allow users
|
||||
to collapse the output of commands. These sequences however do require manual
|
||||
configuration by the user, and are not expected to be able to work in all
|
||||
environments (and shells). While powerful, because of this limitation, we didn't
|
||||
want to architect the entire experience around something that wouldn't always
|
||||
work.
|
||||
|
||||
## Resources
|
||||
|
||||
[comment]: # Be sure to add links to references, resources, footnotes, etc.
|
||||
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]:
|
||||
|
||||
[Jupyter notebooks]: https://jupyter.org/
|
||||
[a Jupyter example]: https://jupyter.org/try-jupyter/retro/notebooks/?path=notebooks/Intro.ipynb
|
||||
[this comment on HackerNews]: https://news.ycombinator.com/item?id=26617656
|
||||
[Marks]: https://github.com/microsoft/terminal/issues/11000
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 868 KiB |
@@ -3,9 +3,11 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "MyPage.h"
|
||||
#include "MySettings.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "MyPage.g.cpp"
|
||||
#include "MySettings.h"
|
||||
#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
|
||||
#include "..\..\..\src\types\inc\utils.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
@@ -26,7 +28,7 @@ namespace winrt::SampleApp::implementation
|
||||
|
||||
void MyPage::Create()
|
||||
{
|
||||
auto settings = winrt::make_self<implementation::MySettings>();
|
||||
auto settings = winrt::make_self<MySettings>();
|
||||
|
||||
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted in-proc...",
|
||||
winrt::hstring{},
|
||||
@@ -44,6 +46,216 @@ namespace winrt::SampleApp::implementation
|
||||
Control::TermControl control{ *settings, *settings, conn };
|
||||
|
||||
InProcContent().Children().Append(control);
|
||||
|
||||
// Once the control loads (and not before that), write some text for debugging:
|
||||
control.Initialized([conn](auto&&, auto&&) {
|
||||
conn.WriteInput(L"This TermControl is hosted in-proc...");
|
||||
});
|
||||
}
|
||||
|
||||
static wil::unique_process_information _createHostClassProcess(const winrt::guid& g)
|
||||
{
|
||||
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(g) };
|
||||
|
||||
// Create an event that the content process will use to signal it is
|
||||
// ready to go. We won't need the event after this function, so the
|
||||
// unique_event will clean up our handle when we leave this scope. The
|
||||
// ContentProcess is responsible for cleaning up its own handle.
|
||||
wil::unique_event ev{ CreateEvent(nullptr, true, false, nullptr) };
|
||||
// Make sure to mark this handle as inheritable! Even with
|
||||
// bInheritHandles=true, this is only inherited when it's explicitly
|
||||
// allowed to be.
|
||||
SetHandleInformation(ev.get(), HANDLE_FLAG_INHERIT, 1);
|
||||
|
||||
// god bless, fmt::format will format a HANDLE like `0xa80`
|
||||
std::wstring commandline{
|
||||
fmt::format(L"WindowsTerminal.exe --content {} --signal {}", guidStr, ev.get())
|
||||
};
|
||||
|
||||
STARTUPINFO siOne{ 0 };
|
||||
siOne.cb = sizeof(STARTUPINFOW);
|
||||
wil::unique_process_information piOne;
|
||||
auto succeeded = CreateProcessW(
|
||||
nullptr,
|
||||
commandline.data(),
|
||||
nullptr, // lpProcessAttributes
|
||||
nullptr, // lpThreadAttributes
|
||||
true, // bInheritHandles
|
||||
CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
|
||||
nullptr, // lpEnvironment
|
||||
nullptr, // startingDirectory
|
||||
&siOne, // lpStartupInfo
|
||||
&piOne // lpProcessInformation
|
||||
);
|
||||
THROW_IF_WIN32_BOOL_FALSE(succeeded);
|
||||
|
||||
// Wait for the child process to signal that they're ready.
|
||||
WaitForSingleObject(ev.get(), INFINITE);
|
||||
|
||||
return piOne;
|
||||
}
|
||||
|
||||
winrt::fire_and_forget MyPage::_writeToLog(std::wstring_view str)
|
||||
{
|
||||
winrt::hstring copy{ str };
|
||||
// Switch back to the UI thread.
|
||||
co_await resume_foreground(Dispatcher());
|
||||
winrt::WUX::Controls::TextBlock block;
|
||||
block.Text(copy);
|
||||
Log().Children().Append(block);
|
||||
}
|
||||
|
||||
winrt::fire_and_forget MyPage::CreateClicked(const IInspectable& sender,
|
||||
const WUX::Input::TappedRoutedEventArgs& eventArgs)
|
||||
{
|
||||
auto guidString = GuidInput().Text();
|
||||
|
||||
// Capture calling context.
|
||||
winrt::apartment_context ui_thread;
|
||||
|
||||
auto canConvert = guidString.size() == 38 &&
|
||||
guidString.front() == '{' &&
|
||||
guidString.back() == '}';
|
||||
bool tryingToAttach = false;
|
||||
winrt::guid contentGuid{ ::Microsoft::Console::Utils::CreateGuid() };
|
||||
|
||||
if (canConvert)
|
||||
{
|
||||
GUID result{};
|
||||
if (SUCCEEDED(IIDFromString(guidString.c_str(), &result)))
|
||||
{
|
||||
contentGuid = result;
|
||||
tryingToAttach = true;
|
||||
}
|
||||
}
|
||||
_writeToLog(tryingToAttach ? L"Attaching to existing content process" : L"Creating new content process");
|
||||
|
||||
co_await winrt::resume_background();
|
||||
if (!tryingToAttach)
|
||||
{
|
||||
// Spawn a wt.exe, with the guid on the commandline
|
||||
piContentProcess = std::move(_createHostClassProcess(contentGuid));
|
||||
}
|
||||
|
||||
// THIS MUST TAKE PLACE AFTER _createHostClassProcess.
|
||||
// * If we're creating a new OOP control, _createHostClassProcess will
|
||||
// spawn the process that will actually host the ContentProcess
|
||||
// object.
|
||||
// * If we're attaching, then that process already exists.
|
||||
Control::ContentProcess content{ nullptr };
|
||||
try
|
||||
{
|
||||
content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
|
||||
}
|
||||
catch (winrt::hresult_error hr)
|
||||
{
|
||||
_writeToLog(L"CreateInstance the ContentProcess object");
|
||||
_writeToLog(fmt::format(L" HR ({}): {}", hr.code(), hr.message().c_str()));
|
||||
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
|
||||
}
|
||||
|
||||
if (content == nullptr)
|
||||
{
|
||||
_writeToLog(L"Failed to connect to the ContentProcess object. It may not have been started fast enough.");
|
||||
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
|
||||
}
|
||||
|
||||
TerminalConnection::ConnectionInformation connectInfo{ nullptr };
|
||||
Control::IControlSettings settings{ *winrt::make_self<implementation::MySettings>() };
|
||||
|
||||
// When creating a terminal for the first time, pass it a connection
|
||||
// info
|
||||
//
|
||||
// otherwise, when attaching to an existing one, just pass null, because
|
||||
// we don't need the connection info.
|
||||
if (!tryingToAttach)
|
||||
{
|
||||
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted out-of-proc...",
|
||||
winrt::hstring{},
|
||||
L"",
|
||||
nullptr,
|
||||
32,
|
||||
80,
|
||||
winrt::guid()) };
|
||||
|
||||
// "Microsoft.Terminal.TerminalConnection.ConptyConnection"
|
||||
winrt::hstring myClass{ winrt::name_of<TerminalConnection::ConptyConnection>() };
|
||||
connectInfo = TerminalConnection::ConnectionInformation(myClass, connectionSettings);
|
||||
|
||||
if (!content.Initialize(settings, settings, connectInfo))
|
||||
{
|
||||
_writeToLog(L"Failed to Initialize the ContentProcess object.");
|
||||
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're attaching, we don't really need to do anything special.
|
||||
}
|
||||
|
||||
// Switch back to the UI thread.
|
||||
co_await ui_thread;
|
||||
|
||||
// Create the XAML control that will be attached to the content process.
|
||||
// We're not passing in a connection, because the contentGuid will be used instead.
|
||||
Control::TermControl control{ contentGuid, settings, settings, nullptr };
|
||||
auto weakControl = winrt::make_weak(control);
|
||||
control.RaiseNotice([this](auto&&, auto& args) {
|
||||
_writeToLog(L"Content process died, probably.");
|
||||
_writeToLog(args.Message());
|
||||
OutOfProcContent().Children().Clear();
|
||||
GuidInput().Text(L"");
|
||||
if (piContentProcess.hProcess)
|
||||
{
|
||||
piContentProcess.reset();
|
||||
}
|
||||
});
|
||||
control.ConnectionStateChanged([this, weakControl](auto&&, auto&) {
|
||||
if (auto strongControl{ weakControl.get() })
|
||||
{
|
||||
const auto newConnectionState = strongControl.ConnectionState();
|
||||
if (newConnectionState == TerminalConnection::ConnectionState::Closed)
|
||||
{
|
||||
_writeToLog(L"Connection was closed");
|
||||
OutOfProcContent().Children().Clear();
|
||||
GuidInput().Text(L"");
|
||||
if (piContentProcess.hProcess)
|
||||
{
|
||||
piContentProcess.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Log().Children().Clear();
|
||||
OutOfProcContent().Children().Append(control);
|
||||
|
||||
if (!tryingToAttach)
|
||||
{
|
||||
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(contentGuid) };
|
||||
GuidInput().Text(guidStr);
|
||||
}
|
||||
}
|
||||
|
||||
void MyPage::CloseClicked(const IInspectable& /*sender*/,
|
||||
const WUX::Input::TappedRoutedEventArgs& /*eventArgs*/)
|
||||
{
|
||||
OutOfProcContent().Children().Clear();
|
||||
GuidInput().Text(L"");
|
||||
if (piContentProcess.hProcess)
|
||||
{
|
||||
piContentProcess.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MyPage::KillClicked(const IInspectable& /*sender*/,
|
||||
const WUX::Input::TappedRoutedEventArgs& /*eventArgs*/)
|
||||
{
|
||||
if (piContentProcess.hProcess)
|
||||
{
|
||||
TerminateProcess(piContentProcess.hProcess, (UINT)-1);
|
||||
piContentProcess.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -14,11 +14,18 @@ namespace winrt::SampleApp::implementation
|
||||
MyPage();
|
||||
|
||||
void Create();
|
||||
|
||||
hstring Title();
|
||||
|
||||
winrt::fire_and_forget CreateClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
|
||||
void CloseClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
|
||||
void KillClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
|
||||
|
||||
private:
|
||||
friend struct MyPageT<MyPage>; // for Xaml to bind events
|
||||
|
||||
wil::unique_process_information piContentProcess;
|
||||
|
||||
winrt::fire_and_forget _writeToLog(std::wstring_view str);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,23 @@
|
||||
<TextBox x:Name="GuidInput"
|
||||
Width="400"
|
||||
PlaceholderText="{}{guid here}" />
|
||||
<Button Grid.Row="0">
|
||||
<Button x:Name="CreateOutOfProcControl"
|
||||
Grid.Row="0"
|
||||
Tapped="CreateClicked">
|
||||
Create
|
||||
</Button>
|
||||
<Button x:Name="CloseOutOfProcControl"
|
||||
Grid.Row="0"
|
||||
Margin="4,0,0,0"
|
||||
Tapped="CloseClicked">
|
||||
Close
|
||||
</Button>
|
||||
<Button x:Name="KillOutOfProcControl"
|
||||
Grid.Row="0"
|
||||
Margin="4,0,0,0"
|
||||
Tapped="KillClicked">
|
||||
Kill
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
@@ -46,14 +60,26 @@
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#ff0000" />
|
||||
|
||||
<Grid x:Name="OutOfProcContent"
|
||||
Grid.Column="1"
|
||||
Padding="16"
|
||||
<Grid Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#0000ff" />
|
||||
VerticalAlignment="Stretch">
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel x:Name="Log"
|
||||
Grid.Row="0"
|
||||
Orientation="Vertical" />
|
||||
|
||||
<Grid x:Name="OutOfProcContent"
|
||||
Grid.Row="1"
|
||||
Padding="16"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#0000ff" />
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -17,9 +17,15 @@
|
||||
<DisableEmbeddedXbf>false</DisableEmbeddedXbf>
|
||||
<XamlComponentResourceLocation>nested</XamlComponentResourceLocation>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
<ClCompile>
|
||||
@@ -147,14 +153,15 @@
|
||||
<!-- ========================= Globals ======================== -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
<!-- sets a bunch of Windows Universal properties -->
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<!-- ========================= XAML files ======================== -->
|
||||
<ItemGroup>
|
||||
<!-- DON'T PUT XAML FILES HERE! Put them in SampleAppLib.vcxproj -->
|
||||
@@ -81,13 +85,11 @@
|
||||
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
@@ -102,4 +104,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -57,8 +57,8 @@ void SampleIslandWindow::MakeWindow() noexcept
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
1024,
|
||||
860,
|
||||
nullptr,
|
||||
nullptr,
|
||||
wc.hInstance,
|
||||
@@ -104,8 +104,6 @@ void SampleIslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam)
|
||||
|
||||
void SampleIslandWindow::Initialize()
|
||||
{
|
||||
const bool initialized = (_interopWindowHandle != nullptr);
|
||||
|
||||
_source = DesktopWindowXamlSource{};
|
||||
|
||||
auto interop = _source.as<IDesktopWindowXamlSourceNative>();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{b4427499-9fde-4208-b456-5bc580637633}</ProjectGuid>
|
||||
@@ -16,7 +15,15 @@
|
||||
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
|
||||
<TerminalVCRTForwarders>true</TerminalVCRTForwarders>
|
||||
<TerminalThemeHelpers>true</TerminalThemeHelpers>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
@@ -138,16 +145,11 @@
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
|
||||
</Target>
|
||||
|
||||
<!-- Override GetPackagingOutputs to roll up all our dependencies.
|
||||
@@ -225,13 +227,24 @@
|
||||
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||
</PackagingOutputs>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Same thing AGAIN here, with OpenConsole.exe If you forget this, then
|
||||
the scratch app will use the inbox conpty with a newer conpty lib, causing
|
||||
us to send the inbox conhost messages that will make it explode. -->
|
||||
<ItemGroup>
|
||||
<_OpenConsoleExe Include="$(OpenConsoleCommonOutDir)\OpenConsole.exe" />
|
||||
|
||||
<PackagingOutputs Include="@(_OpenConsoleExe)">
|
||||
<ProjectName>$(ProjectName)</ProjectName>
|
||||
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
|
||||
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||
</PackagingOutputs>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
|
||||
<Import Project="..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" />
|
||||
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
</Project>
|
||||
|
||||
|
||||
2
src/audio/dirs
Normal file
2
src/audio/dirs
Normal file
@@ -0,0 +1,2 @@
|
||||
DIRS=midi \
|
||||
|
||||
125
src/audio/midi/MidiAudio.cpp
Normal file
125
src/audio/midi/MidiAudio.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "precomp.h"
|
||||
#include "MidiAudio.hpp"
|
||||
#include "../terminal/parser/stateMachine.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class MidiOut
|
||||
{
|
||||
public:
|
||||
static constexpr auto NOTE_OFF = 0x80;
|
||||
static constexpr auto NOTE_ON = 0x90;
|
||||
static constexpr auto PROGRAM_CHANGE = 0xC0;
|
||||
|
||||
// We're using a square wave as an approximation of the sound that the
|
||||
// original VT525 terminals might have produced. This is probably not
|
||||
// quite right, but it works reasonably well.
|
||||
static constexpr auto SQUARE_WAVE_SYNTH = 80;
|
||||
|
||||
MidiOut() noexcept
|
||||
{
|
||||
if constexpr (Feature_DECPSViaMidiPlayer::IsEnabled())
|
||||
{
|
||||
midiOutOpen(&handle, MIDI_MAPPER, NULL, NULL, CALLBACK_NULL);
|
||||
OutputMessage(PROGRAM_CHANGE, SQUARE_WAVE_SYNTH);
|
||||
}
|
||||
}
|
||||
~MidiOut() noexcept
|
||||
{
|
||||
if constexpr (Feature_DECPSViaMidiPlayer::IsEnabled())
|
||||
{
|
||||
midiOutClose(handle);
|
||||
}
|
||||
}
|
||||
void OutputMessage(const int b1, const int b2, const int b3 = 0, const int b4 = 0) noexcept
|
||||
{
|
||||
if constexpr (Feature_DECPSViaMidiPlayer::IsEnabled())
|
||||
{
|
||||
midiOutShortMsg(handle, MAKELONG(MAKEWORD(b1, b2), MAKEWORD(b3, b4)));
|
||||
}
|
||||
}
|
||||
|
||||
MidiOut(const MidiOut&) = delete;
|
||||
MidiOut(MidiOut&&) = delete;
|
||||
MidiOut& operator=(const MidiOut&) = delete;
|
||||
MidiOut& operator=(MidiOut&&) = delete;
|
||||
|
||||
private:
|
||||
HMIDIOUT handle = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
MidiAudio::~MidiAudio() noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
#pragma warning(suppress : 26447)
|
||||
// We acquire the lock here so the class isn't destroyed while in use.
|
||||
// If this throws, we'll catch it, so the C26447 warning is bogus.
|
||||
_inUseMutex.lock();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// If the lock fails, we'll just have to live with the consequences.
|
||||
}
|
||||
}
|
||||
|
||||
void MidiAudio::Initialize()
|
||||
{
|
||||
_shutdownFuture = _shutdownPromise.get_future();
|
||||
}
|
||||
|
||||
void MidiAudio::Shutdown()
|
||||
{
|
||||
// Once the shutdown promise is set, any note that is playing will stop
|
||||
// immediately, and the Unlock call will exit the thread ASAP.
|
||||
_shutdownPromise.set_value();
|
||||
}
|
||||
|
||||
void MidiAudio::Lock()
|
||||
{
|
||||
_inUseMutex.lock();
|
||||
}
|
||||
|
||||
void MidiAudio::Unlock()
|
||||
{
|
||||
// We need to check the shutdown status before releasing the mutex,
|
||||
// because after that the class could be destroyed.
|
||||
const auto shutdownStatus = _shutdownFuture.wait_for(0s);
|
||||
_inUseMutex.unlock();
|
||||
// If the wait didn't timeout, that means the shutdown promise was set,
|
||||
// so we need to exit the thread ASAP by throwing an exception.
|
||||
if (shutdownStatus != std::future_status::timeout)
|
||||
{
|
||||
throw Microsoft::Console::VirtualTerminal::StateMachine::ShutdownException{};
|
||||
}
|
||||
}
|
||||
|
||||
void MidiAudio::PlayNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration) noexcept
|
||||
try
|
||||
{
|
||||
// The MidiOut is a local static because we can only have one instance,
|
||||
// and we only want to construct it when it's actually needed.
|
||||
static MidiOut midiOut;
|
||||
|
||||
if (velocity)
|
||||
{
|
||||
midiOut.OutputMessage(MidiOut::NOTE_ON, noteNumber, velocity);
|
||||
}
|
||||
|
||||
// By waiting on the shutdown future with the duration of the note, we'll
|
||||
// either be paused for the appropriate amount of time, or we'll break out
|
||||
// of the wait early if we've been shutdown.
|
||||
_shutdownFuture.wait_for(duration);
|
||||
|
||||
if (velocity)
|
||||
{
|
||||
midiOut.OutputMessage(MidiOut::NOTE_OFF, noteNumber, velocity);
|
||||
}
|
||||
}
|
||||
CATCH_LOG()
|
||||
36
src/audio/midi/MidiAudio.hpp
Normal file
36
src/audio/midi/MidiAudio.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- MidiAudio.hpp
|
||||
|
||||
Abstract:
|
||||
This modules provide basic MIDI support with blocking sound output.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
|
||||
class MidiAudio
|
||||
{
|
||||
public:
|
||||
MidiAudio() = default;
|
||||
MidiAudio(const MidiAudio&) = delete;
|
||||
MidiAudio(MidiAudio&&) = delete;
|
||||
MidiAudio& operator=(const MidiAudio&) = delete;
|
||||
MidiAudio& operator=(MidiAudio&&) = delete;
|
||||
~MidiAudio() noexcept;
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
void Lock();
|
||||
void Unlock();
|
||||
void PlayNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration) noexcept;
|
||||
|
||||
private:
|
||||
std::promise<void> _shutdownPromise;
|
||||
std::future<void> _shutdownFuture;
|
||||
std::mutex _inUseMutex;
|
||||
};
|
||||
2
src/audio/midi/dirs
Normal file
2
src/audio/midi/dirs
Normal file
@@ -0,0 +1,2 @@
|
||||
DIRS=lib \
|
||||
|
||||
26
src/audio/midi/lib/midi.vcxproj
Normal file
26
src/audio/midi/lib/midi.vcxproj
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{3c67784e-1453-49c2-9660-483e2cc7f7ad}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>midi</RootNamespace>
|
||||
<ProjectName>MidiAudio</ProjectName>
|
||||
<TargetName>MidiAudio</TargetName>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||
<Import Project="$(SolutionDir)src\common.nugetversions.props" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\MidiAudio.cpp" />
|
||||
<ClCompile Include="..\precomp.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\MidiAudio.hpp" />
|
||||
<ClInclude Include="..\precomp.h" />
|
||||
</ItemGroup>
|
||||
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
|
||||
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
||||
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
|
||||
</Project>
|
||||
8
src/audio/midi/lib/sources
Normal file
8
src/audio/midi/lib/sources
Normal file
@@ -0,0 +1,8 @@
|
||||
!include ..\sources.inc
|
||||
|
||||
# -------------------------------------
|
||||
# Program Information
|
||||
# -------------------------------------
|
||||
|
||||
TARGETNAME = ConAudioMidi
|
||||
TARGETTYPE = LIBRARY
|
||||
4
src/audio/midi/precomp.cpp
Normal file
4
src/audio/midi/precomp.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "precomp.h"
|
||||
31
src/audio/midi/precomp.h
Normal file
31
src/audio/midi/precomp.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- precomp.h
|
||||
|
||||
Abstract:
|
||||
- Contains external headers to include in the precompile phase of console build process.
|
||||
- Avoid including internal project headers. Instead include them only in the classes that need them (helps with test project building).
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// clang-format off
|
||||
|
||||
// This includes support libraries from the CRT, STL, WIL, and GSL
|
||||
#include "LibraryIncludes.h"
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#define NOMCX
|
||||
#define NOHELP
|
||||
#define NOCOMM
|
||||
#endif
|
||||
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
#include <mmeapi.h>
|
||||
|
||||
// clang-format on
|
||||
28
src/audio/midi/sources.inc
Normal file
28
src/audio/midi/sources.inc
Normal file
@@ -0,0 +1,28 @@
|
||||
!include ..\..\..\project.inc
|
||||
|
||||
# -------------------------------------
|
||||
# Windows Console
|
||||
# - Console Audio Functions
|
||||
# -------------------------------------
|
||||
|
||||
# -------------------------------------
|
||||
# Build System Settings
|
||||
# -------------------------------------
|
||||
|
||||
# Code in the OneCore depot automatically excludes default Win32 libraries.
|
||||
|
||||
# -------------------------------------
|
||||
# Sources, Headers, and Libraries
|
||||
# -------------------------------------
|
||||
|
||||
PRECOMPILED_CXX = 1
|
||||
PRECOMPILED_INCLUDE = ..\precomp.h
|
||||
|
||||
SOURCES = \
|
||||
..\MidiAudio.cpp \
|
||||
|
||||
INCLUDES = \
|
||||
$(INCLUDES); \
|
||||
..; \
|
||||
..\..\..\inc; \
|
||||
$(MINWIN_INTERNAL_PRIV_SDK_INC_PATH_L); \
|
||||
@@ -11,8 +11,8 @@
|
||||
// - attr - the default text attribute
|
||||
// Return Value:
|
||||
// - constructed object
|
||||
ATTR_ROW::ATTR_ROW(const uint16_t width, const TextAttribute attr) :
|
||||
_data(width, attr) {}
|
||||
ATTR_ROW::ATTR_ROW(const til::CoordType width, const TextAttribute attr) :
|
||||
_data(gsl::narrow_cast<uint16_t>(width), attr) {}
|
||||
|
||||
// Routine Description:
|
||||
// - Sets all properties of the ATTR_ROW to default values
|
||||
@@ -32,9 +32,9 @@ void ATTR_ROW::Reset(const TextAttribute attr)
|
||||
// - newWidth - The new width of the row.
|
||||
// Return Value:
|
||||
// - <none>, throws exceptions on failures.
|
||||
void ATTR_ROW::Resize(const uint16_t newWidth)
|
||||
void ATTR_ROW::Resize(const til::CoordType newWidth)
|
||||
{
|
||||
_data.resize_trailing_extent(newWidth);
|
||||
_data.resize_trailing_extent(gsl::narrow<uint16_t>(newWidth));
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -45,9 +45,9 @@ void ATTR_ROW::Resize(const uint16_t newWidth)
|
||||
// - the text attribute at column
|
||||
// Note:
|
||||
// - will throw on error
|
||||
TextAttribute ATTR_ROW::GetAttrByColumn(const uint16_t column) const
|
||||
TextAttribute ATTR_ROW::GetAttrByColumn(const til::CoordType column) const
|
||||
{
|
||||
return _data.at(column);
|
||||
return _data.at(gsl::narrow<uint16_t>(column));
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -74,7 +74,7 @@ std::vector<uint16_t> ATTR_ROW::GetHyperlinks() const
|
||||
// - attr - Attribute (color) to fill remaining characters with
|
||||
// Return Value:
|
||||
// - <none>
|
||||
bool ATTR_ROW::SetAttrToEnd(const uint16_t beginIndex, const TextAttribute attr)
|
||||
bool ATTR_ROW::SetAttrToEnd(const til::CoordType beginIndex, const TextAttribute attr)
|
||||
{
|
||||
_data.replace(gsl::narrow<uint16_t>(beginIndex), _data.size(), attr);
|
||||
return true;
|
||||
@@ -103,9 +103,9 @@ void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAtt
|
||||
// - newAttr: The attribute to merge into this row.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void ATTR_ROW::Replace(const uint16_t beginIndex, const uint16_t endIndex, const TextAttribute& newAttr)
|
||||
void ATTR_ROW::Replace(const til::CoordType beginIndex, const til::CoordType endIndex, const TextAttribute& newAttr)
|
||||
{
|
||||
_data.replace(beginIndex, endIndex, newAttr);
|
||||
_data.replace(gsl::narrow<uint16_t>(beginIndex), gsl::narrow<uint16_t>(endIndex), newAttr);
|
||||
}
|
||||
|
||||
ATTR_ROW::const_iterator ATTR_ROW::begin() const noexcept
|
||||
|
||||
@@ -30,7 +30,7 @@ class ATTR_ROW final
|
||||
public:
|
||||
using const_iterator = rle_vector::const_iterator;
|
||||
|
||||
ATTR_ROW(uint16_t width, TextAttribute attr);
|
||||
ATTR_ROW(til::CoordType width, TextAttribute attr);
|
||||
|
||||
~ATTR_ROW() = default;
|
||||
|
||||
@@ -40,13 +40,13 @@ public:
|
||||
noexcept = default;
|
||||
ATTR_ROW& operator=(ATTR_ROW&&) noexcept = default;
|
||||
|
||||
TextAttribute GetAttrByColumn(uint16_t column) const;
|
||||
TextAttribute GetAttrByColumn(til::CoordType column) const;
|
||||
std::vector<uint16_t> GetHyperlinks() const;
|
||||
|
||||
bool SetAttrToEnd(uint16_t beginIndex, TextAttribute attr);
|
||||
bool SetAttrToEnd(til::CoordType beginIndex, TextAttribute attr);
|
||||
void ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith);
|
||||
void Resize(uint16_t newWidth);
|
||||
void Replace(uint16_t beginIndex, uint16_t endIndex, const TextAttribute& newAttr);
|
||||
void Resize(til::CoordType newWidth);
|
||||
void Replace(til::CoordType beginIndex, til::CoordType endIndex, const TextAttribute& newAttr);
|
||||
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// Note: will through if unable to allocate char/attribute buffers
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26447) // small_vector's constructor says it can throw but it should not given how we use it. This suppresses this error for the AuditMode build.
|
||||
CharRow::CharRow(size_t rowWidth, ROW* const pParent) noexcept :
|
||||
CharRow::CharRow(til::CoordType rowWidth, ROW* const pParent) noexcept :
|
||||
_data(rowWidth, value_type()),
|
||||
_pParent{ FAIL_FAST_IF_NULL(pParent) }
|
||||
{
|
||||
@@ -30,9 +30,9 @@ CharRow::CharRow(size_t rowWidth, ROW* const pParent) noexcept :
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - the size of the row
|
||||
size_t CharRow::size() const noexcept
|
||||
til::CoordType CharRow::size() const noexcept
|
||||
{
|
||||
return _data.size();
|
||||
return gsl::narrow_cast<til::CoordType>(_data.size());
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -55,7 +55,7 @@ void CharRow::Reset() noexcept
|
||||
// - newSize - the new width of the character and attributes rows
|
||||
// Return Value:
|
||||
// - S_OK on success, otherwise relevant error code
|
||||
[[nodiscard]] HRESULT CharRow::Resize(const size_t newSize) noexcept
|
||||
[[nodiscard]] HRESULT CharRow::Resize(const til::CoordType newSize) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -93,14 +93,14 @@ typename CharRow::const_iterator CharRow::cend() const noexcept
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - The calculated left boundary of the internal string.
|
||||
size_t CharRow::MeasureLeft() const noexcept
|
||||
til::CoordType CharRow::MeasureLeft() const noexcept
|
||||
{
|
||||
auto it = _data.cbegin();
|
||||
while (it != _data.cend() && it->IsSpace())
|
||||
{
|
||||
++it;
|
||||
}
|
||||
return it - _data.cbegin();
|
||||
return gsl::narrow_cast<til::CoordType>(it - _data.cbegin());
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -109,17 +109,17 @@ size_t CharRow::MeasureLeft() const noexcept
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - The calculated right boundary of the internal string.
|
||||
size_t CharRow::MeasureRight() const
|
||||
til::CoordType CharRow::MeasureRight() const
|
||||
{
|
||||
auto it = _data.crbegin();
|
||||
while (it != _data.crend() && it->IsSpace())
|
||||
{
|
||||
++it;
|
||||
}
|
||||
return _data.crend() - it;
|
||||
return gsl::narrow_cast<til::CoordType>(_data.crend() - it);
|
||||
}
|
||||
|
||||
void CharRow::ClearCell(const size_t column)
|
||||
void CharRow::ClearCell(const til::CoordType column)
|
||||
{
|
||||
_data.at(column).Reset();
|
||||
}
|
||||
@@ -149,7 +149,7 @@ bool CharRow::ContainsText() const noexcept
|
||||
// Return Value:
|
||||
// - the attribute
|
||||
// Note: will throw exception if column is out of bounds
|
||||
const DbcsAttribute& CharRow::DbcsAttrAt(const size_t column) const
|
||||
const DbcsAttribute& CharRow::DbcsAttrAt(const til::CoordType column) const
|
||||
{
|
||||
return _data.at(column).DbcsAttr();
|
||||
}
|
||||
@@ -161,7 +161,7 @@ const DbcsAttribute& CharRow::DbcsAttrAt(const size_t column) const
|
||||
// Return Value:
|
||||
// - the attribute
|
||||
// Note: will throw exception if column is out of bounds
|
||||
DbcsAttribute& CharRow::DbcsAttrAt(const size_t column)
|
||||
DbcsAttribute& CharRow::DbcsAttrAt(const til::CoordType column)
|
||||
{
|
||||
return _data.at(column).DbcsAttr();
|
||||
}
|
||||
@@ -173,7 +173,7 @@ DbcsAttribute& CharRow::DbcsAttrAt(const size_t column)
|
||||
// Return Value:
|
||||
// - <none>
|
||||
// Note: will throw exception if column is out of bounds
|
||||
void CharRow::ClearGlyph(const size_t column)
|
||||
void CharRow::ClearGlyph(const til::CoordType column)
|
||||
{
|
||||
_data.at(column).EraseChars();
|
||||
}
|
||||
@@ -185,9 +185,9 @@ void CharRow::ClearGlyph(const size_t column)
|
||||
// Return Value:
|
||||
// - text data at column
|
||||
// - Note: will throw exception if column is out of bounds
|
||||
const CharRow::reference CharRow::GlyphAt(const size_t column) const
|
||||
const CharRow::reference CharRow::GlyphAt(const til::CoordType column) const
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, column >= _data.size());
|
||||
THROW_HR_IF(E_INVALIDARG, column < 0 || column >= gsl::narrow_cast<til::CoordType>(_data.size()));
|
||||
return { const_cast<CharRow&>(*this), column };
|
||||
}
|
||||
|
||||
@@ -198,9 +198,9 @@ const CharRow::reference CharRow::GlyphAt(const size_t column) const
|
||||
// Return Value:
|
||||
// - text data at column
|
||||
// - Note: will throw exception if column is out of bounds
|
||||
CharRow::reference CharRow::GlyphAt(const size_t column)
|
||||
CharRow::reference CharRow::GlyphAt(const til::CoordType column)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, column >= _data.size());
|
||||
THROW_HR_IF(E_INVALIDARG, column < 0 || column >= gsl::narrow_cast<til::CoordType>(_data.size()));
|
||||
return { *this, column };
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ std::wstring CharRow::GetText() const
|
||||
std::wstring wstr;
|
||||
wstr.reserve(_data.size());
|
||||
|
||||
for (size_t i = 0; i < _data.size(); ++i)
|
||||
for (til::CoordType i = 0; i < gsl::narrow_cast<til::CoordType>(_data.size()); ++i)
|
||||
{
|
||||
const auto glyph = GlyphAt(i);
|
||||
if (!DbcsAttrAt(i).IsTrailing())
|
||||
@@ -231,9 +231,9 @@ std::wstring CharRow::GetText() const
|
||||
// - wordDelimiters: the delimiters defined as a part of the DelimiterClass::DelimiterChar
|
||||
// Return Value:
|
||||
// - the delimiter class for the given char
|
||||
const DelimiterClass CharRow::DelimiterClassAt(const size_t column, const std::wstring_view wordDelimiters) const
|
||||
const DelimiterClass CharRow::DelimiterClassAt(const til::CoordType column, const std::wstring_view wordDelimiters) const
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, column >= _data.size());
|
||||
THROW_HR_IF(E_INVALIDARG, column < 0 || column >= gsl::narrow_cast<til::CoordType>(_data.size()));
|
||||
|
||||
const auto glyph = *GlyphAt(column).begin();
|
||||
if (glyph <= UNICODE_SPACE)
|
||||
@@ -265,10 +265,10 @@ const UnicodeStorage& CharRow::GetUnicodeStorage() const noexcept
|
||||
// Arguments:
|
||||
// - column - the column to generate the key for
|
||||
// Return Value:
|
||||
// - the COORD key for data access from UnicodeStorage for the column
|
||||
COORD CharRow::GetStorageKey(const size_t column) const noexcept
|
||||
// - the til::point key for data access from UnicodeStorage for the column
|
||||
til::point CharRow::GetStorageKey(const til::CoordType column) const noexcept
|
||||
{
|
||||
return { gsl::narrow<SHORT>(column), _pParent->GetId() };
|
||||
return { column, _pParent->GetId() };
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
||||
@@ -54,22 +54,22 @@ public:
|
||||
using const_reverse_iterator = typename boost::container::small_vector_base<value_type>::const_reverse_iterator;
|
||||
using reference = typename CharRowCellReference;
|
||||
|
||||
CharRow(size_t rowWidth, ROW* const pParent) noexcept;
|
||||
CharRow(til::CoordType rowWidth, ROW* const pParent) noexcept;
|
||||
|
||||
size_t size() const noexcept;
|
||||
[[nodiscard]] HRESULT Resize(const size_t newSize) noexcept;
|
||||
size_t MeasureLeft() const noexcept;
|
||||
size_t MeasureRight() const;
|
||||
til::CoordType size() const noexcept;
|
||||
[[nodiscard]] HRESULT Resize(const til::CoordType newSize) noexcept;
|
||||
til::CoordType MeasureLeft() const noexcept;
|
||||
til::CoordType MeasureRight() const;
|
||||
bool ContainsText() const noexcept;
|
||||
const DbcsAttribute& DbcsAttrAt(const size_t column) const;
|
||||
DbcsAttribute& DbcsAttrAt(const size_t column);
|
||||
void ClearGlyph(const size_t column);
|
||||
const DbcsAttribute& DbcsAttrAt(const til::CoordType column) const;
|
||||
DbcsAttribute& DbcsAttrAt(const til::CoordType column);
|
||||
void ClearGlyph(const til::CoordType column);
|
||||
|
||||
const DelimiterClass DelimiterClassAt(const size_t column, const std::wstring_view wordDelimiters) const;
|
||||
const DelimiterClass DelimiterClassAt(const til::CoordType column, const std::wstring_view wordDelimiters) const;
|
||||
|
||||
// working with glyphs
|
||||
const reference GlyphAt(const size_t column) const;
|
||||
reference GlyphAt(const size_t column);
|
||||
const reference GlyphAt(const til::CoordType column) const;
|
||||
reference GlyphAt(const til::CoordType column);
|
||||
|
||||
// iterators
|
||||
iterator begin() noexcept;
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
|
||||
UnicodeStorage& GetUnicodeStorage() noexcept;
|
||||
const UnicodeStorage& GetUnicodeStorage() const noexcept;
|
||||
COORD GetStorageKey(const size_t column) const noexcept;
|
||||
til::point GetStorageKey(const til::CoordType column) const noexcept;
|
||||
|
||||
void UpdateParent(ROW* const pParent);
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
|
||||
private:
|
||||
void Reset() noexcept;
|
||||
void ClearCell(const size_t column);
|
||||
void ClearCell(const til::CoordType column);
|
||||
std::wstring GetText() const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -25,7 +25,7 @@ class CharRowCellReference final
|
||||
public:
|
||||
using const_iterator = const wchar_t*;
|
||||
|
||||
CharRowCellReference(CharRow& parent, const size_t index) noexcept :
|
||||
CharRowCellReference(CharRow& parent, const til::CoordType index) noexcept :
|
||||
_parent{ parent },
|
||||
_index{ index }
|
||||
{
|
||||
@@ -51,7 +51,7 @@ private:
|
||||
// what char row the object belongs to
|
||||
CharRow& _parent;
|
||||
// the index of the cell in the parent char row
|
||||
const size_t _index;
|
||||
til::CoordType _index;
|
||||
|
||||
CharRowCell& _cellData();
|
||||
const CharRowCell& _cellData() const;
|
||||
|
||||
@@ -21,16 +21,16 @@ enum class LineRendition
|
||||
DoubleHeightBottom
|
||||
};
|
||||
|
||||
constexpr SMALL_RECT ScreenToBufferLine(const SMALL_RECT& line, const LineRendition lineRendition)
|
||||
constexpr til::inclusive_rect ScreenToBufferLine(const til::inclusive_rect& line, const LineRendition lineRendition)
|
||||
{
|
||||
// Use shift right to quickly divide the Left and Right by 2 for double width lines.
|
||||
const SHORT scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
|
||||
const auto scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
|
||||
return { line.Left >> scale, line.Top, line.Right >> scale, line.Bottom };
|
||||
}
|
||||
|
||||
constexpr SMALL_RECT BufferToScreenLine(const SMALL_RECT& line, const LineRendition lineRendition)
|
||||
constexpr til::inclusive_rect BufferToScreenLine(const til::inclusive_rect& line, const LineRendition lineRendition)
|
||||
{
|
||||
// Use shift left to quickly multiply the Left and Right by 2 for double width lines.
|
||||
const SHORT scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
|
||||
const auto scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
|
||||
return { line.Left << scale, line.Top, (line.Right << scale) + scale, line.Bottom };
|
||||
}
|
||||
|
||||
@@ -531,16 +531,16 @@ OutputCellView OutputCellIterator::s_GenerateView(const OutputCell& cell)
|
||||
// - Gets the distance between two iterators relative to the input data given in.
|
||||
// Return Value:
|
||||
// - The number of items of the input run consumed between these two iterators.
|
||||
ptrdiff_t OutputCellIterator::GetInputDistance(OutputCellIterator other) const noexcept
|
||||
til::CoordType OutputCellIterator::GetInputDistance(OutputCellIterator other) const noexcept
|
||||
{
|
||||
return _pos - other._pos;
|
||||
return gsl::narrow_cast<til::CoordType>(_pos - other._pos);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Gets the distance between two iterators relative to the number of cells inserted.
|
||||
// Return Value:
|
||||
// - The number of cells in the backing buffer filled between these two iterators.
|
||||
ptrdiff_t OutputCellIterator::GetCellDistance(OutputCellIterator other) const noexcept
|
||||
til::CoordType OutputCellIterator::GetCellDistance(OutputCellIterator other) const noexcept
|
||||
{
|
||||
return _distance - other._distance;
|
||||
return gsl::narrow_cast<til::CoordType>(_distance - other._distance);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class OutputCellIterator final
|
||||
public:
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = OutputCellView;
|
||||
using difference_type = ptrdiff_t;
|
||||
using difference_type = til::CoordType;
|
||||
using pointer = OutputCellView*;
|
||||
using reference = OutputCellView&;
|
||||
|
||||
@@ -48,9 +48,9 @@ public:
|
||||
|
||||
operator bool() const noexcept;
|
||||
|
||||
ptrdiff_t GetCellDistance(OutputCellIterator other) const noexcept;
|
||||
ptrdiff_t GetInputDistance(OutputCellIterator other) const noexcept;
|
||||
friend ptrdiff_t operator-(OutputCellIterator one, OutputCellIterator two) = delete;
|
||||
til::CoordType GetCellDistance(OutputCellIterator other) const noexcept;
|
||||
til::CoordType GetInputDistance(OutputCellIterator other) const noexcept;
|
||||
friend til::CoordType operator-(OutputCellIterator one, OutputCellIterator two) = delete;
|
||||
|
||||
OutputCellIterator& operator++();
|
||||
OutputCellIterator operator++(int);
|
||||
|
||||
@@ -21,14 +21,11 @@ OutputCellRect::OutputCellRect() noexcept :
|
||||
// Arguments:
|
||||
// - rows - Rows in the rectangle (height)
|
||||
// - cols - Columns in the rectangle (width)
|
||||
OutputCellRect::OutputCellRect(const size_t rows, const size_t cols) :
|
||||
OutputCellRect::OutputCellRect(const til::CoordType rows, const til::CoordType cols) :
|
||||
_rows(rows),
|
||||
_cols(cols)
|
||||
{
|
||||
size_t totalCells;
|
||||
THROW_IF_FAILED(SizeTMult(rows, cols, &totalCells));
|
||||
|
||||
_storage.resize(totalCells);
|
||||
_storage.resize(gsl::narrow<size_t>(rows * cols));
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -37,7 +34,7 @@ OutputCellRect::OutputCellRect(const size_t rows, const size_t cols) :
|
||||
// - row - The Y position or row index in the buffer.
|
||||
// Return Value:
|
||||
// - Read/write span of OutputCells
|
||||
gsl::span<OutputCell> OutputCellRect::GetRow(const size_t row)
|
||||
gsl::span<OutputCell> OutputCellRect::GetRow(const til::CoordType row)
|
||||
{
|
||||
return gsl::span<OutputCell>(_FindRowOffset(row), _cols);
|
||||
}
|
||||
@@ -48,7 +45,7 @@ gsl::span<OutputCell> OutputCellRect::GetRow(const size_t row)
|
||||
// - row - The Y position or row index in the buffer.
|
||||
// Return Value:
|
||||
// - Read-only iterator of OutputCells
|
||||
OutputCellIterator OutputCellRect::GetRowIter(const size_t row) const
|
||||
OutputCellIterator OutputCellRect::GetRowIter(const til::CoordType row) const
|
||||
{
|
||||
const gsl::span<const OutputCell> view(_FindRowOffset(row), _cols);
|
||||
|
||||
@@ -62,9 +59,9 @@ OutputCellIterator OutputCellRect::GetRowIter(const size_t row) const
|
||||
// - row - The Y position or row index in the buffer.
|
||||
// Return Value:
|
||||
// - Pointer to the location in the rectangle that represents the start of the requested row.
|
||||
OutputCell* OutputCellRect::_FindRowOffset(const size_t row)
|
||||
OutputCell* OutputCellRect::_FindRowOffset(const til::CoordType row)
|
||||
{
|
||||
return &_storage.at(row * _cols);
|
||||
return &_storage.at(gsl::narrow_cast<size_t>(row * _cols));
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -74,16 +71,16 @@ OutputCell* OutputCellRect::_FindRowOffset(const size_t row)
|
||||
// - row - The Y position or row index in the buffer.
|
||||
// Return Value:
|
||||
// - Pointer to the location in the rectangle that represents the start of the requested row.
|
||||
const OutputCell* OutputCellRect::_FindRowOffset(const size_t row) const
|
||||
const OutputCell* OutputCellRect::_FindRowOffset(const til::CoordType row) const
|
||||
{
|
||||
return &_storage.at(row * _cols);
|
||||
return &_storage.at(gsl::narrow_cast<size_t>(row * _cols));
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Gets the height of the rectangle
|
||||
// Return Value:
|
||||
// - Height
|
||||
size_t OutputCellRect::Height() const noexcept
|
||||
til::CoordType OutputCellRect::Height() const noexcept
|
||||
{
|
||||
return _rows;
|
||||
}
|
||||
@@ -92,7 +89,7 @@ size_t OutputCellRect::Height() const noexcept
|
||||
// - Gets the width of the rectangle
|
||||
// Return Value:
|
||||
// - Width
|
||||
size_t OutputCellRect::Width() const noexcept
|
||||
til::CoordType OutputCellRect::Width() const noexcept
|
||||
{
|
||||
return _cols;
|
||||
}
|
||||
|
||||
@@ -30,20 +30,20 @@ class OutputCellRect final
|
||||
{
|
||||
public:
|
||||
OutputCellRect() noexcept;
|
||||
OutputCellRect(const size_t rows, const size_t cols);
|
||||
OutputCellRect(const til::CoordType rows, const til::CoordType cols);
|
||||
|
||||
gsl::span<OutputCell> GetRow(const size_t row);
|
||||
OutputCellIterator GetRowIter(const size_t row) const;
|
||||
gsl::span<OutputCell> GetRow(const til::CoordType row);
|
||||
OutputCellIterator GetRowIter(const til::CoordType row) const;
|
||||
|
||||
size_t Height() const noexcept;
|
||||
size_t Width() const noexcept;
|
||||
til::CoordType Height() const noexcept;
|
||||
til::CoordType Width() const noexcept;
|
||||
|
||||
private:
|
||||
std::vector<OutputCell> _storage;
|
||||
|
||||
OutputCell* _FindRowOffset(const size_t row);
|
||||
const OutputCell* _FindRowOffset(const size_t row) const;
|
||||
OutputCell* _FindRowOffset(const til::CoordType row);
|
||||
const OutputCell* _FindRowOffset(const til::CoordType row) const;
|
||||
|
||||
size_t _cols;
|
||||
size_t _rows;
|
||||
til::CoordType _cols;
|
||||
til::CoordType _rows;
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ OutputCellView::OutputCellView(const std::wstring_view view,
|
||||
// - Reports how many columns we expect the Chars() text data to consume
|
||||
// Return Value:
|
||||
// - Count of column cells on the screen
|
||||
size_t OutputCellView::Columns() const noexcept
|
||||
til::CoordType OutputCellView::Columns() const noexcept
|
||||
{
|
||||
if (DbcsAttr().IsSingle())
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
const TextAttributeBehavior behavior) noexcept;
|
||||
|
||||
const std::wstring_view& Chars() const noexcept;
|
||||
size_t Columns() const noexcept;
|
||||
til::CoordType Columns() const noexcept;
|
||||
DbcsAttribute DbcsAttr() const noexcept;
|
||||
TextAttribute TextAttr() const noexcept;
|
||||
TextAttributeBehavior TextAttrBehavior() const noexcept;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// - pParent - the text buffer that this row belongs to
|
||||
// Return Value:
|
||||
// - constructed object
|
||||
ROW::ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent) :
|
||||
ROW::ROW(const til::CoordType rowId, const til::CoordType rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent) :
|
||||
_id{ rowId },
|
||||
_rowWidth{ rowWidth },
|
||||
_charRow{ rowWidth, this },
|
||||
@@ -58,7 +58,7 @@ bool ROW::Reset(const TextAttribute Attr)
|
||||
// - width - the new width, in cells
|
||||
// Return Value:
|
||||
// - S_OK if successful, otherwise relevant error
|
||||
[[nodiscard]] HRESULT ROW::Resize(const unsigned short width)
|
||||
[[nodiscard]] HRESULT ROW::Resize(const til::CoordType width)
|
||||
{
|
||||
RETURN_IF_FAILED(_charRow.Resize(width));
|
||||
try
|
||||
@@ -78,7 +78,7 @@ bool ROW::Reset(const TextAttribute Attr)
|
||||
// - column - 0-indexed column index
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void ROW::ClearColumn(const size_t column)
|
||||
void ROW::ClearColumn(const til::CoordType column)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, column >= _charRow.size());
|
||||
_charRow.ClearCell(column);
|
||||
@@ -103,7 +103,7 @@ const UnicodeStorage& ROW::GetUnicodeStorage() const noexcept
|
||||
// - limitRight - right inclusive column ID for the last write in this row. (optional, will just write to the end of row if nullopt)
|
||||
// Return Value:
|
||||
// - iterator to first cell that was not written to this row.
|
||||
OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, const std::optional<bool> wrap, std::optional<size_t> limitRight)
|
||||
OutputCellIterator ROW::WriteCells(OutputCellIterator it, const til::CoordType index, const std::optional<bool> wrap, std::optional<til::CoordType> limitRight)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, index >= _charRow.size());
|
||||
THROW_HR_IF(E_INVALIDARG, limitRight.value_or(0) >= _charRow.size());
|
||||
|
||||
@@ -32,9 +32,9 @@ class TextBuffer;
|
||||
class ROW final
|
||||
{
|
||||
public:
|
||||
ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent);
|
||||
ROW(const til::CoordType rowId, const til::CoordType rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent);
|
||||
|
||||
size_t size() const noexcept { return _rowWidth; }
|
||||
til::CoordType size() const noexcept { return _rowWidth; }
|
||||
|
||||
void SetWrapForced(const bool wrap) noexcept { _wrapForced = wrap; }
|
||||
bool WasWrapForced() const noexcept { return _wrapForced; }
|
||||
@@ -51,19 +51,19 @@ public:
|
||||
LineRendition GetLineRendition() const noexcept { return _lineRendition; }
|
||||
void SetLineRendition(const LineRendition lineRendition) noexcept { _lineRendition = lineRendition; }
|
||||
|
||||
SHORT GetId() const noexcept { return _id; }
|
||||
void SetId(const SHORT id) noexcept { _id = id; }
|
||||
til::CoordType GetId() const noexcept { return _id; }
|
||||
void SetId(const til::CoordType id) noexcept { _id = id; }
|
||||
|
||||
bool Reset(const TextAttribute Attr);
|
||||
[[nodiscard]] HRESULT Resize(const unsigned short width);
|
||||
[[nodiscard]] HRESULT Resize(const til::CoordType width);
|
||||
|
||||
void ClearColumn(const size_t column);
|
||||
void ClearColumn(const til::CoordType column);
|
||||
std::wstring GetText() const { return _charRow.GetText(); }
|
||||
|
||||
UnicodeStorage& GetUnicodeStorage() noexcept;
|
||||
const UnicodeStorage& GetUnicodeStorage() const noexcept;
|
||||
|
||||
OutputCellIterator WriteCells(OutputCellIterator it, const size_t index, const std::optional<bool> wrap = std::nullopt, std::optional<size_t> limitRight = std::nullopt);
|
||||
OutputCellIterator WriteCells(OutputCellIterator it, const til::CoordType index, const std::optional<bool> wrap = std::nullopt, std::optional<til::CoordType> limitRight = std::nullopt);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend constexpr bool operator==(const ROW& a, const ROW& b) noexcept;
|
||||
@@ -74,8 +74,8 @@ private:
|
||||
CharRow _charRow;
|
||||
ATTR_ROW _attrRow;
|
||||
LineRendition _lineRendition;
|
||||
SHORT _id;
|
||||
unsigned short _rowWidth;
|
||||
til::CoordType _id;
|
||||
til::CoordType _rowWidth;
|
||||
// Occurs when the user runs out of text in a given row and we're forced to wrap the cursor to the next line
|
||||
bool _wrapForced;
|
||||
// Occurs when the user runs out of text to support a double byte character and we're forced to the next line
|
||||
|
||||
@@ -47,7 +47,7 @@ void UnicodeStorage::Erase(const key_type key) noexcept
|
||||
// - rowMap - A map of the old row IDs to the new row IDs.
|
||||
// - width - The width of the new row. Remove any items that are beyond the row width.
|
||||
// - Use nullopt if we're not resizing the width of the row, just renumbering the rows.
|
||||
void UnicodeStorage::Remap(const std::unordered_map<SHORT, SHORT>& rowMap, const std::optional<SHORT> width)
|
||||
void UnicodeStorage::Remap(const std::unordered_map<til::CoordType, til::CoordType>& rowMap, const std::optional<til::CoordType> width)
|
||||
{
|
||||
// Make a temporary map to hold all the new row positioning
|
||||
std::unordered_map<key_type, mapped_type> newMap;
|
||||
@@ -87,7 +87,7 @@ void UnicodeStorage::Remap(const std::unordered_map<SHORT, SHORT>& rowMap, const
|
||||
const auto newRowId = mapIter->second;
|
||||
|
||||
// Generate a new coordinate with the same X as the old one, but a new Y value.
|
||||
const auto newCoord = COORD{ oldCoord.X, newRowId };
|
||||
const auto newCoord = til::point{ oldCoord.X, newRowId };
|
||||
|
||||
// Put the adjusted coordinate into the map with the original value.
|
||||
newMap.emplace(newCoord, pair.second);
|
||||
|
||||
@@ -20,11 +20,11 @@ Author(s):
|
||||
#include <til/bit.h>
|
||||
#include <til/hash.h>
|
||||
|
||||
// std::unordered_map needs help to know how to hash a COORD
|
||||
// std::unordered_map needs help to know how to hash a til::point
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<COORD>
|
||||
struct hash<til::point>
|
||||
{
|
||||
// Routine Description:
|
||||
// - hashes a coord. coord will be hashed by storing the x and y values consecutively in the lower
|
||||
@@ -33,9 +33,9 @@ namespace std
|
||||
// - coord - the coord to hash
|
||||
// Return Value:
|
||||
// - the hashed coord
|
||||
constexpr size_t operator()(const COORD& coord) const noexcept
|
||||
constexpr size_t operator()(const til::point coord) const noexcept
|
||||
{
|
||||
return til::hash(til::bit_cast<uint32_t>(coord));
|
||||
return til::hash(til::bit_cast<uint64_t>(coord));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace std
|
||||
class UnicodeStorage final
|
||||
{
|
||||
public:
|
||||
using key_type = typename COORD;
|
||||
using key_type = typename til::point;
|
||||
using mapped_type = typename std::vector<wchar_t>;
|
||||
|
||||
UnicodeStorage() noexcept;
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
|
||||
void Erase(const key_type key) noexcept;
|
||||
|
||||
void Remap(const std::unordered_map<SHORT, SHORT>& rowMap, const std::optional<SHORT> width);
|
||||
void Remap(const std::unordered_map<til::CoordType, til::CoordType>& rowMap, const std::optional<til::CoordType> width);
|
||||
|
||||
private:
|
||||
std::unordered_map<key_type, mapped_type> _map;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// - ulSize - The height of the cursor within this buffer
|
||||
Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
|
||||
_parentBuffer{ parentBuffer },
|
||||
_cPosition{ 0 },
|
||||
_fHasMoved(false),
|
||||
_fIsVisible(true),
|
||||
_fIsOn(true),
|
||||
@@ -23,7 +22,6 @@ Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
|
||||
_fIsConversionArea(false),
|
||||
_fIsPopupShown(false),
|
||||
_fDelayedEolWrap(false),
|
||||
_coordDelayedAt{ 0 },
|
||||
_fDeferCursorRedraw(false),
|
||||
_fHaveDeferredCursorRedraw(false),
|
||||
_ulSize(ulSize),
|
||||
@@ -35,7 +33,7 @@ Cursor::~Cursor()
|
||||
{
|
||||
}
|
||||
|
||||
COORD Cursor::GetPosition() const noexcept
|
||||
til::point Cursor::GetPosition() const noexcept
|
||||
{
|
||||
return _cPosition;
|
||||
}
|
||||
@@ -192,59 +190,58 @@ void Cursor::_RedrawCursorAlways() noexcept
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
void Cursor::SetPosition(const COORD cPosition) noexcept
|
||||
void Cursor::SetPosition(const til::point cPosition) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.X = cPosition.X;
|
||||
_cPosition.Y = cPosition.Y;
|
||||
_cPosition = cPosition;
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::SetXPosition(const int NewX) noexcept
|
||||
void Cursor::SetXPosition(const til::CoordType NewX) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.X = gsl::narrow<SHORT>(NewX);
|
||||
_cPosition.X = NewX;
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::SetYPosition(const int NewY) noexcept
|
||||
void Cursor::SetYPosition(const til::CoordType NewY) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.Y = gsl::narrow<SHORT>(NewY);
|
||||
_cPosition.Y = NewY;
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::IncrementXPosition(const int DeltaX) noexcept
|
||||
void Cursor::IncrementXPosition(const til::CoordType DeltaX) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.X += gsl::narrow<SHORT>(DeltaX);
|
||||
_cPosition.X += DeltaX;
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::IncrementYPosition(const int DeltaY) noexcept
|
||||
void Cursor::IncrementYPosition(const til::CoordType DeltaY) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.Y += gsl::narrow<SHORT>(DeltaY);
|
||||
_cPosition.Y += DeltaY;
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::DecrementXPosition(const int DeltaX) noexcept
|
||||
void Cursor::DecrementXPosition(const til::CoordType DeltaX) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.X -= gsl::narrow<SHORT>(DeltaX);
|
||||
_cPosition.X -= DeltaX;
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
|
||||
void Cursor::DecrementYPosition(const int DeltaY) noexcept
|
||||
void Cursor::DecrementYPosition(const til::CoordType DeltaY) noexcept
|
||||
{
|
||||
_RedrawCursor();
|
||||
_cPosition.Y -= gsl::narrow<SHORT>(DeltaY);
|
||||
_cPosition.Y -= DeltaY;
|
||||
_RedrawCursor();
|
||||
ResetDelayEOLWrap();
|
||||
}
|
||||
@@ -284,7 +281,7 @@ void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
|
||||
_cursorType = OtherCursor._cursorType;
|
||||
}
|
||||
|
||||
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
|
||||
void Cursor::DelayEOLWrap(const til::point coordDelayedAt) noexcept
|
||||
{
|
||||
_coordDelayedAt = coordDelayedAt;
|
||||
_fDelayedEolWrap = true;
|
||||
@@ -292,11 +289,11 @@ void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
|
||||
|
||||
void Cursor::ResetDelayEOLWrap() noexcept
|
||||
{
|
||||
_coordDelayedAt = { 0 };
|
||||
_coordDelayedAt = {};
|
||||
_fDelayedEolWrap = false;
|
||||
}
|
||||
|
||||
COORD Cursor::GetDelayedAtPosition() const noexcept
|
||||
til::point Cursor::GetDelayedAtPosition() const noexcept
|
||||
{
|
||||
return _coordDelayedAt;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
bool IsPopupShown() const noexcept;
|
||||
bool GetDelay() const noexcept;
|
||||
ULONG GetSize() const noexcept;
|
||||
COORD GetPosition() const noexcept;
|
||||
til::point GetPosition() const noexcept;
|
||||
|
||||
const CursorType GetType() const noexcept;
|
||||
|
||||
@@ -66,19 +66,19 @@ public:
|
||||
void SetSize(const ULONG ulSize) noexcept;
|
||||
void SetStyle(const ULONG ulSize, const CursorType type) noexcept;
|
||||
|
||||
void SetPosition(const COORD cPosition) noexcept;
|
||||
void SetXPosition(const int NewX) noexcept;
|
||||
void SetYPosition(const int NewY) noexcept;
|
||||
void IncrementXPosition(const int DeltaX) noexcept;
|
||||
void IncrementYPosition(const int DeltaY) noexcept;
|
||||
void DecrementXPosition(const int DeltaX) noexcept;
|
||||
void DecrementYPosition(const int DeltaY) noexcept;
|
||||
void SetPosition(const til::point cPosition) noexcept;
|
||||
void SetXPosition(const til::CoordType NewX) noexcept;
|
||||
void SetYPosition(const til::CoordType NewY) noexcept;
|
||||
void IncrementXPosition(const til::CoordType DeltaX) noexcept;
|
||||
void IncrementYPosition(const til::CoordType DeltaY) noexcept;
|
||||
void DecrementXPosition(const til::CoordType DeltaX) noexcept;
|
||||
void DecrementYPosition(const til::CoordType DeltaY) noexcept;
|
||||
|
||||
void CopyProperties(const Cursor& OtherCursor) noexcept;
|
||||
|
||||
void DelayEOLWrap(const COORD coordDelayedAt) noexcept;
|
||||
void DelayEOLWrap(const til::point coordDelayedAt) noexcept;
|
||||
void ResetDelayEOLWrap() noexcept;
|
||||
COORD GetDelayedAtPosition() const noexcept;
|
||||
til::point GetDelayedAtPosition() const noexcept;
|
||||
bool IsDelayedEOLWrap() const noexcept;
|
||||
|
||||
void SetType(const CursorType type) noexcept;
|
||||
@@ -90,7 +90,7 @@ private:
|
||||
|
||||
// NOTE: If you are adding a property here, go add it to CopyProperties.
|
||||
|
||||
COORD _cPosition; // current position on screen (in screen buffer coords).
|
||||
til::point _cPosition; // current position on screen (in screen buffer coords).
|
||||
|
||||
bool _fHasMoved;
|
||||
bool _fIsVisible; // whether cursor is visible (set only through the API)
|
||||
@@ -102,7 +102,7 @@ private:
|
||||
bool _fIsPopupShown; // if a popup is being shown, turn off, stop blinking.
|
||||
|
||||
bool _fDelayedEolWrap; // don't wrap at EOL till the next char comes in.
|
||||
COORD _coordDelayedAt; // coordinate the EOL wrap was delayed at.
|
||||
til::point _coordDelayedAt; // coordinate the EOL wrap was delayed at.
|
||||
|
||||
bool _fDeferCursorRedraw; // whether we should defer redrawing the cursor or not
|
||||
bool _fHaveDeferredCursorRedraw; // have we been asked to redraw the cursor while it was being deferred?
|
||||
|
||||
@@ -35,7 +35,6 @@ Abstract:
|
||||
#include <intsafe.h>
|
||||
|
||||
// private dependencies
|
||||
#include "../inc/operators.hpp"
|
||||
#include "../inc/unicode.hpp"
|
||||
#pragma warning(pop)
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ Search::Search(IUiaData& uiaData,
|
||||
const std::wstring& str,
|
||||
const Direction direction,
|
||||
const Sensitivity sensitivity,
|
||||
const COORD anchor) :
|
||||
const til::point anchor) :
|
||||
_direction(direction),
|
||||
_sensitivity(sensitivity),
|
||||
_needle(s_CreateNeedleFromString(str)),
|
||||
@@ -124,7 +124,7 @@ void Search::Color(const TextAttribute attr) const
|
||||
// been called and returned true.
|
||||
// Return Value:
|
||||
// - pair containing [start, end] coord positions of text found by search
|
||||
std::pair<COORD, COORD> Search::GetFoundLocation() const noexcept
|
||||
std::pair<til::point, til::point> Search::GetFoundLocation() const noexcept
|
||||
{
|
||||
return { _coordSelStart, _coordSelEnd };
|
||||
}
|
||||
@@ -140,7 +140,7 @@ std::pair<COORD, COORD> Search::GetFoundLocation() const noexcept
|
||||
// - direction - The intended direction of the search
|
||||
// Return Value:
|
||||
// - Coordinate to start the search from.
|
||||
COORD Search::s_GetInitialAnchor(const IUiaData& uiaData, const Direction direction)
|
||||
til::point Search::s_GetInitialAnchor(const IUiaData& uiaData, const Direction direction)
|
||||
{
|
||||
const auto& textBuffer = uiaData.GetTextBuffer();
|
||||
const auto textBufferEndPosition = uiaData.GetTextBufferEndPosition();
|
||||
@@ -187,10 +187,10 @@ COORD Search::s_GetInitialAnchor(const IUiaData& uiaData, const Direction direct
|
||||
// - end - If we found it, this is filled with the coordinate of the last character of the needle.
|
||||
// Return Value:
|
||||
// - True if we found it. False if not.
|
||||
bool Search::_FindNeedleInHaystackAt(const COORD pos, COORD& start, COORD& end) const
|
||||
bool Search::_FindNeedleInHaystackAt(const til::point pos, til::point& start, til::point& end) const
|
||||
{
|
||||
start = { 0 };
|
||||
end = { 0 };
|
||||
start = {};
|
||||
end = {};
|
||||
|
||||
auto bufferPos = pos;
|
||||
|
||||
@@ -269,7 +269,7 @@ wchar_t Search::_ApplySensitivity(const wchar_t wch) const noexcept
|
||||
// - Helper to increment a coordinate in respect to the associated screen buffer
|
||||
// Arguments
|
||||
// - coord - Updated by function to increment one position (will wrap X and Y direction)
|
||||
void Search::_IncrementCoord(COORD& coord) const noexcept
|
||||
void Search::_IncrementCoord(til::point& coord) const noexcept
|
||||
{
|
||||
_uiaData.GetTextBuffer().GetSize().IncrementInBoundsCircular(coord);
|
||||
}
|
||||
@@ -278,7 +278,7 @@ void Search::_IncrementCoord(COORD& coord) const noexcept
|
||||
// - Helper to decrement a coordinate in respect to the associated screen buffer
|
||||
// Arguments
|
||||
// - coord - Updated by function to decrement one position (will wrap X and Y direction)
|
||||
void Search::_DecrementCoord(COORD& coord) const noexcept
|
||||
void Search::_DecrementCoord(til::point& coord) const noexcept
|
||||
{
|
||||
_uiaData.GetTextBuffer().GetSize().DecrementInBoundsCircular(coord);
|
||||
}
|
||||
@@ -314,7 +314,7 @@ void Search::_UpdateNextPosition()
|
||||
{
|
||||
if (_direction == Direction::Forward)
|
||||
{
|
||||
_coordNext = { 0 };
|
||||
_coordNext = {};
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -49,33 +49,33 @@ public:
|
||||
const std::wstring& str,
|
||||
const Direction dir,
|
||||
const Sensitivity sensitivity,
|
||||
const COORD anchor);
|
||||
const til::point anchor);
|
||||
|
||||
bool FindNext();
|
||||
void Select() const;
|
||||
void Color(const TextAttribute attr) const;
|
||||
|
||||
std::pair<COORD, COORD> GetFoundLocation() const noexcept;
|
||||
std::pair<til::point, til::point> GetFoundLocation() const noexcept;
|
||||
|
||||
private:
|
||||
wchar_t _ApplySensitivity(const wchar_t wch) const noexcept;
|
||||
bool _FindNeedleInHaystackAt(const COORD pos, COORD& start, COORD& end) const;
|
||||
bool _FindNeedleInHaystackAt(const til::point pos, til::point& start, til::point& end) const;
|
||||
bool _CompareChars(const std::wstring_view one, const std::wstring_view two) const noexcept;
|
||||
void _UpdateNextPosition();
|
||||
|
||||
void _IncrementCoord(COORD& coord) const noexcept;
|
||||
void _DecrementCoord(COORD& coord) const noexcept;
|
||||
void _IncrementCoord(til::point& coord) const noexcept;
|
||||
void _DecrementCoord(til::point& coord) const noexcept;
|
||||
|
||||
static COORD s_GetInitialAnchor(const Microsoft::Console::Types::IUiaData& uiaData, const Direction dir);
|
||||
static til::point s_GetInitialAnchor(const Microsoft::Console::Types::IUiaData& uiaData, const Direction dir);
|
||||
|
||||
static std::vector<std::vector<wchar_t>> s_CreateNeedleFromString(const std::wstring& wstr);
|
||||
|
||||
bool _reachedEnd = false;
|
||||
COORD _coordNext = { 0 };
|
||||
COORD _coordSelStart = { 0 };
|
||||
COORD _coordSelEnd = { 0 };
|
||||
til::point _coordNext;
|
||||
til::point _coordSelStart;
|
||||
til::point _coordSelEnd;
|
||||
|
||||
const COORD _coordAnchor;
|
||||
const til::point _coordAnchor;
|
||||
const std::vector<std::vector<wchar_t>> _needle;
|
||||
const Direction _direction;
|
||||
const Sensitivity _sensitivity;
|
||||
|
||||
@@ -30,7 +30,7 @@ using PointTree = interval_tree::IntervalTree<til::point, size_t>;
|
||||
// Return Value:
|
||||
// - constructed object
|
||||
// Note: may throw exception
|
||||
TextBuffer::TextBuffer(const COORD screenBufferSize,
|
||||
TextBuffer::TextBuffer(const til::size screenBufferSize,
|
||||
const TextAttribute defaultAttributes,
|
||||
const UINT cursorSize,
|
||||
const bool isActiveBuffer,
|
||||
@@ -47,10 +47,10 @@ TextBuffer::TextBuffer(const COORD screenBufferSize,
|
||||
_currentPatternId{ 0 }
|
||||
{
|
||||
// initialize ROWs
|
||||
_storage.reserve(static_cast<size_t>(screenBufferSize.Y));
|
||||
for (size_t i = 0; i < static_cast<size_t>(screenBufferSize.Y); ++i)
|
||||
_storage.reserve(gsl::narrow<size_t>(screenBufferSize.Y));
|
||||
for (til::CoordType i = 0; i < screenBufferSize.Y; ++i)
|
||||
{
|
||||
_storage.emplace_back(static_cast<SHORT>(i), screenBufferSize.X, _currentAttributes, this);
|
||||
_storage.emplace_back(i, screenBufferSize.X, _currentAttributes, this);
|
||||
}
|
||||
|
||||
_UpdateSize();
|
||||
@@ -74,9 +74,9 @@ void TextBuffer::CopyProperties(const TextBuffer& OtherBuffer) noexcept
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - Total number of rows in the buffer
|
||||
UINT TextBuffer::TotalRowCount() const noexcept
|
||||
til::CoordType TextBuffer::TotalRowCount() const noexcept
|
||||
{
|
||||
return gsl::narrow<UINT>(_storage.size());
|
||||
return gsl::narrow_cast<til::CoordType>(_storage.size());
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -86,13 +86,11 @@ UINT TextBuffer::TotalRowCount() const noexcept
|
||||
// - Number of rows down from the first row of the buffer.
|
||||
// Return Value:
|
||||
// - const reference to the requested row. Asserts if out of bounds.
|
||||
const ROW& TextBuffer::GetRowByOffset(const size_t index) const
|
||||
const ROW& TextBuffer::GetRowByOffset(const til::CoordType index) const noexcept
|
||||
{
|
||||
const size_t totalRows = TotalRowCount();
|
||||
|
||||
// Rows are stored circularly, so the index you ask for is offset by the start position and mod the total of rows.
|
||||
const auto offsetIndex = (_firstRow + index) % totalRows;
|
||||
return _storage.at(offsetIndex);
|
||||
const auto offsetIndex = gsl::narrow_cast<size_t>(_firstRow + index) % _storage.size();
|
||||
return til::at(_storage, offsetIndex);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -102,13 +100,11 @@ const ROW& TextBuffer::GetRowByOffset(const size_t index) const
|
||||
// - Number of rows down from the first row of the buffer.
|
||||
// Return Value:
|
||||
// - reference to the requested row. Asserts if out of bounds.
|
||||
ROW& TextBuffer::GetRowByOffset(const size_t index)
|
||||
ROW& TextBuffer::GetRowByOffset(const til::CoordType index) noexcept
|
||||
{
|
||||
const size_t totalRows = TotalRowCount();
|
||||
|
||||
// Rows are stored circularly, so the index you ask for is offset by the start position and mod the total of rows.
|
||||
const auto offsetIndex = (_firstRow + index) % totalRows;
|
||||
return _storage.at(offsetIndex);
|
||||
const auto offsetIndex = gsl::narrow_cast<size_t>(_firstRow + index) % _storage.size();
|
||||
return til::at(_storage, offsetIndex);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -117,7 +113,7 @@ ROW& TextBuffer::GetRowByOffset(const size_t index)
|
||||
// - at - X,Y position in buffer for iterator start position
|
||||
// Return Value:
|
||||
// - Read-only iterator of text data only.
|
||||
TextBufferTextIterator TextBuffer::GetTextDataAt(const COORD at) const
|
||||
TextBufferTextIterator TextBuffer::GetTextDataAt(const til::point at) const
|
||||
{
|
||||
return TextBufferTextIterator(GetCellDataAt(at));
|
||||
}
|
||||
@@ -128,7 +124,7 @@ TextBufferTextIterator TextBuffer::GetTextDataAt(const COORD at) const
|
||||
// - at - X,Y position in buffer for iterator start position
|
||||
// Return Value:
|
||||
// - Read-only iterator of cell data.
|
||||
TextBufferCellIterator TextBuffer::GetCellDataAt(const COORD at) const
|
||||
TextBufferCellIterator TextBuffer::GetCellDataAt(const til::point at) const
|
||||
{
|
||||
return TextBufferCellIterator(*this, at);
|
||||
}
|
||||
@@ -140,7 +136,7 @@ TextBufferCellIterator TextBuffer::GetCellDataAt(const COORD at) const
|
||||
// - at - X,Y position in buffer for iterator start position
|
||||
// Return Value:
|
||||
// - Read-only iterator of text data only.
|
||||
TextBufferTextIterator TextBuffer::GetTextLineDataAt(const COORD at) const
|
||||
TextBufferTextIterator TextBuffer::GetTextLineDataAt(const til::point at) const
|
||||
{
|
||||
return TextBufferTextIterator(GetCellLineDataAt(at));
|
||||
}
|
||||
@@ -152,9 +148,9 @@ TextBufferTextIterator TextBuffer::GetTextLineDataAt(const COORD at) const
|
||||
// - at - X,Y position in buffer for iterator start position
|
||||
// Return Value:
|
||||
// - Read-only iterator of cell data.
|
||||
TextBufferCellIterator TextBuffer::GetCellLineDataAt(const COORD at) const
|
||||
TextBufferCellIterator TextBuffer::GetCellLineDataAt(const til::point at) const
|
||||
{
|
||||
SMALL_RECT limit;
|
||||
til::inclusive_rect limit;
|
||||
limit.Top = at.Y;
|
||||
limit.Bottom = at.Y;
|
||||
limit.Left = 0;
|
||||
@@ -171,7 +167,7 @@ TextBufferCellIterator TextBuffer::GetCellLineDataAt(const COORD at) const
|
||||
// - limit - boundaries for the iterator to operate within
|
||||
// Return Value:
|
||||
// - Read-only iterator of text data only.
|
||||
TextBufferTextIterator TextBuffer::GetTextDataAt(const COORD at, const Viewport limit) const
|
||||
TextBufferTextIterator TextBuffer::GetTextDataAt(const til::point at, const Viewport limit) const
|
||||
{
|
||||
return TextBufferTextIterator(GetCellDataAt(at, limit));
|
||||
}
|
||||
@@ -184,7 +180,7 @@ TextBufferTextIterator TextBuffer::GetTextDataAt(const COORD at, const Viewport
|
||||
// - limit - boundaries for the iterator to operate within
|
||||
// Return Value:
|
||||
// - Read-only iterator of cell data.
|
||||
TextBufferCellIterator TextBuffer::GetCellDataAt(const COORD at, const Viewport limit) const
|
||||
TextBufferCellIterator TextBuffer::GetCellDataAt(const til::point at, const Viewport limit) const
|
||||
{
|
||||
return TextBufferCellIterator(*this, at, limit);
|
||||
}
|
||||
@@ -337,7 +333,7 @@ OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt)
|
||||
// Return Value:
|
||||
// - The final position of the iterator
|
||||
OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt,
|
||||
const COORD target,
|
||||
const til::point target,
|
||||
const std::optional<bool> wrap)
|
||||
{
|
||||
// Make mutable copy so we can walk.
|
||||
@@ -374,9 +370,9 @@ OutputCellIterator TextBuffer::Write(const OutputCellIterator givenIt,
|
||||
// Return Value:
|
||||
// - The iterator, but advanced to where we stopped writing. Use to find input consumed length or cells written length.
|
||||
OutputCellIterator TextBuffer::WriteLine(const OutputCellIterator givenIt,
|
||||
const COORD target,
|
||||
const til::point target,
|
||||
const std::optional<bool> wrap,
|
||||
std::optional<size_t> limitRight)
|
||||
std::optional<til::CoordType> limitRight)
|
||||
{
|
||||
// If we're not in bounds, exit early.
|
||||
if (!GetSize().IsInBounds(target))
|
||||
@@ -390,7 +386,7 @@ OutputCellIterator TextBuffer::WriteLine(const OutputCellIterator givenIt,
|
||||
|
||||
// Take the cell distance written and notify that it needs to be repainted.
|
||||
const auto written = newIt.GetCellDistance(givenIt);
|
||||
const auto paint = Viewport::FromDimensions(target, { gsl::narrow<SHORT>(written), 1 });
|
||||
const auto paint = Viewport::FromDimensions(target, { written, 1 });
|
||||
TriggerRedraw(paint);
|
||||
|
||||
return newIt;
|
||||
@@ -467,7 +463,7 @@ bool TextBuffer::InsertCharacter(const wchar_t wch, const DbcsAttribute dbcsAttr
|
||||
// - <none> - Always sets to wrap
|
||||
//Return Value:
|
||||
// - <none>
|
||||
void TextBuffer::_SetWrapOnCurrentRow()
|
||||
void TextBuffer::_SetWrapOnCurrentRow() noexcept
|
||||
{
|
||||
_AdjustWrapOnCurrentRow(true);
|
||||
}
|
||||
@@ -479,10 +475,10 @@ void TextBuffer::_SetWrapOnCurrentRow()
|
||||
// - fSet - True if this row has a wrap. False otherwise.
|
||||
//Return Value:
|
||||
// - <none>
|
||||
void TextBuffer::_AdjustWrapOnCurrentRow(const bool fSet)
|
||||
void TextBuffer::_AdjustWrapOnCurrentRow(const bool fSet) noexcept
|
||||
{
|
||||
// The vertical position of the cursor represents the current row we're manipulating.
|
||||
const UINT uiCurrentRowOffset = GetCursor().GetPosition().Y;
|
||||
const auto uiCurrentRowOffset = GetCursor().GetPosition().Y;
|
||||
|
||||
// Set the wrap status as appropriate
|
||||
GetRowByOffset(uiCurrentRowOffset).SetWrapForced(fSet);
|
||||
@@ -501,7 +497,7 @@ bool TextBuffer::IncrementCursor()
|
||||
// Cursor position is stored as logical array indices (starts at 0) for the window
|
||||
// Buffer Size is specified as the "length" of the array. It would say 80 for valid values of 0-79.
|
||||
// So subtract 1 from buffer size in each direction to find the index of the final column in the buffer
|
||||
const short iFinalColumnIndex = GetLineWidth(GetCursor().GetPosition().Y) - 1;
|
||||
const auto iFinalColumnIndex = GetLineWidth(GetCursor().GetPosition().Y) - 1;
|
||||
|
||||
// Move the cursor one position to the right
|
||||
GetCursor().IncrementXPosition(1);
|
||||
@@ -604,17 +600,17 @@ bool TextBuffer::IncrementCircularBuffer(const bool inVtMode)
|
||||
// - The viewport
|
||||
//Return value:
|
||||
// - Coordinate position (relative to the text buffer)
|
||||
COORD TextBuffer::GetLastNonSpaceCharacter(std::optional<const Microsoft::Console::Types::Viewport> viewOptional) const
|
||||
til::point TextBuffer::GetLastNonSpaceCharacter(std::optional<const Microsoft::Console::Types::Viewport> viewOptional) const
|
||||
{
|
||||
const auto viewport = viewOptional.has_value() ? viewOptional.value() : GetSize();
|
||||
|
||||
COORD coordEndOfText = { 0 };
|
||||
til::point coordEndOfText;
|
||||
// Search the given viewport by starting at the bottom.
|
||||
coordEndOfText.Y = viewport.BottomInclusive();
|
||||
|
||||
const auto& currRow = GetRowByOffset(coordEndOfText.Y);
|
||||
// The X position of the end of the valid text is the Right draw boundary (which is one beyond the final valid character)
|
||||
coordEndOfText.X = gsl::narrow<short>(currRow.GetCharRow().MeasureRight()) - 1;
|
||||
coordEndOfText.X = currRow.GetCharRow().MeasureRight() - 1;
|
||||
|
||||
// If the X coordinate turns out to be -1, the row was empty, we need to search backwards for the real end of text.
|
||||
const auto viewportTop = viewport.Top();
|
||||
@@ -625,13 +621,13 @@ COORD TextBuffer::GetLastNonSpaceCharacter(std::optional<const Microsoft::Consol
|
||||
const auto& backupRow = GetRowByOffset(coordEndOfText.Y);
|
||||
// We need to back up to the previous row if this line is empty, AND there are more rows
|
||||
|
||||
coordEndOfText.X = gsl::narrow<short>(backupRow.GetCharRow().MeasureRight()) - 1;
|
||||
coordEndOfText.X = backupRow.GetCharRow().MeasureRight() - 1;
|
||||
fDoBackUp = (coordEndOfText.X < 0 && coordEndOfText.Y > viewportTop);
|
||||
}
|
||||
|
||||
// don't allow negative results
|
||||
coordEndOfText.Y = std::max(coordEndOfText.Y, 0i16);
|
||||
coordEndOfText.X = std::max(coordEndOfText.X, 0i16);
|
||||
coordEndOfText.Y = std::max(coordEndOfText.Y, 0);
|
||||
coordEndOfText.X = std::max(coordEndOfText.X, 0);
|
||||
|
||||
return coordEndOfText;
|
||||
}
|
||||
@@ -643,7 +639,7 @@ COORD TextBuffer::GetLastNonSpaceCharacter(std::optional<const Microsoft::Consol
|
||||
// Return Value:
|
||||
// - Coordinate position in screen coordinates of the character just before the cursor.
|
||||
// - NOTE: Will return 0,0 if already in the top left corner
|
||||
COORD TextBuffer::_GetPreviousFromCursor() const
|
||||
til::point TextBuffer::_GetPreviousFromCursor() const noexcept
|
||||
{
|
||||
auto coordPosition = GetCursor().GetPosition();
|
||||
|
||||
@@ -668,7 +664,7 @@ COORD TextBuffer::_GetPreviousFromCursor() const
|
||||
return coordPosition;
|
||||
}
|
||||
|
||||
const SHORT TextBuffer::GetFirstRowIndex() const noexcept
|
||||
const til::CoordType TextBuffer::GetFirstRowIndex() const noexcept
|
||||
{
|
||||
return _firstRow;
|
||||
}
|
||||
@@ -680,15 +676,15 @@ const Viewport TextBuffer::GetSize() const noexcept
|
||||
|
||||
void TextBuffer::_UpdateSize()
|
||||
{
|
||||
_size = Viewport::FromDimensions({ 0, 0 }, { gsl::narrow<SHORT>(_storage.at(0).size()), gsl::narrow<SHORT>(_storage.size()) });
|
||||
_size = Viewport::FromDimensions({ _storage.at(0).size(), gsl::narrow<til::CoordType>(_storage.size()) });
|
||||
}
|
||||
|
||||
void TextBuffer::_SetFirstRowIndex(const SHORT FirstRowIndex) noexcept
|
||||
void TextBuffer::_SetFirstRowIndex(const til::CoordType FirstRowIndex) noexcept
|
||||
{
|
||||
_firstRow = FirstRowIndex;
|
||||
}
|
||||
|
||||
void TextBuffer::ScrollRows(const SHORT firstRow, const SHORT size, const SHORT delta)
|
||||
void TextBuffer::ScrollRows(const til::CoordType firstRow, const til::CoordType size, const til::CoordType delta)
|
||||
{
|
||||
// If we don't have to move anything, leave early.
|
||||
if (delta == 0)
|
||||
@@ -825,9 +821,9 @@ void TextBuffer::SetCurrentLineRendition(const LineRendition lineRendition)
|
||||
const auto fillChar = L' ';
|
||||
auto fillAttrs = GetCurrentAttributes();
|
||||
fillAttrs.SetStandardErase();
|
||||
const size_t fillOffset = GetLineWidth(rowIndex);
|
||||
const auto fillLength = GetSize().Width() - fillOffset;
|
||||
const auto fillData = OutputCellIterator{ fillChar, fillAttrs, fillLength };
|
||||
const auto fillOffset = GetLineWidth(rowIndex);
|
||||
const auto fillLength = gsl::narrow<size_t>(GetSize().Width() - fillOffset);
|
||||
const OutputCellIterator fillData{ fillChar, fillAttrs, fillLength };
|
||||
row.WriteCells(fillData, fillOffset, false);
|
||||
// We also need to make sure the cursor is clamped within the new width.
|
||||
GetCursor().SetPosition(ClampPositionWithinLine(cursorPosition));
|
||||
@@ -836,7 +832,7 @@ void TextBuffer::SetCurrentLineRendition(const LineRendition lineRendition)
|
||||
}
|
||||
}
|
||||
|
||||
void TextBuffer::ResetLineRenditionRange(const size_t startRow, const size_t endRow)
|
||||
void TextBuffer::ResetLineRenditionRange(const til::CoordType startRow, const til::CoordType endRow) noexcept
|
||||
{
|
||||
for (auto row = startRow; row < endRow; row++)
|
||||
{
|
||||
@@ -844,40 +840,40 @@ void TextBuffer::ResetLineRenditionRange(const size_t startRow, const size_t end
|
||||
}
|
||||
}
|
||||
|
||||
LineRendition TextBuffer::GetLineRendition(const size_t row) const
|
||||
LineRendition TextBuffer::GetLineRendition(const til::CoordType row) const noexcept
|
||||
{
|
||||
return GetRowByOffset(row).GetLineRendition();
|
||||
}
|
||||
|
||||
bool TextBuffer::IsDoubleWidthLine(const size_t row) const
|
||||
bool TextBuffer::IsDoubleWidthLine(const til::CoordType row) const noexcept
|
||||
{
|
||||
return GetLineRendition(row) != LineRendition::SingleWidth;
|
||||
}
|
||||
|
||||
SHORT TextBuffer::GetLineWidth(const size_t row) const
|
||||
til::CoordType TextBuffer::GetLineWidth(const til::CoordType row) const noexcept
|
||||
{
|
||||
// Use shift right to quickly divide the width by 2 for double width lines.
|
||||
const SHORT scale = IsDoubleWidthLine(row) ? 1 : 0;
|
||||
const auto scale = IsDoubleWidthLine(row) ? 1 : 0;
|
||||
return GetSize().Width() >> scale;
|
||||
}
|
||||
|
||||
COORD TextBuffer::ClampPositionWithinLine(const COORD position) const
|
||||
til::point TextBuffer::ClampPositionWithinLine(const til::point position) const noexcept
|
||||
{
|
||||
const SHORT rightmostColumn = GetLineWidth(position.Y) - 1;
|
||||
const auto rightmostColumn = GetLineWidth(position.Y) - 1;
|
||||
return { std::min(position.X, rightmostColumn), position.Y };
|
||||
}
|
||||
|
||||
COORD TextBuffer::ScreenToBufferPosition(const COORD position) const
|
||||
til::point TextBuffer::ScreenToBufferPosition(const til::point position) const noexcept
|
||||
{
|
||||
// Use shift right to quickly divide the X pos by 2 for double width lines.
|
||||
const SHORT scale = IsDoubleWidthLine(position.Y) ? 1 : 0;
|
||||
const auto scale = IsDoubleWidthLine(position.Y) ? 1 : 0;
|
||||
return { position.X >> scale, position.Y };
|
||||
}
|
||||
|
||||
COORD TextBuffer::BufferToScreenPosition(const COORD position) const
|
||||
til::point TextBuffer::BufferToScreenPosition(const til::point position) const noexcept
|
||||
{
|
||||
// Use shift left to quickly multiply the X pos by 2 for double width lines.
|
||||
const SHORT scale = IsDoubleWidthLine(position.Y) ? 1 : 0;
|
||||
const auto scale = IsDoubleWidthLine(position.Y) ? 1 : 0;
|
||||
return { position.X << scale, position.Y };
|
||||
}
|
||||
|
||||
@@ -900,7 +896,7 @@ void TextBuffer::Reset()
|
||||
// - newSize - new size of screen.
|
||||
// Return Value:
|
||||
// - Success if successful. Invalid parameter if screen buffer size is unexpected. No memory if allocation failed.
|
||||
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(const COORD newSize) noexcept
|
||||
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(const til::size newSize) noexcept
|
||||
{
|
||||
RETURN_HR_IF(E_INVALIDARG, newSize.X < 0 || newSize.Y < 0);
|
||||
|
||||
@@ -909,12 +905,12 @@ void TextBuffer::Reset()
|
||||
const auto currentSize = GetSize().Dimensions();
|
||||
const auto attributes = GetCurrentAttributes();
|
||||
|
||||
SHORT TopRow = 0; // new top row of the screen buffer
|
||||
til::CoordType TopRow = 0; // new top row of the screen buffer
|
||||
if (newSize.Y <= GetCursor().GetPosition().Y)
|
||||
{
|
||||
TopRow = GetCursor().GetPosition().Y - newSize.Y + 1;
|
||||
}
|
||||
const SHORT TopRowIndex = (GetFirstRowIndex() + TopRow) % currentSize.Y;
|
||||
const auto TopRowIndex = (GetFirstRowIndex() + TopRow) % currentSize.Y;
|
||||
|
||||
// rotate rows until the top row is at index 0
|
||||
for (auto i = 0; i < TopRowIndex; i++)
|
||||
@@ -934,7 +930,7 @@ void TextBuffer::Reset()
|
||||
// add rows if we're growing
|
||||
while (_storage.size() < static_cast<size_t>(newSize.Y))
|
||||
{
|
||||
_storage.emplace_back(static_cast<short>(_storage.size()), newSize.X, attributes, this);
|
||||
_storage.emplace_back(gsl::narrow_cast<til::CoordType>(_storage.size()), newSize.X, attributes, this);
|
||||
}
|
||||
|
||||
// Now that we've tampered with the row placement, refresh all the row IDs.
|
||||
@@ -983,7 +979,7 @@ void TextBuffer::TriggerRedraw(const Viewport& viewport)
|
||||
}
|
||||
}
|
||||
|
||||
void TextBuffer::TriggerRedrawCursor(const COORD position)
|
||||
void TextBuffer::TriggerRedrawCursor(const til::point position)
|
||||
{
|
||||
if (_isActiveBuffer)
|
||||
{
|
||||
@@ -1007,7 +1003,7 @@ void TextBuffer::TriggerScroll()
|
||||
}
|
||||
}
|
||||
|
||||
void TextBuffer::TriggerScroll(const COORD delta)
|
||||
void TextBuffer::TriggerScroll(const til::point delta)
|
||||
{
|
||||
if (_isActiveBuffer)
|
||||
{
|
||||
@@ -1032,10 +1028,10 @@ void TextBuffer::TriggerNewTextNotification(const std::wstring_view newText)
|
||||
// any high unicode (UnicodeStorage) runs while we're already looping through the rows.
|
||||
// Arguments:
|
||||
// - newRowWidth - Optional new value for the row width.
|
||||
void TextBuffer::_RefreshRowIDs(std::optional<SHORT> newRowWidth)
|
||||
void TextBuffer::_RefreshRowIDs(std::optional<til::CoordType> newRowWidth)
|
||||
{
|
||||
std::unordered_map<SHORT, SHORT> rowMap;
|
||||
SHORT i = 0;
|
||||
std::unordered_map<til::CoordType, til::CoordType> rowMap;
|
||||
til::CoordType i = 0;
|
||||
for (auto& it : _storage)
|
||||
{
|
||||
// Build a map so we can update Unicode Storage
|
||||
@@ -1065,7 +1061,7 @@ void TextBuffer::_RefreshRowIDs(std::optional<SHORT> newRowWidth)
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - reference to the first row.
|
||||
ROW& TextBuffer::_GetFirstRow()
|
||||
ROW& TextBuffer::_GetFirstRow() noexcept
|
||||
{
|
||||
return GetRowByOffset(0);
|
||||
}
|
||||
@@ -1099,23 +1095,23 @@ ROW& TextBuffer::_GetPrevRowNoWrap(const ROW& Row)
|
||||
// - wordDelimiters: the delimiters defined as a part of the DelimiterClass::DelimiterChar
|
||||
// Return Value:
|
||||
// - the delimiter class for the given char
|
||||
const DelimiterClass TextBuffer::_GetDelimiterClassAt(const COORD pos, const std::wstring_view wordDelimiters) const
|
||||
DelimiterClass TextBuffer::_GetDelimiterClassAt(const til::point pos, const std::wstring_view wordDelimiters) const
|
||||
{
|
||||
return GetRowByOffset(pos.Y).GetCharRow().DelimiterClassAt(pos.X, wordDelimiters);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the COORD for the beginning of the word you are on
|
||||
// - Get the til::point for the beginning of the word you are on
|
||||
// Arguments:
|
||||
// - target - a COORD on the word you are currently on
|
||||
// - target - a til::point on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// - accessibilityMode - when enabled, we continue expanding left until we are at the beginning of a readable word.
|
||||
// Otherwise, expand left until a character of a new delimiter class is found
|
||||
// (or a row boundary is encountered)
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - The COORD for the first character on the "word" (inclusive)
|
||||
const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
// - The til::point for the first character on the "word" (inclusive)
|
||||
til::point TextBuffer::GetWordStart(const til::point target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// Consider a buffer with this text in it:
|
||||
// " word other "
|
||||
@@ -1130,7 +1126,7 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
|
||||
#pragma warning(suppress : 26496)
|
||||
auto copy{ target };
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
if (target == bufferSize.Origin())
|
||||
{
|
||||
// can't expand left
|
||||
@@ -1140,12 +1136,12 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
|
||||
{
|
||||
// GH#7664: Treat EndExclusive as EndInclusive so
|
||||
// that it actually points to a space in the buffer
|
||||
copy = { bufferSize.RightInclusive(), bufferSize.BottomInclusive() };
|
||||
copy = bufferSize.BottomRightInclusive();
|
||||
}
|
||||
else if (bufferSize.CompareInBounds(target, limit.to_win32_coord(), true) >= 0)
|
||||
else if (target >= limit)
|
||||
{
|
||||
// if at/past the limit --> clamp to limit
|
||||
copy = limitOptional->to_win32_coord();
|
||||
copy = limitOptional.value_or(bufferSize.BottomRightInclusive());
|
||||
}
|
||||
|
||||
if (accessibilityMode)
|
||||
@@ -1159,13 +1155,13 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper method for GetWordStart(). Get the COORD for the beginning of the word (accessibility definition) you are on
|
||||
// - Helper method for GetWordStart(). Get the til::point for the beginning of the word (accessibility definition) you are on
|
||||
// Arguments:
|
||||
// - target - a COORD on the word you are currently on
|
||||
// - target - a til::point on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// Return Value:
|
||||
// - The COORD for the first character on the current/previous READABLE "word" (inclusive)
|
||||
const COORD TextBuffer::_GetWordStartForAccessibility(const COORD target, const std::wstring_view wordDelimiters) const
|
||||
// - The til::point for the first character on the current/previous READABLE "word" (inclusive)
|
||||
til::point TextBuffer::_GetWordStartForAccessibility(const til::point target, const std::wstring_view wordDelimiters) const
|
||||
{
|
||||
auto result = target;
|
||||
const auto bufferSize = GetSize();
|
||||
@@ -1204,13 +1200,13 @@ const COORD TextBuffer::_GetWordStartForAccessibility(const COORD target, const
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper method for GetWordStart(). Get the COORD for the beginning of the word (selection definition) you are on
|
||||
// - Helper method for GetWordStart(). Get the til::point for the beginning of the word (selection definition) you are on
|
||||
// Arguments:
|
||||
// - target - a COORD on the word you are currently on
|
||||
// - target - a til::point on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// Return Value:
|
||||
// - The COORD for the first character on the current word or delimiter run (stopped by the left margin)
|
||||
const COORD TextBuffer::_GetWordStartForSelection(const COORD target, const std::wstring_view wordDelimiters) const
|
||||
// - The til::point for the first character on the current word or delimiter run (stopped by the left margin)
|
||||
til::point TextBuffer::_GetWordStartForSelection(const til::point target, const std::wstring_view wordDelimiters) const
|
||||
{
|
||||
auto result = target;
|
||||
const auto bufferSize = GetSize();
|
||||
@@ -1233,17 +1229,17 @@ const COORD TextBuffer::_GetWordStartForSelection(const COORD target, const std:
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the COORD for the beginning of the NEXT word
|
||||
// - Get the til::point for the beginning of the NEXT word
|
||||
// Arguments:
|
||||
// - target - a COORD on the word you are currently on
|
||||
// - target - a til::point on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// - accessibilityMode - when enabled, we continue expanding right until we are at the beginning of the next READABLE word
|
||||
// Otherwise, expand right until a character of a new delimiter class is found
|
||||
// (or a row boundary is encountered)
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - The COORD for the last character on the "word" (inclusive)
|
||||
const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
// - The til::point for the last character on the "word" (inclusive)
|
||||
til::point TextBuffer::GetWordEnd(const til::point target, const std::wstring_view wordDelimiters, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// Consider a buffer with this text in it:
|
||||
// " word other "
|
||||
@@ -1257,15 +1253,15 @@ const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view w
|
||||
|
||||
// Already at/past the limit. Can't move forward.
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
|
||||
if (bufferSize.CompareInBounds(target, limit.to_win32_coord(), true) >= 0)
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
if (target >= limit)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
if (accessibilityMode)
|
||||
{
|
||||
return _GetWordEndForAccessibility(target, wordDelimiters, limit.to_win32_coord());
|
||||
return _GetWordEndForAccessibility(target, wordDelimiters, limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1274,19 +1270,19 @@ const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view w
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper method for GetWordEnd(). Get the COORD for the beginning of the next READABLE word
|
||||
// - Helper method for GetWordEnd(). Get the til::point for the beginning of the next READABLE word
|
||||
// Arguments:
|
||||
// - target - a COORD on the word you are currently on
|
||||
// - target - a til::point on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// - limit - the last "valid" position in the text buffer (to improve performance)
|
||||
// Return Value:
|
||||
// - The COORD for the first character of the next readable "word". If no next word, return one past the end of the buffer
|
||||
const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD limit) const
|
||||
// - The til::point for the first character of the next readable "word". If no next word, return one past the end of the buffer
|
||||
til::point TextBuffer::_GetWordEndForAccessibility(const til::point target, const std::wstring_view wordDelimiters, const til::point limit) const
|
||||
{
|
||||
const auto bufferSize{ GetSize() };
|
||||
auto result{ target };
|
||||
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
if (target >= limit)
|
||||
{
|
||||
// if we're already on/past the last RegularChar,
|
||||
// clamp result to that position
|
||||
@@ -1325,13 +1321,13 @@ const COORD TextBuffer::_GetWordEndForAccessibility(const COORD target, const st
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper method for GetWordEnd(). Get the COORD for the beginning of the NEXT word
|
||||
// - Helper method for GetWordEnd(). Get the til::point for the beginning of the NEXT word
|
||||
// Arguments:
|
||||
// - target - a COORD on the word you are currently on
|
||||
// - target - a til::point on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// Return Value:
|
||||
// - The COORD for the last character of the current word or delimiter run (stopped by right margin)
|
||||
const COORD TextBuffer::_GetWordEndForSelection(const COORD target, const std::wstring_view wordDelimiters) const
|
||||
// - The til::point for the last character of the current word or delimiter run (stopped by right margin)
|
||||
til::point TextBuffer::_GetWordEndForSelection(const til::point target, const std::wstring_view wordDelimiters) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
|
||||
@@ -1380,7 +1376,7 @@ void TextBuffer::_PruneHyperlinks()
|
||||
// we have found all hyperlink references in the first row and put them in refs,
|
||||
// now we need to search the rest of the buffer (i.e. all the rows except the first)
|
||||
// to see if those references are anywhere else
|
||||
for (size_t i = 1; i != total; ++i)
|
||||
for (til::CoordType i = 1; i < total; ++i)
|
||||
{
|
||||
const auto nextRowRefs = GetRowByOffset(i).GetAttrRow().GetHyperlinks();
|
||||
for (auto id : nextRowRefs)
|
||||
@@ -1408,22 +1404,22 @@ void TextBuffer::_PruneHyperlinks()
|
||||
// Method Description:
|
||||
// - Update pos to be the position of the first character of the next word. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - pos - a til::point on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first character on the "word" (inclusive)
|
||||
bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional) const
|
||||
// - pos - The til::point for the first character on the "word" (inclusive)
|
||||
bool TextBuffer::MoveToNextWord(til::point& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
// move to the beginning of the next word
|
||||
// NOTE: _GetWordEnd...() returns the exclusive position of the "end of the word"
|
||||
// This is also the inclusive start of the next word.
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
|
||||
const auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, limit.to_win32_coord()) };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
const auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, limit) };
|
||||
|
||||
if (bufferSize.CompareInBounds(copy, limit.to_win32_coord(), true) >= 0)
|
||||
if (copy >= limit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1435,12 +1431,12 @@ bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimite
|
||||
// Method Description:
|
||||
// - Update pos to be the position of the first character of the previous word. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - pos - a til::point on the word you are currently on
|
||||
// - wordDelimiters - what characters are we considering for the separation of words
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first character on the "word" (inclusive)
|
||||
bool TextBuffer::MoveToPreviousWord(COORD& pos, std::wstring_view wordDelimiters) const
|
||||
// - pos - The til::point for the first character on the "word" (inclusive)
|
||||
bool TextBuffer::MoveToPreviousWord(til::point& pos, std::wstring_view wordDelimiters) const
|
||||
{
|
||||
// move to the beginning of the current word
|
||||
auto copy{ GetWordStart(pos, wordDelimiters, true) };
|
||||
@@ -1459,51 +1455,51 @@ bool TextBuffer::MoveToPreviousWord(COORD& pos, std::wstring_view wordDelimiters
|
||||
// Method Description:
|
||||
// - Update pos to be the beginning of the current glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - pos - a til::point on the word you are currently on
|
||||
// - limitOptional - (optional) the last possible position in the buffer that can be explored. This can be used to improve performance.
|
||||
// Return Value:
|
||||
// - pos - The COORD for the first cell of the current glyph (inclusive)
|
||||
const til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional) const
|
||||
// - pos - The til::point for the first cell of the current glyph (inclusive)
|
||||
til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
auto resultPos = pos.to_win32_coord();
|
||||
auto resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
// Clamp pos to limit
|
||||
if (bufferSize.CompareInBounds(resultPos, limit.to_win32_coord(), true) > 0)
|
||||
if (resultPos > limit)
|
||||
{
|
||||
resultPos = limit.to_win32_coord();
|
||||
resultPos = limit;
|
||||
}
|
||||
|
||||
// limit is exclusive, so we need to move back to be within valid bounds
|
||||
if (resultPos != limit.to_win32_coord() && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
{
|
||||
bufferSize.DecrementInBounds(resultPos, true);
|
||||
}
|
||||
|
||||
return til::point{ resultPos };
|
||||
return resultPos;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update pos to be the end of the current glyph/character.
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - pos - a til::point on the word you are currently on
|
||||
// - accessibilityMode - this is being used for accessibility; make the end exclusive.
|
||||
// Return Value:
|
||||
// - pos - The COORD for the last cell of the current glyph (exclusive)
|
||||
const til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
// - pos - The til::point for the last cell of the current glyph (exclusive)
|
||||
til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
auto resultPos = pos.to_win32_coord();
|
||||
auto resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
// Clamp pos to limit
|
||||
if (bufferSize.CompareInBounds(resultPos, limit.to_win32_coord(), true) > 0)
|
||||
if (resultPos > limit)
|
||||
{
|
||||
resultPos = limit.to_win32_coord();
|
||||
resultPos = limit;
|
||||
}
|
||||
|
||||
if (resultPos != limit.to_win32_coord() && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
{
|
||||
bufferSize.IncrementInBounds(resultPos, true);
|
||||
}
|
||||
@@ -1513,24 +1509,34 @@ const til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilit
|
||||
{
|
||||
bufferSize.IncrementInBounds(resultPos, true);
|
||||
}
|
||||
return til::point{ resultPos };
|
||||
return resultPos;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update pos to be the beginning of the next glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - pos - a til::point on the word you are currently on
|
||||
// - allowExclusiveEnd - allow result to be the exclusive limit (one past limit)
|
||||
// - limit - boundaries for the iterator to operate within
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first cell of the current glyph (inclusive)
|
||||
// - pos - The til::point for the first cell of the current glyph (inclusive)
|
||||
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
|
||||
bool pastEndInclusive;
|
||||
til::point limit;
|
||||
{
|
||||
// if the limit is past the end of the buffer,
|
||||
// 1) clamp limit to end of buffer
|
||||
// 2) set pastEndInclusive
|
||||
const auto endInclusive{ bufferSize.BottomRightInclusive() };
|
||||
const auto val = limitOptional.value_or(endInclusive);
|
||||
pastEndInclusive = val > endInclusive;
|
||||
limit = pastEndInclusive ? endInclusive : val;
|
||||
}
|
||||
|
||||
const auto distanceToLimit{ bufferSize.CompareInBounds(pos.to_win32_coord(), limit.to_win32_coord(), true) };
|
||||
const auto distanceToLimit{ bufferSize.CompareInBounds(pos, limit) + (pastEndInclusive ? 1 : 0) };
|
||||
if (distanceToLimit >= 0)
|
||||
{
|
||||
// Corner Case: we're on/past the limit
|
||||
@@ -1547,7 +1553,7 @@ bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::o
|
||||
}
|
||||
|
||||
// Try to move forward, but if we hit the buffer boundary, we fail to move.
|
||||
auto iter{ GetCellDataAt(pos.to_win32_coord(), bufferSize) };
|
||||
auto iter{ GetCellDataAt(pos, bufferSize) };
|
||||
const bool success{ ++iter };
|
||||
|
||||
// Move again if we're on a wide glyph
|
||||
@@ -1556,24 +1562,24 @@ bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::o
|
||||
++iter;
|
||||
}
|
||||
|
||||
pos = til::point{ iter.Pos() };
|
||||
pos = iter.Pos();
|
||||
return success;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update pos to be the beginning of the previous glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - pos - a til::point on the word you are currently on
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first cell of the previous glyph (inclusive)
|
||||
// - pos - The til::point for the first cell of the previous glyph (inclusive)
|
||||
bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
auto resultPos = pos.to_win32_coord();
|
||||
auto resultPos = pos;
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (bufferSize.CompareInBounds(pos.to_win32_coord(), limit.to_win32_coord(), true) > 0)
|
||||
if (pos > limit)
|
||||
{
|
||||
// we're past the end
|
||||
// clamp us to the limit
|
||||
@@ -1588,7 +1594,7 @@ bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point>
|
||||
bufferSize.DecrementInBounds(resultPos, true);
|
||||
}
|
||||
|
||||
pos = til::point{ resultPos };
|
||||
pos = resultPos;
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -1606,24 +1612,24 @@ bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point>
|
||||
// the buffer rather than the screen.
|
||||
// Return Value:
|
||||
// - the delimiter class for the given char
|
||||
const std::vector<SMALL_RECT> TextBuffer::GetTextRects(COORD start, COORD end, bool blockSelection, bool bufferCoordinates) const
|
||||
const std::vector<til::inclusive_rect> TextBuffer::GetTextRects(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const
|
||||
{
|
||||
std::vector<SMALL_RECT> textRects;
|
||||
std::vector<til::inclusive_rect> textRects;
|
||||
|
||||
const auto bufferSize = GetSize();
|
||||
|
||||
// (0,0) is the top-left of the screen
|
||||
// the physically "higher" coordinate is closer to the top-left
|
||||
// the physically "lower" coordinate is closer to the bottom-right
|
||||
const auto [higherCoord, lowerCoord] = bufferSize.CompareInBounds(start, end) <= 0 ?
|
||||
const auto [higherCoord, lowerCoord] = start <= end ?
|
||||
std::make_tuple(start, end) :
|
||||
std::make_tuple(end, start);
|
||||
|
||||
const auto textRectSize = base::ClampedNumeric<short>(1) + lowerCoord.Y - higherCoord.Y;
|
||||
const auto textRectSize = 1 + lowerCoord.Y - higherCoord.Y;
|
||||
textRects.reserve(textRectSize);
|
||||
for (auto row = higherCoord.Y; row <= lowerCoord.Y; row++)
|
||||
{
|
||||
SMALL_RECT textRow;
|
||||
til::inclusive_rect textRow;
|
||||
|
||||
textRow.Top = row;
|
||||
textRow.Bottom = row;
|
||||
@@ -1661,12 +1667,12 @@ const std::vector<SMALL_RECT> TextBuffer::GetTextRects(COORD start, COORD end, b
|
||||
// - selectionRow: the selection row to be expanded
|
||||
// Return Value:
|
||||
// - modifies selectionRow's Left and Right values to expand properly
|
||||
void TextBuffer::_ExpandTextRow(SMALL_RECT& textRow) const
|
||||
void TextBuffer::_ExpandTextRow(til::inclusive_rect& textRow) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
|
||||
// expand left side of rect
|
||||
COORD targetPoint{ textRow.Left, textRow.Top };
|
||||
til::point targetPoint{ textRow.Left, textRow.Top };
|
||||
if (GetCellDataAt(targetPoint)->DbcsAttr().IsTrailing())
|
||||
{
|
||||
if (targetPoint.X == bufferSize.Left())
|
||||
@@ -1708,7 +1714,7 @@ void TextBuffer::_ExpandTextRow(SMALL_RECT& textRow) const
|
||||
// - The text, background color, and foreground color data of the selected region of the text buffer.
|
||||
const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
|
||||
const bool trimTrailingWhitespace,
|
||||
const std::vector<SMALL_RECT>& selectionRects,
|
||||
const std::vector<til::inclusive_rect>& selectionRects,
|
||||
std::function<std::pair<COLORREF, COLORREF>(const TextAttribute&)> GetAttributeColors,
|
||||
const bool formatWrappedRows) const
|
||||
{
|
||||
@@ -1725,9 +1731,9 @@ const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
|
||||
}
|
||||
|
||||
// for each row in the selection
|
||||
for (UINT i = 0; i < rows; i++)
|
||||
for (size_t i = 0; i < rows; i++)
|
||||
{
|
||||
const UINT iRow = selectionRects.at(i).Top;
|
||||
const auto iRow = selectionRects.at(i).Top;
|
||||
|
||||
const auto highlight = Viewport::FromInclusive(selectionRects.at(i));
|
||||
|
||||
@@ -2243,22 +2249,22 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
|
||||
const auto cOldCursorPos = oldCursor.GetPosition();
|
||||
const auto cOldLastChar = oldBuffer.GetLastNonSpaceCharacter(lastCharacterViewport);
|
||||
|
||||
const short cOldRowsTotal = cOldLastChar.Y + 1;
|
||||
const auto cOldRowsTotal = cOldLastChar.Y + 1;
|
||||
|
||||
COORD cNewCursorPos = { 0 };
|
||||
til::point cNewCursorPos;
|
||||
auto fFoundCursorPos = false;
|
||||
auto foundOldMutable = false;
|
||||
auto foundOldVisible = false;
|
||||
auto hr = S_OK;
|
||||
// Loop through all the rows of the old buffer and reprint them into the new buffer
|
||||
short iOldRow = 0;
|
||||
til::CoordType iOldRow = 0;
|
||||
for (; iOldRow < cOldRowsTotal; iOldRow++)
|
||||
{
|
||||
// Fetch the row and its "right" which is the last printable character.
|
||||
const auto& row = oldBuffer.GetRowByOffset(iOldRow);
|
||||
const auto cOldColsTotal = oldBuffer.GetLineWidth(iOldRow);
|
||||
const auto& charRow = row.GetCharRow();
|
||||
auto iRight = gsl::narrow_cast<short>(charRow.MeasureRight());
|
||||
auto iRight = charRow.MeasureRight();
|
||||
|
||||
// If we're starting a new row, try and preserve the line rendition
|
||||
// from the row in the original buffer.
|
||||
@@ -2296,7 +2302,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
|
||||
// Loop through every character in the current row (up to
|
||||
// the "right" boundary, which is one past the final valid
|
||||
// character)
|
||||
short iOldCol = 0;
|
||||
til::CoordType iOldCol = 0;
|
||||
const auto copyRight = iRight;
|
||||
for (; iOldCol < copyRight; iOldCol++)
|
||||
{
|
||||
@@ -2439,7 +2445,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
|
||||
const auto coordNewCursor = newCursor.GetPosition();
|
||||
if (coordNewCursor.X == 0 && coordNewCursor.Y > 0)
|
||||
{
|
||||
if (newBuffer.GetRowByOffset(gsl::narrow_cast<size_t>(coordNewCursor.Y) - 1).WasWrapForced())
|
||||
if (newBuffer.GetRowByOffset(coordNewCursor.Y - 1).WasWrapForced())
|
||||
{
|
||||
hr = newBuffer.NewlineCursor() ? hr : E_OUTOFMEMORY;
|
||||
}
|
||||
@@ -2693,17 +2699,17 @@ void TextBuffer::CopyPatterns(const TextBuffer& OtherBuffer)
|
||||
// - The lastRow to search
|
||||
// Return value:
|
||||
// - An interval tree containing the patterns found
|
||||
PointTree TextBuffer::GetPatterns(const size_t firstRow, const size_t lastRow) const
|
||||
PointTree TextBuffer::GetPatterns(const til::CoordType firstRow, const til::CoordType lastRow) const
|
||||
{
|
||||
PointTree::interval_vector intervals;
|
||||
|
||||
std::wstring concatAll;
|
||||
const auto rowSize = GetRowByOffset(0).size();
|
||||
concatAll.reserve(rowSize * (lastRow - firstRow + 1));
|
||||
concatAll.reserve(gsl::narrow_cast<size_t>(rowSize) * gsl::narrow_cast<size_t>(lastRow - firstRow + 1));
|
||||
|
||||
// to deal with text that spans multiple lines, we will first concatenate
|
||||
// all the text into one string and find the patterns in that string
|
||||
for (auto i = firstRow; i <= lastRow; ++i)
|
||||
for (til::CoordType i = firstRow; i <= lastRow; ++i)
|
||||
{
|
||||
auto& row = GetRowByOffset(i);
|
||||
concatAll += row.GetText();
|
||||
@@ -2718,21 +2724,21 @@ PointTree TextBuffer::GetPatterns(const size_t firstRow, const size_t lastRow) c
|
||||
auto words_begin = std::wsregex_iterator(concatAll.begin(), concatAll.end(), regexObj);
|
||||
auto words_end = std::wsregex_iterator();
|
||||
|
||||
size_t lenUpToThis = 0;
|
||||
til::CoordType lenUpToThis = 0;
|
||||
for (auto i = words_begin; i != words_end; ++i)
|
||||
{
|
||||
// record the locations -
|
||||
// when we find a match, the prefix is text that is between this
|
||||
// match and the previous match, so we use the size of the prefix
|
||||
// along with the size of the match to determine the locations
|
||||
size_t prefixSize = 0;
|
||||
til::CoordType prefixSize = 0;
|
||||
for (const auto parsedGlyph : Utf16Parser::Parse(i->prefix().str()))
|
||||
{
|
||||
const std::wstring_view glyph{ parsedGlyph.data(), parsedGlyph.size() };
|
||||
prefixSize += IsGlyphFullWidth(glyph) ? 2 : 1;
|
||||
}
|
||||
const auto start = lenUpToThis + prefixSize;
|
||||
size_t matchSize = 0;
|
||||
til::CoordType matchSize = 0;
|
||||
for (const auto parsedGlyph : Utf16Parser::Parse(i->str()))
|
||||
{
|
||||
const std::wstring_view glyph{ parsedGlyph.data(), parsedGlyph.size() };
|
||||
@@ -2741,8 +2747,8 @@ PointTree TextBuffer::GetPatterns(const size_t firstRow, const size_t lastRow) c
|
||||
const auto end = start + matchSize;
|
||||
lenUpToThis = end;
|
||||
|
||||
const til::point startCoord{ gsl::narrow<SHORT>(start % rowSize), gsl::narrow<SHORT>(start / rowSize) };
|
||||
const til::point endCoord{ gsl::narrow<SHORT>(end % rowSize), gsl::narrow<SHORT>(end / rowSize) };
|
||||
const til::point startCoord{ start % rowSize, start / rowSize };
|
||||
const til::point endCoord{ end % rowSize, end / rowSize };
|
||||
|
||||
// store the intervals
|
||||
// NOTE: these intervals are relative to the VIEWPORT not the buffer
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Microsoft::Console::Render
|
||||
class TextBuffer final
|
||||
{
|
||||
public:
|
||||
TextBuffer(const COORD screenBufferSize,
|
||||
TextBuffer(const til::size screenBufferSize,
|
||||
const TextAttribute defaultAttributes,
|
||||
const UINT cursorSize,
|
||||
const bool isActiveBuffer,
|
||||
@@ -79,27 +79,27 @@ public:
|
||||
void CopyProperties(const TextBuffer& OtherBuffer) noexcept;
|
||||
|
||||
// row manipulation
|
||||
const ROW& GetRowByOffset(const size_t index) const;
|
||||
ROW& GetRowByOffset(const size_t index);
|
||||
const ROW& GetRowByOffset(const til::CoordType index) const noexcept;
|
||||
ROW& GetRowByOffset(const til::CoordType index) noexcept;
|
||||
|
||||
TextBufferCellIterator GetCellDataAt(const COORD at) const;
|
||||
TextBufferCellIterator GetCellLineDataAt(const COORD at) const;
|
||||
TextBufferCellIterator GetCellDataAt(const COORD at, const Microsoft::Console::Types::Viewport limit) const;
|
||||
TextBufferTextIterator GetTextDataAt(const COORD at) const;
|
||||
TextBufferTextIterator GetTextLineDataAt(const COORD at) const;
|
||||
TextBufferTextIterator GetTextDataAt(const COORD at, const Microsoft::Console::Types::Viewport limit) const;
|
||||
TextBufferCellIterator GetCellDataAt(const til::point at) const;
|
||||
TextBufferCellIterator GetCellLineDataAt(const til::point at) const;
|
||||
TextBufferCellIterator GetCellDataAt(const til::point at, const Microsoft::Console::Types::Viewport limit) const;
|
||||
TextBufferTextIterator GetTextDataAt(const til::point at) const;
|
||||
TextBufferTextIterator GetTextLineDataAt(const til::point at) const;
|
||||
TextBufferTextIterator GetTextDataAt(const til::point at, const Microsoft::Console::Types::Viewport limit) const;
|
||||
|
||||
// Text insertion functions
|
||||
OutputCellIterator Write(const OutputCellIterator givenIt);
|
||||
|
||||
OutputCellIterator Write(const OutputCellIterator givenIt,
|
||||
const COORD target,
|
||||
const til::point target,
|
||||
const std::optional<bool> wrap = true);
|
||||
|
||||
OutputCellIterator WriteLine(const OutputCellIterator givenIt,
|
||||
const COORD target,
|
||||
const til::point target,
|
||||
const std::optional<bool> setWrap = std::nullopt,
|
||||
const std::optional<size_t> limitRight = std::nullopt);
|
||||
const std::optional<til::CoordType> limitRight = std::nullopt);
|
||||
|
||||
bool InsertCharacter(const wchar_t wch, const DbcsAttribute dbcsAttribute, const TextAttribute attr);
|
||||
bool InsertCharacter(const std::wstring_view chars, const DbcsAttribute dbcsAttribute, const TextAttribute attr);
|
||||
@@ -109,36 +109,36 @@ public:
|
||||
// Scroll needs access to this to quickly rotate around the buffer.
|
||||
bool IncrementCircularBuffer(const bool inVtMode = false);
|
||||
|
||||
COORD GetLastNonSpaceCharacter(std::optional<const Microsoft::Console::Types::Viewport> viewOptional = std::nullopt) const;
|
||||
til::point GetLastNonSpaceCharacter(std::optional<const Microsoft::Console::Types::Viewport> viewOptional = std::nullopt) const;
|
||||
|
||||
Cursor& GetCursor() noexcept;
|
||||
const Cursor& GetCursor() const noexcept;
|
||||
|
||||
const SHORT GetFirstRowIndex() const noexcept;
|
||||
const til::CoordType GetFirstRowIndex() const noexcept;
|
||||
|
||||
const Microsoft::Console::Types::Viewport GetSize() const noexcept;
|
||||
|
||||
void ScrollRows(const SHORT firstRow, const SHORT size, const SHORT delta);
|
||||
void ScrollRows(const til::CoordType firstRow, const til::CoordType size, const til::CoordType delta);
|
||||
|
||||
UINT TotalRowCount() const noexcept;
|
||||
til::CoordType TotalRowCount() const noexcept;
|
||||
|
||||
[[nodiscard]] TextAttribute GetCurrentAttributes() const noexcept;
|
||||
|
||||
void SetCurrentAttributes(const TextAttribute& currentAttributes) noexcept;
|
||||
|
||||
void SetCurrentLineRendition(const LineRendition lineRendition);
|
||||
void ResetLineRenditionRange(const size_t startRow, const size_t endRow);
|
||||
LineRendition GetLineRendition(const size_t row) const;
|
||||
bool IsDoubleWidthLine(const size_t row) const;
|
||||
void ResetLineRenditionRange(const til::CoordType startRow, const til::CoordType endRow) noexcept;
|
||||
LineRendition GetLineRendition(const til::CoordType row) const noexcept;
|
||||
bool IsDoubleWidthLine(const til::CoordType row) const noexcept;
|
||||
|
||||
SHORT GetLineWidth(const size_t row) const;
|
||||
COORD ClampPositionWithinLine(const COORD position) const;
|
||||
COORD ScreenToBufferPosition(const COORD position) const;
|
||||
COORD BufferToScreenPosition(const COORD position) const;
|
||||
til::CoordType GetLineWidth(const til::CoordType row) const noexcept;
|
||||
til::point ClampPositionWithinLine(const til::point position) const noexcept;
|
||||
til::point ScreenToBufferPosition(const til::point position) const noexcept;
|
||||
til::point BufferToScreenPosition(const til::point position) const noexcept;
|
||||
|
||||
void Reset();
|
||||
|
||||
[[nodiscard]] HRESULT ResizeTraditional(const COORD newSize) noexcept;
|
||||
[[nodiscard]] HRESULT ResizeTraditional(const til::size newSize) noexcept;
|
||||
|
||||
const UnicodeStorage& GetUnicodeStorage() const noexcept;
|
||||
UnicodeStorage& GetUnicodeStorage() noexcept;
|
||||
@@ -149,23 +149,23 @@ public:
|
||||
Microsoft::Console::Render::Renderer& GetRenderer() noexcept;
|
||||
|
||||
void TriggerRedraw(const Microsoft::Console::Types::Viewport& viewport);
|
||||
void TriggerRedrawCursor(const COORD position);
|
||||
void TriggerRedrawCursor(const til::point position);
|
||||
void TriggerRedrawAll();
|
||||
void TriggerScroll();
|
||||
void TriggerScroll(const COORD delta);
|
||||
void TriggerScroll(const til::point delta);
|
||||
void TriggerNewTextNotification(const std::wstring_view newText);
|
||||
|
||||
const COORD GetWordStart(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
const COORD GetWordEnd(const COORD target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToPreviousWord(COORD& pos, const std::wstring_view wordDelimiters) const;
|
||||
til::point GetWordStart(const til::point target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
til::point GetWordEnd(const til::point target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToNextWord(til::point& pos, const std::wstring_view wordDelimiters, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToPreviousWord(til::point& pos, const std::wstring_view wordDelimiters) const;
|
||||
|
||||
const til::point GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
const til::point GetGlyphEnd(const til::point pos, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
til::point GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
til::point GetGlyphEnd(const til::point pos, bool accessibilityMode = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToNextGlyph(til::point& pos, bool allowBottomExclusive = false, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
bool MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
|
||||
const std::vector<SMALL_RECT> GetTextRects(COORD start, COORD end, bool blockSelection, bool bufferCoordinates) const;
|
||||
const std::vector<til::inclusive_rect> GetTextRects(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const;
|
||||
|
||||
void AddHyperlinkToMap(std::wstring_view uri, uint16_t id);
|
||||
std::wstring GetHyperlinkUriFromId(uint16_t id) const;
|
||||
@@ -184,7 +184,7 @@ public:
|
||||
|
||||
const TextAndColor GetText(const bool includeCRLF,
|
||||
const bool trimTrailingWhitespace,
|
||||
const std::vector<SMALL_RECT>& textRects,
|
||||
const std::vector<til::inclusive_rect>& textRects,
|
||||
std::function<std::pair<COLORREF, COLORREF>(const TextAttribute&)> GetAttributeColors = nullptr,
|
||||
const bool formatWrappedRows = false) const;
|
||||
|
||||
@@ -200,8 +200,8 @@ public:
|
||||
|
||||
struct PositionInformation
|
||||
{
|
||||
short mutableViewportTop{ 0 };
|
||||
short visibleViewportTop{ 0 };
|
||||
til::CoordType mutableViewportTop{ 0 };
|
||||
til::CoordType visibleViewportTop{ 0 };
|
||||
};
|
||||
|
||||
static HRESULT Reflow(TextBuffer& oldBuffer,
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
const size_t AddPatternRecognizer(const std::wstring_view regexString);
|
||||
void ClearPatternRecognizers() noexcept;
|
||||
void CopyPatterns(const TextBuffer& OtherBuffer);
|
||||
interval_tree::IntervalTree<til::point, size_t> GetPatterns(const size_t firstRow, const size_t lastRow) const;
|
||||
interval_tree::IntervalTree<til::point, size_t> GetPatterns(const til::CoordType firstRow, const til::CoordType lastRow) const;
|
||||
|
||||
private:
|
||||
void _UpdateSize();
|
||||
@@ -220,7 +220,7 @@ private:
|
||||
std::vector<ROW> _storage;
|
||||
Cursor _cursor;
|
||||
|
||||
SHORT _firstRow; // indexes top row (not necessarily 0)
|
||||
til::CoordType _firstRow; // indexes top row (not necessarily 0)
|
||||
|
||||
TextAttribute _currentAttributes;
|
||||
|
||||
@@ -234,29 +234,29 @@ private:
|
||||
std::unordered_map<std::wstring, uint16_t> _hyperlinkCustomIdMap;
|
||||
uint16_t _currentHyperlinkId;
|
||||
|
||||
void _RefreshRowIDs(std::optional<SHORT> newRowWidth);
|
||||
void _RefreshRowIDs(std::optional<til::CoordType> newRowWidth);
|
||||
|
||||
void _SetFirstRowIndex(const SHORT FirstRowIndex) noexcept;
|
||||
void _SetFirstRowIndex(const til::CoordType FirstRowIndex) noexcept;
|
||||
|
||||
COORD _GetPreviousFromCursor() const;
|
||||
til::point _GetPreviousFromCursor() const noexcept;
|
||||
|
||||
void _SetWrapOnCurrentRow();
|
||||
void _AdjustWrapOnCurrentRow(const bool fSet);
|
||||
void _SetWrapOnCurrentRow() noexcept;
|
||||
void _AdjustWrapOnCurrentRow(const bool fSet) noexcept;
|
||||
|
||||
// Assist with maintaining proper buffer state for Double Byte character sequences
|
||||
bool _PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute);
|
||||
bool _AssertValidDoubleByteSequence(const DbcsAttribute dbcsAttribute);
|
||||
|
||||
ROW& _GetFirstRow();
|
||||
ROW& _GetFirstRow() noexcept;
|
||||
ROW& _GetPrevRowNoWrap(const ROW& row);
|
||||
|
||||
void _ExpandTextRow(SMALL_RECT& selectionRow) const;
|
||||
void _ExpandTextRow(til::inclusive_rect& selectionRow) const;
|
||||
|
||||
const DelimiterClass _GetDelimiterClassAt(const COORD pos, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordStartForAccessibility(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordStartForSelection(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
const COORD _GetWordEndForAccessibility(const COORD target, const std::wstring_view wordDelimiters, const COORD limit) const;
|
||||
const COORD _GetWordEndForSelection(const COORD target, const std::wstring_view wordDelimiters) const;
|
||||
DelimiterClass _GetDelimiterClassAt(const til::point pos, const std::wstring_view wordDelimiters) const;
|
||||
til::point _GetWordStartForAccessibility(const til::point target, const std::wstring_view wordDelimiters) const;
|
||||
til::point _GetWordStartForSelection(const til::point target, const std::wstring_view wordDelimiters) const;
|
||||
til::point _GetWordEndForAccessibility(const til::point target, const std::wstring_view wordDelimiters, const til::point limit) const;
|
||||
til::point _GetWordEndForSelection(const til::point target, const std::wstring_view wordDelimiters) const;
|
||||
|
||||
void _PruneHyperlinks();
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ using namespace Microsoft::Console::Types;
|
||||
// Arguments:
|
||||
// - buffer - Text buffer to seek through
|
||||
// - pos - Starting position to retrieve text data from (within screen buffer bounds)
|
||||
TextBufferCellIterator::TextBufferCellIterator(const TextBuffer& buffer, COORD pos) :
|
||||
TextBufferCellIterator::TextBufferCellIterator(const TextBuffer& buffer, til::point pos) :
|
||||
TextBufferCellIterator(buffer, pos, buffer.GetSize())
|
||||
{
|
||||
}
|
||||
@@ -30,7 +30,7 @@ TextBufferCellIterator::TextBufferCellIterator(const TextBuffer& buffer, COORD p
|
||||
// - buffer - Pointer to screen buffer to seek through
|
||||
// - pos - Starting position to retrieve text data from (within screen buffer bounds)
|
||||
// - limits - Viewport limits to restrict the iterator within the buffer bounds (smaller than the buffer itself)
|
||||
TextBufferCellIterator::TextBufferCellIterator(const TextBuffer& buffer, COORD pos, const Viewport limits) :
|
||||
TextBufferCellIterator::TextBufferCellIterator(const TextBuffer& buffer, til::point pos, const Viewport limits) :
|
||||
_buffer(buffer),
|
||||
_pos(pos),
|
||||
_pRow(s_GetRow(buffer, pos)),
|
||||
@@ -126,7 +126,7 @@ TextBufferCellIterator& TextBufferCellIterator::operator+=(const ptrdiff_t& move
|
||||
const auto oldX = _pos.X;
|
||||
const auto oldY = _pos.Y;
|
||||
|
||||
// Under MSVC writing the individual members of a COORD generates worse assembly
|
||||
// Under MSVC writing the individual members of a til::point generates worse assembly
|
||||
// compared to having them be local variables. This causes a performance impact.
|
||||
auto newX = oldX;
|
||||
auto newY = oldY;
|
||||
@@ -289,7 +289,7 @@ ptrdiff_t TextBufferCellIterator::operator-(const TextBufferCellIterator& it)
|
||||
// - Sets the coordinate position that this iterator will inspect within the text buffer on dereference.
|
||||
// Arguments:
|
||||
// - newPos - The new coordinate position.
|
||||
void TextBufferCellIterator::_SetPos(const COORD newPos)
|
||||
void TextBufferCellIterator::_SetPos(const til::point newPos)
|
||||
{
|
||||
if (newPos.Y != _pos.Y)
|
||||
{
|
||||
@@ -317,7 +317,7 @@ void TextBufferCellIterator::_SetPos(const COORD newPos)
|
||||
// - pos - Position inside screen buffer bounds to retrieve row
|
||||
// Return Value:
|
||||
// - Pointer to the underlying CharRow structure
|
||||
const ROW* TextBufferCellIterator::s_GetRow(const TextBuffer& buffer, const COORD pos)
|
||||
const ROW* TextBufferCellIterator::s_GetRow(const TextBuffer& buffer, const til::point pos) noexcept
|
||||
{
|
||||
return &buffer.GetRowByOffset(pos.Y);
|
||||
}
|
||||
@@ -354,7 +354,7 @@ const OutputCellView* TextBufferCellIterator::operator->() const noexcept
|
||||
return &_view;
|
||||
}
|
||||
|
||||
COORD TextBufferCellIterator::Pos() const noexcept
|
||||
til::point TextBufferCellIterator::Pos() const noexcept
|
||||
{
|
||||
return _pos;
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ class TextBuffer;
|
||||
class TextBufferCellIterator
|
||||
{
|
||||
public:
|
||||
TextBufferCellIterator(const TextBuffer& buffer, COORD pos);
|
||||
TextBufferCellIterator(const TextBuffer& buffer, COORD pos, const Microsoft::Console::Types::Viewport limits);
|
||||
TextBufferCellIterator(const TextBuffer& buffer, til::point pos);
|
||||
TextBufferCellIterator(const TextBuffer& buffer, til::point pos, const Microsoft::Console::Types::Viewport limits);
|
||||
|
||||
operator bool() const noexcept;
|
||||
|
||||
@@ -47,12 +47,12 @@ public:
|
||||
const OutputCellView& operator*() const noexcept;
|
||||
const OutputCellView* operator->() const noexcept;
|
||||
|
||||
COORD Pos() const noexcept;
|
||||
til::point Pos() const noexcept;
|
||||
|
||||
protected:
|
||||
void _SetPos(const COORD newPos);
|
||||
void _SetPos(const til::point newPos);
|
||||
void _GenerateView();
|
||||
static const ROW* s_GetRow(const TextBuffer& buffer, const COORD pos);
|
||||
static const ROW* s_GetRow(const TextBuffer& buffer, const til::point pos) noexcept;
|
||||
|
||||
OutputCellView _view;
|
||||
|
||||
@@ -61,7 +61,7 @@ protected:
|
||||
const TextBuffer& _buffer;
|
||||
const Microsoft::Console::Types::Viewport _bounds;
|
||||
bool _exceeded;
|
||||
COORD _pos;
|
||||
til::point _pos;
|
||||
|
||||
#if UNIT_TESTING
|
||||
friend class TextBufferIteratorTests;
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace
|
||||
|
||||
struct TestBuffer
|
||||
{
|
||||
COORD size;
|
||||
til::size size;
|
||||
std::vector<TestRow> rows;
|
||||
COORD cursor;
|
||||
til::point cursor;
|
||||
};
|
||||
|
||||
struct TestCase
|
||||
@@ -737,7 +737,7 @@ class ReflowTests
|
||||
{
|
||||
auto buffer = std::make_unique<TextBuffer>(testBuffer.size, TextAttribute{ 0x7 }, 0, false, renderer);
|
||||
|
||||
size_t i{};
|
||||
til::CoordType i{};
|
||||
for (const auto& testRow : testBuffer.rows)
|
||||
{
|
||||
auto& row{ buffer->GetRowByOffset(i) };
|
||||
@@ -745,7 +745,7 @@ class ReflowTests
|
||||
auto& charRow{ row.GetCharRow() };
|
||||
row.SetWrapForced(testRow.wrap);
|
||||
|
||||
size_t j{};
|
||||
til::CoordType j{};
|
||||
for (auto it{ charRow.begin() }; it != charRow.end(); ++it)
|
||||
{
|
||||
// Yes, we're about to manually create a buffer. It is unpleasant.
|
||||
@@ -771,7 +771,7 @@ class ReflowTests
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static std::unique_ptr<TextBuffer> _textBufferByReflowingTextBuffer(TextBuffer& originalBuffer, const COORD newSize)
|
||||
static std::unique_ptr<TextBuffer> _textBufferByReflowingTextBuffer(TextBuffer& originalBuffer, const til::size newSize)
|
||||
{
|
||||
auto buffer = std::make_unique<TextBuffer>(newSize, TextAttribute{ 0x7 }, 0, false, renderer);
|
||||
TextBuffer::Reflow(originalBuffer, *buffer, std::nullopt, std::nullopt);
|
||||
@@ -783,7 +783,7 @@ class ReflowTests
|
||||
VERIFY_ARE_EQUAL(testBuffer.cursor, buffer.GetCursor().GetPosition());
|
||||
VERIFY_ARE_EQUAL(testBuffer.size, buffer.GetSize().Dimensions());
|
||||
|
||||
size_t i{};
|
||||
til::CoordType i{};
|
||||
for (const auto& testRow : testBuffer.rows)
|
||||
{
|
||||
NoThrowString indexString;
|
||||
@@ -794,7 +794,7 @@ class ReflowTests
|
||||
indexString.Format(L"[Row %d]", i);
|
||||
VERIFY_ARE_EQUAL(testRow.wrap, row.WasWrapForced(), indexString);
|
||||
|
||||
size_t j{};
|
||||
til::CoordType j{};
|
||||
for (auto it{ charRow.begin() }; it != charRow.end(); ++it)
|
||||
{
|
||||
indexString.Format(L"[Cell %d, %d; Text line index %d]", it - charRow.begin(), i, j);
|
||||
|
||||
@@ -18,7 +18,7 @@ class UnicodeStorageTests
|
||||
TEST_METHOD(CanOverwriteEmoji)
|
||||
{
|
||||
UnicodeStorage storage;
|
||||
const COORD coord{ 1, 3 };
|
||||
const til::point coord{ 1, 3 };
|
||||
const std::vector<wchar_t> newMoon{ 0xD83C, 0xDF11 };
|
||||
const std::vector<wchar_t> fullMoon{ 0xD83C, 0xDF15 };
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ Abstract:
|
||||
|
||||
// private dependencies
|
||||
#include "../host/conddkrefs.h"
|
||||
#include "../inc/operators.hpp"
|
||||
#include "../inc/unicode.hpp"
|
||||
#pragma warning(pop)
|
||||
|
||||
|
||||
@@ -135,6 +135,10 @@
|
||||
<!-- 16.3.0 - remove non-resources.pri PRI files since we just forced them back in. -->
|
||||
<AppxPackagePayload Remove="@(AppxPackagePayload)" Condition="'%(Extension)' == '.pri' and '%(Filename)' != 'resources'" />
|
||||
<AppxUploadPackagePayload Remove="@(AppxUploadPackagePayload)" Condition="'%(Extension)' == '.pri' and '%(Filename)' != 'resources'" />
|
||||
|
||||
<!-- Remove all of the xaml files, because we are using embedded xbf payloads (saves about 500kb on disk!) -->
|
||||
<AppxPackagePayload Remove="@(AppxPackagePayload)" Condition="'%(Extension)' == '.xaml'" />
|
||||
<AppxUploadPackagePayload Remove="@(AppxUploadPackagePayload)" Condition="'%(Extension)' == '.xaml'" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
<com:ProxyStub Id="DEC4804D-56D1-4F73-9FBE-6828E7C85C56" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
||||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
|
||||
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
|
||||
</com:ComInterface>
|
||||
</com:Extension>
|
||||
<com:Extension Category="windows.comServer">
|
||||
|
||||
@@ -189,6 +189,7 @@
|
||||
<com:ProxyStub Id="1833E661-CC81-4DD0-87C6-C2F74BD39EFA" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
||||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
|
||||
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
|
||||
</com:ComInterface>
|
||||
</com:Extension>
|
||||
<com:Extension Category="windows.comServer">
|
||||
|
||||
@@ -189,6 +189,7 @@
|
||||
<com:ProxyStub Id="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
||||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||
</com:ComInterface>
|
||||
</com:Extension>
|
||||
<com:Extension Category="windows.comServer">
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
<ClCompile Include="DeserializationTests.cpp" />
|
||||
<ClCompile Include="SerializationTests.cpp" />
|
||||
<ClCompile Include="TerminalSettingsTests.cpp" />
|
||||
<ClCompile Include="ThemeTests.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
|
||||
281
src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp
Normal file
281
src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "../TerminalSettingsModel/Theme.h"
|
||||
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
||||
#include "../types/inc/colorTable.hpp"
|
||||
#include "JsonTestClass.h"
|
||||
|
||||
#include <defaults.h>
|
||||
|
||||
using namespace Microsoft::Console;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
||||
using namespace WEX::Logging;
|
||||
using namespace WEX::TestExecution;
|
||||
using namespace WEX::Common;
|
||||
|
||||
namespace SettingsModelLocalTests
|
||||
{
|
||||
// TODO:microsoft/terminal#3838:
|
||||
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
|
||||
// an updated TAEF that will let us install framework packages when the test
|
||||
// package is deployed. Until then, these tests won't deploy in CI.
|
||||
|
||||
class ThemeTests : public JsonTestClass
|
||||
{
|
||||
// Use a custom AppxManifest to ensure that we can activate winrt types
|
||||
// from our test. This property will tell taef to manually use this as
|
||||
// the AppxManifest for this test class.
|
||||
// This does not yet work for anything XAML-y. See TabTests.cpp for more
|
||||
// details on that.
|
||||
BEGIN_TEST_CLASS(ThemeTests)
|
||||
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
|
||||
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
|
||||
END_TEST_CLASS()
|
||||
|
||||
TEST_METHOD(ParseSimpleTheme);
|
||||
TEST_METHOD(ParseEmptyTheme);
|
||||
TEST_METHOD(ParseNoWindowTheme);
|
||||
TEST_METHOD(ParseNullWindowTheme);
|
||||
TEST_METHOD(ParseThemeWithNullThemeColor);
|
||||
TEST_METHOD(InvalidCurrentTheme);
|
||||
|
||||
static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept
|
||||
{
|
||||
return Core::Color{ r, g, b, 255 };
|
||||
}
|
||||
static Core::Color rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
|
||||
{
|
||||
return Core::Color{ r, g, b, a };
|
||||
}
|
||||
};
|
||||
|
||||
void ThemeTests::ParseSimpleTheme()
|
||||
{
|
||||
static constexpr std::string_view orangeTheme{ R"({
|
||||
"name": "orange",
|
||||
"tabRow":
|
||||
{
|
||||
"background": "#FFFF8800",
|
||||
"unfocusedBackground": "#FF8844"
|
||||
},
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
}
|
||||
})" };
|
||||
|
||||
const auto schemeObject = VerifyParseSucceeded(orangeTheme);
|
||||
auto theme = Theme::FromJson(schemeObject);
|
||||
VERIFY_ARE_EQUAL(L"orange", theme->Name());
|
||||
|
||||
VERIFY_IS_NOT_NULL(theme->TabRow());
|
||||
VERIFY_IS_NOT_NULL(theme->TabRow().Background());
|
||||
VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType());
|
||||
VERIFY_ARE_EQUAL(rgba(0xff, 0xff, 0x88, 0x00), theme->TabRow().Background().Color());
|
||||
VERIFY_ARE_EQUAL(rgba(0xff, 0x88, 0x44, 0xff), theme->TabRow().UnfocusedBackground().Color());
|
||||
|
||||
VERIFY_IS_NOT_NULL(theme->Window());
|
||||
VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Light, theme->Window().RequestedTheme());
|
||||
VERIFY_ARE_EQUAL(true, theme->Window().UseMica());
|
||||
}
|
||||
|
||||
void ThemeTests::ParseEmptyTheme()
|
||||
{
|
||||
Log::Comment(L"This theme doesn't have any elements defined.");
|
||||
static constexpr std::string_view emptyTheme{ R"({
|
||||
"name": "empty"
|
||||
})" };
|
||||
|
||||
const auto schemeObject = VerifyParseSucceeded(emptyTheme);
|
||||
auto theme = Theme::FromJson(schemeObject);
|
||||
VERIFY_ARE_EQUAL(L"empty", theme->Name());
|
||||
VERIFY_IS_NULL(theme->TabRow());
|
||||
VERIFY_IS_NULL(theme->Window());
|
||||
VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme());
|
||||
}
|
||||
|
||||
void ThemeTests::ParseNoWindowTheme()
|
||||
{
|
||||
Log::Comment(L"This theme doesn't have a window defined.");
|
||||
static constexpr std::string_view emptyTheme{ R"({
|
||||
"name": "noWindow",
|
||||
"tabRow":
|
||||
{
|
||||
"background": "#112233",
|
||||
"unfocusedBackground": "#FF884400"
|
||||
},
|
||||
})" };
|
||||
|
||||
const auto schemeObject = VerifyParseSucceeded(emptyTheme);
|
||||
auto theme = Theme::FromJson(schemeObject);
|
||||
VERIFY_ARE_EQUAL(L"noWindow", theme->Name());
|
||||
|
||||
VERIFY_IS_NOT_NULL(theme->TabRow());
|
||||
VERIFY_IS_NOT_NULL(theme->TabRow().Background());
|
||||
VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType());
|
||||
VERIFY_ARE_EQUAL(rgb(0x11, 0x22, 0x33), theme->TabRow().Background().Color());
|
||||
|
||||
VERIFY_IS_NULL(theme->Window());
|
||||
VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme());
|
||||
}
|
||||
|
||||
void ThemeTests::ParseNullWindowTheme()
|
||||
{
|
||||
Log::Comment(L"This theme doesn't have a window defined.");
|
||||
static constexpr std::string_view emptyTheme{ R"({
|
||||
"name": "nullWindow",
|
||||
"tabRow":
|
||||
{
|
||||
"background": "#112233",
|
||||
"unfocusedBackground": "#FF884400"
|
||||
},
|
||||
"window": null
|
||||
})" };
|
||||
|
||||
const auto schemeObject = VerifyParseSucceeded(emptyTheme);
|
||||
auto theme = Theme::FromJson(schemeObject);
|
||||
VERIFY_ARE_EQUAL(L"nullWindow", theme->Name());
|
||||
|
||||
VERIFY_IS_NOT_NULL(theme->TabRow());
|
||||
VERIFY_IS_NOT_NULL(theme->TabRow().Background());
|
||||
VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType());
|
||||
VERIFY_ARE_EQUAL(rgb(0x11, 0x22, 0x33), theme->TabRow().Background().Color());
|
||||
|
||||
VERIFY_IS_NULL(theme->Window());
|
||||
VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme());
|
||||
}
|
||||
|
||||
void ThemeTests::ParseThemeWithNullThemeColor()
|
||||
{
|
||||
Log::Comment(L"These themes are all missing a tabRow background. Make sure we don't somehow default-construct one for them");
|
||||
|
||||
static constexpr std::string_view settingsString{ R"json({
|
||||
"themes": [
|
||||
{
|
||||
"name": "backgroundEmpty",
|
||||
"tabRow":
|
||||
{
|
||||
},
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "backgroundNull",
|
||||
"tabRow":
|
||||
{
|
||||
"background": null
|
||||
},
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "backgroundOmittedEntirely",
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
}
|
||||
}
|
||||
]
|
||||
})json" };
|
||||
|
||||
try
|
||||
{
|
||||
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, DefaultJson) };
|
||||
|
||||
const auto& themes{ settings->GlobalSettings().Themes() };
|
||||
{
|
||||
const auto& backgroundEmpty{ themes.Lookup(L"backgroundEmpty") };
|
||||
VERIFY_ARE_EQUAL(L"backgroundEmpty", backgroundEmpty.Name());
|
||||
VERIFY_IS_NOT_NULL(backgroundEmpty.TabRow());
|
||||
VERIFY_IS_NULL(backgroundEmpty.TabRow().Background());
|
||||
}
|
||||
{
|
||||
const auto& backgroundNull{ themes.Lookup(L"backgroundNull") };
|
||||
VERIFY_ARE_EQUAL(L"backgroundNull", backgroundNull.Name());
|
||||
VERIFY_IS_NOT_NULL(backgroundNull.TabRow());
|
||||
VERIFY_IS_NULL(backgroundNull.TabRow().Background());
|
||||
}
|
||||
{
|
||||
const auto& backgroundOmittedEntirely{ themes.Lookup(L"backgroundOmittedEntirely") };
|
||||
VERIFY_ARE_EQUAL(L"backgroundOmittedEntirely", backgroundOmittedEntirely.Name());
|
||||
VERIFY_IS_NULL(backgroundOmittedEntirely.TabRow());
|
||||
}
|
||||
}
|
||||
catch (const SettingsException& ex)
|
||||
{
|
||||
auto loadError = ex.Error();
|
||||
loadError;
|
||||
throw ex;
|
||||
}
|
||||
catch (const SettingsTypedDeserializationException& e)
|
||||
{
|
||||
auto deserializationErrorMessage = til::u8u16(e.what());
|
||||
Log::Comment(NoThrowString().Format(deserializationErrorMessage.c_str()));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeTests::InvalidCurrentTheme()
|
||||
{
|
||||
Log::Comment(L"Make sure specifying an invalid theme falls back to a sensible default.");
|
||||
|
||||
static constexpr std::string_view settingsString{ R"json({
|
||||
"theme": "foo",
|
||||
"themes": [
|
||||
{
|
||||
"name": "bar",
|
||||
"tabRow": {},
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
}
|
||||
}
|
||||
]
|
||||
})json" };
|
||||
|
||||
try
|
||||
{
|
||||
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, DefaultJson) };
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, settings->Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(Settings::Model::SettingsLoadWarnings::UnknownTheme, settings->Warnings().GetAt(0));
|
||||
|
||||
const auto& themes{ settings->GlobalSettings().Themes() };
|
||||
{
|
||||
const auto& bar{ themes.Lookup(L"bar") };
|
||||
VERIFY_ARE_EQUAL(L"bar", bar.Name());
|
||||
VERIFY_IS_NOT_NULL(bar.TabRow());
|
||||
VERIFY_IS_NULL(bar.TabRow().Background());
|
||||
}
|
||||
|
||||
const auto currentTheme{ settings->GlobalSettings().CurrentTheme() };
|
||||
VERIFY_IS_NOT_NULL(currentTheme);
|
||||
VERIFY_ARE_EQUAL(L"system", currentTheme.Name());
|
||||
}
|
||||
catch (const SettingsException& ex)
|
||||
{
|
||||
auto loadError = ex.Error();
|
||||
loadError;
|
||||
throw ex;
|
||||
}
|
||||
catch (const SettingsTypedDeserializationException& e)
|
||||
{
|
||||
auto deserializationErrorMessage = til::u8u16(e.what());
|
||||
Log::Comment(NoThrowString().Format(deserializationErrorMessage.c_str()));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,7 +230,7 @@ HRESULT HwndTerminal::Initialize()
|
||||
RECT windowRect;
|
||||
GetWindowRect(_hwnd.get(), &windowRect);
|
||||
|
||||
const COORD windowSize{ gsl::narrow<short>(windowRect.right - windowRect.left), gsl::narrow<short>(windowRect.bottom - windowRect.top) };
|
||||
const til::size windowSize{ windowRect.right - windowRect.left, windowRect.bottom - windowRect.top };
|
||||
|
||||
// Fist set up the dx engine with the window size in pixels.
|
||||
// Then, using the font, get the number of characters that can fit.
|
||||
@@ -239,7 +239,7 @@ HRESULT HwndTerminal::Initialize()
|
||||
|
||||
_renderEngine = std::move(dxEngine);
|
||||
|
||||
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
|
||||
_terminal->Create({ 80, 25 }, 1000, *_renderer);
|
||||
_terminal->SetWriteInputCallback([=](std::wstring_view input) noexcept { _WriteTextToConnection(input); });
|
||||
localPointerToThread->EnablePainting();
|
||||
|
||||
@@ -343,7 +343,7 @@ IRawElementProviderSimple* HwndTerminal::_GetUiaProvider() noexcept
|
||||
return _uiaProvider.Get();
|
||||
}
|
||||
|
||||
HRESULT HwndTerminal::Refresh(const SIZE windowSize, _Out_ COORD* dimensions)
|
||||
HRESULT HwndTerminal::Refresh(const til::size windowSize, _Out_ til::size* dimensions)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, dimensions);
|
||||
|
||||
@@ -357,8 +357,7 @@ HRESULT HwndTerminal::Refresh(const SIZE windowSize, _Out_ COORD* dimensions)
|
||||
_renderer->TriggerRedrawAll();
|
||||
|
||||
// Convert our new dimensions to characters
|
||||
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 },
|
||||
{ gsl::narrow<short>(windowSize.cx), gsl::narrow<short>(windowSize.cy) });
|
||||
const auto viewInPixels = Viewport::FromDimensions(windowSize);
|
||||
const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels);
|
||||
|
||||
// If this function succeeds with S_FALSE, then the terminal didn't
|
||||
@@ -435,7 +434,7 @@ void _stdcall TerminalSendOutput(void* terminal, LPCWSTR data)
|
||||
/// <param name="height">New height of the terminal in pixels</param>
|
||||
/// <param name="dimensions">Out parameter containing the columns and rows that fit the new size.</param>
|
||||
/// <returns>HRESULT of the attempted resize.</returns>
|
||||
HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ short width, _In_ short height, _Out_ COORD* dimensions)
|
||||
HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions)
|
||||
{
|
||||
const auto publicTerminal = static_cast<HwndTerminal*>(terminal);
|
||||
|
||||
@@ -448,7 +447,7 @@ HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ short width, _I
|
||||
static_cast<int>(height),
|
||||
0));
|
||||
|
||||
const SIZE windowSize{ width, height };
|
||||
const til::size windowSize{ width, height };
|
||||
return publicTerminal->Refresh(windowSize, dimensions);
|
||||
}
|
||||
|
||||
@@ -459,19 +458,19 @@ HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ short width, _I
|
||||
/// <param name="dimensionsInCharacters">New terminal size in row and column count.</param>
|
||||
/// <param name="dimensionsInPixels">Out parameter with the new size of the renderer.</param>
|
||||
/// <returns>HRESULT of the attempted resize.</returns>
|
||||
HRESULT _stdcall TerminalTriggerResizeWithDimension(_In_ void* terminal, _In_ COORD dimensionsInCharacters, _Out_ SIZE* dimensionsInPixels)
|
||||
HRESULT _stdcall TerminalTriggerResizeWithDimension(_In_ void* terminal, _In_ til::size dimensionsInCharacters, _Out_ til::size* dimensionsInPixels)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, dimensionsInPixels);
|
||||
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
|
||||
const auto viewInCharacters = Viewport::FromDimensions({ 0, 0 }, { (dimensionsInCharacters.X), (dimensionsInCharacters.Y) });
|
||||
const auto viewInCharacters = Viewport::FromDimensions(dimensionsInCharacters);
|
||||
const auto viewInPixels = publicTerminal->_renderEngine->GetViewportInPixels(viewInCharacters);
|
||||
|
||||
dimensionsInPixels->cx = viewInPixels.Width();
|
||||
dimensionsInPixels->cy = viewInPixels.Height();
|
||||
|
||||
COORD unused{ 0, 0 };
|
||||
til::size unused;
|
||||
|
||||
return TerminalTriggerResize(terminal, viewInPixels.Width(), viewInPixels.Height(), &unused);
|
||||
}
|
||||
@@ -484,7 +483,7 @@ HRESULT _stdcall TerminalTriggerResizeWithDimension(_In_ void* terminal, _In_ CO
|
||||
/// <param name="height">Height of the terminal area to calculate.</param>
|
||||
/// <param name="dimensions">Out parameter containing the columns and rows that fit the new size.</param>
|
||||
/// <returns>HRESULT of the calculation.</returns>
|
||||
HRESULT _stdcall TerminalCalculateResize(_In_ void* terminal, _In_ short width, _In_ short height, _Out_ COORD* dimensions)
|
||||
HRESULT _stdcall TerminalCalculateResize(_In_ void* terminal, _In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions)
|
||||
{
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
|
||||
@@ -548,11 +547,11 @@ try
|
||||
|
||||
if (multiClickMapper == 3)
|
||||
{
|
||||
_terminal->MultiClickSelection((cursorPosition / fontSize).to_win32_coord(), ::Terminal::SelectionExpansion::Line);
|
||||
_terminal->MultiClickSelection(cursorPosition / fontSize, ::Terminal::SelectionExpansion::Line);
|
||||
}
|
||||
else if (multiClickMapper == 2)
|
||||
{
|
||||
_terminal->MultiClickSelection((cursorPosition / fontSize).to_win32_coord(), ::Terminal::SelectionExpansion::Word);
|
||||
_terminal->MultiClickSelection(cursorPosition / fontSize, ::Terminal::SelectionExpansion::Word);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -593,13 +592,13 @@ try
|
||||
|
||||
if (distanceSquared >= maxDistanceSquared)
|
||||
{
|
||||
_terminal->SetSelectionAnchor((touchdownPoint / fontSize).to_win32_coord());
|
||||
_terminal->SetSelectionAnchor(touchdownPoint / fontSize);
|
||||
// stop tracking the touchdown point
|
||||
_singleClickTouchdownPos = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
this->_terminal->SetSelectionEnd((cursorPosition / fontSize).to_win32_coord());
|
||||
this->_terminal->SetSelectionEnd(cursorPosition / fontSize);
|
||||
this->_renderer->TriggerSelection();
|
||||
|
||||
return S_OK;
|
||||
@@ -701,9 +700,7 @@ try
|
||||
wheelDelta = HIWORD(wParam);
|
||||
|
||||
// If it's a *WHEEL event, it's in screen coordinates, not window (?!)
|
||||
auto coordsToTransform = cursorPosition.to_win32_point();
|
||||
ScreenToClient(_hwnd.get(), &coordsToTransform);
|
||||
cursorPosition = til::point{ coordsToTransform };
|
||||
ScreenToClient(_hwnd.get(), cursorPosition.as_win32_point());
|
||||
}
|
||||
|
||||
const TerminalInput::MouseButtonState state{
|
||||
@@ -712,7 +709,7 @@ try
|
||||
WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed)
|
||||
};
|
||||
|
||||
return _terminal->SendMouseEvent((cursorPosition / fontSize).to_win32_coord(), uMsg, getControlKeyState(), wheelDelta, state);
|
||||
return _terminal->SendMouseEvent(cursorPosition / fontSize, uMsg, getControlKeyState(), wheelDelta, state);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -780,7 +777,7 @@ void _stdcall DestroyTerminal(void* terminal)
|
||||
}
|
||||
|
||||
// Updates the terminal font type, size, color, as well as the background/foreground colors to a specified theme.
|
||||
void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, short fontSize, int newDpi)
|
||||
void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, til::CoordType fontSize, int newDpi)
|
||||
{
|
||||
const auto publicTerminal = static_cast<HwndTerminal*>(terminal);
|
||||
{
|
||||
@@ -810,8 +807,8 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
|
||||
RECT windowRect;
|
||||
GetWindowRect(publicTerminal->_hwnd.get(), &windowRect);
|
||||
|
||||
COORD dimensions = {};
|
||||
const SIZE windowSize{ windowRect.right - windowRect.left, windowRect.bottom - windowRect.top };
|
||||
til::size dimensions;
|
||||
const til::size windowSize{ windowRect.right - windowRect.left, windowRect.bottom - windowRect.top };
|
||||
publicTerminal->Refresh(windowSize, &dimensions);
|
||||
}
|
||||
|
||||
@@ -984,21 +981,21 @@ void HwndTerminal::_StringPaste(const wchar_t* const pData) noexcept
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
COORD HwndTerminal::GetFontSize() const noexcept
|
||||
til::size HwndTerminal::GetFontSize() const noexcept
|
||||
{
|
||||
return _actualFont.GetSize();
|
||||
}
|
||||
|
||||
RECT HwndTerminal::GetBounds() const noexcept
|
||||
til::rect HwndTerminal::GetBounds() const noexcept
|
||||
{
|
||||
RECT windowRect;
|
||||
GetWindowRect(_hwnd.get(), &windowRect);
|
||||
til::rect windowRect;
|
||||
GetWindowRect(_hwnd.get(), windowRect.as_win32_rect());
|
||||
return windowRect;
|
||||
}
|
||||
|
||||
RECT HwndTerminal::GetPadding() const noexcept
|
||||
til::rect HwndTerminal::GetPadding() const noexcept
|
||||
{
|
||||
return { 0 };
|
||||
return {};
|
||||
}
|
||||
|
||||
double HwndTerminal::GetScaleFactor() const noexcept
|
||||
@@ -1006,7 +1003,7 @@ double HwndTerminal::GetScaleFactor() const noexcept
|
||||
return static_cast<double>(_currentDpi) / static_cast<double>(USER_DEFAULT_SCREEN_DPI);
|
||||
}
|
||||
|
||||
void HwndTerminal::ChangeViewport(const SMALL_RECT NewWindow)
|
||||
void HwndTerminal::ChangeViewport(const til::inclusive_rect& NewWindow)
|
||||
{
|
||||
_terminal->UserScrollViewport(NewWindow.Top);
|
||||
}
|
||||
|
||||
@@ -27,16 +27,16 @@ extern "C" {
|
||||
__declspec(dllexport) HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ void** terminal);
|
||||
__declspec(dllexport) void _stdcall TerminalSendOutput(void* terminal, LPCWSTR data);
|
||||
__declspec(dllexport) void _stdcall TerminalRegisterScrollCallback(void* terminal, void __stdcall callback(int, int, int));
|
||||
__declspec(dllexport) HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ short width, _In_ short height, _Out_ COORD* dimensions);
|
||||
__declspec(dllexport) HRESULT _stdcall TerminalTriggerResizeWithDimension(_In_ void* terminal, _In_ COORD dimensions, _Out_ SIZE* dimensionsInPixels);
|
||||
__declspec(dllexport) HRESULT _stdcall TerminalCalculateResize(_In_ void* terminal, _In_ short width, _In_ short height, _Out_ COORD* dimensions);
|
||||
__declspec(dllexport) HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions);
|
||||
__declspec(dllexport) HRESULT _stdcall TerminalTriggerResizeWithDimension(_In_ void* terminal, _In_ til::size dimensions, _Out_ til::size* dimensionsInPixels);
|
||||
__declspec(dllexport) HRESULT _stdcall TerminalCalculateResize(_In_ void* terminal, _In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions);
|
||||
__declspec(dllexport) void _stdcall TerminalDpiChanged(void* terminal, int newDpi);
|
||||
__declspec(dllexport) void _stdcall TerminalUserScroll(void* terminal, int viewTop);
|
||||
__declspec(dllexport) void _stdcall TerminalClearSelection(void* terminal);
|
||||
__declspec(dllexport) const wchar_t* _stdcall TerminalGetSelection(void* terminal);
|
||||
__declspec(dllexport) bool _stdcall TerminalIsSelectionActive(void* terminal);
|
||||
__declspec(dllexport) void _stdcall DestroyTerminal(void* terminal);
|
||||
__declspec(dllexport) void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, short fontSize, int newDpi);
|
||||
__declspec(dllexport) void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, til::CoordType fontSize, int newDpi);
|
||||
__declspec(dllexport) void _stdcall TerminalRegisterWriteCallback(void* terminal, const void __stdcall callback(wchar_t*));
|
||||
__declspec(dllexport) void _stdcall TerminalSendKeyEvent(void* terminal, WORD vkey, WORD scanCode, WORD flags, bool keyDown);
|
||||
__declspec(dllexport) void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch, WORD flags, WORD scanCode);
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
HRESULT Initialize();
|
||||
void Teardown() noexcept;
|
||||
void SendOutput(std::wstring_view data);
|
||||
HRESULT Refresh(const SIZE windowSize, _Out_ COORD* dimensions);
|
||||
HRESULT Refresh(const til::size windowSize, _Out_ til::size* dimensions);
|
||||
void RegisterScrollCallback(std::function<void(int, int, int)> callback);
|
||||
void RegisterWriteCallback(const void _stdcall callback(wchar_t*));
|
||||
::Microsoft::Console::Types::IUiaData* GetUiaData() const noexcept;
|
||||
@@ -91,9 +91,9 @@ private:
|
||||
std::optional<til::point> _singleClickTouchdownPos;
|
||||
|
||||
friend HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ void** terminal);
|
||||
friend HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ short width, _In_ short height, _Out_ COORD* dimensions);
|
||||
friend HRESULT _stdcall TerminalTriggerResizeWithDimension(_In_ void* terminal, _In_ COORD dimensions, _Out_ SIZE* dimensionsInPixels);
|
||||
friend HRESULT _stdcall TerminalCalculateResize(_In_ void* terminal, _In_ short width, _In_ short height, _Out_ COORD* dimensions);
|
||||
friend HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions);
|
||||
friend HRESULT _stdcall TerminalTriggerResizeWithDimension(_In_ void* terminal, _In_ til::size dimensions, _Out_ til::size* dimensionsInPixels);
|
||||
friend HRESULT _stdcall TerminalCalculateResize(_In_ void* terminal, _In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions);
|
||||
friend void _stdcall TerminalDpiChanged(void* terminal, int newDpi);
|
||||
friend void _stdcall TerminalUserScroll(void* terminal, int viewTop);
|
||||
friend void _stdcall TerminalClearSelection(void* terminal);
|
||||
@@ -101,7 +101,7 @@ private:
|
||||
friend bool _stdcall TerminalIsSelectionActive(void* terminal);
|
||||
friend void _stdcall TerminalSendKeyEvent(void* terminal, WORD vkey, WORD scanCode, WORD flags, bool keyDown);
|
||||
friend void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch, WORD scanCode, WORD flags);
|
||||
friend void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, short fontSize, int newDpi);
|
||||
friend void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, til::CoordType fontSize, int newDpi);
|
||||
friend void _stdcall TerminalBlinkCursor(void* terminal);
|
||||
friend void _stdcall TerminalSetCursorVisible(void* terminal, const bool visible);
|
||||
friend void _stdcall TerminalSetFocus(void* terminal);
|
||||
@@ -128,10 +128,10 @@ private:
|
||||
void _SendCharEvent(wchar_t ch, WORD scanCode, WORD flags) noexcept;
|
||||
|
||||
// Inherited via IControlAccessibilityInfo
|
||||
COORD GetFontSize() const noexcept override;
|
||||
RECT GetBounds() const noexcept override;
|
||||
til::size GetFontSize() const noexcept override;
|
||||
til::rect GetBounds() const noexcept override;
|
||||
double GetScaleFactor() const noexcept override;
|
||||
void ChangeViewport(const SMALL_RECT NewWindow) override;
|
||||
void ChangeViewport(const til::inclusive_rect& NewWindow) override;
|
||||
HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) noexcept override;
|
||||
RECT GetPadding() const noexcept override;
|
||||
til::rect GetPadding() const noexcept override;
|
||||
};
|
||||
|
||||
@@ -1036,4 +1036,26 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
|
||||
return winrt::single_threaded_vector(std::move(vec));
|
||||
}
|
||||
|
||||
void Monarch::RequestMoveContent(winrt::hstring window,
|
||||
winrt::hstring content,
|
||||
uint32_t tabIndex)
|
||||
{
|
||||
auto windowId = _lookupPeasantIdForName(window);
|
||||
if (windowId == 0)
|
||||
{
|
||||
/* TODO! try the name as an integer ID */
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto targetPeasant{ _getPeasant(windowId) })
|
||||
{
|
||||
auto request = winrt::make_self<implementation::AttachRequest>(content, tabIndex);
|
||||
targetPeasant.AttachContentToWindow(*request);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*TODO! log */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo> GetPeasantInfos();
|
||||
Windows::Foundation::Collections::IVector<winrt::hstring> GetAllWindowLayouts();
|
||||
|
||||
void RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex);
|
||||
|
||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
@@ -60,6 +60,8 @@ namespace Microsoft.Terminal.Remoting
|
||||
Windows.Foundation.Collections.IVectorView<PeasantInfo> GetPeasantInfos { get; };
|
||||
Windows.Foundation.Collections.IVector<String> GetAllWindowLayouts();
|
||||
|
||||
void RequestMoveContent(String window, String content, UInt32 tabIndex);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "GetWindowLayoutArgs.h"
|
||||
#include "Peasant.g.cpp"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "AttachRequest.g.cpp"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
@@ -275,6 +276,22 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
void Peasant::AttachContentToWindow(Remoting::AttachRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
_AttachRequestedHandlers(*this, request);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Peasant_AttachContentToWindow",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
void Peasant::Quit()
|
||||
{
|
||||
try
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "Peasant.g.h"
|
||||
#include "RenameRequestArgs.h"
|
||||
#include "AttachRequest.g.h"
|
||||
|
||||
namespace RemotingUnitTests
|
||||
{
|
||||
@@ -12,6 +13,18 @@ namespace RemotingUnitTests
|
||||
};
|
||||
namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
{
|
||||
struct AttachRequest : public AttachRequestT<AttachRequest>
|
||||
{
|
||||
WINRT_PROPERTY(winrt::hstring, Content);
|
||||
WINRT_PROPERTY(uint32_t, TabIndex);
|
||||
|
||||
public:
|
||||
AttachRequest(winrt::hstring content,
|
||||
uint32_t tabIndex) :
|
||||
_Content{ content },
|
||||
_TabIndex{ tabIndex } {};
|
||||
};
|
||||
|
||||
struct Peasant : public PeasantT<Peasant>
|
||||
{
|
||||
Peasant();
|
||||
@@ -32,6 +45,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
void RequestQuitAll();
|
||||
void Quit();
|
||||
|
||||
void AttachContentToWindow(Remoting::AttachRequest request);
|
||||
|
||||
winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs GetLastActivatedArgs();
|
||||
|
||||
winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs();
|
||||
@@ -47,12 +62,15 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
TYPED_EVENT(DisplayWindowIdRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(RenameRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RenameRequestArgs);
|
||||
TYPED_EVENT(SummonRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior);
|
||||
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(QuitRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(GetWindowLayoutRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs);
|
||||
|
||||
TYPED_EVENT(AttachRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::AttachRequest);
|
||||
|
||||
private:
|
||||
Peasant(const uint64_t testPID);
|
||||
uint64_t _ourPID;
|
||||
|
||||
@@ -52,6 +52,11 @@ namespace Microsoft.Terminal.Remoting
|
||||
MonitorBehavior ToMonitor;
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass AttachRequest {
|
||||
String Content { get; };
|
||||
UInt32 TabIndex { get; };
|
||||
}
|
||||
|
||||
interface IPeasant
|
||||
{
|
||||
CommandlineArgs InitialArgs { get; };
|
||||
@@ -70,23 +75,31 @@ namespace Microsoft.Terminal.Remoting
|
||||
void RequestIdentifyWindows(); // Tells us to raise a IdentifyWindowsRequested
|
||||
void RequestRename(RenameRequestArgs args); // Tells us to raise a RenameRequested
|
||||
void Summon(SummonWindowBehavior behavior);
|
||||
|
||||
void RequestShowNotificationIcon();
|
||||
void RequestHideNotificationIcon();
|
||||
void RequestQuitAll();
|
||||
void Quit();
|
||||
String GetWindowLayout();
|
||||
|
||||
void AttachContentToWindow(AttachRequest request);
|
||||
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, WindowActivatedArgs> WindowActivated;
|
||||
event Windows.Foundation.TypedEventHandler<Object, CommandlineArgs> ExecuteCommandlineRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> DisplayWindowIdRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, RenameRequestArgs> RenameRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, SummonWindowBehavior> SummonRequested;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, GetWindowLayoutArgs> GetWindowLayoutRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, AttachRequest> AttachRequested;
|
||||
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass Peasant : IPeasant
|
||||
|
||||
@@ -788,4 +788,13 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::fire_and_forget WindowManager::RequestMoveContent(winrt::hstring window,
|
||||
winrt::hstring content,
|
||||
uint32_t tabIndex)
|
||||
{
|
||||
co_await winrt::resume_background();
|
||||
_monarch.RequestMoveContent(window, content, tabIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,9 +48,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
winrt::fire_and_forget RequestHideNotificationIcon();
|
||||
winrt::fire_and_forget RequestQuitAll();
|
||||
bool DoesQuakeWindowExist();
|
||||
|
||||
void UpdateActiveTabTitle(winrt::hstring title);
|
||||
Windows::Foundation::Collections::IVector<winrt::hstring> GetAllWindowLayouts();
|
||||
|
||||
winrt::fire_and_forget RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex);
|
||||
|
||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||
TYPED_EVENT(BecameMonarch, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(WindowCreated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
@@ -22,7 +22,11 @@ namespace Microsoft.Terminal.Remoting
|
||||
void RequestQuitAll();
|
||||
void UpdateActiveTabTitle(String title);
|
||||
Boolean DoesQuakeWindowExist();
|
||||
|
||||
Windows.Foundation.Collections.IVectorView<PeasantInfo> GetPeasantInfos();
|
||||
|
||||
void RequestMoveContent(String window, String content, UInt32 tabIndex);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> BecameMonarch;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowCreated;
|
||||
|
||||
@@ -97,7 +97,7 @@ HRESULT OpenTerminalHere::GetTitle(IShellItemArray* /*psiItemArray*/,
|
||||
return SHStrDup(resource.data(), ppszName);
|
||||
}
|
||||
|
||||
HRESULT OpenTerminalHere::GetState(IShellItemArray* /*psiItemArray*/,
|
||||
HRESULT OpenTerminalHere::GetState(IShellItemArray* psiItemArray,
|
||||
BOOL /*fOkToBeSlow*/,
|
||||
EXPCMDSTATE* pCmdState)
|
||||
{
|
||||
@@ -106,10 +106,25 @@ HRESULT OpenTerminalHere::GetState(IShellItemArray* /*psiItemArray*/,
|
||||
// E_PENDING and this object will be called back on a background thread with
|
||||
// fOkToBeSlow == TRUE
|
||||
|
||||
// We however don't need to bother with any of that, so we'll just return
|
||||
// ECS_ENABLED.
|
||||
// We however don't need to bother with any of that.
|
||||
|
||||
// If no item was selected when the context menu was opened and Explorer
|
||||
// is not at a valid path (e.g. This PC or Quick Access), we should hide
|
||||
// the verb from the context menu.
|
||||
if (psiItemArray == nullptr)
|
||||
{
|
||||
const auto path = this->_GetPathFromExplorer();
|
||||
*pCmdState = path.empty() ? ECS_HIDDEN : ECS_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
winrt::com_ptr<IShellItem> psi;
|
||||
psiItemArray->GetItemAt(0, psi.put());
|
||||
SFGAOF attributes;
|
||||
const bool isFileSystemItem = (psi->GetAttributes(SFGAO_FILESYSTEM, &attributes) == S_OK);
|
||||
*pCmdState = isFileSystemItem ? ECS_ENABLED : ECS_HIDDEN;
|
||||
}
|
||||
|
||||
*pCmdState = ECS_ENABLED;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,10 +153,6 @@
|
||||
|
||||
<StaticResource x:Key="UnfocusedBorderBrush"
|
||||
ResourceKey="ApplicationPageBackgroundThemeBrush" />
|
||||
|
||||
<StaticResource x:Key="SettingsPageBackground"
|
||||
ResourceKey="SolidBackgroundFillColorTertiary" />
|
||||
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
@@ -170,9 +166,6 @@
|
||||
|
||||
<StaticResource x:Key="UnfocusedBorderBrush"
|
||||
ResourceKey="ApplicationPageBackgroundThemeBrush" />
|
||||
|
||||
<StaticResource x:Key="SettingsPageBackground"
|
||||
ResourceKey="SolidBackgroundFillColorTertiary" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
@@ -190,9 +183,6 @@
|
||||
-->
|
||||
<StaticResource x:Key="TabViewBackground"
|
||||
ResourceKey="SystemColorButtonFaceColorBrush" />
|
||||
|
||||
<StaticResource x:Key="SettingsPageBackground"
|
||||
ResourceKey="SystemColorWindowColorBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
else if (const auto& realArgs = args.ActionArgs().try_as<MovePaneArgs>())
|
||||
{
|
||||
auto moved = _MovePane(realArgs.TabIndex());
|
||||
auto moved = _MovePane(realArgs);
|
||||
args.Handled(moved);
|
||||
}
|
||||
}
|
||||
@@ -201,10 +201,15 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
_SplitPane(realArgs.SplitDirection(),
|
||||
// This is safe, we're already filtering so the value is (0, 1)
|
||||
::base::saturated_cast<float>(realArgs.SplitSize()),
|
||||
_MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
|
||||
// _SplitPaneActiveTab(realArgs.SplitDirection(),
|
||||
// // This is safe, we're already filtering so the value is (0, 1)
|
||||
// ::base::saturated_cast<float>(realArgs.SplitSize()),
|
||||
// _MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
|
||||
|
||||
_asyncSplitPaneActiveTab(realArgs.SplitDirection(),
|
||||
// This is safe, we're already filtering so the value is (0, 1)
|
||||
::base::saturated_cast<float>(realArgs.SplitSize()),
|
||||
_prepareContentProc(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
@@ -278,6 +283,55 @@ namespace winrt::TerminalApp::implementation
|
||||
args.Handled(true);
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleScrollToMark(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<ScrollToMarkArgs>())
|
||||
{
|
||||
_ApplyToActiveControls([&realArgs](auto& control) {
|
||||
control.ScrollToMark(realArgs.Direction());
|
||||
});
|
||||
}
|
||||
args.Handled(true);
|
||||
}
|
||||
void TerminalPage::_HandleAddMark(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<AddMarkArgs>())
|
||||
{
|
||||
_ApplyToActiveControls([realArgs](auto& control) {
|
||||
Control::ScrollMark mark;
|
||||
if (realArgs.Color())
|
||||
{
|
||||
mark.Color.Color = realArgs.Color().Value();
|
||||
mark.Color.HasValue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mark.Color.HasValue = false;
|
||||
}
|
||||
control.AddMark(mark);
|
||||
});
|
||||
}
|
||||
args.Handled(true);
|
||||
}
|
||||
void TerminalPage::_HandleClearMark(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
_ApplyToActiveControls([](auto& control) {
|
||||
control.ClearMark();
|
||||
});
|
||||
args.Handled(true);
|
||||
}
|
||||
void TerminalPage::_HandleClearAllMarks(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
_ApplyToActiveControls([](auto& control) {
|
||||
control.ClearAllMarks();
|
||||
});
|
||||
args.Handled(true);
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleFindMatch(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
@@ -702,17 +756,8 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto& realArgs = actionArgs.ActionArgs().try_as<MoveTabArgs>())
|
||||
{
|
||||
auto direction = realArgs.Direction();
|
||||
if (direction != MoveTabDirection::None)
|
||||
{
|
||||
if (auto focusedTabIndex = _GetFocusedTabIndex())
|
||||
{
|
||||
auto currentTabIndex = focusedTabIndex.value();
|
||||
auto delta = direction == MoveTabDirection::Forward ? 1 : -1;
|
||||
_TryMoveTab(currentTabIndex, currentTabIndex + delta);
|
||||
}
|
||||
}
|
||||
actionArgs.Handled(true);
|
||||
auto moved = _MoveTab(realArgs);
|
||||
actionArgs.Handled(moved);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1043,4 +1088,34 @@ namespace winrt::TerminalApp::implementation
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleMarkMode(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
control.ToggleMarkMode();
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleToggleBlockSelection(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
const auto handled = control.ToggleBlockSelection();
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleSwitchSelectionEndpoint(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
const auto handled = control.SwitchSelectionEndpoint();
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ static const std::array settingsLoadWarningsLabels {
|
||||
USES_RESOURCE(L"InvalidSplitSize"),
|
||||
USES_RESOURCE(L"FailedToParseStartupActions"),
|
||||
USES_RESOURCE(L"FailedToParseSubCommands"),
|
||||
USES_RESOURCE(L"UnknownTheme"),
|
||||
};
|
||||
static const std::array settingsLoadErrorsLabels {
|
||||
USES_RESOURCE(L"NoProfilesText"),
|
||||
@@ -292,7 +293,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_root->Maximized(true);
|
||||
}
|
||||
|
||||
if (WI_IsFlagSet(launchMode, LaunchMode::FullscreenMode))
|
||||
if (WI_IsFlagSet(launchMode, LaunchMode::FullscreenMode) && !IsQuakeWindow())
|
||||
{
|
||||
_root->SetFullscreen(true);
|
||||
}
|
||||
@@ -367,11 +368,12 @@ namespace winrt::TerminalApp::implementation
|
||||
// details here, but it does have the desired effect.
|
||||
// It's not enough to set the theme on the dialog alone.
|
||||
auto themingLambda{ [this](const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) {
|
||||
auto theme{ _settings.GlobalSettings().Theme() };
|
||||
auto theme{ _settings.GlobalSettings().CurrentTheme() };
|
||||
auto requestedTheme{ theme.RequestedTheme() };
|
||||
auto element{ sender.try_as<winrt::Windows::UI::Xaml::FrameworkElement>() };
|
||||
while (element)
|
||||
{
|
||||
element.RequestedTheme(theme);
|
||||
element.RequestedTheme(requestedTheme);
|
||||
element = element.Parent().try_as<winrt::Windows::UI::Xaml::FrameworkElement>();
|
||||
}
|
||||
} };
|
||||
@@ -737,13 +739,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
winrt::Windows::UI::Xaml::ElementTheme AppLogic::GetRequestedTheme()
|
||||
{
|
||||
if (!_loadedInitialSettings)
|
||||
{
|
||||
// Load settings if we haven't already
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
return _settings.GlobalSettings().Theme();
|
||||
return Theme().RequestedTheme();
|
||||
}
|
||||
|
||||
bool AppLogic::GetShowTabsInTitlebar()
|
||||
@@ -962,9 +958,16 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
CATCH_LOG()
|
||||
|
||||
// Method Description:
|
||||
// - Update the current theme of the application. This will trigger our
|
||||
// RequestedThemeChanged event, to have our host change the theme of the
|
||||
// root of the application.
|
||||
// Arguments:
|
||||
// - newTheme: The ElementTheme to apply to our elements.
|
||||
void AppLogic::_RefreshThemeRoutine()
|
||||
{
|
||||
_ApplyTheme(_settings.GlobalSettings().Theme());
|
||||
// Propagate the event to the host layer, so it can update its own UI
|
||||
_RequestedThemeChangedHandlers(*this, Theme());
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
@@ -1073,18 +1076,6 @@ namespace winrt::TerminalApp::implementation
|
||||
return _settings;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update the current theme of the application. This will trigger our
|
||||
// RequestedThemeChanged event, to have our host change the theme of the
|
||||
// root of the application.
|
||||
// Arguments:
|
||||
// - newTheme: The ElementTheme to apply to our elements.
|
||||
void AppLogic::_ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme)
|
||||
{
|
||||
// Propagate the event to the host layer, so it can update its own UI
|
||||
_RequestedThemeChangedHandlers(*this, newTheme);
|
||||
}
|
||||
|
||||
UIElement AppLogic::GetRoot() noexcept
|
||||
{
|
||||
return _root.as<winrt::Windows::UI::Xaml::Controls::Control>();
|
||||
@@ -1219,6 +1210,19 @@ namespace winrt::TerminalApp::implementation
|
||||
return {};
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::Media::Brush AppLogic::TitlebarBrush()
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
return _root->TitlebarBrush();
|
||||
}
|
||||
return { nullptr };
|
||||
}
|
||||
void AppLogic::WindowActivated(const bool activated)
|
||||
{
|
||||
_root->WindowActivated(activated);
|
||||
}
|
||||
|
||||
bool AppLogic::HasCommandlineArguments() const noexcept
|
||||
{
|
||||
return _hasCommandLineArguments;
|
||||
@@ -1645,4 +1649,22 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
return _settings.GlobalSettings().ShowTitleInTitlebar();
|
||||
}
|
||||
|
||||
Microsoft::Terminal::Settings::Model::Theme AppLogic::Theme()
|
||||
{
|
||||
if (!_loadedInitialSettings)
|
||||
{
|
||||
// Load settings if we haven't already
|
||||
LoadSettings();
|
||||
}
|
||||
return _settings.GlobalSettings().CurrentTheme();
|
||||
}
|
||||
|
||||
void AppLogic::AttachContent(winrt::hstring content, uint32_t tabIndex)
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
_root->AttachContent(content, tabIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,18 +117,33 @@ namespace winrt::TerminalApp::implementation
|
||||
void WindowVisibilityChanged(const bool showOrHide);
|
||||
|
||||
winrt::TerminalApp::TaskbarState TaskbarState();
|
||||
winrt::Windows::UI::Xaml::Media::Brush TitlebarBrush();
|
||||
void WindowActivated(const bool activated);
|
||||
|
||||
bool GetMinimizeToNotificationArea();
|
||||
bool GetAlwaysShowNotificationIcon();
|
||||
bool GetShowTitleInTitlebar();
|
||||
|
||||
void AttachContent(winrt::hstring content, uint32_t tabIndex);
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||
void DismissDialog();
|
||||
|
||||
Windows::Foundation::Collections::IMapView<Microsoft::Terminal::Control::KeyChord, Microsoft::Terminal::Settings::Model::Command> GlobalHotkeys();
|
||||
|
||||
Microsoft::Terminal::Settings::Model::Theme Theme();
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
|
||||
// PropertyChanged is surprisingly not a typed event, so we'll define that one manually.
|
||||
// Usually we'd just do
|
||||
// WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
//
|
||||
// But what we're doing here is exposing the Page's PropertyChanged _as
|
||||
// our own event_. It's a FORWARDED_CALLBACK, essentially.
|
||||
winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler) { return _root->PropertyChanged(handler); }
|
||||
void PropertyChanged(winrt::event_token const& token) { _root->PropertyChanged(token); }
|
||||
|
||||
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Settings::Model::Theme);
|
||||
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs);
|
||||
|
||||
@@ -183,8 +198,6 @@ namespace winrt::TerminalApp::implementation
|
||||
void _ReloadSettings();
|
||||
void _OpenSettingsUI();
|
||||
|
||||
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);
|
||||
|
||||
bool _hasCommandLineArguments{ false };
|
||||
bool _hasSettingsStartupActions{ false };
|
||||
std::vector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> _warnings;
|
||||
@@ -205,11 +218,14 @@ namespace winrt::TerminalApp::implementation
|
||||
FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested);
|
||||
FORWARDED_TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IsQuakeWindowChanged);
|
||||
FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested);
|
||||
|
||||
FORWARDED_TYPED_EVENT(CloseRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, CloseRequested);
|
||||
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);
|
||||
|
||||
FORWARDED_TYPED_EVENT(RequestMoveContent, Windows::Foundation::IInspectable, winrt::TerminalApp::RequestMoveContentArgs, _root, RequestMoveContent);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class TerminalAppLocalTests::CommandlineTest;
|
||||
#endif
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace TerminalApp
|
||||
|
||||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||
// information.
|
||||
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter
|
||||
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
AppLogic();
|
||||
|
||||
@@ -94,6 +94,8 @@ namespace TerminalApp
|
||||
void WindowVisibilityChanged(Boolean showOrHide);
|
||||
|
||||
TaskbarState TaskbarState{ get; };
|
||||
Windows.UI.Xaml.Media.Brush TitlebarBrush { get; };
|
||||
void WindowActivated(Boolean activated);
|
||||
|
||||
Boolean ShouldUsePersistedLayout();
|
||||
Boolean ShouldImmediatelyHandoffToElevated();
|
||||
@@ -105,7 +107,10 @@ namespace TerminalApp
|
||||
Boolean GetAlwaysShowNotificationIcon();
|
||||
Boolean GetShowTitleInTitlebar();
|
||||
|
||||
Microsoft.Terminal.Settings.Model.Theme Theme { get; };
|
||||
|
||||
FindTargetWindowResult FindTargetWindow(String[] args);
|
||||
void AttachContent(String content, UInt32 tabIndex);
|
||||
|
||||
Windows.Foundation.Collections.IMapView<Microsoft.Terminal.Control.KeyChord, Microsoft.Terminal.Settings.Model.Command> GlobalHotkeys();
|
||||
|
||||
@@ -117,7 +122,7 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, LastTabClosedEventArgs> LastTabClosed;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.ElementTheme> RequestedThemeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Theme> RequestedThemeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusModeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FullscreenChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ChangeMaximizeRequested;
|
||||
@@ -134,5 +139,8 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.ShowWindowArgs> ShowWindowChanged;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, RequestMoveContentArgs> RequestMoveContent;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,15 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
|
||||
void DebugTapConnection::_OutputHandler(const hstring str)
|
||||
{
|
||||
_TerminalOutputHandlers(til::visualize_control_codes(str));
|
||||
auto output = til::visualize_control_codes(str);
|
||||
// To make the output easier to read, we introduce a line break whenever
|
||||
// an LF control is encountered. But at this point, the LF would have
|
||||
// been converted to U+240A (␊), so that's what we need to search for.
|
||||
for (size_t lfPos = 0; (lfPos = output.find(L'\u240A', lfPos)) != std::wstring::npos;)
|
||||
{
|
||||
output.insert(++lfPos, L"\r\n");
|
||||
}
|
||||
_TerminalOutputHandlers(output);
|
||||
}
|
||||
|
||||
// Called by the DebugInputTapConnection to print user input
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "winrt/Microsoft.UI.Xaml.Controls.h"
|
||||
|
||||
#include "HighlightedTextSegment.g.h"
|
||||
#include "HighlightedText.g.h"
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ Pane::Pane(std::shared_ptr<Pane> first,
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - Arguments appropriate for a SplitPane or NewTab action
|
||||
NewTerminalArgs Pane::GetTerminalArgsForPane() const
|
||||
NewTerminalArgs Pane::GetTerminalArgsForPane(const bool asContent) const
|
||||
{
|
||||
// Leaves are the only things that have controls
|
||||
assert(_IsLeaf());
|
||||
@@ -164,6 +164,11 @@ NewTerminalArgs Pane::GetTerminalArgsForPane() const
|
||||
// object. That would work for schemes set by the Terminal, but not ones set
|
||||
// by VT, but that seems good enough.
|
||||
|
||||
if (asContent)
|
||||
{
|
||||
args.ContentGuid(_control.ContentGuid());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -175,14 +180,15 @@ NewTerminalArgs Pane::GetTerminalArgsForPane() const
|
||||
// Arguments:
|
||||
// - currentId: the id to use for the current/first pane
|
||||
// - nextId: the id to use for a new pane if we split
|
||||
// - asContent: TODO!
|
||||
// Return Value:
|
||||
// - The state from building the startup actions, includes a vector of commands,
|
||||
// the original root pane, the id of the focused pane, and the number of panes
|
||||
// created.
|
||||
Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t nextId)
|
||||
Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t nextId, const bool asContent)
|
||||
{
|
||||
// if we are a leaf then all there is to do is defer to the parent.
|
||||
if (_IsLeaf())
|
||||
if (/*!asContent && */ _IsLeaf())
|
||||
{
|
||||
if (_lastActive)
|
||||
{
|
||||
@@ -195,16 +201,29 @@ Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t n
|
||||
auto buildSplitPane = [&](auto newPane) {
|
||||
ActionAndArgs actionAndArgs;
|
||||
actionAndArgs.Action(ShortcutAction::SplitPane);
|
||||
const auto terminalArgs{ newPane->GetTerminalArgsForPane() };
|
||||
const auto terminalArgs{ newPane->GetTerminalArgsForPane(asContent) };
|
||||
// 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;
|
||||
SplitPaneArgs args{ SplitType::Manual, splitDirection, 1. - _desiredSplitPosition, terminalArgs };
|
||||
// const auto splitSize = (asContent && _IsLeaf()) ? .5 : (1. - _desiredSplitPosition);
|
||||
const auto splitSize = (1. - _desiredSplitPosition);
|
||||
SplitPaneArgs args{ SplitType::Manual, splitDirection, splitSize, terminalArgs };
|
||||
actionAndArgs.Args(args);
|
||||
|
||||
return actionAndArgs;
|
||||
};
|
||||
|
||||
// if (asContent && _IsLeaf())
|
||||
// {
|
||||
// // TODO! This probably won't work. We probably do need to ask the parent
|
||||
// // of this pane to generate the action for us. Consider moving a pane
|
||||
// // that's 25% of the parent - the pane doesn't know that. Only the
|
||||
// // parent does. When we recieve it, we can determine if we're putting it
|
||||
// // into a tab or a pane, and then parse the NewTerminalArgs out of
|
||||
// // either the splitPane or the newTab action.
|
||||
// return { { buildSplitPane(shared_from_this()) }, shared_from_this(), currentId, 1 };
|
||||
// }
|
||||
|
||||
auto buildMoveFocus = [](auto direction) {
|
||||
MoveFocusArgs args{ direction };
|
||||
|
||||
|
||||
@@ -91,8 +91,8 @@ public:
|
||||
std::optional<uint32_t> focusedPaneId;
|
||||
uint32_t panesCreated;
|
||||
};
|
||||
BuildStartupState BuildStartupActions(uint32_t currentId, uint32_t nextId);
|
||||
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetTerminalArgsForPane() const;
|
||||
BuildStartupState BuildStartupActions(uint32_t currentId, uint32_t nextId, const bool asContent = false);
|
||||
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetTerminalArgsForPane(const bool asContent = false) const;
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile);
|
||||
|
||||
@@ -158,15 +158,15 @@
|
||||
<value>Windows Terminal with a preview of upcoming features</value>
|
||||
</data>
|
||||
<data name="ShellExtension_OpenInTerminalMenuItem_Dev" xml:space="preserve">
|
||||
<value>Open in Terminal (Dev)</value>
|
||||
<value>Open in Terminal (&Dev)</value>
|
||||
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
|
||||
</data>
|
||||
<data name="ShellExtension_OpenInTerminalMenuItem_Preview" xml:space="preserve">
|
||||
<value>Open in Terminal Preview</value>
|
||||
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal</comment>
|
||||
<value>Open in Terminal &Preview</value>
|
||||
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
|
||||
</data>
|
||||
<data name="ShellExtension_OpenInTerminalMenuItem" xml:space="preserve">
|
||||
<value>Open in Terminal</value>
|
||||
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the non-preview version of Windows Terminal</comment>
|
||||
<value>Open in &Terminal</value>
|
||||
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the non-preview version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -242,6 +242,10 @@
|
||||
<value>• Found a keybinding that was missing a required parameter value. This keybinding will be ignored.</value>
|
||||
<comment>{Locked="•"} This glyph is a bullet, used in a bulleted list.</comment>
|
||||
</data>
|
||||
<data name="UnknownTheme" xml:space="preserve">
|
||||
<value>• The specified "theme" was not found in the list of themes. Temporarily falling back to the default value.</value>
|
||||
<comment>{Locked="•"} This glyph is a bullet, used in a bulleted list.</comment>
|
||||
</data>
|
||||
<data name="LegacyGlobalsProperty" xml:space="preserve">
|
||||
<value>The "globals" property is deprecated - your settings might need updating. </value>
|
||||
<comment>{Locked="\"globals\""} </comment>
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - The list of actions.
|
||||
std::vector<ActionAndArgs> SettingsTab::BuildStartupActions() const
|
||||
std::vector<ActionAndArgs> SettingsTab::BuildStartupActions(const bool /*asContent*/) const
|
||||
{
|
||||
ActionAndArgs action;
|
||||
action.Action(ShortcutAction::OpenSettings);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void UpdateSettings(Microsoft::Terminal::Settings::Model::CascadiaSettings settings);
|
||||
void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override;
|
||||
|
||||
std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions() const override;
|
||||
std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions(const bool asContent = false) const override;
|
||||
|
||||
private:
|
||||
void _MakeTabViewItem() override;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs);
|
||||
void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap);
|
||||
virtual std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions() const = 0;
|
||||
virtual std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions(const bool asContent = false) const = 0;
|
||||
|
||||
WINRT_CALLBACK(RequestFocusActiveControl, winrt::delegate<void()>);
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - existingConnection: An optional connection that is already established to a PTY
|
||||
// for this tab to host instead of creating one.
|
||||
// If not defined, the tab will create the connection.
|
||||
HRESULT TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection)
|
||||
HRESULT TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs)
|
||||
try
|
||||
{
|
||||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
@@ -72,10 +72,10 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
|
||||
const auto controlSettings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
|
||||
|
||||
// Try to handle auto-elevation
|
||||
if (_maybeElevate(newTerminalArgs, settings, profile))
|
||||
if (_maybeElevate(newTerminalArgs, controlSettings, profile))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
@@ -83,35 +83,42 @@ namespace winrt::TerminalApp::implementation
|
||||
// unfortunately. This seems to be due to Centennial quirks. It works
|
||||
// unpackaged, but not packaged.
|
||||
//
|
||||
// This call to _MakePane won't return nullptr, we already checked that
|
||||
// case above with the _maybeElevate call.
|
||||
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection));
|
||||
// // This call to _MakePane won't return nullptr, we already checked that
|
||||
// // case above with the _maybeElevate call.
|
||||
// _CreateNewTabFromPane(_MakePane(newTerminalArgs, false, nullptr));
|
||||
|
||||
const auto tabCount = _tabs.Size();
|
||||
const auto usedManualProfile = (newTerminalArgs != nullptr) &&
|
||||
(newTerminalArgs.ProfileIndex() != nullptr ||
|
||||
newTerminalArgs.Profile().empty());
|
||||
// TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||
// Profile profile{ nullptr };
|
||||
// _evaluateSettings(newTerminalArgs, false /*duplicate*/, controlSettings, profile);
|
||||
auto initContentProc = (newTerminalArgs && newTerminalArgs.ContentGuid() != winrt::guid{}) ?
|
||||
_AttachToContentProcess(newTerminalArgs.ContentGuid()) :
|
||||
_CreateNewContentProcess(profile, controlSettings);
|
||||
_createNewTabFromContent(PreparedContent{ initContentProc, controlSettings, profile });
|
||||
// const auto tabCount = _tabs.Size();
|
||||
// const auto usedManualProfile = (newTerminalArgs != nullptr) &&
|
||||
// (newTerminalArgs.ProfileIndex() != nullptr ||
|
||||
// newTerminalArgs.Profile().empty());
|
||||
|
||||
// Lookup the name of the color scheme used by this profile.
|
||||
const auto scheme = _settings.GetColorSchemeForProfile(profile);
|
||||
// If they explicitly specified `null` as the scheme (indicating _no_ scheme), log
|
||||
// that as the empty string.
|
||||
const auto schemeName = scheme ? scheme.Name() : L"\0";
|
||||
// // Lookup the name of the color scheme used by this profile.
|
||||
// const auto scheme = _settings.GetColorSchemeForProfile(profile);
|
||||
// // If they explicitly specified `null` as the scheme (indicating _no_ scheme), log
|
||||
// // that as the empty string.
|
||||
// const auto schemeName = scheme ? scheme.Name() : L"\0";
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
|
||||
"TabInformation",
|
||||
TraceLoggingDescription("Event emitted upon new tab creation in TerminalApp"),
|
||||
TraceLoggingUInt32(1u, "EventVer", "Version of this event"),
|
||||
TraceLoggingUInt32(tabCount, "TabCount", "Count of tabs currently opened in TerminalApp"),
|
||||
TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"),
|
||||
TraceLoggingGuid(profile.Guid(), "ProfileGuid", "The GUID of the profile spawned in the new tab"),
|
||||
TraceLoggingBool(settings.DefaultSettings().UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"),
|
||||
TraceLoggingFloat64(settings.DefaultSettings().Opacity(), "TintOpacity", "Opacity preference from the settings"),
|
||||
TraceLoggingWideString(settings.DefaultSettings().FontFace().c_str(), "FontFace", "Font face chosen in the settings"),
|
||||
TraceLoggingWideString(schemeName.data(), "SchemeName", "Color scheme set in the settings"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
// TraceLoggingWrite(
|
||||
// g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
|
||||
// "TabInformation",
|
||||
// TraceLoggingDescription("Event emitted upon new tab creation in TerminalApp"),
|
||||
// TraceLoggingUInt32(1u, "EventVer", "Version of this event"),
|
||||
// TraceLoggingUInt32(tabCount, "TabCount", "Count of tabs currently opened in TerminalApp"),
|
||||
// TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"),
|
||||
// TraceLoggingGuid(profile.Guid(), "ProfileGuid", "The GUID of the profile spawned in the new tab"),
|
||||
// TraceLoggingBool(settings.DefaultSettings().UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"),
|
||||
// TraceLoggingFloat64(settings.DefaultSettings().Opacity(), "TintOpacity", "Opacity preference from the settings"),
|
||||
// TraceLoggingWideString(settings.DefaultSettings().FontFace().c_str(), "FontFace", "Font face chosen in the settings"),
|
||||
// TraceLoggingWideString(schemeName.data(), "SchemeName", "Color scheme set in the settings"),
|
||||
// TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
// TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -123,10 +130,20 @@ namespace winrt::TerminalApp::implementation
|
||||
// - newTabImpl: the uninitialized tab.
|
||||
void TerminalPage::_InitializeTab(winrt::com_ptr<TerminalTab> newTabImpl)
|
||||
{
|
||||
newTabImpl->Initialize();
|
||||
// newTabImpl->Initialize();
|
||||
|
||||
uint32_t insertPosition = _tabs.Size();
|
||||
if (_settings.GlobalSettings().NewTabPosition() == NewTabPosition::AfterCurrentTab)
|
||||
{
|
||||
auto currentTabIndex = _GetFocusedTabIndex();
|
||||
if (currentTabIndex.has_value())
|
||||
{
|
||||
insertPosition = currentTabIndex.value() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new tab to the list of our tabs.
|
||||
_tabs.Append(*newTabImpl);
|
||||
_tabs.InsertAt(insertPosition, *newTabImpl);
|
||||
_mruTabs.Append(*newTabImpl);
|
||||
|
||||
newTabImpl->SetDispatch(*_actionDispatch);
|
||||
@@ -154,6 +171,8 @@ namespace winrt::TerminalApp::implementation
|
||||
// Possibly update the icon of the tab.
|
||||
page->_UpdateTabIcon(*tab);
|
||||
|
||||
page->_updateThemeColors();
|
||||
|
||||
// Update the taskbar progress as well. We'll raise our own
|
||||
// SetTaskbarProgress event here, to get tell the hosting
|
||||
// application to re-query this value from us.
|
||||
@@ -193,7 +212,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
if (page && tab)
|
||||
{
|
||||
page->_SplitTab(*tab);
|
||||
page->_SplitTab(tab);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -220,16 +239,20 @@ namespace winrt::TerminalApp::implementation
|
||||
});
|
||||
|
||||
auto tabViewItem = newTabImpl->TabViewItem();
|
||||
_tabView.TabItems().Append(tabViewItem);
|
||||
_tabView.TabItems().InsertAt(insertPosition, tabViewItem);
|
||||
|
||||
// Set this tab's icon to the icon from the user's profile
|
||||
if (const auto profile{ newTabImpl->GetFocusedProfile() })
|
||||
{
|
||||
if (!profile.Icon().empty())
|
||||
{
|
||||
newTabImpl->UpdateIcon(profile.Icon());
|
||||
}
|
||||
}
|
||||
//
|
||||
// TODO! This doesn't need ot live in TerminalPage like, at all. This
|
||||
// should get moved inside TerminalTab::AttachRootPane, or
|
||||
// TerminalTab::Initialize or something.
|
||||
// if (const auto profile{ newTabImpl->GetFocusedProfile() })
|
||||
// {
|
||||
// if (!profile.Icon().empty())
|
||||
// {
|
||||
// newTabImpl->UpdateIcon(profile.Icon());
|
||||
// }
|
||||
// }
|
||||
|
||||
tabViewItem.PointerReleased({ this, &TerminalPage::_OnTabClick });
|
||||
|
||||
@@ -279,6 +302,41 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
winrt::fire_and_forget TerminalPage::_createNewTabFromContent(PreparedContent preppedContent,
|
||||
std::function<void(const winrt::com_ptr<TerminalTab>&)> postInitTab /* defaults to nullptr*/)
|
||||
{
|
||||
auto newTabImpl = winrt::make_self<TerminalTab>(nullptr);
|
||||
// TODO! This tab should have a Content that's initialized with a blank
|
||||
// grid that takes up the whole space, with the BG set to the BG color
|
||||
// of the TerminalControl. So that the tab has something to show
|
||||
// initially.
|
||||
//
|
||||
// Alternatively, the Control could be initialized with a
|
||||
// AsyncAction<ContentProcess> and then when _that_ returns, the
|
||||
// TermControl starts to initialize itself?
|
||||
//
|
||||
// That's an idea. We do already have the settings for the control, just not the content. Huh.
|
||||
_InitializeTab(newTabImpl); // Adds tab to list, tabview
|
||||
|
||||
// If the caller requested additional setup for the tab, do that now.
|
||||
// For example, DuplicateTab uses this to copy the runtime tab text from
|
||||
// the old tab to the new one.
|
||||
if (postInitTab)
|
||||
{
|
||||
postInitTab(newTabImpl);
|
||||
}
|
||||
|
||||
// TODO! Do we need both this and the resume_background in _CreateNewContentProcess
|
||||
co_await winrt::resume_background();
|
||||
auto content = co_await preppedContent.initContentProc;
|
||||
co_await wil::resume_foreground(Dispatcher(), CoreDispatcherPriority::High);
|
||||
|
||||
auto pane = _makePaneFromContent(content, preppedContent.controlSettings, preppedContent.profile);
|
||||
newTabImpl->AttachRootPane(pane);
|
||||
|
||||
// TODO! DebugTap
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the icon of the currently focused terminal control, and set its
|
||||
// tab's icon to that icon.
|
||||
@@ -348,30 +406,40 @@ namespace winrt::TerminalApp::implementation
|
||||
// In the future, it may be preferable to just duplicate the
|
||||
// current control's live settings (which will include changes
|
||||
// made through VT).
|
||||
_CreateNewTabFromPane(_MakePane(nullptr, true, nullptr));
|
||||
|
||||
const auto runtimeTabText{ tab.GetTabText() };
|
||||
if (!runtimeTabText.empty())
|
||||
{
|
||||
if (auto newTab{ _GetFocusedTabImpl() })
|
||||
// _CreateNewTabFromPane(_MakePane(nullptr, true, nullptr));
|
||||
|
||||
auto initRuntimeTabTitle = [&tab](auto& newTab) {
|
||||
const auto runtimeTabText{ tab.GetTabText() };
|
||||
if (!runtimeTabText.empty())
|
||||
{
|
||||
newTab->SetTabText(runtimeTabText);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||
// Profile profile{ nullptr };
|
||||
// _evaluateSettings(nullptr, true, controlSettings, profile);
|
||||
// auto initContentProc = _CreateNewContentProcess(profile, controlSettings);
|
||||
auto preppedContent = _prepareContentProc(nullptr, true);
|
||||
_createNewTabFromContent(preppedContent, initRuntimeTabTitle);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the specified tab as the focused tab and splits its active pane
|
||||
// - Sets the specified tab as the focused tab and splits its active pane.
|
||||
// This will duplicate the profile that's currently active in the given
|
||||
// tab.
|
||||
// Arguments:
|
||||
// - tab: tab to split
|
||||
void TerminalPage::_SplitTab(TerminalTab& tab)
|
||||
void TerminalPage::_SplitTab(winrt::com_ptr<TerminalTab>& tab)
|
||||
{
|
||||
try
|
||||
{
|
||||
_SetFocusedTab(tab);
|
||||
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
|
||||
_SetFocusedTab(*tab);
|
||||
// _SplitPaneOnTab(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
|
||||
_asyncSplitPaneOnTab(tab, SplitDirection::Automatic, 0.5f, _prepareContentProc(nullptr, true));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
@@ -925,6 +993,8 @@ namespace winrt::TerminalApp::implementation
|
||||
_TitleChangedHandlers(*this, tab.Title());
|
||||
}
|
||||
|
||||
_updateThemeColors();
|
||||
|
||||
auto tab_impl = _GetTerminalTabImpl(tab);
|
||||
if (tab_impl)
|
||||
{
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
Background="{ThemeResource TabViewBackground}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<!-- GH#13143: Make sure that the Background is actually TabViewBackground here, not Transparent. This is load bearing, for showTabsInTitlebar=false. -->
|
||||
|
||||
<mux:TabView x:Name="TabView"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
@@ -57,7 +60,8 @@
|
||||
FontSize="12">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip Placement="Mouse">
|
||||
<TextBlock IsTextSelectionEnabled="False">
|
||||
<TextBlock IsTextSelectionEnabled="False"
|
||||
TextWrapping="Wrap">
|
||||
<Run x:Uid="NewTabRun" /> <LineBreak />
|
||||
<Run x:Uid="NewPaneRun"
|
||||
FontStyle="Italic" /> <LineBreak />
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user