Compare commits
2 Commits
dev/migrie
...
dev/pabhoj
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22a7a5bc5f | ||
|
|
b3997a3dad |
3156
.github/fabricbot.json
vendored
@@ -26,10 +26,10 @@
|
||||
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
||||
"Microsoft.VisualStudio.Component.VC.Tools.ARM64",
|
||||
"Microsoft.VisualStudio.Component.VC.ASAN",
|
||||
"Microsoft.VisualStudio.Component.VC.v143.x86.x64",
|
||||
"Microsoft.VisualStudio.Component.VC.v143.ARM64",
|
||||
"Microsoft.VisualStudio.Component.VC.v142.x86.x64",
|
||||
"Microsoft.VisualStudio.Component.VC.v142.ARM64",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.VC",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.VC.v143",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.VC.v142",
|
||||
"Microsoft.VisualStudio.Component.UWP.VC.ARM64"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ When you hit "New Issue", select the type of issue closest to what you want to r
|
||||
Microsoft Windows [Version 10.0.18900.1001]
|
||||
```
|
||||
|
||||
* What tools and apps you're using (e.g. VS 2022, VSCode, etc.)
|
||||
* What tools and apps you're using (e.g. VS 2019, VSCode, etc.)
|
||||
* Don't assume we're experts in setting up YOUR environment and don't assume we are experts in `<your distro/tool of choice>`. Teach us to help you!
|
||||
* **We LOVE detailed repro steps!** What steps do we need to take to reproduce the issue? Assume we love to read repro steps. As much detail as you can stand is probably _barely_ enough detail for us!
|
||||
* If you're reporting a particular character/glyph not rendering correctly, the specific Unicode codepoint would be MOST welcome (e.g. U+1F4AF, U+4382)
|
||||
|
||||
33
NOTICE.md
@@ -276,39 +276,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## wyhash
|
||||
|
||||
**Source**: [https://github.com/wangyi-fudan/wyhash](https://github.com/wangyi-fudan/wyhash)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
```
|
||||
|
||||
## ConEmu
|
||||
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "CascadiaPackage", "src\casc
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.EXE", "src\host\exe\Host.EXE.vcxproj", "{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}
|
||||
{0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
|
||||
{5D23E8E1-3C64-4CC1-A8F7-6861677F7239} = {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}
|
||||
{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropertiesLibrary", "src\propslib\propslib.vcxproj", "{345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}"
|
||||
@@ -64,9 +64,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererGdi", "src\renderer
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host", "src\host\lib\hostlib.vcxproj", "{06EC74CB-9A12-429C-B551-8562EC954746}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
|
||||
{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}
|
||||
{0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.unittest", "src\host\ut_lib\host.unittest.vcxproj", "{06EC74CB-9A12-429C-B551-8562EC954747}"
|
||||
@@ -77,8 +77,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.unittest", "src\host\u
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.Tests.Unit", "src\host\ut_host\Host.UnitTests.vcxproj", "{531C23E7-4B76-4C08-8AAD-04164CB628C9}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{06EC74CB-9A12-429C-B551-8562EC954747} = {06EC74CB-9A12-429C-B551-8562EC954747}
|
||||
{0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714}
|
||||
{06EC74CB-9A12-429C-B551-8562EC954747} = {06EC74CB-9A12-429C-B551-8562EC954747}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TextBuffer.Unit.Tests", "src\buffer\out\ut_textbuffer\TextBuffer.Unit.Tests.vcxproj", "{531C23E7-4B76-4C08-8BBD-04164CB628C9}"
|
||||
@@ -89,9 +89,9 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.Tests.Feature", "src\host\ft_host\Host.FeatureTests.vcxproj", "{8CDB8850-7484-4EC7-B45B-181F85B2EE54}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
|
||||
{FC802440-AD6A-4919-8F2C-7701F2B38D79} = {FC802440-AD6A-4919-8F2C-7701F2B38D79}
|
||||
{58A03BB2-DF5A-4B66-91A0-7EF3BA01269A} = {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}
|
||||
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
|
||||
{FC802440-AD6A-4919-8F2C-7701F2B38D79} = {FC802440-AD6A-4919-8F2C-7701F2B38D79}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalParser.UnitTests", "src\terminal\parser\ut_parser\Parser.UnitTests.vcxproj", "{12144E07-FE63-4D33-9231-748B8D8C3792}"
|
||||
@@ -114,8 +114,8 @@ EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Host.Tests.UIA", "src\host\ft_uia\Host.Tests.UIA.csproj", "{C17E1BF3-9D34-4779-9458-A8EF98CC5662}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{099193A0-1E43-4BBC-BA7F-7B351E1342DF} = {099193A0-1E43-4BBC-BA7F-7B351E1342DF}
|
||||
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
|
||||
{C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB} = {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}
|
||||
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VTApp", "src\tools\vtapp\VTApp.csproj", "{099193A0-1E43-4BBC-BA7F-7B351E1342DF}"
|
||||
@@ -172,13 +172,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalCore", "src\cascadi
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control.Lib", "src\cascadia\TerminalControl\TerminalControlLib.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
|
||||
{CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
|
||||
{1CF55140-EF6A-4736-A403-957E4F7430BB} = {1CF55140-EF6A-4736-A403-957E4F7430BB}
|
||||
{48D21369-3D7B-4431-9967-24E81292CF62} = {48D21369-3D7B-4431-9967-24E81292CF62}
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63} = {48D21369-3D7B-4431-9967-24E81292CF63}
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {8222900C-8B6C-452A-91AC-BE95DB04B95F}
|
||||
{AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F} = {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}
|
||||
{CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
|
||||
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}"
|
||||
@@ -188,21 +187,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}
|
||||
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
|
||||
{CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070}
|
||||
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
|
||||
{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}
|
||||
{CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
|
||||
{CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070}
|
||||
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}
|
||||
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia\TerminalApp\dll\TerminalApp.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
|
||||
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
|
||||
{CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746}
|
||||
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
|
||||
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
|
||||
{CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070}
|
||||
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
|
||||
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminalShellExt", "src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj", "{F2ED628A-DB22-446F-A081-4CC845B51A2B}"
|
||||
@@ -252,15 +251,15 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\cascadia\TerminalApp\TerminalAppLib.vcxproj", "{CA5CAD1A-9A12-429C-B551-8562EC954746}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
|
||||
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
|
||||
{CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070}
|
||||
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_TerminalApp", "src\cascadia\LocalTests_TerminalApp\TerminalApp.LocalTests.vcxproj", "{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746}
|
||||
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
|
||||
{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}
|
||||
{CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746}
|
||||
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
@@ -274,9 +273,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winconpty.DLL", "src\wincon
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestHostApp", "src\cascadia\LocalTests_TerminalApp\TestHostApp\TestHostApp.vcxproj", "{A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506} = {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}
|
||||
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
|
||||
{CA5CAD1A-9B68-456A-B13E-C8218070DC42} = {CA5CAD1A-9B68-456A-B13E-C8218070DC42}
|
||||
{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506} = {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BDB237B6-1D1D-400F-84CC-40A58FA59C8E}"
|
||||
@@ -331,8 +330,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxp
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "src\cascadia\WpfTerminalTestNetCore\WpfTerminalTestNetCore.csproj", "{1588FD7C-241E-4E7D-9113-43735F3E6BAD}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{84848BFA-931D-42CE-9ADF-01EE54DE7890} = {84848BFA-931D-42CE-9ADF-01EE54DE7890}
|
||||
{A22EC5F6-7851-4B88-AC52-47249D437A52} = {A22EC5F6-7851-4B88-AC52-47249D437A52}
|
||||
{84848BFA-931D-42CE-9ADF-01EE54DE7890} = {84848BFA-931D-42CE-9ADF-01EE54DE7890}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wt", "src\cascadia\wt\wt.vcxproj", "{506FD703-BAA7-4F6E-9361-64F550EC8FCA}"
|
||||
@@ -357,9 +356,9 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_SettingsModel", "src\cascadia\LocalTests_SettingsModel\SettingsModel.LocalTests.vcxproj", "{CA5CAD1A-9B68-456A-B13E-C8218070DC42}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
|
||||
{CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070}
|
||||
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
|
||||
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
|
||||
{CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MonarchPeasantSample", "src\tools\MonarchPeasantSample\MonarchPeasantSample.vcxproj", "{21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}"
|
||||
@@ -378,8 +377,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Remoting
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Remoting", "src\cascadia\UnitTests_Remoting\Remoting.UnitTests.vcxproj", "{68A10CD3-AA64-465B-AF5F-ED4E9700543C}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}
|
||||
{43CE4CE5-0010-4B99-9569-672670D26E26} = {43CE4CE5-0010-4B99-9569-672670D26E26}
|
||||
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wpf", "wpf", "{4DAF0299-495E-4CD1-A982-9BAC16A45932}"
|
||||
@@ -401,6 +400,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Control", "src\ca
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests", "src\cascadia\WindowsTerminal_UIATests\WindowsTerminal.UIA.Tests.csproj", "{F19DACD5-0C6E-40DC-B6E4-767A3200542C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utils", "Utils", "{61901E80-E97D-4D61-A9BB-E8F2FDA8B40C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererAtlas", "src\renderer\atlas\atlas.vcxproj", "{8222900C-8B6C-452A-91AC-BE95DB04B95F}"
|
||||
@@ -3299,6 +3300,49 @@ Global
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.Build.0 = Release|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.Build.0 = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x64Test.Build.0 = Debug|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x86Test.Build.0 = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x64.Build.0 = Debug|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x64Test.Build.0 = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x86Test.Build.0 = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.ActiveCfg = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
@@ -3547,6 +3591,7 @@ Global
|
||||
{05D9052F-D78F-478F-968A-2DE38A6DB996} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
|
||||
{61901E80-E97D-4D61-A9BB-E8F2FDA8B40C} = {59840756-302F-44DF-AA47-441A9D673202}
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
|
||||
{06EC74CB-9A12-428C-B551-8537EC964726} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
|
||||
18
README.md
@@ -21,7 +21,7 @@ Related repositories include:
|
||||
|
||||
## Installing and running Windows Terminal
|
||||
|
||||
> **Note**: Windows Terminal requires Windows 10 2004 (build 19041) or later
|
||||
> 🔴 Note: Windows Terminal requires Windows 10 2004 (build 19041) or later
|
||||
|
||||
### Microsoft Store [Recommended]
|
||||
|
||||
@@ -52,10 +52,8 @@ fails for any reason, you can try the following command at a PowerShell prompt:
|
||||
Add-AppxPackage Microsoft.WindowsTerminal_<versionNumber>.msixbundle
|
||||
```
|
||||
|
||||
> **Note**: If you install Terminal manually:
|
||||
> 🔴 Note: If you install Terminal manually:
|
||||
>
|
||||
> * You may need to install the [VC++ v14 Desktop Framework Package](https://docs.microsoft.com/troubleshoot/cpp/c-runtime-packages-desktop-bridge#how-to-install-and-update-desktop-framework-packages).
|
||||
> This should only be necessary on older builds of Windows 10 and only if you get an error about missing framework packages.
|
||||
> * Terminal will not auto-update when new builds are released so you will need
|
||||
> to regularly install the latest Terminal release to receive all the latest
|
||||
> fixes and improvements!
|
||||
@@ -177,7 +175,7 @@ While overhauling Windows Console, we modernized its codebase considerably,
|
||||
cleanly separating logical entities into modules and classes, introduced some
|
||||
key extensibility points, replaced several old, home-grown collections and
|
||||
containers with safer, more efficient [STL
|
||||
containers](https://docs.microsoft.com/en-us/cpp/standard-library/stl-containers?view=vs-2022),
|
||||
containers](https://docs.microsoft.com/en-us/cpp/standard-library/stl-containers?view=vs-2019),
|
||||
and made the code simpler and safer by using Microsoft's [Windows Implementation
|
||||
Libraries - WIL](https://github.com/Microsoft/wil).
|
||||
|
||||
@@ -235,7 +233,7 @@ Cause: You're launching the incorrect solution in Visual Studio.
|
||||
Solution: Make sure you're building & deploying the `CascadiaPackage` project in
|
||||
Visual Studio.
|
||||
|
||||
> **Note**: `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic
|
||||
> ⚠ Note: `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic
|
||||
> Windows Console that hosts Windows' command-line infrastructure. OpenConsole
|
||||
> is used by Windows Terminal to connect to and communicate with command-line
|
||||
> applications (via
|
||||
@@ -266,7 +264,7 @@ help avoid any wasted or duplicate effort.
|
||||
The easiest way to communicate with the team is via GitHub issues.
|
||||
|
||||
Please file new issues, feature requests and suggestions, but **DO search for
|
||||
similar open/closed preexisting issues before creating a new issue.**
|
||||
similar open/closed pre-existing issues before creating a new issue.**
|
||||
|
||||
If you would like to ask a question that you feel doesn't warrant an issue
|
||||
(yet), please reach out to us via Twitter:
|
||||
@@ -293,14 +291,14 @@ If you would like to ask a question that you feel doesn't warrant an issue
|
||||
SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/)
|
||||
installed
|
||||
* You must have at least [VS
|
||||
2022](https://visualstudio.microsoft.com/downloads/) installed
|
||||
2019](https://visualstudio.microsoft.com/downloads/) installed
|
||||
* You must install the following Workloads via the VS Installer. Note: Opening
|
||||
the solution in VS 2022 will [prompt you to install missing components
|
||||
the solution in VS 2019 will [prompt you to install missing components
|
||||
automatically](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/):
|
||||
* Desktop Development with C++
|
||||
* Universal Windows Platform Development
|
||||
* **The following Individual Components**
|
||||
* C++ (v143) Universal Windows Platform Tools
|
||||
* C++ (v142) Universal Windows Platform Tools
|
||||
* You must install the [.NET Framework Targeting Pack](https://docs.microsoft.com/dotnet/framework/install/guide-for-developers#to-install-the-net-framework-developer-pack-or-targeting-pack) to build test projects
|
||||
|
||||
## Building the Code
|
||||
|
||||
@@ -55,9 +55,8 @@ Copy-Item "build\helix\runtests.cmd" $payloadDir
|
||||
Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir"
|
||||
Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
|
||||
|
||||
# Copy the APPX package from the 'drop' artifact dir and Windows Kits
|
||||
# Copy the APPX package from the 'drop' artifact dir
|
||||
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir\CascadiaPackage.zip
|
||||
Copy-Item "C:\program files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\Microsoft.VCLibs.Desktop\14.0\Appx\Retail\x64\Microsoft.VCLibs.x64.14.00.Desktop.appx" $payloadDir\VCLibs.zip
|
||||
|
||||
# Rename it to extension of ZIP because Expand-Archive is real sassy on the build machines
|
||||
# and refuses to unzip it because of its file extension while on a desktop, it just
|
||||
@@ -65,4 +64,3 @@ Copy-Item "C:\program files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\M
|
||||
|
||||
# Extract the APPX package
|
||||
Expand-Archive -LiteralPath $payloadDir\CascadiaPackage.zip -DestinationPath $payloadDir\appx
|
||||
Expand-Archive -LiteralPath $payloadDir\VCLibs.zip -DestinationPath $payloadDir\appx -Force
|
||||
|
||||
@@ -4,7 +4,5 @@
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
|
||||
<!-- This cannot be included in another project that depends on XAML (as it would be a duplicate package ID) -->
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
|
||||
<package id="Microsoft.Debugging.Tools.PdbStr" version="20220617.1556.0" targetFramework="native" />
|
||||
<package id="Microsoft.Debugging.Tools.SrcTool" version="20220617.1556.0" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.0" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Microsoft.Internal.Windows.Terminal.PGODatabase</id>
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
trigger: none
|
||||
pr: none
|
||||
schedules:
|
||||
- cron: "0 3 * * 2-6" # Run at 03:00 UTC Tuesday through Saturday (After the work day in Pacific, Mon-Fri)
|
||||
displayName: "Nightly Localization Build"
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
always: false # only run if there's code changes!
|
||||
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
resources:
|
||||
repositories:
|
||||
- repository: self
|
||||
type: git
|
||||
ref: main
|
||||
- repository: internal
|
||||
type: git
|
||||
name: Terminal.Internal
|
||||
ref: main
|
||||
|
||||
steps:
|
||||
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: false
|
||||
fetchDepth: 1 # Don't need a deep checkout for loc files!
|
||||
persistCredentials: true
|
||||
path: s # Adding a second repo made Azure DevOps change where we're checked out.
|
||||
|
||||
- checkout: internal
|
||||
clean: true
|
||||
submodules: false
|
||||
fetchDepth: 1
|
||||
persistCredentials: true
|
||||
path: s/Terminal.Internal
|
||||
|
||||
- task: MicrosoftTDBuild.tdbuild-task.tdbuild-task.TouchdownBuildTask@1
|
||||
displayName: 'Touchdown Build - 7105, PRODEXT'
|
||||
inputs:
|
||||
teamId: 7105
|
||||
authId: '$(TouchdownApplicationID)'
|
||||
authKey: '$(TouchdownApplicationKey)'
|
||||
resourceFilePath: |
|
||||
**\en-US\*.resw
|
||||
Terminal.Internal\PDPs\Stable\PDPs\en-us\PDP.xml
|
||||
Terminal.Internal\PDPs\Preview\PDPs\en-us\PDP.xml
|
||||
outputDirectoryRoot: LocOutput
|
||||
appendRelativeDir: true
|
||||
pseudoSetting: Included
|
||||
|
||||
# Saving one of these makes it really easy to inspect the loc output...
|
||||
- powershell: 'tar czf LocOutput.tar.gz LocOutput'
|
||||
displayName: 'Archive Loc Output for Submission'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: LocOutput'
|
||||
inputs:
|
||||
PathtoPublish: LocOutput.tar.gz
|
||||
ArtifactName: LocOutput
|
||||
@@ -2,9 +2,9 @@
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
pool:
|
||||
pool:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
parameters:
|
||||
- name: branding
|
||||
@@ -134,6 +134,8 @@ jobs:
|
||||
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
- template: .\templates\restore-nuget-steps.yml
|
||||
# Pull the Windows SDK for the developer tools like the debuggers so we can index sources later
|
||||
- template: .\templates\install-winsdk-steps.yml
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
@@ -193,6 +195,7 @@ 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)
|
||||
@@ -219,6 +222,7 @@ 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)
|
||||
@@ -227,6 +231,7 @@ 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)
|
||||
@@ -236,7 +241,6 @@ jobs:
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
|
||||
errorActionPreference: silentlyContinue
|
||||
pwsh: true
|
||||
- task: PowerShell@2
|
||||
displayName: Run Unit Tests
|
||||
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
@@ -299,6 +303,8 @@ jobs:
|
||||
inputs:
|
||||
Contents: >-
|
||||
**/PublicTerminalCore.dll
|
||||
|
||||
**/api-ms-win-core-synch-l1-2-0.dll
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/wpf
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
@@ -321,7 +327,7 @@ jobs:
|
||||
|
||||
- ${{ if eq(parameters.runCompliance, true) }}:
|
||||
- template: ./templates/build-console-compliance-job.yml
|
||||
|
||||
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- job: BundleAndSign
|
||||
strategy:
|
||||
@@ -330,13 +336,6 @@ jobs:
|
||||
${{ windowsVersion }}:
|
||||
TerminalTargetWindowsVersion: ${{ windowsVersion }}
|
||||
displayName: Create and sign AppX/MSIX bundles
|
||||
variables:
|
||||
${{ if eq(parameters.branding, 'Release') }}:
|
||||
BundleStemName: Microsoft.WindowsTerminal
|
||||
${{ elseif eq(parameters.branding, 'Preview') }}:
|
||||
BundleStemName: Microsoft.WindowsTerminalPreview
|
||||
${{ else }}:
|
||||
BundleStemName: WindowsTerminalDev
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -361,15 +360,14 @@ jobs:
|
||||
$Components = "$(XES_APPXMANIFESTVERSION)" -Split "\."
|
||||
$Components[0] = ([int]$Components[0] + $VersionEpoch)
|
||||
$BundleVersion = $Components -Join "."
|
||||
New-Item -Type Directory "$(System.ArtifactsDirectory)\bundle"
|
||||
.\build\scripts\Create-AppxBundle.ps1 -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(TerminalTargetWindowsVersion)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
.\build\scripts\Create-AppxBundle.ps1 -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminal_$(TerminalTargetWindowsVersion)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
displayName: Create WindowsTerminal*.msixbundle
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.msixbundle to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(System.ArtifactsDirectory)\bundle
|
||||
Pattern: $(BundleStemName)*.msixbundle
|
||||
FolderPath: $(System.ArtifactsDirectory)
|
||||
Pattern: Microsoft.WindowsTerminal*.msixbundle
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
@@ -402,7 +400,7 @@ jobs:
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: appxbundle-signed'
|
||||
inputs:
|
||||
PathtoPublish: $(System.ArtifactsDirectory)\bundle
|
||||
PathtoPublish: $(System.ArtifactsDirectory)
|
||||
ArtifactName: appxbundle-signed-$(TerminalTargetWindowsVersion)
|
||||
|
||||
- ${{ if eq(parameters.buildConPTY, true) }}:
|
||||
@@ -548,6 +546,7 @@ 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)
|
||||
@@ -613,8 +612,6 @@ jobs:
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
|
||||
- template: .\templates\restore-nuget-steps.yml
|
||||
|
||||
# Download the appx-PLATFORM-CONFIG-VERSION artifact for every platform/version combo
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- ${{ each windowsVersion in parameters.buildWindowsVersions }}:
|
||||
@@ -637,12 +634,13 @@ jobs:
|
||||
}
|
||||
displayName: Extract symbols for public consumption
|
||||
|
||||
# Pull the Windows SDK for the developer tools like the debuggers so we can index sources later
|
||||
- template: .\templates\install-winsdk-steps.yml
|
||||
- task: PowerShell@2
|
||||
displayName: Source Index PDBs (the public ones)
|
||||
inputs:
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
arguments: -SearchDir '$(Build.SourcesDirectory)/appxsym-temp' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
|
||||
pwsh: true
|
||||
|
||||
# Publish the app symbols to the public MSDL symbol server
|
||||
# accessible via https://msdl.microsoft.com/download/symbols
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS17-latest
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -27,6 +27,7 @@ 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 WinDevVS17-latest
|
||||
demands: ImageOverride -equals WinDevVS16-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}"
|
||||
- template: restore-nuget-steps.yml
|
||||
- steps: restore-nuget-steps.yml
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
# 1ES Component Governance onboarding (Detects open source components). See https://docs.opensource.microsoft.com/tools/cg.html
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: Component Detection
|
||||
|
||||
|
||||
# # PREfast and PoliCheck need Node. Install that first.
|
||||
- task: NodeTool@0
|
||||
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
# step instead that builds the code normally before calling them.
|
||||
# Also... PREfast will rebuild anyway so that's why we're not running a normal build first.
|
||||
# Waste of time to build twice.
|
||||
# PREfast. See https://www.1eswiki.com/wiki/SDL_Native_Rules_Build_Task
|
||||
# PREfast. See https://www.1eswiki.com/wiki/SDL_Native_Rules_Build_Task
|
||||
|
||||
# The following 1ES tasks all operate completely differently and have a different syntax for usage.
|
||||
# Most notable is every one of them has a different way of excluding things.
|
||||
@@ -98,9 +98,7 @@ jobs:
|
||||
displayName: 'Run the PREfast SDL Native Rules for MSBuild'
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
setupCommandlines: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsMSBuildCmd.bat"'
|
||||
msBuildCommandline: msbuild.exe /nologo /m /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /p:WindowsTerminalReleaseBuild=true /p:platform=$(BuildPlatform) /p:configuration=$(BuildConfiguration) /t:Terminal\Window\WindowsTerminal /p:VisualStudioVersion=17.0 $(Build.SourcesDirectory)\OpenConsole.sln
|
||||
msBuildVersion: "17.0"
|
||||
msBuildCommandline: msbuild.exe /nologo /m /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /p:WindowsTerminalReleaseBuild=true /p:platform=$(BuildPlatform) /p:configuration=$(BuildConfiguration) /t:Terminal\Window\WindowsTerminal /p:VisualStudioVersion=16.0 $(Build.SourcesDirectory)\OpenConsole.sln
|
||||
|
||||
# Copies output from PREfast SDL Native Rules task to expected location for consumption by PkgESSecComp
|
||||
- task: CopyFiles@1
|
||||
@@ -148,7 +146,7 @@ jobs:
|
||||
continueOnError: true
|
||||
|
||||
# Set XES_SERIALPOSTBUILDREADY to run Security and Compliance task once per build
|
||||
- powershell: Write-Host "##vso[task.setvariable variable=XES_SERIALPOSTBUILDREADY;]true"
|
||||
- powershell: Write-Host “##vso[task.setvariable variable=XES_SERIALPOSTBUILDREADY;]true”
|
||||
displayName: 'Set XES_SERIALPOSTBUILDREADY Vars'
|
||||
|
||||
# https://www.osgwiki.com/wiki/Package_ES_Security_and_Compliance
|
||||
@@ -158,12 +156,12 @@ jobs:
|
||||
# (PREfast, PoliCheck, Credscan)
|
||||
# - Runs Windows-specific compliance tasks inside the task
|
||||
# + CheckCFlags - ensures that compiler and linker flags meet Windows standards
|
||||
# + CFGCheck/XFGCheck - ensures that Control Flow Guard (CFG) or
|
||||
# + CFGCheck/XFGCheck - ensures that Control Flow Guard (CFG) or
|
||||
# eXtended Flow Guard (XFG) are enabled on binaries
|
||||
# NOTE: CFG is deprecated and XFG isn't fully ready yet.
|
||||
# NOTE2: CFG fails on an XFG'd binary
|
||||
# - Brokers all security/compliance task logs to "Trust Services Automation (TSA)" (https://aka.ms/tsa)
|
||||
# which is a system that maps all errors into the appropriate bug database
|
||||
# which is a system that maps all errors into the appropriate bug database
|
||||
# template for each organization since they all vary. It should also suppress
|
||||
# new bugs when one already exists for the product.
|
||||
# This one is set up to go to the OS repository and use the given parameters
|
||||
@@ -200,4 +198,4 @@ jobs:
|
||||
- toolName: CredScan
|
||||
enable: false
|
||||
- toolName: XFGCheck
|
||||
enable: false
|
||||
enable: false
|
||||
@@ -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 WinDevVS17-latest
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -32,11 +32,12 @@ 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 }}"
|
||||
@@ -87,4 +88,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 WinDevVS17-latest
|
||||
demands: ImageOverride -equals WinDevVS16-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,6 +28,7 @@ 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"
|
||||
|
||||
9
build/pipelines/templates/install-winsdk-steps.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
parameters:
|
||||
sdkVersion: 18362
|
||||
steps:
|
||||
- task: powershell@2
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Install-WindowsSdkISO.ps1
|
||||
arguments: ${{ parameters.sdkVersion }}
|
||||
displayName: 'Install Windows SDK (${{ parameters.sdkVersion }})'
|
||||
@@ -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 WinDevVS17-latest
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<_WTBrandingPreprocessorToken Condition="'$(WindowsTerminalBranding)'=='Preview'">WT_BRANDING_PREVIEW</_WTBrandingPreprocessorToken>
|
||||
<_WTBrandingPreprocessorToken Condition="'$(WindowsTerminalBranding)'=='Release'">WT_BRANDING_RELEASE</_WTBrandingPreprocessorToken>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- THIS PROJECT CANNOT BE LOADED INTO THE SOLUTION. -->
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<BeforeLinkTargets Condition="'$(WindowsTargetPlatformVersion)' >= '10.0.18362.0'">
|
||||
$(BeforeLinkTargets);
|
||||
|
||||
@@ -8,11 +8,10 @@ Param(
|
||||
[switch]$recursive
|
||||
)
|
||||
|
||||
$pdbStrPackage = ([xml](Get-Content "$SourceRoot\build\packages.config")).packages.package | Where-Object id -like "*PdbStr*"
|
||||
# This assumes that we rev PdbStr and SrcTool at the same time.
|
||||
$debugPackageVersions = $pdbStrPackage.version
|
||||
$srctoolExe = Join-Path $SourceRoot "packages" "Microsoft.Debugging.Tools.SrcTool.$debugPackageVersions" "content" "amd64" "srctool.exe"
|
||||
$pdbstrExe = Join-Path $SourceRoot "packages" "Microsoft.Debugging.Tools.PdbStr.$debugPackageVersions" "content" "amd64" "pdbstr.exe"
|
||||
$debuggerPath = (Get-ItemProperty -path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots" -name WindowsDebuggersRoot10).WindowsDebuggersRoot10
|
||||
$srcsrvPath = Join-Path $debuggerPath "x64\srcsrv"
|
||||
$srctoolExe = Join-Path $srcsrvPath "srctool.exe"
|
||||
$pdbstrExe = Join-Path $srcsrvPath "pdbstr.exe"
|
||||
|
||||
$fileTable = @{}
|
||||
foreach ($gitFile in & git ls-files)
|
||||
|
||||
346
build/scripts/Install-WindowsSdkISO.ps1
Normal file
@@ -0,0 +1,346 @@
|
||||
[CmdletBinding()]
|
||||
param([Parameter(Mandatory=$true, Position=0)]
|
||||
[string]$buildNumber)
|
||||
|
||||
# Ensure the error action preference is set to the default for PowerShell3, 'Stop'
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# Constants
|
||||
$WindowsSDKOptions = @("OptionId.UWPCpp", "OptionId.DesktopCPPx64", "OptionId.DesktopCPPx86", "OptionId.DesktopCPPARM64", "OptionId.DesktopCPPARM", "OptionId.WindowsDesktopDebuggers")
|
||||
$WindowsSDKRegPath = "HKLM:\Software\WOW6432Node\Microsoft\Windows Kits\Installed Roots"
|
||||
$WindowsSDKRegRootKey = "KitsRoot10"
|
||||
$WindowsSDKVersion = "10.0.$buildNumber.0"
|
||||
$WindowsSDKInstalledRegPath = "$WindowsSDKRegPath\$WindowsSDKVersion\Installed Options"
|
||||
$StrongNameRegPath = "HKLM:\SOFTWARE\Microsoft\StrongName\Verification"
|
||||
$PublicKeyTokens = @("31bf3856ad364e35")
|
||||
|
||||
if ($buildNumber -notmatch "^\d{5,}$")
|
||||
{
|
||||
Write-Host "ERROR: '$buildNumber' doesn't look like a windows build number"
|
||||
Write-Host
|
||||
Exit 1
|
||||
}
|
||||
|
||||
function Download-File
|
||||
{
|
||||
param ([string] $outDir,
|
||||
[string] $downloadUrl,
|
||||
[string] $downloadName)
|
||||
|
||||
$downloadPath = Join-Path $outDir "$downloadName.download"
|
||||
$downloadDest = Join-Path $outDir $downloadName
|
||||
$downloadDestTemp = Join-Path $outDir "$downloadName.tmp"
|
||||
|
||||
Write-Host -NoNewline "Downloading $downloadName..."
|
||||
|
||||
$retries = 10
|
||||
$downloaded = $false
|
||||
while (-not $downloaded)
|
||||
{
|
||||
try
|
||||
{
|
||||
$webclient = new-object System.Net.WebClient
|
||||
$webclient.DownloadFile($downloadUrl, $downloadPath)
|
||||
$downloaded = $true
|
||||
}
|
||||
catch [System.Net.WebException]
|
||||
{
|
||||
Write-Host
|
||||
Write-Warning "Failed to fetch updated file from $downloadUrl : $($error[0])"
|
||||
if (!(Test-Path $downloadDest))
|
||||
{
|
||||
if ($retries -gt 0)
|
||||
{
|
||||
Write-Host "$retries retries left, trying download again"
|
||||
$retries--
|
||||
start-sleep -Seconds 10
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "$downloadName was not found at $downloadDest"
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Warning "$downloadName may be out of date"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unblock-File $downloadPath
|
||||
|
||||
$downloadDestTemp = $downloadPath;
|
||||
|
||||
# Delete and rename to final dest
|
||||
Write-Host "testing $downloadDest"
|
||||
if (Test-Path $downloadDest)
|
||||
{
|
||||
Write-Host "Deleting: $downloadDest"
|
||||
Remove-Item $downloadDest -Force
|
||||
}
|
||||
|
||||
Move-Item -Force $downloadDestTemp $downloadDest
|
||||
Write-Host "Done"
|
||||
|
||||
return $downloadDest
|
||||
}
|
||||
|
||||
function Get-ISODriveLetter
|
||||
{
|
||||
param ([string] $isoPath)
|
||||
|
||||
$diskImage = Get-DiskImage -ImagePath $isoPath
|
||||
if ($diskImage)
|
||||
{
|
||||
$volume = Get-Volume -DiskImage $diskImage
|
||||
|
||||
if ($volume)
|
||||
{
|
||||
$driveLetter = $volume.DriveLetter
|
||||
if ($driveLetter)
|
||||
{
|
||||
$driveLetter += ":"
|
||||
return $driveLetter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Mount-ISO
|
||||
{
|
||||
param ([string] $isoPath)
|
||||
|
||||
# Check if image is already mounted
|
||||
$isoDrive = Get-ISODriveLetter $isoPath
|
||||
|
||||
if (!$isoDrive)
|
||||
{
|
||||
Mount-DiskImage -ImagePath $isoPath -StorageType ISO | Out-Null
|
||||
}
|
||||
|
||||
$isoDrive = Get-ISODriveLetter $isoPath
|
||||
Write-Verbose "$isoPath mounted to ${isoDrive}:"
|
||||
}
|
||||
|
||||
function Dismount-ISO
|
||||
{
|
||||
param ([string] $isoPath)
|
||||
|
||||
$isoDrive = (Get-DiskImage -ImagePath $isoPath | Get-Volume).DriveLetter
|
||||
|
||||
if ($isoDrive)
|
||||
{
|
||||
Write-Verbose "$isoPath dismounted"
|
||||
Dismount-DiskImage -ImagePath $isoPath | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
function Disable-StrongName
|
||||
{
|
||||
param ([string] $publicKeyToken = "*")
|
||||
|
||||
reg ADD "HKLM\SOFTWARE\Microsoft\StrongName\Verification\*,$publicKeyToken" /f | Out-Null
|
||||
if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64")
|
||||
{
|
||||
reg ADD "HKLM\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\*,$publicKeyToken" /f | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
function Test-Admin
|
||||
{
|
||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal $identity
|
||||
$principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
|
||||
function Test-RegistryPathAndValue
|
||||
{
|
||||
param (
|
||||
[parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $path,
|
||||
[parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $value)
|
||||
|
||||
try
|
||||
{
|
||||
if (Test-Path $path)
|
||||
{
|
||||
Get-ItemProperty -Path $path | Select-Object -ExpandProperty $value -ErrorAction Stop | Out-Null
|
||||
return $true
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
|
||||
function Test-InstallWindowsSDK
|
||||
{
|
||||
$retval = $true
|
||||
|
||||
if (Test-RegistryPathAndValue -Path $WindowsSDKRegPath -Value $WindowsSDKRegRootKey)
|
||||
{
|
||||
# A Windows SDK is installed
|
||||
# Is an SDK of our version installed with the options we need?
|
||||
$allRequiredSdkOptionsInstalled = $true
|
||||
foreach($sdkOption in $WindowsSDKOptions)
|
||||
{
|
||||
if (!(Test-RegistryPathAndValue -Path $WindowsSDKInstalledRegPath -Value $sdkOption))
|
||||
{
|
||||
$allRequiredSdkOptionsInstalled = $false
|
||||
}
|
||||
}
|
||||
|
||||
if($allRequiredSdkOptionsInstalled)
|
||||
{
|
||||
# It appears we have what we need. Double check the disk
|
||||
$sdkRoot = Get-ItemProperty -Path $WindowsSDKRegPath | Select-Object -ExpandProperty $WindowsSDKRegRootKey
|
||||
if ($sdkRoot)
|
||||
{
|
||||
if (Test-Path $sdkRoot)
|
||||
{
|
||||
$refPath = Join-Path $sdkRoot "References\$WindowsSDKVersion"
|
||||
if (Test-Path $refPath)
|
||||
{
|
||||
$umdPath = Join-Path $sdkRoot "UnionMetadata\$WindowsSDKVersion"
|
||||
if (Test-Path $umdPath)
|
||||
{
|
||||
# Pretty sure we have what we need
|
||||
$retval = $false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $retval
|
||||
}
|
||||
|
||||
function Test-InstallStrongNameHijack
|
||||
{
|
||||
foreach($publicKeyToken in $PublicKeyTokens)
|
||||
{
|
||||
$key = "$StrongNameRegPath\*,$publicKeyToken"
|
||||
if (!(Test-Path $key))
|
||||
{
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
|
||||
Write-Host -NoNewline "Checking for installed Windows SDK $WindowsSDKVersion..."
|
||||
$InstallWindowsSDK = Test-InstallWindowsSDK
|
||||
if ($InstallWindowsSDK)
|
||||
{
|
||||
Write-Host "Installation required"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "INSTALLED"
|
||||
}
|
||||
|
||||
$StrongNameHijack = Test-InstallStrongNameHijack
|
||||
Write-Host -NoNewline "Checking if StrongName bypass required..."
|
||||
|
||||
if ($StrongNameHijack)
|
||||
{
|
||||
Write-Host "REQUIRED"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Done"
|
||||
}
|
||||
|
||||
if ($StrongNameHijack -or $InstallWindowsSDK)
|
||||
{
|
||||
if (!(Test-Admin))
|
||||
{
|
||||
Write-Host
|
||||
throw "ERROR: Elevation required"
|
||||
}
|
||||
}
|
||||
|
||||
if ($InstallWindowsSDK)
|
||||
{
|
||||
# Static(ish) link for Windows SDK
|
||||
# Note: there is a delay from Windows SDK announcements to availability via the static link
|
||||
$uri = "https://software-download.microsoft.com/download/sg/Windows_InsiderPreview_SDK_en-us_$($buildNumber)_1.iso";
|
||||
|
||||
if ($env:TEMP -eq $null)
|
||||
{
|
||||
$env:TEMP = Join-Path $env:SystemDrive 'temp'
|
||||
}
|
||||
|
||||
$winsdkTempDir = Join-Path (Join-Path $env:TEMP ([System.IO.Path]::GetRandomFileName())) "WindowsSDK"
|
||||
|
||||
if (![System.IO.Directory]::Exists($winsdkTempDir))
|
||||
{
|
||||
[void][System.IO.Directory]::CreateDirectory($winsdkTempDir)
|
||||
}
|
||||
|
||||
$file = "winsdk_$buildNumber.iso"
|
||||
|
||||
Write-Verbose "Getting WinSDK from $uri"
|
||||
$downloadFile = Download-File $winsdkTempDir $uri $file
|
||||
Write-Verbose "File is at $downloadFile"
|
||||
$downloadFileItem = Get-Item $downloadFile
|
||||
|
||||
# Check to make sure the file is at least 10 MB.
|
||||
if ($downloadFileItem.Length -lt 10*1024*1024)
|
||||
{
|
||||
Write-Host
|
||||
Write-Host "ERROR: Downloaded file doesn't look large enough to be an ISO. The requested version may not be on microsoft.com yet."
|
||||
Write-Host
|
||||
Exit 1
|
||||
}
|
||||
|
||||
# TODO Check if zip, exe, iso, etc.
|
||||
try
|
||||
{
|
||||
Write-Host -NoNewline "Mounting ISO $file..."
|
||||
Mount-ISO $downloadFile
|
||||
Write-Host "Done"
|
||||
|
||||
$isoDrive = Get-ISODriveLetter $downloadFile
|
||||
|
||||
if (Test-Path $isoDrive)
|
||||
{
|
||||
Write-Host -NoNewLine "Installing WinSDK..."
|
||||
|
||||
$setupPath = Join-Path "$isoDrive" "WinSDKSetup.exe"
|
||||
Start-Process -Wait $setupPath "/features $WindowsSDKOptions /q"
|
||||
Write-Host "Done"
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Could not find mounted ISO at ${isoDrive}"
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Write-Host -NoNewline "Dismounting ISO $file..."
|
||||
Dismount-ISO $downloadFile
|
||||
Write-Host "Done"
|
||||
}
|
||||
}
|
||||
|
||||
if ($StrongNameHijack)
|
||||
{
|
||||
Write-Host -NoNewline "Disabling StrongName for Windows SDK..."
|
||||
|
||||
foreach($key in $PublicKeyTokens)
|
||||
{
|
||||
Disable-StrongName $key
|
||||
}
|
||||
|
||||
Write-Host "Done"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!--
|
||||
This props file is a workaround for the fact that for wapproj projects,
|
||||
@@ -18,14 +18,14 @@
|
||||
|
||||
This version should be tracked in all project packages.config files for projects that depend on Xaml.
|
||||
-->
|
||||
<TerminalMUXVersion>2.7.3-prerelease.220816001</TerminalMUXVersion>
|
||||
<TerminalMUXVersion>2.7.2-prerelease.220406002</TerminalMUXVersion>
|
||||
<!--
|
||||
For the Windows 11-specific build, we're targeting the public version of Microsoft.UI.Xaml.
|
||||
This version emits a package dependency instead of embedding the dependency in our own package.
|
||||
|
||||
This version should be tracked in build/packages.config.
|
||||
-->
|
||||
<TerminalMUXVersion Condition="'$(TerminalTargetWindowsVersion)'=='Win11'">2.7.3</TerminalMUXVersion>
|
||||
<TerminalMUXVersion Condition="'$(TerminalTargetWindowsVersion)'=='Win11'">2.7.1</TerminalMUXVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"/doc/user-docs/",
|
||||
"/src/tools/MonarchPeasantSample/",
|
||||
"/src/tools/MonarchPeasantPackage/",
|
||||
"/src/api-ms-win-core-synch-l1-2-0/",
|
||||
"/src/tools/ansi-color/",
|
||||
"/src/tools/ColorTool/",
|
||||
"/scratch/",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- This file is read by XES, which we use in our Release builds. -->
|
||||
<PropertyGroup Label="Version">
|
||||
<!--
|
||||
@@ -17,7 +17,7 @@
|
||||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2022</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>16</VersionMinor>
|
||||
<VersionMinor>15</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/CLIUtils/CLI11",
|
||||
"commitHash": "dd0d8e4fe729e5b1110232c7a5c9566dad884686"
|
||||
}
|
||||
}
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/CLIUtils/CLI11",
|
||||
"commitHash": "dd0d8e4fe729e5b1110232c7a5c9566dad884686"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/open-source-parsers/jsoncpp",
|
||||
"commitHash": "6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2"
|
||||
}
|
||||
}
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/open-source-parsers/jsoncpp",
|
||||
"commitHash": "6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.6.220404001" targetFramework="native" />
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Native" version="2.3.2262" targetFramework="native" developmentDependency="true" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3-prerelease.220816001" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.2-prerelease.220406002" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" developmentDependency="true" />
|
||||
|
||||
<!-- 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="13.0.1" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="12.0.3" 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
|
||||
```
|
||||
|
||||
@@ -139,18 +139,3 @@ powershell -Command Set-Location -Path %OPENCON%\src\cascadia\CascadiaPackage\Ap
|
||||
(yes, the cmd version is just calling powershell to do the powershell version. Too lazy to convert the rest by hand, I'm already copying from `.vscode\tasks.json`)
|
||||
|
||||
Building the package from VS generates the loose layout to begin with, and then registers the loose manifest, skipping the msix stop. It's a lot faster than the commandline inner loop here, unfortunately.
|
||||
|
||||
### 2022 Update
|
||||
|
||||
The following command can be used to build the terminal package, and then deploy it.
|
||||
|
||||
```cmd
|
||||
pushd %OPENCON%\src\cascadia\CascadiaPackage
|
||||
bx
|
||||
"C:\Program Files\Microsoft Visual Studio\2022\Preview\Common7\IDE\DeployAppRecipe.exe" bin\%ARCH%\%_LAST_BUILD_CONF%\CascadiaPackage.build.appxrecipe
|
||||
popd
|
||||
```
|
||||
|
||||
The `bx` will build just the Terminal package, critically, populating the `CascadiaPackage.build.appxrecipe` file. Once that's been built, then the `DeployAppRecipe.exe` command can be used to deploy a loose layout in the same way that Visual Studio does.
|
||||
|
||||
Notably, this method of building the Terminal package can't leverage the FastUpToDate check in Visual Studio, so the builds end up being considerably slower for the whole package, as cppwinrt does a lot of work before confirming that it's up to date and doing nothing.
|
||||
|
||||
@@ -14,12 +14,6 @@
|
||||
"type": "string",
|
||||
"format": "color"
|
||||
},
|
||||
"ColorOrIndex": {
|
||||
"default": "#",
|
||||
"pattern": "^(?:#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?|i[A-Fa-f0-9]{2})$",
|
||||
"type": "string",
|
||||
"format": "color"
|
||||
},
|
||||
"Coordinates": {
|
||||
"pattern": "^(-?\\d+)?(,\\s?(-?\\d+)?)?$",
|
||||
"type": "string"
|
||||
@@ -64,20 +58,20 @@
|
||||
"default": "",
|
||||
"description": "Sets the file location of the sound played when the application emits a BEL character. If the path is invalid no sound will be played. This property also accepts an array of sounds and the terminal will pick one at random.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
{
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
"AppearanceConfig": {
|
||||
"properties": {
|
||||
"colorScheme": {
|
||||
@@ -213,14 +207,8 @@
|
||||
"type": "string"
|
||||
},
|
||||
"adjustIndistinguishableColors": {
|
||||
"default": "never",
|
||||
"description": "Setting to adjust the foreground color to make it more visible, based on the background color. When set to \"indexed\", we will only adjust the colors if they came from the color scheme. Other possible values are \"never\" and \"always\".",
|
||||
"enum": [
|
||||
"never",
|
||||
"indexed",
|
||||
"always"
|
||||
],
|
||||
"type": "string"
|
||||
"description": "When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.retroTerminalEffect": {
|
||||
"description": "When set to true, enable retro terminal effects when unfocused. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
@@ -312,7 +300,6 @@
|
||||
"enum": [
|
||||
"adjustFontSize",
|
||||
"clearBuffer",
|
||||
"closeOtherPanes",
|
||||
"closeOtherTabs",
|
||||
"closePane",
|
||||
"closeTab",
|
||||
@@ -321,7 +308,6 @@
|
||||
"commandPalette",
|
||||
"copy",
|
||||
"duplicateTab",
|
||||
"expandSelectionToWord",
|
||||
"exportBuffer",
|
||||
"find",
|
||||
"findMatch",
|
||||
@@ -364,11 +350,9 @@
|
||||
"switchToTab",
|
||||
"tabSearch",
|
||||
"toggleAlwaysOnTop",
|
||||
"toggleBlockSelection",
|
||||
"toggleFocusMode",
|
||||
"selectAll",
|
||||
"setFocusMode",
|
||||
"switchSelectionEndpoint",
|
||||
"toggleFullscreen",
|
||||
"setFullScreen",
|
||||
"setMaximized",
|
||||
@@ -380,11 +364,6 @@
|
||||
"quit",
|
||||
"adjustOpacity",
|
||||
"restoreLastClosed",
|
||||
"addMark",
|
||||
"scrollToMark",
|
||||
"clearMark",
|
||||
"clearAllMarks",
|
||||
"experimental.colorSelection",
|
||||
"unbound"
|
||||
],
|
||||
"type": "string"
|
||||
@@ -404,15 +383,6 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ScrollToMarkDirection": {
|
||||
"enum": [
|
||||
"previous",
|
||||
"next",
|
||||
"first",
|
||||
"last"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ResizeDirection": {
|
||||
"enum": [
|
||||
"left",
|
||||
@@ -762,30 +732,6 @@
|
||||
"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": [
|
||||
@@ -845,43 +791,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ColorSelectionAction": {
|
||||
"description": "Arguments corresponding to a Color Selection Action",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/ShortcutAction"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"const": "experimental.colorSelection"
|
||||
},
|
||||
"matchMode": {
|
||||
"type": "string",
|
||||
"default": "none",
|
||||
"description": "Specifies if only the selected text should be colored (0), or all instances of selected text (case-insensitive) (1).",
|
||||
"enum": [
|
||||
"none",
|
||||
"all"
|
||||
]
|
||||
},
|
||||
"foreground": {
|
||||
"$ref": "#/$defs/ColorOrIndex",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The foreground color to use, as an RGB value (\"#rrggbb\"), or color index (\"iNN\"). If left unspecified it falls back to the default text foreground color."
|
||||
},
|
||||
"background": {
|
||||
"$ref": "#/$defs/ColorOrIndex",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The background color to use, as an RGB value (\"#rrggbb\"), or color index (\"iNN\"). If left unspecified it falls back to the default text background color."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"OpenSettingsAction": {
|
||||
"description": "Arguments corresponding to a Open Settings Action",
|
||||
"allOf": [
|
||||
@@ -930,27 +839,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"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": [
|
||||
@@ -1657,9 +1545,6 @@
|
||||
{
|
||||
"$ref": "#/$defs/AdjustOpacityAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/ColorSelectionAction"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
@@ -1782,11 +1667,6 @@
|
||||
"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.enableColorSelection": {
|
||||
"default": false,
|
||||
"description": "When set to true, adds preset \"Color Selection\" actions (keybindings) to allow colorizing selected text via keystroke, similar to the legacy conhost EnableColorSelection feature (such as alt+6 to color the selection red).",
|
||||
"type": "boolean"
|
||||
},
|
||||
"disableAnimations": {
|
||||
"default": false,
|
||||
"description": "When set to `true`, visual animations will be disabled across the application.",
|
||||
@@ -2018,20 +1898,6 @@
|
||||
"useAnyExisting"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"newTabPosition": {
|
||||
"default": "afterLastTab",
|
||||
"description": "Position of newly created tabs. Possible values are \"afterLastTab\" and \"afterCurrentTab\".",
|
||||
"enum": [
|
||||
"afterLastTab",
|
||||
"afterCurrentTab"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"autoHideWindow": {
|
||||
"default": false,
|
||||
"description": "If enabled, Terminal window will be hidden as soon as it loses focus.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2145,20 +2011,15 @@
|
||||
"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": "automatic",
|
||||
"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 -\"automatic\" (behave as \"graceful\" only for processes launched by terminal, behave as \"always\" otherwise)\n -\"never\" (never close).\ntrue and false are accepted as synonyms for \"graceful\" and \"never\" respectively.",
|
||||
"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.",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"never",
|
||||
"graceful",
|
||||
"always",
|
||||
"automatic"
|
||||
"always"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
@@ -2215,11 +2076,6 @@
|
||||
"default": false,
|
||||
"description": "When true, this profile should always open in an elevated context. If the window isn't running as an Administrator, then a new elevated window will be created."
|
||||
},
|
||||
"experimental.autoMarkPrompts": {
|
||||
"default": false,
|
||||
"description": "When set to true, prompts will automatically be marked.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.connection.passthroughMode": {
|
||||
"description": "When set to true, directs the PTY for this connection to use pass-through mode instead of the original Conhost PTY simulation engine. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"type": "boolean"
|
||||
@@ -2228,11 +2084,6 @@
|
||||
"description": "When set to true, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"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"
|
||||
},
|
||||
"experimental.pixelShaderPath": {
|
||||
"description": "Use to set a path to a pixel shader to use with the Terminal. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"type": "string"
|
||||
@@ -2336,14 +2187,8 @@
|
||||
]
|
||||
},
|
||||
"adjustIndistinguishableColors": {
|
||||
"default": "never",
|
||||
"description": "Setting to adjust the foreground color to make it more visible, based on the background color. When set to \"indexed\", we will only adjust the colors if they came from the color scheme. Other possible values are \"never\" and \"always\".",
|
||||
"enum": [
|
||||
"never",
|
||||
"indexed",
|
||||
"always"
|
||||
],
|
||||
"type": "string"
|
||||
"description": "When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"scrollbarState": {
|
||||
"default": "visible",
|
||||
|
||||
@@ -5,7 +5,7 @@ Feature flags are controlled by an XML document stored at `src/features.xml`.
|
||||
## Example Document
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0"?>
|
||||
<featureStaging xmlns="http://microsoft.com/TilFeatureStaging-Schema.xsd">
|
||||
<feature>
|
||||
<!-- This will produce Feature_XYZ::IsEnabled() and TIL_FEATURE_XYZ_ENABLED (preprocessor) -->
|
||||
|
||||
@@ -74,7 +74,7 @@ Should not affect security.
|
||||
|
||||
### Reliability
|
||||
|
||||
Aside from additional parsing required for the settings file (which inherently offers more locations for parsing to fail), we need to be careful about badly formed/nonexistent feature tags or axes specified in the user-defined dictionaries. We must make sure to ignore such declarations (perhaps alongside emitting a warning to the user) and only apply those that are correctly formed and exist.
|
||||
Aside from additional parsing required for the settings file (which inherently offers more locations for parsing to fail), we need to be careful about badly formed/non-existent feature tags or axes specified in the user-defined dictionaries. We must make sure to ignore such declarations (perhaps alongside emitting a warning to the user) and only apply those that are correctly formed and exist.
|
||||
|
||||
### Compatibility
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ The delegation repeats the same dance as above as well:
|
||||
|
||||
The terminal will be its own complete presentation and input solution on top of a ConPTY connection, separating the concerns between API servicing and the user experience.
|
||||
|
||||
Today the Terminal knows how to start and then launches a ConPTY under it. The Terminal will need to be updated to accept a preexisting ConPTY connection on launch (or when the multi-process model arrives, as an inbound connection), and connect that to a new tab/pane instead of using the `winconpty.lib` libraries to make its own.
|
||||
Today the Terminal knows how to start and then launches a ConPTY under it. The Terminal will need to be updated to accept a pre-existing ConPTY connection on launch (or when the multi-process model arrives, as an inbound connection), and connect that to a new tab/pane instead of using the `winconpty.lib` libraries to make its own.
|
||||
|
||||
For now, I'm considering only the fresh-start scenario.
|
||||
- The Terminal will have to detect the inbound connection through ~~its argument parsing (or through~~ a new entrypoint in the COM alternative ~~)~~ and store the PTY in/out/signal handles for that connection in the startup arguments information
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
---
|
||||
author: Carlos Zamora @carlos-zamora
|
||||
created on: 2019-08-30
|
||||
last updated: 2022-07-06
|
||||
issue id: 715
|
||||
---
|
||||
|
||||
# Keyboard Selection
|
||||
|
||||
## Abstract
|
||||
|
||||
This spec describes a new set of key bindings that allows the user to create and update a selection without the use of a mouse or stylus.
|
||||
|
||||
## Inspiration
|
||||
|
||||
ConHost allows the user to modify a selection using the keyboard. Holding `Shift` allows the user to move the second selection endpoint in accordance with the arrow keys. The selection endpoint updates by one cell per key event, allowing the user to refine the selected region.
|
||||
|
||||
### Creating a selection
|
||||
Mark Mode is a ConHost feature that allows the user to create a selection using only the keyboard. In CMD, pressing <kbd>ctrl+m</kbd> enters mark mode. The current cursor position becomes a selection endpoint. The user can use the arrow keys to move that endpoint. While the user then holds <kbd>shift</kbd>, the selection endpoint ('start') is anchored to it's current position, and the arrow keys move the other selection endpoint ('end').
|
||||
|
||||
Additionally, pressing <kbd>shift+arrow</kbd> also initiates a selection, but it anchors the first selection endpoint to the cursor position.
|
||||
|
||||
Other terminal emulators have different approaches to this feature. iTerm2, for example, has Copy Mode (documentation [linked here](https://iterm2.com/documentation-copymode.html)). Here, <kbd>cmd+shift+c</kbd> makes the current cursor position become a selection endpoint. The arrow keys can be used to move that endpoint. However, unlike Mark Mode, a key binding <kbd>c+space</kbd> is used to change the start/stop selecting. The first time it's pressed, the 'start' endpoint is anchored. The second time it's pressed, the 'end' endpoint is set. After this, you can still move a cursor, but the selection persists until a new selection is created (either by pressing the key binding again, or using the mouse).
|
||||
|
||||
Though tmux is not a terminal emulator, it does also have Copy Mode that behaves fairly similarly to that of iTerm2's.
|
||||
|
||||
|
||||
## Solution Design
|
||||
|
||||
The fundamental solution design for keyboard selection is that the responsibilities between the Terminal Control and Terminal Core must be very distinct. The Terminal Control is responsible for handling user interaction and directing the Terminal Core to update the selection. The Terminal Core will need to update the selection according to the direction of the Terminal Control. Terminal Core maintains the state of the selection.
|
||||
|
||||
Relatively recently, TerminalControl was split into `TerminalControl`, `ControlInteractivity`, and `ControlCore`. Changes made to `ControlInteractivity`, `ControlCore`, and below propagate functionality to all consumers, meaning that the WPF terminal would benefit from these changes with no additional work required.
|
||||
|
||||
### Fundamental Terminal Control Changes
|
||||
|
||||
`ControlCore::TrySendKeyEvent()` is responsible for handling the key events after key bindings are dealt with in `TermControl`. At the time of writing this spec, there are 2 cases handled in this order:
|
||||
- Clear the selection (except in a few key scenarios)
|
||||
- Send Key Event
|
||||
|
||||
The first branch will be updated to _modify_ the selection instead of usually _clearing_ it. This will happen by converting the key event into parameters to forward to `TerminalCore`, which then updates the selection appropriately.
|
||||
|
||||
#### Abandoned Idea: Make keyboard selection a collection of standard keybindings
|
||||
One idea is to introduce an `updateSelection` action that conditionally works if a selection is active (similar to the `copy` action). For these key bindings, if there is no selection, the key events are forwarded to the application.
|
||||
|
||||
Thanks to Keybinding Args, there would only be 1 new command:
|
||||
| Action | Keybinding Args | Description |
|
||||
|--|--|--|
|
||||
| `updateSelection` | | If a selection exists, moves the last selection endpoint. |
|
||||
| | `Enum direction { up, down, left, right }` | The direction the selection will be moved in. |
|
||||
| | `Enum mode { char, word, view, buffer }` | The context for which to move the selection endpoint to. (defaults to `char`) |
|
||||
|
||||
|
||||
By default, the following keybindings will be set:
|
||||
```JS
|
||||
// Character Selection
|
||||
{ "command": {"action": "updateSelection", "direction": "left", "mode": "char" }, "keys": "shift+left" },
|
||||
{ "command": {"action": "updateSelection", "direction": "right", "mode": "char" }, "keys": "shift+right" },
|
||||
{ "command": {"action": "updateSelection", "direction": "up", "mode": "char" }, "keys": "shift+up" },
|
||||
{ "command": {"action": "updateSelection", "direction": "down", "mode": "char" }, "keys": "shift+down" },
|
||||
|
||||
// Word Selection
|
||||
{ "command": {"action": "updateSelection", "direction": "left", "mode": "word" }, "keys": "ctrl+shift+left" },
|
||||
{ "command": {"action": "updateSelection", "direction": "right", "mode": "word" }, "keys": "ctrl+shift+right" },
|
||||
|
||||
// Viewport Selection
|
||||
{ "command": {"action": "updateSelection", "direction": "left", "mode": "view" }, "keys": "shift+home" },
|
||||
{ "command": {"action": "updateSelection", "direction": "right", "mode": "view" }, "keys": "shift+end" },
|
||||
{ "command": {"action": "updateSelection", "direction": "up", "mode": "view" }, "keys": "shift+pgup" },
|
||||
{ "command": {"action": "updateSelection", "direction": "down", "mode": "view" }, "keys": "shift+pgdn" },
|
||||
|
||||
// Buffer Corner Selection
|
||||
{ "command": {"action": "updateSelection", "direction": "up", "mode": "buffer" }, "keys": "ctrl+shift+home" },
|
||||
{ "command": {"action": "updateSelection", "direction": "down", "mode": "buffer" }, "keys": "ctrl+shift+end" },
|
||||
```
|
||||
These are in accordance with ConHost's keyboard selection model.
|
||||
|
||||
This idea was abandoned due to several reasons:
|
||||
1. Keyboard selection should be a standard way to interact with a terminal across all consumers (i.e. WPF control, etc.)
|
||||
2. There isn't really another set of key bindings that makes sense for this. We already hardcoded <kbd>ESC</kbd> as a way to clear the selection. This is just an extension of that.
|
||||
3. Adding 12 conditionally effective key bindings takes the spot of 12 potential non-conditional key bindings. It would be nice if a different key binding could be set when the selection is not active, but that makes the settings design much more complicated.
|
||||
4. 12 new items in the command palette is also pretty excessive.
|
||||
5. If proven wrong when this is in WT Preview, we can revisit this and make them customizable then. It's better to add the ability to customize it later than take it away.
|
||||
|
||||
#### Abandoned Idea: Make keyboard selection a simulation of mouse selection
|
||||
It may seem that some effort can be saved by making the keyboard selection act as a simulation of mouse selection. There is a union of mouse and keyboard activity that can be represented in a single set of selection motion interfaces that are commanded by the TermControl's Mouse/Keyboard handler and adapted into appropriate motions in the Terminal Core.
|
||||
|
||||
However, the mouse handler operates by translating a pixel coordinate on the screen to a text buffer coordinate. This would have to be rewritten and the approach was deemed unworthy.
|
||||
|
||||
|
||||
### Fundamental Terminal Core Changes
|
||||
|
||||
The Terminal Core will need to expose a `UpdateSelection()` function that is called by the keybinding handler. The following parameters will need to be passed in:
|
||||
- `enum SelectionDirection`: the direction that the selection endpoint will attempt to move to. Possible values include `Up`, `Down`, `Left`, and `Right`.
|
||||
- `enum SelectionExpansion`: the selection expansion mode that the selection endpoint will adhere to. Possible values include `Char`, `Word`, `View`, `Buffer`.
|
||||
|
||||
#### Moving by Cell
|
||||
For `SelectionExpansion = Char`, the selection endpoint will be updated according to the buffer's output pattern. For **horizontal movements**, the selection endpoint will attempt to move left or right. If a viewport boundary is hit, the endpoint will wrap appropriately (i.e.: hitting the left boundary moves it to the last cell of the line above it).
|
||||
|
||||
For **vertical movements**, the selection endpoint will attempt to move up or down. If a **viewport boundary** is hit and there is a scroll buffer, the endpoint will move and scroll accordingly by a line.
|
||||
|
||||
If a **buffer boundary** is hit, the endpoint will not move. In this case, however, the event will still be considered handled.
|
||||
|
||||
**NOTE**: An important thing to handle properly in all cases is wide glyphs. The user should not be allowed to select a portion of a wide glyph; it should be all or none of it. When calling `_ExpandWideGlyphSelection` functions, the result must be saved to the endpoint.
|
||||
|
||||
#### Moving by Word
|
||||
For `SelectionExpansion = Word`, the selection endpoint will also be updated according to the buffer's output pattern, as above. However, the selection will be updated in accordance with "chunk selection" (performing a double-click and dragging the mouse to expand the selection). For **horizontal movements**, the selection endpoint will be updated according to the `_ExpandDoubleClickSelection` functions. The result must be saved to the endpoint. As before, if a boundary is hit, the endpoint will wrap appropriately. See [Future Considerations](#FutureConsiderations) for how this will interact with line wrapping.
|
||||
|
||||
For **vertical movements**, the movement is a little more complicated than before. The selection will still respond to buffer and viewport boundaries as before. If the user is trying to move up, the selection endpoint will attempt to move up by one line, then selection will be expanded leftwards. Alternatively, if the user is trying to move down, the selection endpoint will attempt to move down by one line, then the selection will be expanded rightwards.
|
||||
|
||||
#### Moving by Viewport
|
||||
For `SelectionExpansion = View`, the selection endpoint will be updated according to the viewport's height. Horizontal movements will be updated according to the viewport's width, thus resulting in the endpoint being moved to the left/right boundary of the viewport.
|
||||
|
||||
#### Moving by Buffer
|
||||
|
||||
For `SelectionExpansion = Buffer`, the selection endpoint will be moved to the beginning or end of all the text within the buffer. If moving up or left, set the position to 0,0 (the origin of the buffer). If moving down or right, set the position to the last character in the buffer.
|
||||
|
||||
|
||||
**NOTE**: In all cases, horizontal movements attempting to move past the left/right viewport boundaries result in a wrap. Vertical movements attempting to move past the top/bottom viewport boundaries will scroll such that the selection is at the edge of the screen. Vertical movements attempting to move past the top/bottom buffer boundaries will be clamped to be within buffer boundaries.
|
||||
|
||||
**NOTE**: If `copyOnSelect` is enabled, we need to make sure we **DO NOT** update the clipboard on every change in selection. The user must explicitly choose to copy the selected text from the buffer.
|
||||
|
||||
### Mark Mode
|
||||
|
||||
Mark Mode is a mode where the user can create and modify a selection using only the keyboard.
|
||||
|
||||
When no selection is present, the user may use the `markMode` action to enter mark mode. Upon doing so, a selection will be created at the current cursor position.
|
||||
|
||||
When in mark mode, the user may...
|
||||
- press <kbd>ESC</kbd> to clear the selection and exit mark mode
|
||||
- invoke the `markMode` action to exit mark mode
|
||||
- invoke the `copy` action (this includes right-clicking the terminal) to copy the selected text, clear the selection, and exit mark mode
|
||||
- move the cursor in the following ways:
|
||||
- arrow keys --> move by character
|
||||
- ctrl + left/right --> move by word
|
||||
- ctrl + home/end --> move to the beginning/end of the buffer
|
||||
- home/end --> move to the beginning/end of the line respectively
|
||||
- pgup/pgdn --> move up/down by viewport respectively
|
||||
- expand the selection in the following ways:
|
||||
- shift + arrow keys --> move the "end" endpoint by character
|
||||
- ctrl + shift + left/right --> move the "end" endpoint by word
|
||||
- ctrl + shift + home/end --> move the "end" endpoint to the beginning/end of the buffer
|
||||
- shift + home/end --> move the "end" endpoint to the beginning/end of the line respectively
|
||||
- shift + pgup/pgdn --> move the "end" endpoint up/down by viewport respectively
|
||||
|
||||
As with mouse selections, keybindings are still respected and pressing a key that is not bound to a keybinding (or mentioned above) will clear the selection and exit mark mode.
|
||||
|
||||
#### Corner cases
|
||||
|
||||
- In mark mode, if a selection was created via the keyboard, moving the cursor moves at the "end" endpoint. This is consistent with conhost.
|
||||
- If a user creates a selection using the mouse, then enters mark mode, mark mode inherits the existing selection as if it was made using the keyboard.
|
||||
- If `copyOnSelect` is enabled, the selection is copied when the selection operation is "complete". Thus, the selection is copied when the `copy` keybinding is used or the selection is copied using the mouse.
|
||||
- If `copyOnSelect` is enabled, `ESC` is interpreted as "cancelling" the selection, so nothing is copied. Keys that generate input are also interpreted as "cancelling" the selection. Only the `copy` keybinding or copying using the mouse is considered "completing" the selection operation, and copying the content to the clipboard.
|
||||
|
||||
**NOTE** - Related to #3884:
|
||||
If the user has chosen to have selections persist after a copy operation, the selection created by Copy Mode is treated no differently than one created with the mouse. The selection will persist after a copy operation. However, if the user exits Copy Mode in any of the other situations, the selection is cleared.
|
||||
|
||||
#### Block Selection
|
||||
A user can normally create a block selection by holding <kbd>alt</kbd> then creating a selection.
|
||||
|
||||
If the user is in Mark Mode, and desires to make a block selection, they can use the `toggleBlockSelection()` action. `toggleBlockSelection()` takes an existing selection, and transforms it into a block selection (or vice-versa).
|
||||
|
||||
All selections created in Mark Mode will have block selection disabled by default.
|
||||
|
||||
#### Rendering during Copy Mode
|
||||
Since we are just moving the selection endpoints, rendering the selection rects should operate normally. We need to ensure that we still scroll when we move a selection point past the top/bottom of the viewport.
|
||||
|
||||
In ConHost, output would be paused when a selection was present. Windows Terminal does not pause the output when a selection is present, however, it does not scroll to the new output.
|
||||
|
||||
#### Interaction with Mouse Selection
|
||||
If a selection exists, the user is basically already in Copy Mode. The user should be modifying the "end" endpoint of the selection when using the `updateSelection()` bindings. The existing selection should not be cleared (contrary to prior behavior). However, the half-y-beam will not be drawn. Once the user presses the `copyMode` or `moveSelectionPoint` keybinding, the half-y-beam is drawn on the targeted endpoint (which will then be "start").
|
||||
|
||||
During Copy Mode, if the user attempts to create a selection using the mouse, any existing selections are cleared and the mouse creates a selection normally. However, contrary to prior behavior, the user will still be in Copy Mode. The target endpoint being modified in Copy Mode, however, will be the "end" endpoint of the selection, instead of the cursor (as explained earlier in the flowchart).
|
||||
|
||||
|
||||
#### Abandoned Idea: Copy Mode
|
||||
Copy Mode is a more complex version of Mark Mode that is intended to provide a built-in way to switch the active selection endpoint. This idea was abandoned because we would then run into a user education issue. Rather than reinventing the wheel, selection should feel natural like that of a text editor, and any diversion from that model should be introduced separately (i.e. keybindings). Doing so ensures that users can "hit the ground running" when trying to make a selection, but won't be hindered by new functionality that is available.
|
||||
|
||||
Copy Mode is a mode where the user can create and modify a selection using only the keyboard. The following flowchart covers how the new `copymode()` action works:
|
||||
|
||||
![Copy Mode Flowchart][images/CopyModeFlowchart.png]
|
||||
|
||||
**NOTE**: `copyMode()` refers to the action, whereas `updateSelection()` refers to the underlying function that is being called in the code.
|
||||
|
||||
If a selection is not active, a "start" and "end" selection point is created at the cursor position. `updateSelection()` calls then move "start" and "end" together as one position.
|
||||
|
||||
Invoking `copyMode()` again, will then anchor "start" (meaning that it will be kept in place). Subsequent `updateSelection()` calls move the "end" selection point.
|
||||
|
||||
Invoking `copyMode()` essentially cycles between which selection point is targeted.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
### Key Bindings
|
||||
|
||||
| Action | Keybinding Args | Description |
|
||||
|--|--|--|
|
||||
| `selectAll` | none | Select the entire text buffer. |
|
||||
| `markMode` | none | Toggle mark mode. If no selection exists, create a selection at the cursor position. Otherwise, use the existing selection as one in mark mode. |
|
||||
| `toggleBlockSelection` | none | Transform the existing selection between a block selection and a line selection. |
|
||||
| `switchSelectionEndpoint` | none | If a selection is present, switch which selection endpoint is targeted when in mark mode or another keyboard selection mode (i.e. modified a mouse selection using the keyboard). |
|
||||
|
||||
By default, the following key binding will be set:
|
||||
```JS
|
||||
{ "command": "selectAll", "keys": "ctrl+shift+a" },
|
||||
|
||||
// Copy Mode
|
||||
{ "command": "copyMode", "keys": "ctrl+shift+m" },
|
||||
{ "command": "toggleBlockSelection" },
|
||||
{ "command": "switchSelectionEndpoint" },
|
||||
```
|
||||
|
||||
### Selection Markers
|
||||
|
||||
A y-beam will be used to identify which selection endpoint is currently being moved when in mark mode. The y-beam will match the cursor color and the font size so that it essentially fills a cell in the buffer.
|
||||
|
||||
When we're moving the cursor (this happens when mark mode is entered from no existing selection), a full y-beam will be displayed at the cursor position.
|
||||
|
||||

|
||||
|
||||
When <kbd>shift</kbd> is held, we're expanding the selection. In this case, the y-beam will be split, and the relevant half will be rendered on the active endpoint functioning as a selection marker.
|
||||
|
||||

|
||||
|
||||
If the selection is up against the end (or beginning) of the line, the selection marker can't be rendered normally because there is no space to render it off the side of the terminal. Instead, the selection marker will be horizontally flipped. Alternatively, it can be rendered on the next available cell (i.e. end of line translates to the beginning of the next line), but that would cause issues when the selection is positioned at the beginning or end of the buffer, thus the idea was abandoned.
|
||||
|
||||
If the active endpoint crosses the inactive endpoint, the selection marker will be flipped. In a sense, the flag will always point away from the selection.
|
||||
|
||||
The y-beam doesn't make as much sense for block selections, so instead an L-shaped marker will be placed hugging the corner of the active selection endpoint.
|
||||
|
||||
**NOTE:** Both half y-beams could have been presented as shown in the image below. This idea was omitted because then there is no indication for which half y-beam is currently focused.
|
||||
|
||||

|
||||
|
||||
### Miscellaneous
|
||||
|
||||
When mark mode is enabled, the cursor will stop blinking.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Accessibility
|
||||
|
||||
Using the keyboard is generally a more accessible experience than using the mouse. Being able to modify a selection by using the keyboard is a good first step towards making selecting text more accessible.
|
||||
|
||||
We will be expected to send "selection changed" events via UIA every time the cursor moves or selection updates (both are considered the same event).
|
||||
|
||||
### Security
|
||||
|
||||
N/A
|
||||
|
||||
### Reliability
|
||||
|
||||
With regards to the Terminal Core, the newly introduced code should rely on already existing and tested code. Thus no crash-related bugs are expected.
|
||||
|
||||
With regards to Terminal Control and the settings model, crash-related bugs are not expected. However, ensuring that the selection is updated and cleared in general use-case scenarios must be ensured.
|
||||
|
||||
### Compatibility
|
||||
|
||||
N/A
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
N/A
|
||||
|
||||
## Potential Issues
|
||||
|
||||
### Grapheme Clusters
|
||||
When grapheme cluster support is inevitably added to the Text Buffer, moving by "cell" is expected to move by "character" or "cluster". This is similar to how wide glyphs are handled today. Either all of it is selected, or none of it.
|
||||
|
||||
### Circling the buffer
|
||||
As usual, if the buffer is circling, the selection should be updated to follow the content (and "scroll up" appropriately).
|
||||
|
||||
In the event that one endpoint "scrolls" off the buffer, we must clamp "start" to the buffer origin. Conversely, in the event that both endpoints "scroll" off the buffer, the selection must be considered cleared.
|
||||
|
||||
## Future considerations
|
||||
|
||||
### Word Selection Wrap
|
||||
At the time of writing this spec, expanding or moving by word is interrupted by the beginning or end of the line, regardless of the wrap flag being set. In the future, selection and the accessibility models will respect the wrap flag on the text buffer.
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
- https://blogs.windows.com/windowsdeveloper/2014/10/07/console-improvements-in-the-windows-10-technical-preview/
|
||||
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 88 KiB |
@@ -659,7 +659,7 @@ loading until that generator is complete.
|
||||
However, if the user disables that generator entirely, we'll never display that
|
||||
profile to the user, even if they've done that setup before.
|
||||
|
||||
So the trade-off with this design is that nonexistent dynamic profiles will
|
||||
So the trade-off with this design is that non-existent dynamic profiles will
|
||||
never roam to machines where they don't exist and aren't valid, but the
|
||||
generators _must_ be enabled to use the dynamic profiles.
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ We need a way to determine where an action came from to minimize how many action
|
||||
- Construct the `Command` (basically the `Command::LayerJson` we have today)
|
||||
- Add it to the `ActionMap`
|
||||
- this should update the internal state of `ActionMap` appropriately
|
||||
- if the newly added key chord conflicts with a preexisting one,
|
||||
- if the newly added key chord conflicts with a pre-existing one,
|
||||
redirect `_KeyMap` to the newly added `Command` instead,
|
||||
and update the conflicting one.
|
||||
2. Load settings.json
|
||||
|
||||
171
doc/specs/Keyboard-Selection.md
Normal file
@@ -0,0 +1,171 @@
|
||||
---
|
||||
author: Carlos Zamora @carlos-zamora
|
||||
created on: 2019-08-30
|
||||
last updated: 2021-09-17
|
||||
issue id: 715
|
||||
---
|
||||
|
||||
# Keyboard Selection
|
||||
|
||||
## Abstract
|
||||
|
||||
This spec describes a new set of non-configurable keybindings that allows the user to update a selection without the use of a mouse or stylus.
|
||||
|
||||
## Inspiration
|
||||
|
||||
ConHost allows the user to modify a selection using the keyboard. Holding `Shift` allows the user to move the second selection endpoint in accordance with the arrow keys. The selection endpoint updates by one cell per key event, allowing the user to refine the selected region.
|
||||
|
||||
Mark mode allows the user to create a selection using only the keyboard, then edit it as mentioned above.
|
||||
|
||||
|
||||
## Solution Design
|
||||
|
||||
The fundamental solution design for keyboard selection is that the responsibilities between the Terminal Control and Terminal Core must be very distinct. The Terminal Control is responsible for handling user interaction and directing the Terminal Core to update the selection. The Terminal Core will need to update the selection according to the preferences of the Terminal Control.
|
||||
|
||||
Relatively recently, TerminalControl was split into `TerminalControl`, `ControlInteractivity`, and `ControlCore`. Changes made to `ControlInteractivity`, `ControlCore`, and below propagate functionality to all consumers, meaning that the WPF terminal would benefit from these changes with no additional work required.
|
||||
|
||||
### Fundamental Terminal Control Changes
|
||||
|
||||
`ControlCore::TrySendKeyEvent()` is responsible for handling the key events after key bindings are dealt with in `TermControl`. At the time of writing this spec, there are 2 cases handled in this order:
|
||||
- Clear the selection (except in a few key scenarios)
|
||||
- Send Key Event
|
||||
|
||||
The first branch will be updated to _modify_ the selection instead of usually _clearing_ it. This will happen by converting the key event into parameters to forward to `TerminalCore`, which then updates the selection appropriately.
|
||||
|
||||
#### Idea: Make keyboard selection a collection of standard keybindings
|
||||
One idea is to introduce an `updateSelection` action that conditionally works if a selection is active (similar to the `copy` action). For these key bindings, if there is no selection, the key events are forwarded to the application.
|
||||
|
||||
Thanks to Keybinding Args, there would only be 1 new command:
|
||||
| Action | Keybinding Args | Description |
|
||||
|--|--|--|
|
||||
| `updateSelection` | | If a selection exists, moves the last selection endpoint. |
|
||||
| | `Enum direction { up, down, left, right }` | The direction the selection will be moved in. |
|
||||
| | `Enum mode { char, word, view, buffer }` | The context for which to move the selection endpoint to. (defaults to `char`) |
|
||||
|
||||
|
||||
By default, the following keybindings will be set:
|
||||
```JS
|
||||
// Character Selection
|
||||
{ "command": {"action": "updateSelection", "direction": "left", "mode": "char" }, "keys": "shift+left" },
|
||||
{ "command": {"action": "updateSelection", "direction": "right", "mode": "char" }, "keys": "shift+right" },
|
||||
{ "command": {"action": "updateSelection", "direction": "up", "mode": "char" }, "keys": "shift+up" },
|
||||
{ "command": {"action": "updateSelection", "direction": "down", "mode": "char" }, "keys": "shift+down" },
|
||||
|
||||
// Word Selection
|
||||
{ "command": {"action": "updateSelection", "direction": "left", "mode": "word" }, "keys": "ctrl+shift+left" },
|
||||
{ "command": {"action": "updateSelection", "direction": "right", "mode": "word" }, "keys": "ctrl+shift+right" },
|
||||
|
||||
// Viewport Selection
|
||||
{ "command": {"action": "updateSelection", "direction": "left", "mode": "view" }, "keys": "shift+home" },
|
||||
{ "command": {"action": "updateSelection", "direction": "right", "mode": "view" }, "keys": "shift+end" },
|
||||
{ "command": {"action": "updateSelection", "direction": "up", "mode": "view" }, "keys": "shift+pgup" },
|
||||
{ "command": {"action": "updateSelection", "direction": "down", "mode": "view" }, "keys": "shift+pgdn" },
|
||||
|
||||
// Buffer Corner Selection
|
||||
{ "command": {"action": "updateSelection", "direction": "up", "mode": "buffer" }, "keys": "ctrl+shift+home" },
|
||||
{ "command": {"action": "updateSelection", "direction": "down", "mode": "buffer" }, "keys": "ctrl+shift+end" },
|
||||
```
|
||||
These are in accordance with ConHost's keyboard selection model.
|
||||
|
||||
This idea was abandoned due to several reasons:
|
||||
1. Keyboard selection should be a standard way to interact with a terminal across all consumers (i.e. WPF control, etc.)
|
||||
2. There isn't really another set of key bindings that makes sense for this. We already hardcoded <kbd>ESC</kbd> as a way to clear the selection. This is just an extension of that.
|
||||
3. Adding 12 conditionally effective key bindings takes the spot of 12 potential non-conditional key bindings. It would be nice if a different key binding could be set when the selection is not active, but that makes the settings design much more complicated.
|
||||
4. 12 new items in the command palette is also pretty excessive.
|
||||
5. If proven wrong when this is in WT Preview, we can revisit this and make them customizable then. It's better to add the ability to customize it later than take it away.
|
||||
|
||||
#### Idea: Make keyboard selection a simulation of mouse selection
|
||||
It may seem that some effort can be saved by making the keyboard selection act as a simulation of mouse selection. There is a union of mouse and keyboard activity that can be represented in a single set of selection motion interfaces that are commanded by the TermControl's Mouse/Keyboard handler and adapted into appropriate motions in the Terminal Core.
|
||||
|
||||
However, the mouse handler operates by translating a pixel coordinate on the screen to a text buffer coordinate. This would have to be rewritten and the approach was deemed unworthy.
|
||||
|
||||
|
||||
### Fundamental Terminal Core Changes
|
||||
|
||||
The Terminal Core will need to expose a `UpdateSelection()` function that is called by the keybinding handler. The following parameters will need to be passed in:
|
||||
- `enum SelectionDirection`: the direction that the selection endpoint will attempt to move to. Possible values include `Up`, `Down`, `Left`, and `Right`.
|
||||
- `enum SelectionExpansion`: the selection expansion mode that the selection endpoint will adhere to. Possible values include `Char`, `Word`, `View`, `Buffer`.
|
||||
|
||||
#### Moving by Cell
|
||||
For `SelectionExpansion = Char`, the selection endpoint will be updated according to the buffer's output pattern. For **horizontal movements**, the selection endpoint will attempt to move left or right. If a viewport boundary is hit, the endpoint will wrap appropriately (i.e.: hitting the left boundary moves it to the last cell of the line above it).
|
||||
|
||||
For **vertical movements**, the selection endpoint will attempt to move up or down. If a **viewport boundary** is hit and there is a scroll buffer, the endpoint will move and scroll accordingly by a line.
|
||||
|
||||
If a **buffer boundary** is hit, the endpoint will not move. In this case, however, the event will still be considered handled.
|
||||
|
||||
**NOTE**: An important thing to handle properly in all cases is wide glyphs. The user should not be allowed to select a portion of a wide glyph; it should be all or none of it. When calling `_ExpandWideGlyphSelection` functions, the result must be saved to the endpoint.
|
||||
|
||||
#### Moving by Word
|
||||
For `SelectionExpansion = Word`, the selection endpoint will also be updated according to the buffer's output pattern, as above. However, the selection will be updated in accordance with "chunk selection" (performing a double-click and dragging the mouse to expand the selection). For **horizontal movements**, the selection endpoint will be updated according to the `_ExpandDoubleClickSelection` functions. The result must be saved to the endpoint. As before, if a boundary is hit, the endpoint will wrap appropriately. See [Future Considerations](#FutureConsiderations) for how this will interact with line wrapping.
|
||||
|
||||
For **vertical movements**, the movement is a little more complicated than before. The selection will still respond to buffer and viewport boundaries as before. If the user is trying to move up, the selection endpoint will attempt to move up by one line, then selection will be expanded leftwards. Alternatively, if the user is trying to move down, the selection endpoint will attempt to move down by one line, then the selection will be expanded rightwards.
|
||||
|
||||
#### Moving by Viewport
|
||||
For `SelectionExpansion = View`, the selection endpoint will be updated according to the viewport's height. Horizontal movements will be updated according to the viewport's width, thus resulting in the endpoint being moved to the left/right boundary of the viewport.
|
||||
|
||||
#### Moving by Buffer
|
||||
|
||||
For `SelectionExpansion = Buffer`, the selection endpoint will be moved to the beginning or end of all the text within the buffer. If moving up or left, set the position to 0,0 (the origin of the buffer). If moving down or right, set the position to the last character in the buffer.
|
||||
|
||||
|
||||
**NOTE**: In all cases, horizontal movements attempting to move past the left/right viewport boundaries result in a wrap. Vertical movements attempting to move past the top/bottom viewport boundaries will scroll such that the selection is at the edge of the screen. Vertical movements attempting to move past the top/bottom buffer boundaries will be clamped to be within buffer boundaries.
|
||||
|
||||
Every combination of the `SelectionDirection` and `SelectionExpansion` will map to a keybinding. These pairings are shown below in the UI/UX Design --> Keybindings section.
|
||||
|
||||
**NOTE**: If `copyOnSelect` is enabled, we need to make sure we **DO NOT** update the clipboard on every change in selection. The user must explicitly choose to copy the selected text from the buffer.
|
||||
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
### Key Bindings
|
||||
|
||||
There will only be 1 new command that needs to be added:
|
||||
| Action | Keybinding Args | Description |
|
||||
|--|--|--|
|
||||
| `selectAll` | | Select the entire text buffer.
|
||||
|
||||
By default, the following key binding will be set:
|
||||
```JS
|
||||
{ "command": "selectAll", "keys": "ctrl+shift+a" },
|
||||
```
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Accessibility
|
||||
|
||||
Using the keyboard is generally a more accessible experience than using the mouse. Being able to modify a selection by using the keyboard is a good first step towards making selecting text more accessible.
|
||||
|
||||
### Security
|
||||
|
||||
N/A
|
||||
|
||||
### Reliability
|
||||
|
||||
With regards to the Terminal Core, the newly introduced code should rely on already existing and tested code. Thus no crash-related bugs are expected.
|
||||
|
||||
With regards to Terminal Control and the settings model, crash-related bugs are not expected. However, ensuring that the selection is updated and cleared in general use-case scenarios must be ensured.
|
||||
|
||||
### Compatibility
|
||||
|
||||
N/A
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
## Potential Issues
|
||||
|
||||
### Grapheme Clusters
|
||||
When grapheme cluster support is inevitably added to the Text Buffer, moving by "cell" is expected to move by "character" or "cluster". This is similar to how wide glyphs are handled today. Either all of it is selected, or none of it.
|
||||
|
||||
## Future considerations
|
||||
|
||||
### Word Selection Wrap
|
||||
At the time of writing this spec, expanding or moving by word is interrupted by the beginning or end of the line, regardless of the wrap flag being set. In the future, selection and the accessibility models will respect the wrap flag on the text buffer.
|
||||
|
||||
## Mark Mode
|
||||
|
||||
This functionality will be expanded to create a feature similar to Mark Mode. This will allow a user to create a selection using only the keyboard.
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
- https://blogs.windows.com/windowsdeveloper/2014/10/07/console-improvements-in-the-windows-10-technical-preview/
|
||||
@@ -17,7 +17,7 @@ This spec will outline how various terminal frontends will be able to interact w
|
||||
Terminal component.
|
||||
* **Terminal Layer**: This is the shared core implementation of the terminal.
|
||||
This is the Terminal Connection, Parser/Adapter, Buffer, and Renderer (but not
|
||||
the UX-dependent RenderEngine).
|
||||
the UX-dependant RenderEngine).
|
||||
|
||||
## User Stories
|
||||
1. "Project Cascadia" should be able to have both global settings (such as
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2022-02-15
|
||||
last updated: 2022-04-25
|
||||
issue id: #10509
|
||||
---
|
||||
|
||||
|
||||
# Mica in the Terminal
|
||||
|
||||
## Abstract
|
||||
|
||||
This document serves as a companion doc to the [Theming Spec], rather than a
|
||||
spec on it's own. The context of broader application-level theming support is
|
||||
necessary to understand the big picture of the designs in this discussion.
|
||||
|
||||
|
||||
This spec is intended to help understand the problem space of adding [Mica] to
|
||||
the Windows Terminal. Introduced in Windows 11, Mica is a new type of material
|
||||
that incorporates theme and desktop wallpaper to paint the background of
|
||||
windows. The effect results in a blurred, transparency-like effect, quite
|
||||
similar to [Acrylic]. However, the technical limitations of Mica make it more
|
||||
complicated to integrate seamlessly with the Terminal experience.
|
||||
|
||||
## Background
|
||||
|
||||
Mica is a material that can only be applied to the root of the UI tree, and
|
||||
applies to the entire background surface. It's recommended to be used at the
|
||||
`Page` level, in place of a solid brush like
|
||||
`ApplicationPageBackgroundThemeBrush`. If the developer wants a surface within
|
||||
the page to have a Mica background, they need to make sure to have that element
|
||||
(and all elements behind it up until the `Page`) have a `Transparent`
|
||||
background, so that Mica will be visible through the elements.
|
||||
|
||||
This is contrasted with something like Acrylic, where the acrylic effect is
|
||||
specified at the Element layer itself. An element can request having a
|
||||
`HostBackdrop` brush for its background, and the element will have the Acrylic
|
||||
effect regardless of the structure of the rest of the elements in the UI tree.
|
||||
|
||||
Another important use case here is "Vintage Transparency" (or "unblurred
|
||||
transparency"), which is an unblurred transparency effect for the Terminal
|
||||
window. This is achieved with the `TransparentBackground` API, which enables the
|
||||
Terminal to disable the emergency backstop of the XAML Island. When that's
|
||||
enabled, controls that are transparent will be blended, unblurred, with whatever
|
||||
is visible behind the window. This works because the entire tree of the Terminal
|
||||
window underneath the `TermControl`s are `Transparent`, all the way up to the
|
||||
window itself.
|
||||
|
||||
Right now, the Terminal exposes three settings<sup>[[1]](#footnote-1)</sup>:
|
||||
* Background color
|
||||
* Background Opacity
|
||||
* Whether the user would like to enable acrylic or not
|
||||
|
||||
These settings are exposed at the "Profile"<sup>[[2]](#footnote-2)</sup> level.
|
||||
Properties on a profile are roughly considered to be "what the terminal control
|
||||
will look like when I run this settings profile". Users can have one profile
|
||||
with acrylic, one without, and open [Panes] with these profiles side-by-side in
|
||||
the Terminal. It's entirely possible that a user would have both a pane with and
|
||||
acrylic background, and one with an unblurred background in the same window.
|
||||
|
||||
### User Stories
|
||||
|
||||
* The Terminal should be able to have Mica in the title bar, behind the tabs.
|
||||
* Users will want Mica in the control area, as well as in the titlebar
|
||||
* Users may want Mica in the control, but with a solid titlebar, or an accent
|
||||
colored title bar, or an acrylic one...
|
||||
* Users will want mica in the titlebar with other effects (acrylic, vintage
|
||||
transparency) in the control area
|
||||
|
||||
This is where things get complicated. Given that a control can choose what type
|
||||
of material it has now, users would likely expect to be able to choose between
|
||||
acrylic, unblurred transparency, or Mica. However, Mica can only be applied at
|
||||
the root of the window. It's applied behind everything else in the window. From
|
||||
an implementation standpoint, Mica is a window-level property, not a control
|
||||
level one. If we want to have Mica under one control, we need to enable it for
|
||||
the _whole window_. If we enable Mica for the whole window, that would
|
||||
simultaneously prevent Vintage Transparency from working as expected. This is
|
||||
because the semi-transparent controls would no longer have a fully transparent
|
||||
window background to sit on top of - they'd be blended instead with the Mica
|
||||
background behind the window.
|
||||
|
||||
## Solution design
|
||||
|
||||
### Mica for `TermControl`s
|
||||
If we make enabling Mica for the control a per-profile setting, I believe that
|
||||
will lead to greater user confusion. It would result in "spooky action at a
|
||||
distance", where creating any pane with Mica would force the entire window to
|
||||
have a Mica background. This would change the appearance of any other unblurred
|
||||
transparent panes in the window, causing them to also be subjected to the Mica
|
||||
treatment as well.
|
||||
|
||||
**Proposal**: create a window-level theme property `window.background.useMica`
|
||||
(or similar), which will enable Mica for the entire window. When enabled, users
|
||||
can use a fully transparent, unblurred background for their profile to achieve
|
||||
the Mica effect within the control. When enabled, users **won't** be able to see
|
||||
through to the desktop with any vintage opacity settings.
|
||||
|
||||
By nesting Mica usage under `"window.background"`, it will be clearer that it's
|
||||
something that applies to the whole window, as the background for everything.
|
||||
I believe this is the most acceptable way to expose Mica to our users without
|
||||
"spooky action at a distance".
|
||||
|
||||
An example of what mica in the control area might look like:
|
||||
|
||||

|
||||
|
||||
### Mica in the titlebar
|
||||
|
||||
To achieve Mica in the titlebar, we'll similarly need to allow users to set the
|
||||
titlebar area to totally transparent, to allow the mica behind the window to be
|
||||
visible. A simple theme to achieve that might look like:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"theme": "My Mica Titlebar Theme",
|
||||
"themes": [
|
||||
{
|
||||
"name": "My Mica Titlebar Theme",
|
||||
"window":{
|
||||
"background.useMica": true, // Use mica behind the window
|
||||
},
|
||||
"tabRow":{
|
||||
"background": "#00000000", // Make the TabView Transparent
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
As noted before, due to the intentional limitations of the Mica material, if the
|
||||
user wants Mica in the tab row, they won't be able to use vintage opacity in any
|
||||
controls. The vintage opacity of the controls will show through to the Mica
|
||||
layer, instead of transparent through the whole window.
|
||||
|
||||
## Considered implementations
|
||||
|
||||
* We experimented with a new DWM API in SV2 which should enable us to set the
|
||||
background of our window to Mica. This did seem to work for the root window.
|
||||
It however, did not seem to work for the "drag window", the child HWND which
|
||||
we use to intercept nonclient messages in our titlebar area. Apparently, that
|
||||
API does not work at all for `WS_CHILD` windows, by design. This unfortunately
|
||||
prevents us from allowing Mica only in the titlebar area, without also
|
||||
applying it to the rest of the main window.
|
||||
* We considered rolling our own Mica brush to allow us to style individual
|
||||
elements. This didn't seem terribly hard at face value, considering [the Mica
|
||||
recipe] is basically open-source. However, it seems to rely on some
|
||||
closed-source `IGraphicsEffect`s from the `Composition.Effects` namespace.
|
||||
Apparently, those effects are only [implemented in Win2D]. It's unclear at
|
||||
this time if the Terminal would be capable of ingesting Win2D now or in the
|
||||
future. It does seem as though [Win2D is available via cppwinrt], so that's of
|
||||
some solace.
|
||||
|
||||
**However**, that does leave us in the world where we're rolling our own
|
||||
custom Mica brush, and would need to keep it up to date with the OS
|
||||
implementation. We'd be firmly off the rails of the recommended Mica usage,
|
||||
and our support would be likely very minimal. This is reason alone to
|
||||
avoid this path, and instead push for a platform-supported solution.
|
||||
|
||||
**TODO!**: We should make sure to have a Future Considerations section on how
|
||||
we'd implement per-element Mica, should that option be available to us in the
|
||||
future.
|
||||
|
||||
## Potential Issues
|
||||
|
||||
This is not a particularly ergonomic design. From a UX perspective, the user
|
||||
needs to enable one setting in the UI to enable Mica, and then go to profile
|
||||
settings to set the profile to _transparent_ for each of the profiles they want
|
||||
with Mica. That's not very intuitive by any means.
|
||||
|
||||
Mica would also impact our ability to enable the "acrylic on an unfocused
|
||||
window" functionality, requested in [#7158]. To support that feature, we need to
|
||||
have a transparent window backdrop, so that the in-app acrylic will magically
|
||||
use the desktop background. With Mica and this setting enabled, the acrylic
|
||||
would apply on top of the Mica layer. Either warnings would need to be
|
||||
displayed, or one setting would have to disable the other. At the very least,
|
||||
the documentation needs to be very clear about this.
|
||||
|
||||
In [this comment], the poster shows a pretty cool mockup of what a background
|
||||
image for the _window_ might look like. This kinda fills a similar problem space
|
||||
as Mica. If there were a background image for the whole Terminal window, then
|
||||
in-app acrylic would apply on top of the image. Vintage transparency wouldn't
|
||||
work through the image, it would apply on _top_ of the image. Perhaps, because
|
||||
of these related concerns, there should be a singular `window.background`
|
||||
property, that contains an object of settings. Or, to follow the solely dot
|
||||
notation from before
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"theme": "My Background Theme",
|
||||
"themes": [
|
||||
{
|
||||
"name": "My Background Theme",
|
||||
"window":{
|
||||
"background.useMica": true, // Use mica behind the window
|
||||
"background.image": "some/path/to/image", // Use a BG image
|
||||
"background.imageOpacity": 25, // Image is mostly transparent
|
||||
},
|
||||
"tabRow":{
|
||||
"background": "#00000000", // Make the TabView Transparent
|
||||
}
|
||||
}
|
||||
],
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"opacity": 0 // Panes are all totally transparent
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Future considerations
|
||||
|
||||
* I believe Insiders builds have support for two different variants of Mica -
|
||||
standard Mica, and "Thin" Mica. We may need to support a future enum value
|
||||
here, with values `"none", "original", "thin"`. For compatibility with the
|
||||
boolean values, `true=="original"`, `false=="none"`.
|
||||
|
||||
## Resources
|
||||
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]: For simplicity of the spec, I'm ignoring the
|
||||
background image settings. I'm also ignoring the small quirk where (at the time
|
||||
of writing), vintage opacity doesn't work on Windows 10. That creates some weird
|
||||
quirks where acrylic is always enabled if the user wants transparency on Windows
|
||||
10. A full discussion of this would only serve to complicate what is
|
||||
fundamentally a Windows 11-centric discussion.
|
||||
|
||||
<a name="footnote-2"><a>[2]: We're also gonna leave out a discussion of focused
|
||||
& unfocused "appearance" setting objects, again for brevity.
|
||||
|
||||
[Theming Spec]: ./%233327%20-%20Application%20Theming.md
|
||||
[Mica]: https://docs.microsoft.com/en-us/windows/apps/design/style/mica
|
||||
[Acrylic]: https://docs.microsoft.com/en-us/windows/apps/design/style/acrylic
|
||||
[Panes]: https://docs.microsoft.com/en-us/windows/terminal/panes
|
||||
[#3327]: https://github.com/microsoft/terminal/issues/3327
|
||||
[#10509]: https://github.com/microsoft/terminal/issues/10509
|
||||
[#7158]: https://github.com/microsoft/terminal/issues/7158
|
||||
[this comment]: https://github.com/microsoft/terminal/issues/3327#issuecomment-765493313
|
||||
[the Mica recipe]: https://github.com/microsoft/microsoft-ui-xaml/blob/0db5d0398cb38d69b06e26ef734cbbdebdebe774/dev/Materials/Backdrop/SystemBackdropBrushFactory.cpp#L8-L54
|
||||
[implemented in Win2D]: https://docs.microsoft.com/en-us/uwp/api/windows.ui.composition.compositioneffectbrush?view=winrt-22000#remarks
|
||||
[Win2D is available via cppwinrt]: https://stackoverflow.com/questions/49342164/is-win2d-yet-available-in-c-winrt
|
||||
@@ -1,728 +0,0 @@
|
||||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2019-12-13
|
||||
last updated: 2022-04-25
|
||||
issue id: #3327
|
||||
---
|
||||
|
||||
|
||||
TODO!S:
|
||||
* How do themes play with different window title settings? (different themes for different windows. `_quake` esp.))
|
||||
* any clever ideas for elevated themes?
|
||||
* Reconcile with global `experimental.useBackgroundImageForWindow` from [#12893]
|
||||
|
||||
# Application Theming
|
||||
|
||||
## Abstract
|
||||
|
||||
This spec outlines how the Windows Terminal will enable users to create custom
|
||||
"themes" for the application, enabling further customization of the window.
|
||||
These themes will be implemented as objects containing a group of UI-specific
|
||||
properties, so users can quickly apply a group of properties atomically.
|
||||
|
||||
## Inspiration
|
||||
|
||||
Much of the inspiration for this feature comes from VsCode and its themes. These
|
||||
themes can be more than just different color palettes for the editor - these
|
||||
themes can control the appearance of a variety of UI elements of the VsCode
|
||||
window.
|
||||
|
||||
## Solution Design
|
||||
|
||||
### Requested Functionality ("User Stories")
|
||||
|
||||
The following is a long list of ideas of elements of the window that the user
|
||||
should be able to customize:
|
||||
|
||||
* [ ] Pane Border colors (both the background, and the "focused" color) ([#3061])
|
||||
* [ ] Pane border width ([#3062])
|
||||
* [ ] Tab _Row_ and _Item_ Background color ([#702]/[#1337]/[#2994]/[#3774]/[#1963])
|
||||
- Some users want to set these to the accent color
|
||||
- Some users want to set these to a specific custom color
|
||||
- Some users want this to use the color straight from the active Terminal,
|
||||
allowing the tab or titlebar to "blend into" the terminal
|
||||
* [ ] Feature Request: Setting to hide/remove close ("x") button from tabs ([#3335])
|
||||
* [ ] Various different tab sizing modes
|
||||
- the current sizing, which is `SizeToContent`
|
||||
- Setting a min/max width on tabs
|
||||
- Configuring tabs to split the available space
|
||||
|
||||
Other lower-priority ideas:
|
||||
* [ ] Enable hiding the tab icon altogether
|
||||
* [ ] Enable forcing tab icons to monochrome
|
||||
* [ ] Tab row height
|
||||
* [ ] Tab row font size, font face
|
||||
* [ ] Tab corner radius
|
||||
* [ ] Margin between tabs? Padding within the tab?
|
||||
* [ ] Left-justify / Center / right-justify tab text, when tabs are wider than
|
||||
their text?
|
||||
* [ ] Control colors for light vs dark vs high-contrast modes
|
||||
* [ ] Enable/disable a shadow underneath the tab row, between tabs and content
|
||||
* [ ] Enable/disable a shadow cast by terminals on pane borders or a shadow cast
|
||||
by pane borders on Terminal panes
|
||||
* [ ] Similarly to the tabs, styling the Status Bar ([#3459])
|
||||
- Maybe enable it to have the same color as the active TermControl, causing
|
||||
the same "seamless" effect (see [this
|
||||
comment](https://github.com/microsoft/terminal/issues/3459#issuecomment-550501577))
|
||||
- Change font size, face, colors
|
||||
- Control the borders on the status bar - no top border would give the
|
||||
impression it's "seamless"
|
||||
|
||||
Additionally, the user should be able to easily switch from one installed theme
|
||||
to another. The user should be able to copy a simple blob of settings from the
|
||||
web and paste it into their settings to be able to easily try the theme out.
|
||||
|
||||
### Difference between "Themes" and "Schemes"
|
||||
|
||||
The avid follower of the Windows Terminal might know that the Terminal already
|
||||
contains support for "color schemes". What makes themes different from these
|
||||
schemes, and why should they be separate objects?
|
||||
|
||||
**Color Schemes** are objects that generally control the appearance of the
|
||||
Terminal Control itself (the proverbial "black rectangle with text in it").
|
||||
Primarily, color schemes are used for setting the "color table" of a terminal
|
||||
instance, setting the values for each of the 16 colors in the terminal's color
|
||||
table, and the default foreground and background colors. These are properties
|
||||
that only apply to the contents of the terminal itself, and not necessarily the
|
||||
entire application. Individual terminal control instances can have different
|
||||
color schemes. Furthermore, these schemes are largely in-line with schemes
|
||||
available on other platform's terminals. These schemes were heavily inspired by
|
||||
the great work done at [iTerm2-Color-Schemes].
|
||||
|
||||
Alternatively, **Themes** are sets of properties that apply primarily to the
|
||||
window of the application itself, but not necessarily the terminal content.
|
||||
These properties apply globally to the entire window, as opposed to controlling
|
||||
the appearance of individual terminals. These properties include things such as
|
||||
the coloration and styling of the tabs in the tab row.
|
||||
|
||||
### Theme objects
|
||||
|
||||
Themes will be implemented largely similar to the color schemes implementation.
|
||||
Currently, the terminal contains a list of available color schemes, and profiles
|
||||
can chose to apply a scheme from the list of schemes. We'll add a list of
|
||||
`themes`, and globally, the user will be able to specify one of these themes to
|
||||
apply.
|
||||
|
||||
Take for example the following settings excerpt:
|
||||
|
||||
```json
|
||||
{
|
||||
"theme": "My Boxy Theme",
|
||||
"themes": [
|
||||
{
|
||||
"name": "My Boxy Theme",
|
||||
"window":{
|
||||
"applicationTheme": "dark"
|
||||
},
|
||||
"tab": {
|
||||
"radius": 0,
|
||||
"padding": 5,
|
||||
"background": "terminalBackground",
|
||||
"textColor": "key:SystemAccentColorLight3",
|
||||
"icon": "outline",
|
||||
"closeButton": "hidden",
|
||||
},
|
||||
"tabRow":{
|
||||
"background": "accent",
|
||||
"shadows": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "My small light theme",
|
||||
"window":{
|
||||
"applicationTheme": "light"
|
||||
},
|
||||
"tab": {
|
||||
"background": "#80ff0000",
|
||||
"height": 8,
|
||||
"icon": "hidden",
|
||||
"closeButton": "hover"
|
||||
},
|
||||
"tabRow":{
|
||||
"background": "#ffffffff",
|
||||
"acrylicOpacity": 50,
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
In the above settings snippet, we see the following things:
|
||||
1. A list of `themes` that the user can pick from. Each theme has a `name`
|
||||
property used to identify the theme, and a group of properties for the theme.
|
||||
2. The user has set the `theme` to `"My Boxy Theme"`, the first theme
|
||||
in the list of themes. If the user wanted to switch to the other installed
|
||||
theme, `"My small light theme"`, they'd simply need to change this property.
|
||||
|
||||
> _note_: Initially, we had considered a `elementPropertyName`-like syntax as
|
||||
opposed to the object-grouped one above. We also considered a
|
||||
`element.propertyName`-like syntax. Overall, we liked the object based one best.
|
||||
>
|
||||
> **For simplicity, we'll be using `element.propertyName` syntax throughout to**
|
||||
> **refer to these properties, when grouped under `element` objects in the theme.**
|
||||
|
||||
These Theme objects are designed to make it simple for the user to be able to
|
||||
quickly download these as an extension in the future, and hot-switch between
|
||||
them. Imagine: an application that would provide a gallery of uploaded themes,
|
||||
and the user could install them as [fragment extensions].
|
||||
|
||||
### Exposed theme properties
|
||||
|
||||
Themes should be able to control a variety of elements of the Terminal UI. Some
|
||||
of these settings will be easier to implement than others. As such, below is a
|
||||
set of properties that seems appropriate to include as part of a "v1" theming
|
||||
implementation. In [Future Considerations](#future-considerations), we'll
|
||||
enumerate additional properties that could be added in the future to further
|
||||
control the UI.
|
||||
|
||||
#### Highest priority theming properties
|
||||
|
||||
These are the elements that have orders of magnitude more requests:
|
||||
* Customizing the titlebar color, including the unfocused titlebar color. This
|
||||
includes merging with the existing `useAcrylicInTabRow` setting.
|
||||
* Customizing the tab color
|
||||
* Enabling Mica for the window
|
||||
|
||||
These represent the most important asks of theming in the Terminal. Everything
|
||||
else that follows is merely "nice to have". The most important elements then
|
||||
are:
|
||||
|
||||
* Properties:
|
||||
- `tab.background`
|
||||
- `tabRow.background`
|
||||
- `tabRow.acrylicOpacity`
|
||||
- `tabRow.unfocusedBackground`
|
||||
- `window.background.useMica`
|
||||
* Theme color variants:
|
||||
- `"#rrggbb"` or `"#rrggbbaa"`
|
||||
- `"accent"`
|
||||
- `"terminalBackground"`
|
||||
|
||||
#### Additional theming v1 Properties
|
||||
|
||||
These are additional settings that seem of higher priority or would be easier to
|
||||
implement. They are categorized by the element of the Terminal they are
|
||||
controlling:
|
||||
|
||||
##### Individual Tabs
|
||||
|
||||
* `tab.cornerRadius`: Control the radius of the corners of the tab items.
|
||||
Accepts a `double`. If this is set to `0`, then the tabs will have squared-off
|
||||
corners. No particular limit is set on the max value accepted, though larger
|
||||
values might not be aesthetically pleasing.
|
||||
* `tab.bottomCornerRadius`: Control the radius of the bottom corners of the tab
|
||||
items. This can be used to make the tabs look like "buttons" in the tab row,
|
||||
instead of tabs.
|
||||
* `tab.closeButton`: Control the visibility of the close button for a tab item.
|
||||
Accepts the following values:
|
||||
- `visible`: The default behavior of the tab item close button - always
|
||||
visible.
|
||||
- `hover`: The close button on a tab item only appears when the tab is
|
||||
hovered.
|
||||
- `hidden`: The close button on a tab is always hidden.
|
||||
* `tab.icon`: Control the visibility, appearance of the tab icon
|
||||
- `visible`: The default behavior of the tab item icon - always visible, and
|
||||
in full color.
|
||||
- `outline`: The icon is always visible, but is only drawn as an outline,
|
||||
using `BitmapIconSource.ShowAsMonochrome(true)`
|
||||
- `hidden`: The icon is hidden
|
||||
* `tab.background`: Control the color of the background of tab items. See below
|
||||
for accepted colors.
|
||||
|
||||
##### Tab Row / "Titlebar"
|
||||
|
||||
* `tabRow.background`: Control the color of the background of the tab row. When
|
||||
tabs in the titlebar are enabled, this sets the color of the titlebar. See
|
||||
below for accepted colors.
|
||||
- Notably, this is named `tabRow.background`, **not** `titlebar.background`.
|
||||
Outside of tabs-in-titlebar mode, we can't control the window titlebar
|
||||
color.
|
||||
- This ignores any alpha and always uses 1.0 for the alpha channel. See
|
||||
[Titlebar complications](#Titlebar-complications) for details.
|
||||
* `tabRow.unfocusedBackground`: Control the color of the background of the tab
|
||||
row, when the window is unfocused. See below for accepted colors.
|
||||
- **TODO!** When omitted, should this default to the `tabRow.background`
|
||||
value (if set), or just the normal unfocused window color? "the normal
|
||||
unfocused window color" is a SUBSTANTIALLY easier implementation.
|
||||
- This ignores any alpha and always uses 1.0 for the alpha channel. See
|
||||
[Titlebar complications](#Titlebar-complications) for details.
|
||||
* `tabRow.acrylicOpacity`: Optional integer representation of an opacity
|
||||
(0-100). When provided, the `tabRow.background` color is treated as an acrylic
|
||||
brush, with the given `TintOpacity`. When omitted, `tabRow.background` is
|
||||
treated as a solid color.
|
||||
- This is to replace the original `useAcrylicInTabRow` setting.
|
||||
- This is NOT provided for the `tabRow.unfocusedBackground` setting. See
|
||||
[Titlebar complications](#Titlebar-complications) for details.
|
||||
|
||||
##### Panes
|
||||
|
||||
* `pane.borderColor`: Control the color of the border used to separate panes.
|
||||
This is the color of the inactive border between panes.
|
||||
* `pane.activeBorderColor`: Control the color of the border of the active pane
|
||||
* `pane.borderWidth`: Control the width of the borders used to separate panes.
|
||||
|
||||
##### Window Properties
|
||||
|
||||
* `window.applicationTheme`: If set, will set the XAML `RequestedTheme`
|
||||
property. This can be one of `light`, `dark` or `system`. This controls how
|
||||
XAML fundamentally styles UI elements. If not provided, will use the default
|
||||
value "system", which will use whatever the system's default theme is.
|
||||
* `window.roundedCorners`: A boolean, to control whether the window has rounded
|
||||
corners on Windows 11.
|
||||
* `window.background.useMica`: a boolean that enables/disables Mica. For more
|
||||
discussion, see [Mica Spec].
|
||||
* `window.background.image`: a path to an image to use as the background for the
|
||||
whole of the content of the Terminal, including in the tab row space.
|
||||
- Additional properties to control the sizing of this image (`padding`,
|
||||
`stretchMode`, `opacity`, etc) would also be exposed as
|
||||
`window.background.imagePadding`, a la the similar Profile settings.
|
||||
|
||||
#### Theme Colors
|
||||
|
||||
For properties like `tab.background` and `tabRow.background`, these colors can
|
||||
be one of:
|
||||
* an `#rrggbb`, `#aarrggbb` color. (Alpha is ignored for `tabRow.background`)
|
||||
* `accent` for the _titlebar_ version of the accent color. Notably, this is
|
||||
**not** just some `SystemAccentColor` value, it's apparently some other value.
|
||||
This has a different value depending on if the window is focused or not. Refer
|
||||
to Edge the "use accent color on titlebars" setting enabled as a reference.
|
||||
* `terminalBackground` to use the default background color of the active
|
||||
terminal instance.
|
||||
* `terminalForeground` to use the default foreground color of the active
|
||||
terminal instance.
|
||||
* `key:SomeXamlKey` to try and look `SomeXamlKey` up from our resources as a
|
||||
`Color`, and use that color for the value.
|
||||
- `accent` is NOT the same thing as `key:SystemAccentColor`? If it is, is it a reasonable
|
||||
alias that we'd want to provide anyways?
|
||||
- **TODO! DISCUSSION**: PR[#5280] suggested `{ "key": "SomeResourceKey" }` for
|
||||
string resources, should we use that format for colors like this as well?
|
||||
|
||||
This will enable users to not only provide custom colors, but also use the
|
||||
dynamic color of the active terminal instance as well.
|
||||
|
||||
Using `terminalBackground` with multiple concurrent panes with different
|
||||
backgrounds could certainly lead to some odd behavior. The intention of the
|
||||
setting is to provide a way for the tab/titlebar to "seamlessly" connect to the
|
||||
terminal content. However, two panes side-by-side could have different
|
||||
background colors, which might have an unexpected appearance. Since the user
|
||||
must have opted in to this behavior, they'll need to decide personally if
|
||||
that's something that bothers them aesthetically. It's entirely possible that a
|
||||
user doesn't use panes, and this wouldn't even be a problem for them.
|
||||
|
||||
<!-- We could maybe mitigate this by providing the user a way of specifying the
|
||||
`tab.background` color as having both a "single pane" and "multiple pane" mode,
|
||||
though I'm not sure I'm in love with this:
|
||||
|
||||
```json
|
||||
"tab.background": {"single": "terminalBackground", "multiple": null},
|
||||
"tab.background": {"single": "terminalBackground", "multiple": "#ff0000"},
|
||||
"tab.background": [ "terminalBackground", null ]
|
||||
```
|
||||
|
||||
Also shown is an array based implementation, as an option. Overall I'm not
|
||||
happy with this, so I think it shouldn't be in the final draft of the spec, but
|
||||
I'm leaving it for now as an option.
|
||||
-->
|
||||
|
||||
### Implementation of theming
|
||||
|
||||
Largely, whenever possible, we should be able to implement this theming support
|
||||
by modifying our application's `ResourceDictionary` with custom values to
|
||||
control the appearance of UI elements.
|
||||
|
||||
For example, the `TabView` already exposes a number of XAML resources we can
|
||||
modify to adjust it's appearance.
|
||||
* `TabViewBackground` controls the appearance of the background of the tab view.
|
||||
In `showTabsInTitlebar: true` mode, this is the color of the titlebar.
|
||||
* `TabViewItemHeaderBackground` and `TabViewItemHeaderBackgroundSelected`
|
||||
control the appearance of an individual tab.
|
||||
|
||||
By modifying the values of these brushes, we can control the appearance of the
|
||||
tabs. So long as we only in-place modify the resources, XAML is smart enough to
|
||||
be able to update it's appearance automatically. We can do this by querying the
|
||||
`ResourceDictionary` for a given resource, and changing it's value, rather than
|
||||
`insert`ing a new value into the `ResourceDictionary` to replace the old one.
|
||||
|
||||
In addition to the above properties, I propose adding a couple of our own
|
||||
properties: `PaneBorderWidth`: To control the width of pane borders
|
||||
`PaneBorderBrush`: To control the appearance of _inactive_ pane borders
|
||||
`ActivePaneBorderBrush`: To control the appearance of _active_ pane borders
|
||||
|
||||
In order to respond to the live-updating of the `TermControl`'s background
|
||||
color, we'll need to add some more specific logic beyond simply updating a XAML
|
||||
resource when settings change. Whenever a `TermControl`'s background color
|
||||
changes, or the active pane in a tab changes:
|
||||
* If `tab.background == "terminalBackground"`:
|
||||
- If this control is the tab's active terminal control (and the tab doesn't
|
||||
have a custom color set by the color picker), update the tab's own
|
||||
`TabViewItem` with updated `TabViewItemHeaderBackground` and
|
||||
`TabViewItemHeaderBackgroundSelected` values.
|
||||
- Here, we _don't_ want to update the `App`'s resources, since those
|
||||
apply globally, and each tab might have a control with a different
|
||||
color.
|
||||
- The color set by the color picker should override the color from the
|
||||
theme (as the former is a run-time property set to override the
|
||||
latter).
|
||||
* If `tabRow.background == "terminalBackground"`:
|
||||
- If this control is the active terminal of the active `Tab`, then we need
|
||||
to raise an event to communicate this updated value up to the window
|
||||
layer. We'll raise a `"TabRowBackgroundBrush"` property changed event,
|
||||
that the app host can listen for and use to set the titlebar's color, if
|
||||
needed.
|
||||
- The `TerminalPage` also will need to set the Background of the
|
||||
`TabRowControl` to match.
|
||||
|
||||
The `tab.cornerRadius` might be a bit trickier to implement. Currently, there's
|
||||
not a XAML resource that controls this, nor is this something that's exposed by
|
||||
the TabView control. Fortunately, this is something that's exposed to us
|
||||
programmatically. We'll need to manually set that value on each `TabViewItem` as
|
||||
we create new tabs. When we reload settings, we'll need to make sure to come
|
||||
through and update those values manually.
|
||||
|
||||
> NOTE: [microsoft-ui-xaml#2201] suggested that this will be possible with a
|
||||
> future MUX version and changing the `OverlayCornerRadius`.
|
||||
|
||||
### Tab Background Color, Overline Color, and the Tab Color Picker
|
||||
|
||||
Concurrently with the writing of this spec, work is being done to add a "color
|
||||
picker" for tabs, that lets the user manually set a background color for tabs.
|
||||
This may in the future cause some complications with setting a color for tabs
|
||||
from the theme.
|
||||
|
||||
When both features are combined, the color set at runtime but the color picker
|
||||
should override whatever color the user has set in the theme. When the color
|
||||
picker "clears" the color it has set for the tab, it should revert to the color
|
||||
from the theme (if one is set).
|
||||
|
||||
Also mentioned in the implementation of the color picker feature was the ability
|
||||
to not set the entire color of the tab, but just the color of a tab "overline",
|
||||
similar to the way Firefox (by default) styles the focused tab.
|
||||
|
||||
Currently, the `TabView` doesn't support a tab "overline" like this, however, in
|
||||
the future where this is possible, we'd love to also support such an overline.
|
||||
However, the story of setting the tab color manually becomes a bit more
|
||||
confusing now.
|
||||
|
||||
* The user should be able to set both the `tab.background` and `tab.overline`
|
||||
colors in a theme.
|
||||
* The user should be able to configure whether the color picker sets the
|
||||
`background` or the `overline` color of the tab.
|
||||
|
||||
The second setting added above will allow the user to change what's controlled
|
||||
by the color picker. Similarly to how the color picker can set the background of
|
||||
the tab to override the background from the theme, the user could configure the
|
||||
color picker to be able to change the overline color, not the background color
|
||||
of the tab. Then, when the user uses the color picker, the overline color will
|
||||
be overridden by the color picker, instead of the tab background color.
|
||||
|
||||
**Other things to consider:**
|
||||
* Users might want to be able to set a tab color as a part of the profile. One
|
||||
could imagine wanting to set the tab background color for Windows PowerShell
|
||||
to `rgb(1, 36, 86)` automatically. If we make this property part of the
|
||||
Profile, then we should use the profile's value as the runtime-override (of
|
||||
the theme value) for this property. If the color picker is used to set the
|
||||
color of the tab, then it'll override the runtime color for that tab.
|
||||
- How does this interact with multiple Panes in a tab? Should the Tab
|
||||
override color be per-terminal instance? If the terminal has a tab color,
|
||||
then that would override the theme, but not the tab's own override color?
|
||||
- If that were the case, the order of precedence would be:
|
||||
1. A color set at runtime with the color picker
|
||||
2. A color from the active terminal within the tab, if it has one
|
||||
3. The tab color from the theme
|
||||
* Users might want to be able to configure the titlebar to use a color based off
|
||||
the active tab color. We might need an additional special value like
|
||||
`terminalBackground` that lets users say "I want to use the active tab color
|
||||
as the titlebar color".
|
||||
- During [#3789], there was a point where the terminal raised actually
|
||||
implemented something like this. In it's implementation, the titlebar color
|
||||
would be slightly lighter or darker than the tab color (to provide some
|
||||
contrast). We'd want to make sure that the user could specify both "I want
|
||||
to use the tab color with some contrast applied" or just literally "Use
|
||||
whatever the active tab's color is."
|
||||
|
||||
### Default Themes
|
||||
|
||||
Late in 1.0, we renamed the old property `requestedTheme` to just `theme`.
|
||||
Currently, the user can use that property to simply set the XAML
|
||||
`RequestedTheme` property, which controls the theming of all the XAML UI
|
||||
elements. Currently, they can set that value to one of `light`, `dark` or
|
||||
`system`.
|
||||
|
||||
To maintain backwards compatibility with that setting, we'll introduce _three_
|
||||
themes to `defaults.json`:
|
||||
|
||||
```json
|
||||
"themes": [
|
||||
{
|
||||
"name": "light",
|
||||
"window":{
|
||||
"applicationTheme": "light"
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "dark",
|
||||
"window":{
|
||||
"applicationTheme": "dark"
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "system",
|
||||
"window":{
|
||||
"applicationTheme": "system"
|
||||
},
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Each of these themes will only define one property by default: the
|
||||
`window.applicationTheme` property, which is now responsible for setting the
|
||||
XAML `RequestedTheme` property. With these default themes, the user will still
|
||||
be able to use the old names seamlessly to get the same behavior.
|
||||
|
||||
Additionally, the user will NOT be able to override these built-in themes.
|
||||
Experience trying to not serialize the default color schemes has proven
|
||||
exceptionally tricky, so we're not going to allow that for the built-in themes.
|
||||
The user will always need to fork them to create a new theme. If they're found
|
||||
in the user settings file, we'll just ignore them.
|
||||
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
[TODO!]: # TODO: We should include more mockups here. That would be nice.
|
||||
|
||||

|
||||
_fig 1_: Using a tab color set to "terminalBackground". The Windows PowerShell
|
||||
tab has also set its color with the color picker.
|
||||
|
||||

|
||||
_fig 2_: Using an acrylic titlebar color, with a tab color set to
|
||||
"terminalBackground"
|
||||
|
||||

|
||||
_fig 3_: Using an acrylic terminal background, and the titlebar color is set to
|
||||
"terminalBackground"
|
||||
|
||||
 _fig
|
||||
4_: Using a single image as the background for the window, with a transparent
|
||||
tab row, and rounded bottoms on the TabViewItems. Courtesy of
|
||||
[@Shomnipotence](https://github.com/microsoft/terminal/issues/3327#issuecomment-765493313)
|
||||
|
||||
 _fig
|
||||
5_: Using a bottom corner radius to make tabs appear like buttons on the tab row. Courtesy of
|
||||
[@simioni](https://github.com/microsoft/terminal/issues/3774#issuecomment-609408305)
|
||||
|
||||
|
||||
[TODO!]: # TODO: Settings UI mocks? These pretty substantially affect the UI.
|
||||
<!-- We probably need to expose them in the UI in some way, and not just leave them as "power user settings" -->
|
||||
|
||||
## Potential Issues
|
||||
|
||||
It's totally possible for the user to set some sort of theme that just looks
|
||||
bad. This is absolutely a "beauty in the eye of the beholder" situation - not
|
||||
everyone is going to like the appearance of every theme. The goal of the
|
||||
Terminal is to provide a basic theme that's appropriate for anyone, but empower
|
||||
users to customize the terminal however they see fit. If the user chooses a
|
||||
theme that's not particularly appealing, they can always change it back.
|
||||
|
||||
### Accessibility
|
||||
|
||||
For people using the default theming, there should not be any particular
|
||||
regressions. However, this change does open up the Terminal to changes that
|
||||
might make the Terminal less accessible with certain theme configurations. As
|
||||
these themes would all be user-defined and controlled by the user, we're not
|
||||
concerned that this will be much of an issue. If a user finds one of their
|
||||
themes is less accessible, they can always change the theme to be more
|
||||
appropriate for them, or even switch to another theme.
|
||||
|
||||
Furthermore, this might _help_ certain accessibility stories. Users could pick
|
||||
themes with _even more_ contrast than the Terminal provides by default, or
|
||||
larger font sizes, which might help make parts of the Terminal _more_ visible
|
||||
than the default UI.
|
||||
|
||||
### Security
|
||||
|
||||
This should not introduce any _new_ security concerns. We're relying on the
|
||||
security of jsoncpp for parsing json. Adding new keys to the settings file
|
||||
will rely on jsoncpp's ability to securely parse those json values.
|
||||
|
||||
### Reliability
|
||||
|
||||
This change should not have any particular reliability concerns.
|
||||
|
||||
### Compatibility
|
||||
|
||||
The biggest compatibility concern is regarding the existing values for the
|
||||
`theme` property, which is addressed above.
|
||||
|
||||
#### `useAcrylicInTabRow` migration
|
||||
|
||||
[TODO!]: # TODO: Deprecating the current titlebar acrylic setting, or totally overriding in theme.
|
||||
|
||||
#### `experimental.useBackgroundImageForWindow` migration
|
||||
|
||||
[TODO!]: # TODO: Deprecating the current setting or migrating or whatever
|
||||
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
This change should not have any particular performance concerns. Additional
|
||||
acrylic usage might impact battery life. There's not much concern for any
|
||||
substantial new impacts, however.
|
||||
|
||||
### Branding
|
||||
|
||||
Are we concerned that by enabling theming, the appearance of the Terminal won't
|
||||
be as static, and won't necessarily have as specific a look? It might be harder
|
||||
for potential users see a screenshot of the Terminal and _know_ "Thats the
|
||||
Windows Terminal". Is this something we're really all that concerned about
|
||||
though? If this is something users want (it is), then shouldn't that be what
|
||||
matters?
|
||||
|
||||
### Titlebar complications
|
||||
|
||||
Unfortunately, the original User32 titlebar is actually always drawn underneath
|
||||
our titlebar. Even when the tabs are in the titlebar, that's actually just XAML
|
||||
content drawn on top of the original frame. The rest of the window is
|
||||
transparent, but the titlebar is there.
|
||||
|
||||
Our design to enable unfocused acrylic to work relies on in-app acrylic to allow
|
||||
the acrylic to blur with the transparent window contents. However, since the
|
||||
User32 titlebar is always there, in-app acrylic would end up always blurring
|
||||
_the original titlebar_, which looks ridiculous. This means we can't have
|
||||
unfocused acrylic without showing that titlebar. We'd rather remove that
|
||||
foot gun, and make it explicit that this setting does not exist.
|
||||
|
||||
### Light & dark mode theming
|
||||
|
||||
One request that comes up with frequency is the ability to change the color
|
||||
scheme of a profile automatically based on the system theme. Many users have
|
||||
scripts that automatically change between light and dark theme in the OS based
|
||||
on time of day.
|
||||
|
||||
One thing this design does not do well is account for such theme-switching
|
||||
scenarios. This design assumes a static set of colors for a whole Terminal
|
||||
theme, regardless of whatever `window.applicationTheme` is set to. Should the
|
||||
user leave `window.applicationTheme` set to `system`, it's entirely likely that
|
||||
they would like the rest of their colors to automatically update to match.
|
||||
|
||||
To address this, we'll allow the window-level `theme` property to not only allow
|
||||
a string for a name-based lookup in the list of themes, but als an object. That
|
||||
object will accept two properties: `light` and `dark`. Each of these accepts a
|
||||
string representing the name of a theme to use for that specific OS theme. These
|
||||
strings will default to `"light"` and `"dark"` respectively.
|
||||
```jsonc
|
||||
{
|
||||
"theme": {
|
||||
"light": "my light theme",
|
||||
"dark": "my dark theme"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Also considered: allow the user to set their own brushes as part of a theme, like:
|
||||
```jsonc
|
||||
{
|
||||
"name": "My theme aware theme",
|
||||
"brushes": {
|
||||
"light": {
|
||||
"Foo": "#ff0000"
|
||||
},
|
||||
"dark": {
|
||||
"Foo": "#00ff00"
|
||||
}
|
||||
},
|
||||
"window.applicationTheme": "system",
|
||||
"tabRow.background": "key:Foo",
|
||||
}
|
||||
```
|
||||
This seemed far too complicated to actually understand. -->
|
||||
|
||||
### Admin window themes
|
||||
|
||||
[TODO!]: # TODO! Any clever ideas?
|
||||
|
||||
Same idea as the light vs dark mode theme ideas. How should users be able to
|
||||
style admin vs regular windows?
|
||||
|
||||
## Addenda
|
||||
|
||||
This spec also has a follow-up spec which elaborates on the complexities of Mica
|
||||
in the Terminal. Please also refer to:
|
||||
|
||||
* [Mica in the Terminal]
|
||||
|
||||
## Future considerations
|
||||
|
||||
* Mentioned in [#7005] was the idea of shipping a default theme that had values
|
||||
aligned with the appearance of the Edge browser. Perhaps something like:
|
||||
```jsonc
|
||||
{
|
||||
"name": "Edge",
|
||||
"window":{
|
||||
"applicationTheme": "system"
|
||||
},
|
||||
"tab": {
|
||||
"background": "#whatever-color-edge-is" // Might need a "key:" resource here for light/dark theme switching
|
||||
},
|
||||
"tabRow":{
|
||||
"background": "accent",
|
||||
}
|
||||
},
|
||||
```
|
||||
* Applications should be able to install themes as fragments.
|
||||
- We probably shouldn't allow layering for fragment themes - don't want
|
||||
`foo.exe` installing a `light` theme that totally overrides the built-in
|
||||
one. Right? **TODO! DISCUSSION**
|
||||
* ~I don't think it's unreasonable to implement support for `theme` as either a
|
||||
string or an object. If `theme` is a string, then we can do a name-based
|
||||
lookup in a table of themes. If it's an object, we can just use that object
|
||||
immediately. Doing this might provide a simpler implementation plan whereby we
|
||||
allow `"default"|"light"|"dark"|{object}` at first, and then later add the
|
||||
list of themes.~
|
||||
- This was a cool idea, but ultimately discarded in favor of the OS light/dark
|
||||
theme switching, which needed the object version of `theme` to be reserved
|
||||
for the OS mode lookup.
|
||||
* A cool idea from discussion: `window.highContrastSchemes` as a theme member
|
||||
that controls a per-control property. This would override the color scheme of
|
||||
any pane with a high contrast version, ignoring any colors emitted by the
|
||||
client application. Details are left for a future spec.
|
||||
|
||||
#### Theming v2 Properties
|
||||
|
||||
* `tab.padding`: Control the padding _within_ a tab between the text and the
|
||||
"sides" of the tab
|
||||
* `tab.textColor`: Change the color of the text on a tab
|
||||
* `tabRow.shadows`: Enable/disable the tab "shadows"
|
||||
- note that they're enabled by default and already nearly impossible to see in
|
||||
dark mode.
|
||||
* `tabRow.height`: Change the height of the tab row.
|
||||
* `tabRow.underlineHeight`: Controls the height of a border placed between the
|
||||
tab row and the Terminal panes beneath it. This border doesn't exist
|
||||
currently.
|
||||
* `tabRow.underlineColor`: Controls the color of the aforementioned underline
|
||||
* `window.frameColor`: The `DWMWA_BORDER_COLOR` DWM attribute is [SUPER fun to
|
||||
play with], and trivial to set. We should definitely exposed it.
|
||||
|
||||
<!-- Footnotes -->
|
||||
|
||||
[iTerm2-Color-Schemes]: https://github.com/mbadolato/iTerm2-Color-Schemes
|
||||
[#3061]: https://github.com/microsoft/terminal/issues/3061
|
||||
[#3062]: https://github.com/microsoft/terminal/issues/3062
|
||||
[#702]: https://github.com/microsoft/terminal/issues/702
|
||||
[#1337]: https://github.com/microsoft/terminal/issues/1337
|
||||
[#2994]: https://github.com/microsoft/terminal/issues/2994
|
||||
[#3774]: https://github.com/microsoft/terminal/issues/3774
|
||||
[#3789]: https://github.com/microsoft/terminal/pull/3789
|
||||
[#1963]: https://github.com/microsoft/terminal/issues/1963
|
||||
[#3335]: https://github.com/microsoft/terminal/issues/3335
|
||||
[#3459]: https://github.com/microsoft/terminal/issues/3459
|
||||
[#7005]: https://github.com/microsoft/terminal/issues/7005
|
||||
|
||||
[#5280]: https://github.com/microsoft/terminal/pull/5280
|
||||
|
||||
[microsoft-ui-xaml#2201]: https://github.com/microsoft/microsoft-ui-xaml/pull/2201#issuecomment-606888293
|
||||
[#12893]: https://github.com/microsoft/terminal/pull/12893
|
||||
[Mica in the Terminal]: ./%2310509%20-%20Mica.md
|
||||
[Mica Spec]: ./%2310509%20-%20Mica.md
|
||||
[SUPER fun to play with]: https://github.com/microsoft/terminal/issues/12950
|
||||
[fragment extensions]: https://docs.microsoft.com/en-us/windows/terminal/json-fragment-extensions
|
||||
|
Before Width: | Height: | Size: 401 KiB |
|
Before Width: | Height: | Size: 779 KiB |
|
Before Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 905 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 2.0 MiB |
@@ -114,7 +114,7 @@ The jumplist will have to be saved each time a profile change occurs but the fre
|
||||
|
||||
#### Should it open a new instance of the terminal or open in a new tab?
|
||||
|
||||
#### What should happen if a nonexistent profile is launched
|
||||
#### What should happen if a non existent profile is launched
|
||||
The jumplist is only updated when the application is running so the profiles could be modified or deleted outside and the jumplist will not be updated. Handling will be done by whatever handles the command line parsing.
|
||||
|
||||
## Future considerations
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/chromium/chromium",
|
||||
"commitHash": "d8710dd959da8e3be56f20af8cc94fbf560fbb6b"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/chromium/chromium",
|
||||
"commitHash": "d8710dd959da8e3be56f20af8cc94fbf560fbb6b"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/pinam45/dynamic_bitset",
|
||||
"commitHash": "00f2d066ce9deebf28b006636150e5a882beb83f"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/pinam45/dynamic_bitset",
|
||||
"commitHash": "00f2d066ce9deebf28b006636150e5a882beb83f"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/fmtlib/fmt",
|
||||
"commitHash": "7bdf0628b1276379886c7f6dda2cef2b3b374f0b"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/fmtlib/fmt",
|
||||
"commitHash": "7bdf0628b1276379886c7f6dda2cef2b3b374f0b"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/ekg/intervaltree",
|
||||
"commitHash": "b90527f9e6d51cd36ecbb50429e4524d3a418ea5"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/kimwalisch/libpopcnt",
|
||||
"commitHash": "043a99fba31121a70bcb2f589faa17f534ae6085"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/kimwalisch/libpopcnt",
|
||||
"commitHash": "043a99fba31121a70bcb2f589faa17f534ae6085"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
### Notes for Future Maintainers
|
||||
|
||||
[wyhash](https://github.com/wangyi-fudan/wyhash) is used as the hash algorithm for `<til/hash.h>` and its `til::hasher`.
|
||||
The source code was directly integrated into that header file and can be found in `/src/inc/til/hash.h`.
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/wangyi-fudan/wyhash",
|
||||
"commitHash": "e77036ac1943369dc03e611cde52a8570f8ceefe"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://gitlab.freedesktop.org/xorg/app/rgb.git",
|
||||
"commitHash": "97820e748eb496a1f6d3fc3bf89688f0ce1f64f9"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://gitlab.freedesktop.org/xorg/app/rgb.git",
|
||||
"commitHash": "97820e748eb496a1f6d3fc3bf89688f0ce1f64f9"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
||||
@@ -2,46 +2,47 @@
|
||||
Texture2D shaderTexture;
|
||||
SamplerState samplerState;
|
||||
|
||||
cbuffer PixelShaderSettings
|
||||
{
|
||||
float time;
|
||||
float scale;
|
||||
float2 resolution;
|
||||
float4 background;
|
||||
cbuffer PixelShaderSettings {
|
||||
float Time;
|
||||
float Scale;
|
||||
float2 Resolution;
|
||||
float4 Background;
|
||||
};
|
||||
|
||||
#define SCANLINE_FACTOR 0.5f
|
||||
#define SCALED_SCANLINE_PERIOD scale
|
||||
#define SCALED_GAUSSIAN_SIGMA (2.0f * scale)
|
||||
#define SCANLINE_FACTOR 0.5
|
||||
#define SCALED_SCANLINE_PERIOD Scale
|
||||
#define SCALED_GAUSSIAN_SIGMA (2.0*Scale)
|
||||
|
||||
static const float M_PI = 3.14159265f;
|
||||
|
||||
float Gaussian2D(float x, float y, float sigma)
|
||||
{
|
||||
return 1 / (sigma * sqrt(2 * M_PI)) * exp(-0.5 * (x * x + y * y) / sigma / sigma);
|
||||
return 1/(sigma*sqrt(2*M_PI)) * exp(-0.5*(x*x + y*y)/sigma/sigma);
|
||||
}
|
||||
|
||||
float4 Blur(Texture2D input, float2 tex_coord, float sigma)
|
||||
{
|
||||
float width, height;
|
||||
uint width, height;
|
||||
shaderTexture.GetDimensions(width, height);
|
||||
|
||||
float texelWidth = 1.0f / width;
|
||||
float texelHeight = 1.0f / height;
|
||||
float texelWidth = 1.0f/width;
|
||||
float texelHeight = 1.0f/height;
|
||||
|
||||
float4 color = { 0, 0, 0, 0 };
|
||||
|
||||
float sampleCount = 13;
|
||||
int sampleCount = 13;
|
||||
|
||||
for (float x = 0; x < sampleCount; x++)
|
||||
for (int x = 0; x < sampleCount; x++)
|
||||
{
|
||||
float2 samplePos = { 0, 0 };
|
||||
samplePos.x = tex_coord.x + (x - sampleCount / 2.0f) * texelWidth;
|
||||
|
||||
for (float y = 0; y < sampleCount; y++)
|
||||
samplePos.x = tex_coord.x + (x - sampleCount/2) * texelWidth;
|
||||
for (int y = 0; y < sampleCount; y++)
|
||||
{
|
||||
samplePos.y = tex_coord.y + (y - sampleCount / 2.0f) * texelHeight;
|
||||
color += input.Sample(samplerState, samplePos) * Gaussian2D(x - sampleCount / 2.0f, y - sampleCount / 2.0f, sigma);
|
||||
samplePos.y = tex_coord.y + (y - sampleCount/2) * texelHeight;
|
||||
if (samplePos.x <= 0 || samplePos.y <= 0 || samplePos.x >= width || samplePos.y >= height) continue;
|
||||
|
||||
color += input.Sample(samplerState, samplePos) * Gaussian2D((x - sampleCount/2), (y - sampleCount/2), sigma);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +51,7 @@ float4 Blur(Texture2D input, float2 tex_coord, float sigma)
|
||||
|
||||
float SquareWave(float y)
|
||||
{
|
||||
return 1.0f - (floor(y / SCALED_SCANLINE_PERIOD) % 2.0f) * SCANLINE_FACTOR;
|
||||
return 1 - (floor(y / SCALED_SCANLINE_PERIOD) % 2) * SCANLINE_FACTOR;
|
||||
}
|
||||
|
||||
float4 Scanline(float4 color, float4 pos)
|
||||
@@ -59,9 +60,9 @@ float4 Scanline(float4 color, float4 pos)
|
||||
|
||||
// TODO:GH#3929 make this configurable.
|
||||
// Remove the && false to draw scanlines everywhere.
|
||||
if (length(color.rgb) < 0.2f && false)
|
||||
if (length(color.rgb) < 0.2 && false)
|
||||
{
|
||||
return color + wave * 0.1f;
|
||||
return color + wave*0.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -69,14 +70,14 @@ float4 Scanline(float4 color, float4 pos)
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
|
||||
// clang-format on
|
||||
{
|
||||
Texture2D input = shaderTexture;
|
||||
|
||||
// TODO:GH#3930 Make these configurable in some way.
|
||||
float4 color = shaderTexture.Sample(samplerState, tex);
|
||||
color += Blur(shaderTexture, tex, SCALED_GAUSSIAN_SIGMA) * 0.3f;
|
||||
float4 color = input.Sample(samplerState, tex);
|
||||
color += Blur(input, tex, SCALED_GAUSSIAN_SIGMA)*0.3;
|
||||
color = Scanline(color, pos);
|
||||
|
||||
return color;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\wap-common.build.pre.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
@@ -87,6 +87,10 @@
|
||||
Since PRI file generation is _before_ manifest generation (for possibly obvious or
|
||||
important reasons), that doesn't work for us.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<!-- Only for MSBuild versions < 16.3.0 -->
|
||||
<_GenerateProjectPriFileDependsOn Condition="$(MSBuildVersion) < '16.3.0'">OpenConsoleLiftDesktopBridgePriFiles;$(_GenerateProjectPriFileDependsOn)</_GenerateProjectPriFileDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="OpenConsoleLiftDesktopBridgePriFiles" DependsOnTargets="_ConvertItems">
|
||||
<ItemGroup>
|
||||
<_PriFile Include="@(_NonWapProjProjectOutput)" Condition="'%(Extension)' == '.pri'" />
|
||||
@@ -136,12 +140,12 @@
|
||||
<!-- **END VC LIBS HACK** -->
|
||||
|
||||
<!-- This is required to get the package dependency in the AppXManifest. -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<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')" />
|
||||
<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.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<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'))" />
|
||||
</Target>
|
||||
|
||||
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "MyPage.h"
|
||||
#include "MySettings.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "MyPage.g.cpp"
|
||||
#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
|
||||
#include "..\..\..\src\types\inc\utils.hpp"
|
||||
#include "MySettings.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
@@ -28,7 +26,7 @@ namespace winrt::SampleApp::implementation
|
||||
|
||||
void MyPage::Create()
|
||||
{
|
||||
auto settings = winrt::make_self<MySettings>();
|
||||
auto settings = winrt::make_self<implementation::MySettings>();
|
||||
|
||||
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted in-proc...",
|
||||
winrt::hstring{},
|
||||
@@ -46,216 +44,6 @@ 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,18 +14,11 @@ 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);
|
||||
hstring Title();
|
||||
|
||||
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,23 +23,9 @@
|
||||
<TextBox x:Name="GuidInput"
|
||||
Width="400"
|
||||
PlaceholderText="{}{guid here}" />
|
||||
<Button x:Name="CreateOutOfProcControl"
|
||||
Grid.Row="0"
|
||||
Tapped="CreateClicked">
|
||||
<Button Grid.Row="0">
|
||||
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>
|
||||
|
||||
@@ -60,26 +46,14 @@
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#ff0000" />
|
||||
|
||||
<Grid Grid.Column="1"
|
||||
<Grid x:Name="OutOfProcContent"
|
||||
Grid.Column="1"
|
||||
Padding="16"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#0000ff" />
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{a4394404-37f7-41c1-802b-49788d3720e3}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
@@ -17,15 +17,9 @@
|
||||
<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>
|
||||
@@ -153,15 +147,14 @@
|
||||
<!-- ========================= Globals ======================== -->
|
||||
<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" />
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<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')" />
|
||||
<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.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.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'))" />
|
||||
<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>
|
||||
|
||||
<!--
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{26c51792-41a3-4fe0-ab5e-8b69d557bf91}</ProjectGuid>
|
||||
<ProjectName>SampleApp</ProjectName>
|
||||
@@ -11,13 +11,9 @@
|
||||
<!-- 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 -->
|
||||
@@ -83,20 +79,15 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ====================== Compiler & Linker Flags ===================== -->
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(OpenConsoleCommonOutDir)\ConTypes.lib;WindowsApp.lib;shell32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.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')" />
|
||||
<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.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.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'))" />
|
||||
<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>
|
||||
@@ -111,7 +102,4 @@
|
||||
</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,
|
||||
1024,
|
||||
860,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
nullptr,
|
||||
nullptr,
|
||||
wc.hInstance,
|
||||
@@ -104,6 +104,8 @@ void SampleIslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam)
|
||||
|
||||
void SampleIslandWindow::Initialize()
|
||||
{
|
||||
const bool initialized = (_interopWindowHandle != nullptr);
|
||||
|
||||
_source = DesktopWindowXamlSource{};
|
||||
|
||||
auto interop = _source.as<IDesktopWindowXamlSourceNative>();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<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>
|
||||
@@ -15,15 +16,7 @@
|
||||
<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>
|
||||
@@ -144,12 +137,17 @@
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<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.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.3-prerelease.220816001\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<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.
|
||||
@@ -227,24 +225,13 @@
|
||||
<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" />
|
||||
|
||||
<!-- 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)\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')" />
|
||||
</Project>
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="Console Rules" Description="These rules enforce static analysis on console code." ToolsVersion="17.0">
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="Console Rules" Description="These rules enforce static analysis on console code." ToolsVersion="15.0">
|
||||
|
||||
<Include Path="cppcorecheckrules.ruleset" Action="Error" />
|
||||
|
||||
<Rules AnalyzerId="Microsoft.Analyzers.NativeCodeAnalysis" RuleNamespace="Microsoft.Rules.Native">
|
||||
<Rule Id="C6001" Action="Error" />
|
||||
<Rule Id="C6011" Action="Error" />
|
||||
<Rules AnalyzerId="Microsoft.Analyzers.NativeCodeAnalysis" RuleNamespace="Microsoft.Rules.Native">
|
||||
<Rule Id="C6001" Action="Error" />
|
||||
<Rule Id="C6011" Action="Error" />
|
||||
<!-- We can't do dynamic cast because RTTI is off. -->
|
||||
<!-- RTTI is off because Windows OS policies believe RTTI has too much binary size impact for the value and is less portable than RTTI-off modules. -->
|
||||
<Rule Id="C26466" Action="None" />
|
||||
<!-- This one has caught us off guard as it suddenly showed up. Re-enablement is going to be in #2941 -->
|
||||
<Rule Id="C26814" Action="None" />
|
||||
|
||||
<!-- There are *so many* enums that should be enum classes. -->
|
||||
<Rule Id="C26812" Action="None" />
|
||||
</Rules>
|
||||
|
||||
|
||||
</RuleSet>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{9cf74355-f018-4c19-81ad-9dc6b7f2c6f5}</ProjectGuid>
|
||||
<RootNamespace>apimswincoresynchl120</RootNamespace>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="definitions.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>kernel32.lib</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>definitions.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="definitions.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
19
src/api-ms-win-core-synch-l1-2-0/definitions.def
Normal file
@@ -0,0 +1,19 @@
|
||||
LIBRARY
|
||||
EXPORTS
|
||||
DeleteSynchronizationBarrier = kernel32.DeleteSynchronizationBarrier
|
||||
EnterSynchronizationBarrier = kernel32.EnterSynchronizationBarrier
|
||||
InitOnceBeginInitialize = kernel32.InitOnceBeginInitialize
|
||||
InitOnceComplete = kernel32.InitOnceComplete
|
||||
InitOnceExecuteOnce = kernel32.InitOnceExecuteOnce
|
||||
InitOnceInitialize = kernel32.InitOnceInitialize
|
||||
InitializeConditionVariable = kernel32.InitializeConditionVariable
|
||||
InitializeSynchronizationBarrier = kernel32.InitializeSynchronizationBarrier
|
||||
SignalObjectAndWait = kernel32.SignalObjectAndWait
|
||||
Sleep = kernel32.Sleep
|
||||
SleepConditionVariableCS = kernel32.SleepConditionVariableCS
|
||||
SleepConditionVariableSRW = kernel32.SleepConditionVariableSRW
|
||||
WaitOnAddress
|
||||
WakeAllConditionVariable = kernel32.WakeAllConditionVariable
|
||||
WakeByAddressAll
|
||||
WakeByAddressSingle
|
||||
WakeConditionVariable = kernel32.WakeConditionVariable
|
||||
189
src/api-ms-win-core-synch-l1-2-0/main.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
//
|
||||
// The code in this file was adapted from the STL on the 2021-07-05. Commit:
|
||||
// https://github.com/microsoft/STL/blob/e745bad3b1d05b5b19ec652d68abb37865ffa454/stl/src/atomic_wait.cpp
|
||||
//
|
||||
// It backports the following Windows 8 functions to Windows 7:
|
||||
// * WaitOnAddress
|
||||
// * WakeByAddressSingle
|
||||
// * WakeByAddressAll
|
||||
//
|
||||
|
||||
#include <cstdint>
|
||||
#include <new>
|
||||
|
||||
#include <winsdkver.h>
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#include <sdkddkver.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <intrin.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
class [[nodiscard]] SRWLockGuard
|
||||
{
|
||||
public:
|
||||
explicit SRWLockGuard(SRWLOCK& lock) noexcept :
|
||||
_lock(&lock)
|
||||
{
|
||||
AcquireSRWLockExclusive(_lock);
|
||||
}
|
||||
|
||||
~SRWLockGuard()
|
||||
{
|
||||
ReleaseSRWLockExclusive(_lock);
|
||||
}
|
||||
|
||||
SRWLockGuard(const SRWLockGuard&) = delete;
|
||||
SRWLockGuard& operator=(const SRWLockGuard&) = delete;
|
||||
|
||||
SRWLockGuard(SRWLockGuard&&) = delete;
|
||||
SRWLockGuard& operator=(SRWLockGuard&&) = delete;
|
||||
|
||||
private:
|
||||
SRWLOCK* _lock;
|
||||
};
|
||||
|
||||
struct WaitContext
|
||||
{
|
||||
const volatile void* address;
|
||||
WaitContext* next;
|
||||
WaitContext* prev;
|
||||
CONDITION_VARIABLE cv;
|
||||
};
|
||||
|
||||
struct [[nodiscard]] GuardedWaitContext : WaitContext
|
||||
{
|
||||
GuardedWaitContext(const volatile void* storage, WaitContext* head) noexcept :
|
||||
WaitContext{ storage, head, head->prev, CONDITION_VARIABLE_INIT }
|
||||
{
|
||||
prev->next = this;
|
||||
next->prev = this;
|
||||
}
|
||||
|
||||
~GuardedWaitContext()
|
||||
{
|
||||
const auto n = next;
|
||||
const auto p = prev;
|
||||
next->prev = p;
|
||||
prev->next = n;
|
||||
}
|
||||
|
||||
GuardedWaitContext(const GuardedWaitContext&) = delete;
|
||||
GuardedWaitContext& operator=(const GuardedWaitContext&) = delete;
|
||||
|
||||
GuardedWaitContext(GuardedWaitContext&&) = delete;
|
||||
GuardedWaitContext& operator=(GuardedWaitContext&&) = delete;
|
||||
};
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
|
||||
struct alignas(std::hardware_destructive_interference_size) WaitTableEntry
|
||||
{
|
||||
SRWLOCK lock = SRWLOCK_INIT;
|
||||
WaitContext head = { nullptr, &head, &head, CONDITION_VARIABLE_INIT };
|
||||
};
|
||||
#pragma warning(pop)
|
||||
|
||||
[[nodiscard]] WaitTableEntry& GetWaitTableEntry(const volatile void* const storage) noexcept
|
||||
{
|
||||
// A prime number for the hash table size was chosen to prevent collisions.
|
||||
constexpr size_t size = 251;
|
||||
constexpr std::hash<uintptr_t> hasher;
|
||||
|
||||
static WaitTableEntry table[size];
|
||||
#pragma warning(suppress : 26446) // Prefer to use gsl::at() instead of unchecked subscript operator
|
||||
#pragma warning(suppress : 26482) // Only index into arrays using constant expressions
|
||||
#pragma warning(suppress : 26490) // Don't use reinterpret_cast
|
||||
return table[hasher(reinterpret_cast<uintptr_t>(storage)) % size];
|
||||
}
|
||||
|
||||
#pragma warning(suppress : 26429) // Symbol 'comparand' is never tested for nullness, it can be marked as not_null
|
||||
bool AreEqual(const volatile void* storage, const void* comparand, size_t size) noexcept
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
return __iso_volatile_load8(static_cast<const volatile __int8*>(storage)) == *static_cast<const __int8*>(comparand);
|
||||
case 2:
|
||||
return __iso_volatile_load16(static_cast<const volatile __int16*>(storage)) == *static_cast<const __int16*>(comparand);
|
||||
case 4:
|
||||
return __iso_volatile_load32(static_cast<const volatile __int32*>(storage)) == *static_cast<const __int32*>(comparand);
|
||||
case 8:
|
||||
return __iso_volatile_load64(static_cast<const volatile __int64*>(storage)) == *static_cast<const __int64*>(comparand);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
} // unnamed namespace
|
||||
|
||||
extern "C" BOOL WINAPI WaitOnAddress(_In_reads_bytes_(AddressSize) volatile VOID* Address, _In_reads_bytes_(AddressSize) PVOID CompareAddress, _In_ SIZE_T AddressSize, _In_opt_ DWORD dwMilliseconds)
|
||||
{
|
||||
auto& entry = GetWaitTableEntry(Address);
|
||||
|
||||
SRWLockGuard guard{ entry.lock };
|
||||
GuardedWaitContext context{ Address, &entry.head };
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// NOTE: under lock to prevent lost wakes
|
||||
if (!AreEqual(Address, CompareAddress, AddressSize))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!SleepConditionVariableSRW(&context.cv, &entry.lock, dwMilliseconds, 0))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (GetLastError() != ERROR_TIMEOUT)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dwMilliseconds != INFINITE)
|
||||
{
|
||||
// spurious wake to recheck the clock
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" VOID WINAPI WakeByAddressSingle(_In_ PVOID Address)
|
||||
{
|
||||
auto& entry = GetWaitTableEntry(Address);
|
||||
SRWLockGuard guard(entry.lock);
|
||||
|
||||
for (auto context = entry.head.next; context != &entry.head; context = context->next)
|
||||
{
|
||||
if (context->address == Address)
|
||||
{
|
||||
// Can't move wake outside SRWLOCKed section: SRWLOCK also protects the context itself
|
||||
WakeAllConditionVariable(&context->cv);
|
||||
// This break; is the difference between WakeByAddressSingle and WakeByAddressAll
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" VOID WINAPI WakeByAddressAll(_In_ PVOID Address)
|
||||
{
|
||||
auto& entry = GetWaitTableEntry(Address);
|
||||
SRWLockGuard guard(entry.lock);
|
||||
|
||||
for (auto context = entry.head.next; context != &entry.head; context = context->next)
|
||||
{
|
||||
if (context->address == Address)
|
||||
{
|
||||
// Can't move wake outside SRWLOCKed section: SRWLOCK also protects the context itself
|
||||
WakeAllConditionVariable(&context->cv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
DIRS=midi \
|
||||
|
||||
@@ -5,30 +5,55 @@
|
||||
#include "MidiAudio.hpp"
|
||||
#include "../terminal/parser/stateMachine.hpp"
|
||||
|
||||
#include <dsound.h>
|
||||
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
#pragma comment(lib, "dsound.lib")
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
// The WAVE_DATA below is an 8-bit PCM encoding of a triangle wave form.
|
||||
// We just play this on repeat at varying frequencies to produce our notes.
|
||||
constexpr auto WAVE_SIZE = 16u;
|
||||
constexpr auto WAVE_DATA = std::array<byte, WAVE_SIZE>{ 128, 159, 191, 223, 255, 223, 191, 159, 128, 96, 64, 32, 0, 32, 64, 96 };
|
||||
|
||||
MidiAudio::MidiAudio(HWND windowHandle)
|
||||
namespace
|
||||
{
|
||||
if (SUCCEEDED(DirectSoundCreate8(nullptr, &_directSound, nullptr)))
|
||||
class MidiOut
|
||||
{
|
||||
if (SUCCEEDED(_directSound->SetCooperativeLevel(windowHandle, DSSCL_NORMAL)))
|
||||
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
|
||||
{
|
||||
_createBuffers();
|
||||
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
|
||||
@@ -36,7 +61,7 @@ MidiAudio::~MidiAudio() noexcept
|
||||
#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.
|
||||
const auto lock = std::unique_lock{ _inUseMutex };
|
||||
_inUseMutex.lock();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -78,26 +103,13 @@ void MidiAudio::Unlock()
|
||||
void MidiAudio::PlayNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration) noexcept
|
||||
try
|
||||
{
|
||||
const auto& buffer = _buffers.at(_activeBufferIndex);
|
||||
if (velocity && buffer)
|
||||
// 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)
|
||||
{
|
||||
// The formula for frequency is 2^(n/12) * 440Hz, where n is zero for
|
||||
// the A above middle C (A4). In MIDI terms, A4 is note number 69,
|
||||
// which is why we subtract 69. We also need to multiply by the size
|
||||
// of the wave form to determine the frequency that the sound buffer
|
||||
// has to be played to achieve the equivalent note frequency.
|
||||
const auto frequency = std::pow(2.0, (noteNumber - 69.0) / 12.0) * 440.0 * WAVE_SIZE;
|
||||
buffer->SetFrequency(gsl::narrow_cast<DWORD>(frequency));
|
||||
// For the volume, we're using the formula defined in the General
|
||||
// MIDI Level 2 specification: Gain in dB = 40 * log10(v/127). We need
|
||||
// to multiply by 4000, though, because the SetVolume method expects
|
||||
// the volume to be in hundredths of a decibel.
|
||||
const auto volume = 4000.0 * std::log10(velocity / 127.0);
|
||||
buffer->SetVolume(gsl::narrow_cast<LONG>(volume));
|
||||
// Resetting the buffer to a position that is slightly off from the
|
||||
// last position will help to produce a clearer separation between
|
||||
// tones when repeating sequences of the same note.
|
||||
buffer->SetCurrentPosition((_lastBufferPosition + 12) % WAVE_SIZE);
|
||||
midiOut.OutputMessage(MidiOut::NOTE_ON, noteNumber, velocity);
|
||||
}
|
||||
|
||||
// By waiting on the shutdown future with the duration of the note, we'll
|
||||
@@ -105,48 +117,9 @@ try
|
||||
// of the wait early if we've been shutdown.
|
||||
_shutdownFuture.wait_for(duration);
|
||||
|
||||
if (velocity && buffer)
|
||||
if (velocity)
|
||||
{
|
||||
// When the note ends, we just turn the volume down instead of stopping
|
||||
// the sound buffer. This helps reduce unwanted static between notes.
|
||||
buffer->SetVolume(DSBVOLUME_MIN);
|
||||
buffer->GetCurrentPosition(&_lastBufferPosition, nullptr);
|
||||
midiOut.OutputMessage(MidiOut::NOTE_OFF, noteNumber, velocity);
|
||||
}
|
||||
|
||||
// Cycling between multiple buffers can also help reduce the static.
|
||||
_activeBufferIndex = (_activeBufferIndex + 1) % _buffers.size();
|
||||
}
|
||||
CATCH_LOG()
|
||||
|
||||
void MidiAudio::_createBuffers() noexcept
|
||||
{
|
||||
auto waveFormat = WAVEFORMATEX{};
|
||||
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
waveFormat.nChannels = 1;
|
||||
waveFormat.nSamplesPerSec = 8000;
|
||||
waveFormat.wBitsPerSample = 8;
|
||||
waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
|
||||
waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
|
||||
|
||||
auto bufferDescription = DSBUFFERDESC{};
|
||||
bufferDescription.dwSize = sizeof(DSBUFFERDESC);
|
||||
bufferDescription.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS;
|
||||
bufferDescription.dwBufferBytes = WAVE_SIZE;
|
||||
bufferDescription.lpwfxFormat = &waveFormat;
|
||||
|
||||
for (auto& buffer : _buffers)
|
||||
{
|
||||
if (SUCCEEDED(_directSound->CreateSoundBuffer(&bufferDescription, &buffer, nullptr)))
|
||||
{
|
||||
LPVOID bufferPtr;
|
||||
DWORD bufferSize;
|
||||
if (SUCCEEDED(buffer->Lock(0, 0, &bufferPtr, &bufferSize, nullptr, nullptr, DSBLOCK_ENTIREBUFFER)))
|
||||
{
|
||||
std::memcpy(bufferPtr, WAVE_DATA.data(), WAVE_DATA.size());
|
||||
buffer->Unlock(bufferPtr, bufferSize, nullptr, 0);
|
||||
}
|
||||
buffer->SetVolume(DSBVOLUME_MIN);
|
||||
buffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,13 @@ Abstract:
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
|
||||
struct IDirectSound8;
|
||||
struct IDirectSoundBuffer;
|
||||
|
||||
class MidiAudio
|
||||
{
|
||||
public:
|
||||
MidiAudio(HWND windowHandle);
|
||||
MidiAudio() = default;
|
||||
MidiAudio(const MidiAudio&) = delete;
|
||||
MidiAudio(MidiAudio&&) = delete;
|
||||
MidiAudio& operator=(const MidiAudio&) = delete;
|
||||
@@ -34,12 +30,6 @@ public:
|
||||
void PlayNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration) noexcept;
|
||||
|
||||
private:
|
||||
void _createBuffers() noexcept;
|
||||
|
||||
Microsoft::WRL::ComPtr<IDirectSound8> _directSound;
|
||||
std::array<Microsoft::WRL::ComPtr<IDirectSoundBuffer>, 2> _buffers;
|
||||
size_t _activeBufferIndex = 0;
|
||||
DWORD _lastBufferPosition = 0;
|
||||
std::promise<void> _shutdownPromise;
|
||||
std::future<void> _shutdownFuture;
|
||||
std::mutex _inUseMutex;
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
DIRS=lib \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<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>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
!include ..\sources.inc
|
||||
|
||||
# -------------------------------------
|
||||
# Program Information
|
||||
# -------------------------------------
|
||||
|
||||
TARGETNAME = ConAudioMidi
|
||||
TARGETTYPE = LIBRARY
|
||||
@@ -26,6 +26,5 @@ Abstract:
|
||||
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
#include <mmeapi.h>
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
!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); \
|
||||
@@ -28,13 +28,6 @@ constexpr til::inclusive_rect ScreenToBufferLine(const til::inclusive_rect& line
|
||||
return { line.Left >> scale, line.Top, line.Right >> scale, line.Bottom };
|
||||
}
|
||||
|
||||
constexpr til::point ScreenToBufferLine(const til::point& line, const LineRendition lineRendition)
|
||||
{
|
||||
// Use shift right to quickly divide the Left and Right by 2 for double width lines.
|
||||
const auto scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
|
||||
return { line.X >> scale, line.Y };
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@@ -357,6 +357,11 @@ void TextAttribute::SetReverseVideo(bool isReversed) noexcept
|
||||
WI_UpdateFlag(_wAttrLegacy, COMMON_LVB_REVERSE_VIDEO, isReversed);
|
||||
}
|
||||
|
||||
ExtendedAttributes TextAttribute::GetExtendedAttributes() const noexcept
|
||||
{
|
||||
return _extendedAttrs;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - swaps foreground and background color
|
||||
void TextAttribute::Invert() noexcept
|
||||
|
||||
@@ -109,10 +109,7 @@ public:
|
||||
void SetOverlined(bool isOverlined) noexcept;
|
||||
void SetReverseVideo(bool isReversed) noexcept;
|
||||
|
||||
constexpr ExtendedAttributes GetExtendedAttributes() const noexcept
|
||||
{
|
||||
return _extendedAttrs;
|
||||
}
|
||||
ExtendedAttributes GetExtendedAttributes() const noexcept;
|
||||
|
||||
bool IsHyperlink() const noexcept;
|
||||
|
||||
@@ -164,13 +161,6 @@ public:
|
||||
{
|
||||
return WI_IsAnyFlagSet(_wAttrLegacy, COMMON_LVB_GRID_HORIZONTAL | COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL | COMMON_LVB_UNDERSCORE);
|
||||
}
|
||||
constexpr bool HasAnyExtendedAttributes() const noexcept
|
||||
{
|
||||
return GetExtendedAttributes() != ExtendedAttributes::Normal ||
|
||||
IsAnyGridLineEnabled() ||
|
||||
GetHyperlinkId() != 0 ||
|
||||
IsReverseVideo();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::array<TextColor, 16> s_legacyForegroundColorMap;
|
||||
|
||||
@@ -17,6 +17,7 @@ Author(s):
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <til/bit.h>
|
||||
#include <til/hash.h>
|
||||
|
||||
// std::unordered_map needs help to know how to hash a til::point
|
||||
@@ -32,9 +33,9 @@ namespace std
|
||||
// - coord - the coord to hash
|
||||
// Return Value:
|
||||
// - the hashed coord
|
||||
size_t operator()(const til::point coord) const noexcept
|
||||
constexpr size_t operator()(const til::point coord) const noexcept
|
||||
{
|
||||
return til::hash(coord);
|
||||
return til::hash(til::bit_cast<uint64_t>(coord));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{0CF235BD-2DA0-407E-90EE-C467E8BBC714}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
|
||||
@@ -23,7 +23,7 @@ using namespace Microsoft::Console::Types;
|
||||
// - direction - The direction to search (upward or downward)
|
||||
// - sensitivity - Whether or not you care about case
|
||||
Search::Search(IUiaData& uiaData,
|
||||
const std::wstring_view str,
|
||||
const std::wstring& str,
|
||||
const Direction direction,
|
||||
const Sensitivity sensitivity) :
|
||||
_direction(direction),
|
||||
@@ -47,7 +47,7 @@ Search::Search(IUiaData& uiaData,
|
||||
// - sensitivity - Whether or not you care about case
|
||||
// - anchor - starting search location in screenInfo
|
||||
Search::Search(IUiaData& uiaData,
|
||||
const std::wstring_view str,
|
||||
const std::wstring& str,
|
||||
const Direction direction,
|
||||
const Sensitivity sensitivity,
|
||||
const til::point anchor) :
|
||||
@@ -106,13 +106,14 @@ void Search::Select() const
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Applies the supplied TextAttribute to the current search result.
|
||||
// - In console host, we take the found word and apply the given color to it in the screen buffer
|
||||
// - In Windows Terminal, we just select the found word, but we do not modify the buffer
|
||||
// Arguments:
|
||||
// - attr - The attribute to apply to the result
|
||||
// - ulAttr - The legacy color attribute to apply to the word
|
||||
void Search::Color(const TextAttribute attr) const
|
||||
{
|
||||
// Only select if we've found something.
|
||||
if (_coordSelEnd >= _coordSelStart)
|
||||
if (_coordSelStart != _coordSelEnd)
|
||||
{
|
||||
_uiaData.ColorSelection(_coordSelStart, _coordSelEnd, attr);
|
||||
}
|
||||
@@ -329,7 +330,7 @@ void Search::_UpdateNextPosition()
|
||||
// - wstr - String that will be our search term
|
||||
// Return Value:
|
||||
// - Structured text data for comparison to screen buffer text data.
|
||||
std::vector<std::vector<wchar_t>> Search::s_CreateNeedleFromString(const std::wstring_view wstr)
|
||||
std::vector<std::vector<wchar_t>> Search::s_CreateNeedleFromString(const std::wstring& wstr)
|
||||
{
|
||||
const auto charData = Utf16Parser::Parse(wstr);
|
||||
std::vector<std::vector<wchar_t>> cells;
|
||||
|
||||
@@ -41,12 +41,12 @@ public:
|
||||
};
|
||||
|
||||
Search(Microsoft::Console::Types::IUiaData& uiaData,
|
||||
const std::wstring_view str,
|
||||
const std::wstring& str,
|
||||
const Direction dir,
|
||||
const Sensitivity sensitivity);
|
||||
|
||||
Search(Microsoft::Console::Types::IUiaData& uiaData,
|
||||
const std::wstring_view str,
|
||||
const std::wstring& str,
|
||||
const Direction dir,
|
||||
const Sensitivity sensitivity,
|
||||
const til::point anchor);
|
||||
@@ -68,7 +68,7 @@ private:
|
||||
|
||||
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_view wstr);
|
||||
static std::vector<std::vector<wchar_t>> s_CreateNeedleFromString(const std::wstring& wstr);
|
||||
|
||||
bool _reachedEnd = false;
|
||||
til::point _coordNext;
|
||||
|
||||
@@ -1138,7 +1138,7 @@ til::point TextBuffer::GetWordStart(const til::point target, const std::wstring_
|
||||
// that it actually points to a space in the buffer
|
||||
copy = bufferSize.BottomRightInclusive();
|
||||
}
|
||||
else if (target >= limit)
|
||||
else if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
// if at/past the limit --> clamp to limit
|
||||
copy = limitOptional.value_or(bufferSize.BottomRightInclusive());
|
||||
@@ -1254,7 +1254,7 @@ til::point TextBuffer::GetWordEnd(const til::point target, const std::wstring_vi
|
||||
// Already at/past the limit. Can't move forward.
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
if (target >= limit)
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
@@ -1282,7 +1282,7 @@ til::point TextBuffer::_GetWordEndForAccessibility(const til::point target, cons
|
||||
const auto bufferSize{ GetSize() };
|
||||
auto result{ target };
|
||||
|
||||
if (target >= limit)
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
// if we're already on/past the last RegularChar,
|
||||
// clamp result to that position
|
||||
@@ -1419,7 +1419,7 @@ bool TextBuffer::MoveToNextWord(til::point& pos, const std::wstring_view wordDel
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
const auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, limit) };
|
||||
|
||||
if (copy >= limit)
|
||||
if (bufferSize.CompareInBounds(copy, limit, true) >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1466,7 +1466,7 @@ til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional<til::po
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
// Clamp pos to limit
|
||||
if (resultPos > limit)
|
||||
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
|
||||
{
|
||||
resultPos = limit;
|
||||
}
|
||||
@@ -1494,7 +1494,7 @@ til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode,
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
// Clamp pos to limit
|
||||
if (resultPos > limit)
|
||||
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
|
||||
{
|
||||
resultPos = limit;
|
||||
}
|
||||
@@ -1524,19 +1524,9 @@ til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode,
|
||||
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
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 limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
const auto distanceToLimit{ bufferSize.CompareInBounds(pos, limit) + (pastEndInclusive ? 1 : 0) };
|
||||
const auto distanceToLimit{ bufferSize.CompareInBounds(pos, limit, true) };
|
||||
if (distanceToLimit >= 0)
|
||||
{
|
||||
// Corner Case: we're on/past the limit
|
||||
@@ -1579,7 +1569,7 @@ bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point>
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (pos > limit)
|
||||
if (bufferSize.CompareInBounds(pos, limit, true) > 0)
|
||||
{
|
||||
// we're past the end
|
||||
// clamp us to the limit
|
||||
@@ -1611,7 +1601,7 @@ bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point>
|
||||
// - bufferCoordinates: when enabled, treat the coordinates as relative to
|
||||
// the buffer rather than the screen.
|
||||
// Return Value:
|
||||
// - One or more rects corresponding to the selection area
|
||||
// - the delimiter class for the given char
|
||||
const std::vector<til::inclusive_rect> TextBuffer::GetTextRects(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const
|
||||
{
|
||||
std::vector<til::inclusive_rect> textRects;
|
||||
@@ -1621,7 +1611,7 @@ const std::vector<til::inclusive_rect> TextBuffer::GetTextRects(til::point start
|
||||
// (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] = start <= end ?
|
||||
const auto [higherCoord, lowerCoord] = bufferSize.CompareInBounds(start, end) <= 0 ?
|
||||
std::make_tuple(start, end) :
|
||||
std::make_tuple(end, start);
|
||||
|
||||
@@ -1660,69 +1650,6 @@ const std::vector<til::inclusive_rect> TextBuffer::GetTextRects(til::point start
|
||||
return textRects;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Computes the span(s) for the given selection
|
||||
// - If not a blockSelection, returns a single span (start - end)
|
||||
// - Else if a blockSelection, returns spans corresponding to each line in the block selection
|
||||
// Arguments:
|
||||
// - start: beginning of the text region of interest (inclusive)
|
||||
// - end: the other end of the text region of interest (inclusive)
|
||||
// - blockSelection: when enabled, get spans for each line covered by the block
|
||||
// - bufferCoordinates: when enabled, treat the coordinates as relative to
|
||||
// the buffer rather than the screen.
|
||||
// Return Value:
|
||||
// - one or more sets of start-end coordinates, representing spans of text in the buffer
|
||||
std::vector<til::point_span> TextBuffer::GetTextSpans(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const
|
||||
{
|
||||
std::vector<til::point_span> textSpans;
|
||||
if (blockSelection)
|
||||
{
|
||||
// If blockSelection, this is effectively the same operation as GetTextRects, but
|
||||
// expressed in til::point coordinates.
|
||||
const auto rects = GetTextRects(start, end, /*blockSelection*/ true, bufferCoordinates);
|
||||
textSpans.reserve(rects.size());
|
||||
|
||||
for (auto rect : rects)
|
||||
{
|
||||
const til::point first = { rect.Left, rect.Top };
|
||||
const til::point second = { rect.Right, rect.Bottom };
|
||||
textSpans.emplace_back(first, second);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
auto [higherCoord, lowerCoord] = start <= end ?
|
||||
std::make_tuple(start, end) :
|
||||
std::make_tuple(end, start);
|
||||
|
||||
textSpans.reserve(1);
|
||||
|
||||
// If we were passed screen coordinates, convert the given range into
|
||||
// equivalent buffer offsets, taking line rendition into account.
|
||||
if (!bufferCoordinates)
|
||||
{
|
||||
higherCoord = ScreenToBufferLine(higherCoord, GetLineRendition(higherCoord.Y));
|
||||
lowerCoord = ScreenToBufferLine(lowerCoord, GetLineRendition(lowerCoord.Y));
|
||||
}
|
||||
|
||||
til::inclusive_rect asRect = { higherCoord.X, higherCoord.Y, lowerCoord.X, lowerCoord.Y };
|
||||
_ExpandTextRow(asRect);
|
||||
higherCoord.X = asRect.Left;
|
||||
higherCoord.Y = asRect.Top;
|
||||
lowerCoord.X = asRect.Right;
|
||||
lowerCoord.Y = asRect.Bottom;
|
||||
|
||||
textSpans.emplace_back(higherCoord, lowerCoord);
|
||||
}
|
||||
|
||||
return textSpans;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Expand the selection row according to include wide glyphs fully
|
||||
// - this is particularly useful for box selections (ALT + selection)
|
||||
@@ -1837,8 +1764,9 @@ const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
#pragma warning(suppress : 26444)
|
||||
// TODO GH 2675: figure out why there's custom construction/destruction happening here
|
||||
it++;
|
||||
}
|
||||
|
||||
// We apply formatting to rows if the row was NOT wrapped or formatting of wrapped rows is allowed
|
||||
@@ -1894,43 +1822,6 @@ const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t TextBuffer::SpanLength(const til::point coordStart, const til::point coordEnd) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
// The coords are inclusive, so to get the (inclusive) length we add 1.
|
||||
const auto length = bufferSize.CompareInBounds(coordEnd, coordStart) + 1;
|
||||
return gsl::narrow<size_t>(length);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Retrieves the plain text data between the specified coordinates.
|
||||
// Arguments:
|
||||
// - trimTrailingWhitespace - remove the trailing whitespace at the end of the result.
|
||||
// - start - where to start getting text (should be at or prior to "end")
|
||||
// - end - where to end getting text
|
||||
// Return Value:
|
||||
// - Just the text.
|
||||
std::wstring TextBuffer::GetPlainText(const til::point& start, const til::point& end) const
|
||||
{
|
||||
std::wstring text;
|
||||
auto spanLength = SpanLength(start, end);
|
||||
text.reserve(spanLength);
|
||||
|
||||
auto it = GetCellDataAt(start);
|
||||
|
||||
for (; it && spanLength > 0; ++it, --spanLength)
|
||||
{
|
||||
const auto& cell = *it;
|
||||
if (!cell.DbcsAttr().IsTrailing())
|
||||
{
|
||||
const auto chars = cell.Chars();
|
||||
text.append(chars);
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Generates a CF_HTML compliant structure based on the passed in text and color data
|
||||
// Arguments:
|
||||
|
||||
@@ -166,7 +166,6 @@ public:
|
||||
bool MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
|
||||
const std::vector<til::inclusive_rect> GetTextRects(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const;
|
||||
std::vector<til::point_span> GetTextSpans(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;
|
||||
@@ -183,16 +182,12 @@ public:
|
||||
std::vector<std::vector<COLORREF>> BkAttr;
|
||||
};
|
||||
|
||||
size_t SpanLength(const til::point coordStart, const til::point coordEnd) const;
|
||||
|
||||
const TextAndColor GetText(const bool includeCRLF,
|
||||
const bool trimTrailingWhitespace,
|
||||
const std::vector<til::inclusive_rect>& textRects,
|
||||
std::function<std::pair<COLORREF, COLORREF>(const TextAttribute&)> GetAttributeColors = nullptr,
|
||||
const bool formatWrappedRows = false) const;
|
||||
|
||||
std::wstring GetPlainText(const til::point& start, const til::point& end) const;
|
||||
|
||||
static std::string GenHTML(const TextAndColor& rows,
|
||||
const int fontHeightPoints,
|
||||
const std::wstring_view fontFaceName,
|
||||
|
||||