Compare commits

..

2 Commits

Author SHA1 Message Date
Dustin L. Howett
22a7a5bc5f Migrate spelling-0.0.21 changes from main 2022-06-13 15:03:41 -07:00
Pankaj Bhojwani
b3997a3dad preview connection ctor takes preview string 2022-06-13 15:03:41 -07:00
1526 changed files with 146303 additions and 51451 deletions

View File

@@ -1,25 +1,57 @@
---
Language: Cpp
BasedOnStyle: Microsoft
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AllowAllArgumentsOnNextLine: true
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AllowAllConstructorInitializersOnNextLine: true
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: All
AllowShortCaseLabelsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: Never
#AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
ColumnLimit: 0
CommentPragmas: "suppress"
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
FixNamespaceComments: false
IncludeBlocks: Regroup
IncludeCategories:
@@ -31,13 +63,35 @@ IncludeCategories:
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: "BEGIN_TEST_METHOD_PROPERTIES|BEGIN_MODULE|BEGIN_TEST_CLASS|BEGIN_TEST_METHOD"
MacroBlockEnd: "END_TEST_METHOD_PROPERTIES|END_MODULE|END_TEST_CLASS|END_TEST_METHOD"
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
PointerAlignment: Left
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
TabWidth: 4
UseTab: Never

View File

@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"XamlStyler.Console": {
"version": "3.2206.4",
"version": "3.2008.4",
"commands": [
"xstyler"
]

View File

@@ -1,15 +0,0 @@
# Commits mentioned in this file will automatically
# be skipped by GitHub's blame view.
# To use it with "git", run
# > git blame --ignore-revs-file ./.git-blame-ignore-revs
# Reformatted the entire codebase
9b92986b49bed8cc41fde4d6ef080921c41e6d9e
# Line Endings changes
cb7a76d96c92aa9fc7b03f69148fb0c75dff191d
5bbf61af8c8f12e6c05d07a696bf7d411b330a67
d07546a6fef73fa4e1fb1c2f01535843d1fcc212
# UTF-8 BOM changes
ddae2a1d49d604487d3c963e5eacbeb73861d986

View File

@@ -1,6 +1,6 @@
name: "Bug report 🐛"
description: Report errors or unexpected behavior
labels: [Issue-Bug, Needs-Triage]
labels: [Issue-Bug]
body:
- type: markdown
attributes:
@@ -14,7 +14,7 @@ body:
label: Windows Terminal version
placeholder: "1.7.3651.0"
description: |
You can copy the version number from the About dialog. Open the About dialog by opening the menu with the "V" button (to the right of the "+" button that opens a new tab) and choosing About from the end of the list.
You can find the version in the about dialog, or by running `wt -v` at the commandline.
validations:
required: false

View File

@@ -1,14 +1,20 @@
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
## References and Relevant Issues
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #xxx
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
## PR Checklist
- [ ] Closes #xxx
- [ ] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)

View File

@@ -2,7 +2,6 @@ admins
allcolors
Apc
apc
backpressure
breadcrumb
breadcrumbs
bsd
@@ -13,23 +12,18 @@ clickable
clig
CMMI
copyable
CtrlDToClose
cybersecurity
dalet
Dcs
dcs
deselection
dialytika
diffing
dje
downside
downsides
dze
dzhe
DTo
EDDB
EDDC
Emacspeak
Enum'd
Fitt
formattings
@@ -66,7 +60,6 @@ lol
lorem
Lorigin
maxed
megathread
minimalistic
mkmk
mnt
@@ -92,7 +85,6 @@ shcha
slnt
Sos
ssh
stakeholders
timeline
timelines
timestamped

View File

@@ -34,6 +34,7 @@ DNE
DONTADDTORECENT
DWMSBT
DWMWA
DWMWA
DWORDLONG
endfor
ENDSESSION
@@ -54,8 +55,6 @@ GETMOUSEHOVERTIME
Hashtable
HIGHCONTRASTON
HIGHCONTRASTW
hinternet
HINTERNET
hotkeys
href
hrgn
@@ -159,7 +158,6 @@ rcx
REGCLS
RETURNCMD
rfind
RLO
ROOTOWNER
roundf
RSHIFT
@@ -216,8 +214,6 @@ Viewbox
virtualalloc
wcsstr
wcstoui
WDJ
winhttp
winmain
winsta
winstamin
@@ -225,7 +221,6 @@ wmemcmp
wpc
WSF
wsregex
WWH
wwinmain
xchg
XDocument
@@ -251,4 +246,3 @@ xtree
xutility
YIcon
YMax
zwstring

View File

@@ -9,11 +9,9 @@ appxbundle
appxerror
appxmanifest
ATL
autoexec
backplating
bitmaps
BOMs
COMPUTERNAME
CPLs
cpptools
cppvsdbg
@@ -28,7 +26,6 @@ dotnetfeed
DTDs
DWINRT
enablewttlogging
HOMESHARE
Intelli
IVisual
libucrt
@@ -36,7 +33,6 @@ libucrtd
LKG
LOCKFILE
Lxss
makepri
mfcribbon
microsoft
microsoftonline
@@ -54,19 +50,14 @@ pgo
pgosweep
powerrename
powershell
priconfig
PRIINFO
propkey
pscustomobject
QWORD
regedit
resfiles
robocopy
SACLs
segoe
sdkddkver
Shobjidl
sid
Skype
SRW
sxs
@@ -79,7 +70,6 @@ tdbuildteamid
ucrt
ucrtd
unvirtualized
USERDNSDOMAIN
VCRT
vcruntime
Virtualization

View File

@@ -23,7 +23,6 @@ Griese
Hernan
Howett
Illhardt
Imms
iquilezles
italo
jantari
@@ -35,7 +34,6 @@ KODELIFE
Kodelife
Kourosh
kowalczyk
leonardder
leonmsft
Lepilleur
lhecker
@@ -79,18 +77,15 @@ sonpham
stakx
talo
thereses
Thysell
Walisch
WDX
Wellons
Westerman
Wirt
Wojciech
zadjii
Zamor
Zamora
zamora
zljubisic
Zoey
zorio
Zverovich

View File

@@ -109,7 +109,6 @@
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
^src/tools/lnkd/lnkd\.bat$
^src/tools/pixels/pixels\.bat$
^src/tools/RenderingTests/main.cpp$
^src/tools/texttests/fira\.txt$
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
^src/types/ut_types/UtilsTests.cpp$

View File

@@ -18,7 +18,6 @@ BBBBBBBB
BBBBBCCC
BBBBCCCCC
BBGGRR
efg
EFG
EFGh
QQQQQQQQQQABCDEFGHIJ

View File

@@ -2,7 +2,6 @@ aabbcc
ABANDONFONT
abbcc
ABCDEFGHIJKLMNOPQRSTUVWXY
ABCF
abgr
abi
ABORTIFHUNG
@@ -38,7 +37,6 @@ ansicpg
ANSISYS
ANSISYSRC
ANSISYSSC
answerback
antialiasing
ANull
anycpu
@@ -63,6 +61,7 @@ argb
ARRAYSIZE
ARROWKEYS
asan
ASBRST
ASBSET
ASDF
asdfghjkl
@@ -177,6 +176,7 @@ CConsole
CConversion
CCRT
cdd
CDeclaration
CEdit
CELLSIZE
cfae
@@ -194,6 +194,7 @@ chh
chk
CHT
Cic
CLA
Clcompile
CLE
cleartype
@@ -251,13 +252,11 @@ conattrs
conbufferout
concfg
conclnt
concretizations
conddkrefs
condrv
conechokey
conemu
configurability
confusables
conhost
conime
conimeinfo
@@ -312,6 +311,7 @@ CPLINFO
cplusplus
CPPCORECHECK
cppcorecheckrules
cpprest
cpprestsdk
cppwinrt
CProc
@@ -332,7 +332,7 @@ Cspace
csrmsg
CSRSS
csrutil
CSTYLE
cstyle
CSwitch
CTerminal
CText
@@ -409,26 +409,21 @@ DECAUPSS
DECAWM
DECBKM
DECCARA
DECCIR
DECCKM
DECCKSR
DECCOLM
DECCRA
DECCTR
DECDHL
decdld
DECDMAC
DECDWL
DECEKBD
DECERA
DECFRA
DECID
DECINVM
DECKPAM
DECKPM
DECKPNM
DECLRMM
DECMSR
DECNKM
DECNRCM
DECOM
@@ -438,13 +433,9 @@ DECRARA
DECRC
DECREQTPARM
DECRLM
DECRPM
DECRQCRA
DECRQM
DECRQPSR
DECRQSS
DECRQTSR
DECRSPS
decrst
DECSACE
DECSASD
@@ -462,10 +453,8 @@ DECSLRM
DECSMKR
DECSR
DECSTBM
DECSTGLT
DECSTR
DECSWL
DECTABSR
DECTCEM
DECXCPR
DEFAPP
@@ -485,6 +474,7 @@ defterm
DELAYLOAD
DELETEONRELEASE
Delt
demoable
depersist
deprioritized
deserializers
@@ -541,6 +531,7 @@ DSSCL
DSwap
DTest
DTTERM
DUMMYUNIONNAME
dup'ed
dvi
dwl
@@ -593,6 +584,7 @@ ETW
EUDC
EVENTID
eventing
everytime
evflags
evt
execd
@@ -614,12 +606,8 @@ FACESIZE
FAILIFTHERE
fastlink
fcharset
FDEA
fdw
FECF
FEEF
fesb
FFAF
FFDE
FFrom
fgbg
@@ -816,8 +804,6 @@ hkl
HKLM
hlocal
hlsl
HMB
HMK
hmod
hmodule
hmon
@@ -825,7 +811,6 @@ HORZ
hostable
hostlib
HPA
hpcon
HPCON
hpj
HPR
@@ -907,6 +892,7 @@ INSERTMODE
INTERACTIVITYBASE
INTERCEPTCOPYPASTE
INTERNALNAME
inthread
intsafe
INVALIDARG
INVALIDATERECT
@@ -1125,7 +1111,6 @@ Mip
MMBB
mmcc
MMCPL
MMIX
mmsystem
MNC
MNOPQ
@@ -1264,12 +1249,14 @@ ntm
nto
ntrtl
ntstatus
ntsubauth
NTSYSCALLAPI
nttree
nturtl
ntuser
NTVDM
ntverp
NTWIN
nugetversions
nullability
nullness
@@ -1308,6 +1295,8 @@ opencode
opencon
openconsole
openconsoleproxy
OPENIF
OPENLINK
openps
openvt
ORIGINALFILENAME
@@ -1360,7 +1349,9 @@ pcg
pch
PCIDLIST
PCIS
PCLIENT
PCLONG
PCOBJECT
pcon
PCONSOLE
PCONSOLEENDTASK
@@ -1372,6 +1363,7 @@ pcshell
PCSHORT
PCSR
PCSTR
PCUNICODE
PCWCH
PCWCHAR
PCWSTR
@@ -1420,6 +1412,7 @@ PLOGICAL
pnm
PNMLINK
pntm
PNTSTATUS
POBJECT
Podcast
POINTSLIST
@@ -1437,7 +1430,9 @@ PPEB
ppf
ppguid
ppidl
pplx
PPROC
PPROCESS
ppropvar
ppsi
ppsl
@@ -1501,6 +1496,7 @@ ptrs
ptsz
PTYIn
PUCHAR
PUNICODE
pwch
PWDDMCONSOLECONTEXT
pws
@@ -1562,6 +1558,7 @@ REGISTEROS
REGISTERVDM
regkey
REGSTR
reingest
RELBINPATH
remoting
renamer
@@ -1573,7 +1570,6 @@ replatformed
Replymessage
repositorypath
Requiresx
rerasterize
rescap
Resequence
RESETCONTENT
@@ -1774,7 +1770,6 @@ srv
srvinit
srvpipe
ssa
startdir
STARTF
STARTUPINFO
STARTUPINFOEX
@@ -1823,7 +1818,6 @@ SYSCOMMAND
SYSDEADCHAR
SYSKEYDOWN
SYSKEYUP
SYSLIB
SYSLINK
SYSMENU
sysparams
@@ -1857,7 +1851,6 @@ TDP
TEAMPROJECT
tearoff
Teb
Techo
tellp
teraflop
terminalcore
@@ -1949,7 +1942,6 @@ trx
tsattrs
tsf
tsgr
tsm
TStr
TSTRFORMAT
TSub
@@ -2001,6 +1993,7 @@ unittesting
unittests
unk
unknwn
unmark
UNORM
unparseable
unregistering
@@ -2113,6 +2106,7 @@ WDDMCONSOLECONTEXT
wdm
webpage
websites
websockets
wekyb
wex
wextest
@@ -2189,7 +2183,6 @@ wnd
WNDALLOC
WNDCLASS
WNDCLASSEX
WNDCLASSEXW
WNDCLASSW
Wndproc
WNegative
@@ -2295,7 +2288,6 @@ YOffset
YSubstantial
YVIRTUALSCREEN
YWalk
zabcd
Zabcdefghijklmnopqrstuvwxyz
ZCmd
ZCtrl

View File

@@ -10,4 +10,4 @@
\\tests(?![a-z])
\\thread(?![a-z])
\\tools(?![a-z])
\\types?(?![a-z])
\\types(?![a-z])

View File

@@ -35,7 +35,7 @@ ROY\sG\.\sBIV
# hit-count: 71 file-count: 35
# Compiler flags
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
(?:^|[\t ,"'`=(])-[X](?!aml)(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# hit-count: 41 file-count: 28
# version suffix <word>v#

3156
.github/fabricbot.json vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +0,0 @@
name: Add triaged bugs & tasks to project board
# https://github.com/actions/add-to-project
on:
issues:
types:
- labeled
- unlabeled
permissions: {}
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.3.0
with:
project-url: https://github.com/orgs/microsoft/projects/159
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
labeled: Issue-Feature, Needs-Triage, Needs-Author-Feedback, Issue-Scenario
label-operator: NOT

View File

@@ -1,24 +0,0 @@
name: Publish to Winget
on:
release:
types: [published]
env:
REGEX: 'Microsoft\.WindowsTerminal(?:Preview)?_([\d.]+)_8wekyb3d8bbwe\.msixbundle$'
jobs:
publish:
runs-on: windows-latest # Action can only run on Windows
steps:
- name: Publish Windows Terminal ${{ github.event.release.prerelease && 'Preview' || 'Stable' }}
run: |
$assets = '${{ toJSON(github.event.release.assets) }}' | ConvertFrom-Json
$wingetRelevantAsset = $assets | Where-Object { $_.name -like '*.msixbundle' } | Select-Object -First 1
$regex = [Regex]::New($env:REGEX)
$version = $regex.Match($wingetRelevantAsset.name).Groups[1].Value
$wingetPackage = "Microsoft.WindowsTerminal${{ github.event.release.prerelease && '.Preview' || '' }}"
& curl.exe -JLO https://aka.ms/wingetcreate/latest
& .\wingetcreate.exe update $wingetPackage -s -v $version -u $wingetRelevantAsset.browser_download_url -t "${{ secrets.WINGET_TOKEN }}"

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "dep/gsl"]
path = dep/gsl
url = https://github.com/microsoft/gsl
[submodule "dep/wil"]
path = dep/wil
url = https://github.com/microsoft/wil

View File

@@ -6,7 +6,7 @@
"C_Cpp.loggingLevel": "None",
"files.associations": {
"xstring": "cpp",
"*.idl": "midl3",
"*.idl": "cpp",
"array": "cpp",
"future": "cpp",
"istream": "cpp",
@@ -106,4 +106,4 @@
"**/packages/**": true,
"**/Generated Files/**": true
}
}
}

View File

@@ -17,7 +17,7 @@
"Microsoft.Net.Component.4.5.TargetingPack",
"Microsoft.VisualStudio.Component.DiagnosticTools",
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
"Microsoft.VisualStudio.Component.Windows11SDK.22621",
"Microsoft.VisualStudio.Component.Windows11SDK.22000",
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
"Microsoft.VisualStudio.Component.VC.CoreIde",
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
@@ -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"
]
}

View File

@@ -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)
@@ -101,7 +101,7 @@ If you don't have any additional info/context to add but would like to indicate
If you're able & willing to help fix issues and/or implement features, we'd love your contribution!
The best place to start is the list of ["good first issue"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22++label%3A%22good+first+issue%22+)s. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue you're interested in and hop in!
The best place to start is the list of ["Easy Starter"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+label%3A%22Easy+Starter%22+) issues. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue your interested in and hop in!
Generally, we categorize issues in the following way, which is largely derived from our old internal work tracking system:
* ["Bugs"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Bug%22+) are parts of the Terminal & Console that are not quite working the right way. There's code to already support some scenario, but it's not quite working right. Fixing these is generally a matter of debugging the broken functionality and fixing the wrong code.

View File

@@ -215,6 +215,39 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## boost
**Source**: [https://github.com/boostorg/boost](https://github.com/boostorg/boost)
### License
```
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
```
## PCG Random Number Generation
**Source**: [https://github.com/imneme/pcg-cpp](https://github.com/imneme/pcg-cpp)
@@ -243,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)

File diff suppressed because it is too large Load Diff

View File

@@ -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!
@@ -67,7 +65,7 @@ the latest Terminal release by installing the `Microsoft.WindowsTerminal`
package:
```powershell
winget install --id Microsoft.WindowsTerminal -e
winget install --id=Microsoft.WindowsTerminal -e
```
#### Via Chocolatey (unofficial)
@@ -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:
@@ -289,18 +287,18 @@ If you would like to ask a question that you feel doesn't warrant an issue
app](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development)
to locally install and run Windows Terminal
* You must have [PowerShell 7 or later](https://github.com/PowerShell/PowerShell/releases/latest) installed
* You must have the [Windows 11 (10.0.22621.0)
* You must have the [Windows 11 (10.0.22000.0)
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

View File

@@ -55,7 +55,12 @@ Copy-Item "build\helix\runtests.cmd" $payloadDir
Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir"
Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
# Extract the unpackaged distribution of Windows Terminal to the payload directory,
# where it will create a subdirectory named terminal-0.0.1.0
# This is referenced in TerminalApp.cs later as part of the test harness.
& tar -x -v -f "$repoDirectory\Artifacts\$ArtifactName\unpackaged\WindowsTerminalDev_0.0.1.0_x64.zip" -C "$payloadDir"
# 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
# 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
# does the job without complaining.
# Extract the APPX package
Expand-Archive -LiteralPath $payloadDir\CascadiaPackage.zip -DestinationPath $payloadDir\appx

View File

@@ -70,7 +70,7 @@ foreach ($testRun in $testRuns.value)
foreach ($testResult in $testResults.value)
{
$info = ConvertFrom-Json ([System.Web.HttpUtility]::HtmlDecode($testResult.comment))
$info = ConvertFrom-Json $testResult.comment
$helixJobId = $info.HelixJobId
$helixWorkItemName = $info.HelixWorkItemName

View File

@@ -1,5 +1,5 @@
{
"msbuild-sdks": {
"Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.22525.5"
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20277.5"
}
}

View File

@@ -1,72 +0,0 @@
{
"Version": "1.0.0",
"UseMinimatch": false,
"SignBatches": [
{
"MatchedPath": [
// Namespaced DLLs
"Microsoft.Terminal.*.dll",
"Microsoft.Terminal.*.winmd",
// ConPTY and DefTerm
"OpenConsole.exe",
"OpenConsoleProxy.dll",
// VCRT Forwarders
"*_app.dll",
// Legacy DLLs with old names
"TerminalApp.dll",
"TerminalApp.winmd",
"TerminalConnection.dll",
"TerminalThemeHelpers.dll",
"WindowsTerminalShellExt.dll",
// The rest
"TerminalAzBridge.exe",
"wt.exe",
"WindowsTerminal.exe",
"elevate-shim.exe"
],
"SigningInfo": {
"Operations": [
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolSign",
"Parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolVerify",
"Parameters": [],
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
}
}
]
}

View File

@@ -4,7 +4,7 @@
"collection": "microsoft",
"project": "OS",
"repo": "os.2020",
"name": "official/rs_we_adept_e4d2",
"name": "official/rs_wdx_dxp_windev",
"workitem": "38106206",
"CheckinFiles": [
{
@@ -21,4 +21,4 @@
"sendOnErrorOnly": "False"
}
]
}
}

View File

@@ -3,6 +3,6 @@
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" 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" />
<!-- 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.0" targetFramework="native" />
</packages>

View File

@@ -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>

View File

@@ -14,16 +14,16 @@
<!-- Mandatory. Name of the NuGet package which will contain PGO databases for consumption by build system. -->
<PGOPackageName>Microsoft.Internal.Windows.Terminal.PGODatabase</PGOPackageName>
<!-- Mandatory. Major version number of the PGO database which should match the version of the product. This can be hard-coded or obtained from other sources in build system. -->
<!-- Mandatory. Major version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<PGOPackageVersionMajor>$(VersionMajor)</PGOPackageVersionMajor>
<!-- Mandatory. Minor version number of the PGO database which should match the version of the product. This can be hard-coded or obtained from other sources in build system. -->
<!-- Mandatory. Minor version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<PGOPackageVersionMinor>$(VersionMinor)</PGOPackageVersionMinor>
<!-- Mandatory, defaults to 0. Patch version number of the PGO database which should match the version of the product. This can be hard-coded or obtained from other sources in build system. -->
<!-- Mandatory, defaults to 0. Patch version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<PGOPackageVersionPatch>0</PGOPackageVersionPatch>
<!-- Optional, defaults to empty. Prerelease version number of the PGO database which should match the version of the product. This can be hard-coded or obtained from other sources in build system. -->
<!-- Optional, defaults to empty. Prerelease version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<PGOPackageVersionPrerelease></PGOPackageVersionPrerelease>
<!-- Mandatory. Path to nuget.config file for the project. Path is relative to where the props file will be. -->

View File

@@ -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

View File

@@ -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
@@ -56,10 +56,14 @@ parameters:
- x64
- x86
- arm64
- name: buildWindowsVersions
type: object
default:
- Win10
- Win11
variables:
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe'
TerminalInternalPackageVersion: "0.0.8"
TerminalInternalPackageVersion: "0.0.7"
# If we are building a branch called "release-*", change the NuGet suffix
# to "preview". If we don't do that, XES will set the suffix to "release1"
# because it truncates the value after the first period.
@@ -82,6 +86,13 @@ variables:
NuGetPackBetaVersion: preview
${{ elseif eq(variables['Build.SourceBranchName'], 'main') }}:
NuGetPackBetaVersion: experimental
# The NuGet packages have to use *somebody's* DLLs. We used to force them to
# use the Win10 build outputs, but if there isn't a Win10 build we should use
# the Win11 one.
${{ if containsValue(parameters.buildWindowsVersions, 'Win10') }}:
TerminalBestVersionForNuGetPackages: Win10
${{ else }}:
TerminalBestVersionForNuGetPackages: Win11
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
resources:
@@ -95,9 +106,11 @@ jobs:
matrix:
${{ each config in parameters.buildConfigurations }}:
${{ each platform in parameters.buildPlatforms }}:
${{ config }}_${{ platform }}:
BuildConfiguration: ${{ config }}
BuildPlatform: ${{ platform }}
${{ each windowsVersion in parameters.buildWindowsVersions }}:
${{ config }}_${{ platform }}_${{ windowsVersion }}:
BuildConfiguration: ${{ config }}
BuildPlatform: ${{ platform }}
TerminalTargetWindowsVersion: ${{ windowsVersion }}
displayName: Build
timeoutInMinutes: 240
cancelTimeoutInMinutes: 1
@@ -121,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:
@@ -171,11 +186,16 @@ jobs:
arguments: -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
pwsh: true
- ${{ if eq(parameters.buildTerminal, true) }}:
- pwsh: |-
./build/scripts/Patch-ManifestsToWindowsVersion.ps1 -NewWindowsVersion "10.0.22000.0"
displayName: Update manifest target version to Win11 (if necessary)
condition: and(succeeded(), eq(variables['TerminalTargetWindowsVersion'], 'Win11'))
- task: VSBuild@1
displayName: Build solution **\OpenConsole.sln
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)
@@ -187,7 +207,7 @@ jobs:
continueOnError: True
inputs:
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
ArtifactName: binlog-$(BuildPlatform)
ArtifactName: binlog-$(BuildPlatform)-$(TerminalTargetWindowsVersion)
- task: PowerShell@2
displayName: Check MSIX for common regressions
inputs:
@@ -202,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)
@@ -210,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)
@@ -219,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')))
@@ -236,12 +257,16 @@ jobs:
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
- ${{ if eq(parameters.buildTerminal, true) }}:
- task: CopyFiles@2
displayName: Copy *.msix and symbols to Artifacts
displayName: Copy *.appx/*.msix to Artifacts
inputs:
Contents: >-
**/*.appx
**/*.msix
**/*.appxsym
!**/Microsoft.VCLibs*.appx
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
OverWrite: true
flattenFolders: true
@@ -249,43 +274,11 @@ jobs:
displayName: 'Generate SBOM manifest'
inputs:
BuildDropPath: '$(System.ArtifactsDirectory)/appx'
- pwsh: |-
$Package = (Get-ChildItem "$(Build.ArtifactStagingDirectory)/appx" -Recurse -Filter "Cascadia*.msix" | Select -First 1)
$PackageFilename = $Package.FullName
Write-Host "##vso[task.setvariable variable=WindowsTerminalPackagePath]${PackageFilename}"
& "$(MakeAppxPath)" unpack /p $PackageFilename /d "$(Build.SourcesDirectory)\UnpackedTerminalPackage"
displayName: Unpack the new Terminal package for signing
- task: EsrpCodeSigning@1
displayName: Submit Terminal's binaries for signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: '$(Build.SourcesDirectory)\UnpackedTerminalPackage'
signType: batchSigning
batchSignPolicyFile: '$(Build.SourcesDirectory)\build\config\ESRPSigning_Terminal.json'
- pwsh: |-
$PackageFilename = "$(WindowsTerminalPackagePath)"
Remove-Item "$(Build.SourcesDirectory)\UnpackedTerminalPackage\CodeSignSummary*"
& "$(MakeAppxPath)" pack /h SHA256 /o /p $PackageFilename /d "$(Build.SourcesDirectory)\UnpackedTerminalPackage"
displayName: Re-pack the new Terminal package after signing
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (appx)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)
- pwsh: |-
$XamlAppxPath = (Get-Item "src\cascadia\CascadiaPackage\AppPackages\*\Dependencies\$(BuildPlatform)\Microsoft.UI.Xaml*.appx").FullName
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 -TerminalAppX $(WindowsTerminalPackagePath) -XamlAppX $XamlAppxPath -Destination "$(Build.ArtifactStagingDirectory)/unpackaged"
displayName: Build Unpackaged Distribution
- publish: $(Build.ArtifactStagingDirectory)/unpackaged
artifact: unpackaged-$(BuildPlatform)-$(BuildConfiguration)
displayName: Publish Artifact (unpackaged)
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
- ${{ if eq(parameters.buildConPTY, true) }}:
- task: CopyFiles@2
displayName: Copy ConPTY to Artifacts
@@ -303,13 +296,15 @@ jobs:
displayName: Publish Artifact (ConPTY)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/conpty
ArtifactName: conpty-dll-$(BuildPlatform)-$(BuildConfiguration)
ArtifactName: conpty-dll-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
- ${{ if eq(parameters.buildWPF, true) }}:
- task: CopyFiles@2
displayName: Copy PublicTerminalCore.dll to Artifacts
inputs:
Contents: >-
**/PublicTerminalCore.dll
**/api-ms-win-core-synch-l1-2-0.dll
TargetFolder: $(Build.ArtifactStagingDirectory)/wpf
OverWrite: true
flattenFolders: true
@@ -317,7 +312,7 @@ jobs:
displayName: Publish Artifact (PublicTerminalCore)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/wpf
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
- task: PublishSymbols@2
displayName: Publish symbols path
@@ -332,17 +327,15 @@ jobs:
- ${{ if eq(parameters.runCompliance, true) }}:
- template: ./templates/build-console-compliance-job.yml
- ${{ if eq(parameters.buildTerminal, true) }}:
- job: BundleAndSign
strategy:
matrix:
${{ each windowsVersion in parameters.buildWindowsVersions }}:
${{ 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
@@ -356,9 +349,9 @@ jobs:
disableOutputRedirect: true
- ${{ each platform in parameters.buildPlatforms }}:
- task: DownloadBuildArtifacts@0
displayName: Download Artifacts ${{ platform }}
displayName: Download Artifacts ${{ platform }} $(TerminalTargetWindowsVersion)
inputs:
artifactName: appx-${{ platform }}-Release
artifactName: appx-${{ platform }}-Release-$(TerminalTargetWindowsVersion)
# Add 3000 to the major version component, but only for the bundle.
# This is to ensure that it is newer than "2022.xx.yy.zz" or whatever the original bundle versions were before
# we switched to uniform naming.
@@ -367,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)_$(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: >-
@@ -408,8 +400,8 @@ jobs:
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: appxbundle-signed'
inputs:
PathtoPublish: $(System.ArtifactsDirectory)\bundle
ArtifactName: appxbundle-signed
PathtoPublish: $(System.ArtifactsDirectory)
ArtifactName: appxbundle-signed-$(TerminalTargetWindowsVersion)
- ${{ if eq(parameters.buildConPTY, true) }}:
- job: PackageAndSignConPTY
@@ -434,7 +426,7 @@ jobs:
- task: DownloadBuildArtifacts@0
displayName: Download ${{ platform }} ConPTY binaries
inputs:
artifactName: conpty-dll-${{ platform }}-$(BuildConfiguration)
artifactName: conpty-dll-${{ platform }}-$(BuildConfiguration)-$(TerminalBestVersionForNuGetPackages)
downloadPath: bin\${{ platform }}\$(BuildConfiguration)\
extractTars: false
- task: PowerShell@2
@@ -525,7 +517,7 @@ jobs:
- task: DownloadBuildArtifacts@0
displayName: Download ${{ platform }} PublicTerminalCore
inputs:
artifactName: wpf-dll-${{ platform }}-$(BuildConfiguration)
artifactName: wpf-dll-${{ platform }}-$(BuildConfiguration)-$(TerminalBestVersionForNuGetPackages)
itemPattern: '**/*.dll'
downloadPath: bin\${{ platform }}\$(BuildConfiguration)\
extractTars: false
@@ -554,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)
@@ -619,14 +612,13 @@ 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 }}:
- task: DownloadBuildArtifacts@0
displayName: Download Symbols ${{ platform }}
inputs:
artifactName: appx-${{ platform }}-Release
- ${{ each windowsVersion in parameters.buildWindowsVersions }}:
- task: DownloadBuildArtifacts@0
displayName: Download Symbols ${{ platform }} ${{ windowsVersion }}
inputs:
artifactName: appx-${{ platform }}-Release-${{ windowsVersion }}
# It seems easier to do this -- download every appxsym -- then enumerate all the PDBs in the build directory for the
# public symbol push. Otherwise, we would have to list all of the PDB files one by one.
@@ -642,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
@@ -686,7 +679,7 @@ jobs:
- task: DownloadBuildArtifacts@0
displayName: Download Build Artifacts
inputs:
artifactName: appxbundle-signed
artifactName: appxbundle-signed-Win11
extractTars: false
- task: PowerShell@2
displayName: Rename and stage packages for vpack
@@ -695,7 +688,7 @@ jobs:
script: >-
# Rename to known/fixed name for Windows build system
Get-ChildItem Microsoft.WindowsTerminal_*.msixbundle | Rename-Item -NewName { 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle' }
Get-ChildItem Microsoft.WindowsTerminal_Win11_*.msixbundle | Rename-Item -NewName { 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle' }
# Create vpack directory and place item inside
@@ -703,17 +696,16 @@ jobs:
mkdir WindowsTerminal.app
mv Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle .\WindowsTerminal.app\
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed-Win11
- task: PkgESVPack@12
displayName: 'Package ES - VPack'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
inputs:
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed\WindowsTerminal.app
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed-Win11\WindowsTerminal.app
description: VPack for the Windows Terminal Application
pushPkgName: WindowsTerminal.app
owner: conhost
githubToken: $(GitHubTokenForVpackProvenance)
- task: PublishPipelineArtifact@1
displayName: 'Copy VPack Manifest to Drop'
inputs:

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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
@@ -144,11 +142,11 @@ jobs:
inputs:
TargetPattern: guardianGlob
# See https://aka.ms/gdn-globs for how to do match patterns
AnalyzeTargetGlob: $(Build.SourcesDirectory)\bin\**\*.dll;$(Build.SourcesDirectory)\bin\**\*.exe;-:file|**\Microsoft.UI.Xaml.dll;-:file|**\Microsoft.Toolkit.Win32.UI.XamlHost.dll;-:file|**\vcruntime*.dll;-:file|**\vcomp*.dll;-:file|**\vccorlib*.dll;-:file|**\vcamp*.dll;-:file|**\msvcp*.dll;-:file|**\concrt*.dll;-:file|**\TerminalThemeHelpers*.dll
AnalyzeTargetGlob: $(Build.SourcesDirectory)\bin\**\*.dll;$(Build.SourcesDirectory)\bin\**\*.exe;-:file|**\Microsoft.UI.Xaml.dll;-:file|**\Microsoft.Toolkit.Win32.UI.XamlHost.dll;-:file|**\vcruntime*.dll;-:file|**\vcomp*.dll;-:file|**\vccorlib*.dll;-:file|**\vcamp*.dll;-:file|**\msvcp*.dll;-:file|**\concrt*.dll;-:file|**\TerminalThemeHelpers*.dll;-:file|**\cpprest*.dll
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

View File

@@ -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'

View File

@@ -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'

View File

@@ -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"
@@ -64,24 +65,17 @@ steps:
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
- task: CopyFiles@2
displayName: 'Copy *.msix to Artifacts'
displayName: 'Copy *.appx/*.msix to Artifacts (Non-PR builds only)'
inputs:
Contents: |
**/*.appx
**/*.msix
**/*.appxsym
!**/Microsoft.VCLibs*.appx
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
OverWrite: true
flattenFolders: true
- pwsh: |-
$TerminalMsixPath = (Get-Item "$(Build.ArtifactStagingDirectory)\appx\Cascadia*.msix").FullName
$XamlAppxPath = (Get-Item "src\cascadia\CascadiaPackage\AppPackages\*\Dependencies\$(BuildPlatform)\Microsoft.UI.Xaml*.appx").FullName
& .\build\scripts\New-UnpackagedTerminalDistribution.ps1 -TerminalAppX $TerminalMsixPath -XamlAppX $XamlAppxPath -Destination "$(Build.ArtifactStagingDirectory)/unpackaged"
displayName: Build Unpackaged Distribution
- publish: $(Build.ArtifactStagingDirectory)/unpackaged
artifact: unpackaged-$(BuildPlatform)-$(BuildConfiguration)
displayName: Publish Artifact (unpackaged)
condition: succeeded()
- task: CopyFiles@2
displayName: 'Copy outputs needed for test runs to Artifacts'

View File

@@ -2,7 +2,7 @@
jobs:
- job: CodeFormatCheck
displayName: Proper Code Formatting Check
pool: { vmImage: windows-2022 }
pool: { vmImage: windows-2019 }
steps:
- checkout: self

View File

@@ -14,8 +14,8 @@ parameters:
platform: ''
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
useBuildOutputFromPipeline: $(System.DefinitionId)
openHelixTargetQueues: 'windows.11.amd64.client.open.reunion'
closedHelixTargetQueues: 'windows.11.amd64.client.reunion'
openHelixTargetQueues: 'windows.10.amd64.client21h1.open.xaml'
closedHelixTargetQueues: 'windows.10.amd64.client21h1.xaml'
jobs:
- job: ${{ parameters.name }}
@@ -43,9 +43,9 @@ jobs:
filename: 'set'
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 6.3.0'
displayName: 'Use NuGet 5.2.0'
inputs:
versionSpec: 6.3.0
versionSpec: 5.2.0
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet restore build/Helix/packages.config'

View 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 }})'

View File

@@ -27,9 +27,9 @@ jobs:
displayName: 'Retrieve VC tools directory'
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 6.3.0'
displayName: 'Use NuGet 5.2.0'
inputs:
versionSpec: 6.3.0
versionSpec: 5.2.0
- task: NuGetAuthenticate@0

View File

@@ -1,15 +1,11 @@
steps:
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 6.3.0'
displayName: 'Use NuGet 5.2.0'
inputs:
versionSpec: 6.3.0
versionSpec: 5.2.0
- task: NuGetAuthenticate@0
- script: |-
echo ##vso[task.setvariable variable=NUGET_RESTORE_MSBUILD_ARGS]/p:Platform=$(BuildPlatform)
displayName: Ensure NuGet restores for $(BuildPlatform)
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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')" />

View File

@@ -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)' &gt;= '10.0.18362.0'">
$(BeforeLinkTargets);

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
This file contains targets that override behavior in Microsoft.UI.Xaml and
related packages.
For example: All XAML needs is a reference to WebView2; it does not need the
DLL and it does not need for us to copy the WinMD into the output folder. It
also doesn't require the WebView2 loader since we're not actually using
WebView2. Therefore, we can get away with *not including the WebView2
package* and only adding a reference to its winmd.
-->
<ItemGroup>
<Reference Include="$(WebView2PackageRoot)\lib\Microsoft.Web.WebView2.Core.winmd" />
</ItemGroup>
</Project>

View File

@@ -22,7 +22,7 @@ Param(
[Parameter(HelpMessage="Path to makeappx.exe")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe"
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86\MakeAppx.exe"
)
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {

View File

@@ -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)

View 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"
}

View File

@@ -1,78 +0,0 @@
Param(
[Parameter(Mandatory,
HelpMessage="List of PRI files or XML dumps (detailed only) to merge")]
[string[]]
$Path,
[Parameter(Mandatory,
HelpMessage="Output Path")]
[string]
$OutputPath,
[Parameter(HelpMessage="Name of index in output file; defaults to 'Application'")]
[string]
$IndexName = "Application",
[Parameter(HelpMessage="Path to makepri.exe")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakePriPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakePri.exe"
)
$ErrorActionPreference = 'Stop'
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
New-Item -ItemType Directory -Path $tempDir | Out-Null
$priConfig = Join-Path $tempDir "priconfig.xml"
$priListFile = Join-Path $tempDir "pri.resfiles"
$dumpListFile = Join-Path $tempDir "dump.resfiles"
@"
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="dump.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRIINFO" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="pri.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
</resources>
"@ | Out-File -Encoding:utf8NoBOM $priConfig
$Path | Where { $_ -Like "*.pri" } | ForEach-Object {
Get-Item $_ | Select -Expand FullName
} | Out-File -Encoding:utf8NoBOM $priListFile
$Path | Where { $_ -Like "*.xml" } | ForEach-Object {
Get-Item $_ | Select -Expand FullName
} | Out-File -Encoding:utf8NoBOM $dumpListFile
& $MakePriPath new /pr $tempDir /cf $priConfig /o /in $IndexName /of $OutputPath
Remove-Item -Recurse -Force $tempDir

View File

@@ -1,47 +0,0 @@
Param(
[Parameter(Mandatory,
HelpMessage="Root directory of extracted Terminal AppX")]
[string[]]
$TerminalRoot,
[Parameter(Mandatory,
HelpMessage="Root directory of extracted Xaml AppX")]
[string[]]
$XamlRoot,
[Parameter(Mandatory,
HelpMessage="Output Path")]
[string]
$OutputPath,
[Parameter(HelpMessage="Path to makepri.exe")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakePriPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakePri.exe"
)
$ErrorActionPreference = 'Stop'
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
New-Item -ItemType Directory -Path $tempDir | Out-Null
$terminalDump = Join-Path $tempDir "terminal.pri.xml"
& $MakePriPath dump /if (Join-Path $TerminalRoot "resources.pri") /of $terminalDump /dt detailed
Write-Verbose "Removing Microsoft.UI.Xaml node from Terminal to prevent a collision with XAML"
$terminalXMLDocument = [xml](Get-Content $terminalDump)
$resourceMap = $terminalXMLDocument.PriInfo.ResourceMap
$fileSubtree = $resourceMap.ResourceMapSubtree | Where-Object { $_.Name -eq "Files" }
$subtrees = $fileSubtree.ResourceMapSubtree
$xamlSubtreeChild = ($subtrees | Where-Object { $_.Name -eq "Microsoft.UI.Xaml" })
if ($Null -Ne $xamlSubtreeChild) {
$null = $fileSubtree.RemoveChild($xamlSubtreeChild)
$terminalXMLDocument.Save($terminalDump)
}
$indexName = $terminalXMLDocument.PriInfo.ResourceMap.name
& (Join-Path $PSScriptRoot "Merge-PriFiles.ps1") -Path $terminalDump, (Join-Path $XamlRoot "resources.pri") -IndexName $indexName -OutputPath $OutputPath -MakePriPath $MakePriPath
Remove-Item -Recurse -Force $tempDir

View File

@@ -1,140 +0,0 @@
[CmdletBinding(DefaultParameterSetName = 'AppX')]
Param(
[Parameter(Mandatory, HelpMessage="Path to Terminal AppX", ParameterSetName = 'AppX')]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$TerminalAppX,
[Parameter(Mandatory, HelpMessage="Path to Terminal Layout Deployment", ParameterSetName='Layout')]
[ValidateScript({Test-Path $_ -Type Container})]
[string]
$TerminalLayout,
[Parameter(Mandatory, HelpMessage="Path to Xaml AppX", ParameterSetName='AppX')]
[Parameter(Mandatory, HelpMessage="Path to Xaml AppX", ParameterSetName='Layout')]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$XamlAppX,
[Parameter(HelpMessage="Output Directory", ParameterSetName='AppX')]
[Parameter(HelpMessage="Output Directory", ParameterSetName='Layout')]
[string]
$Destination = ".",
[Parameter(HelpMessage="Path to makeappx.exe", ParameterSetName='AppX')]
[Parameter(HelpMessage="Path to makeappx.exe", ParameterSetName='Layout')]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakeAppx.exe"
)
$filesToRemove = @("*.xml", "*.winmd", "Appx*", "Images/*Tile*", "Images/*Logo*") # Remove from Terminal
$filesToKeep = @("Microsoft.Terminal.Remoting.winmd") # ... except for these
$filesToCopyFromXaml = @("Microsoft.UI.Xaml.dll", "Microsoft.UI.Xaml") # We don't need the .winmd
$ErrorActionPreference = 'Stop'
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {
Write-Error "Could not find MakeAppx.exe at `"$MakeAppxPath`".`nMake sure that -MakeAppxPath points to a valid SDK."
Exit 1
}
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "tmp$([Convert]::ToString((Get-Random 65535),16).PadLeft(4,'0')).tmp"
New-Item -ItemType Directory -Path $tempDir | Out-Null
$XamlAppX = Get-Item $XamlAppX | Select-Object -Expand FullName
########
# Reading the AppX Manifest for preliminary info
########
If ($TerminalAppX) {
$appxManifestPath = Join-Path $tempDir AppxManifest.xml
& tar.exe -x -f "$TerminalAppX" -C $tempDir AppxManifest.xml
} ElseIf($TerminalLayout) {
$appxManifestPath = Join-Path $TerminalLayout AppxManifest.xml
}
$manifest = [xml](Get-Content $appxManifestPath)
$pfn = $manifest.Package.Identity.Name
$version = $manifest.Package.Identity.Version
$architecture = $manifest.Package.Identity.ProcessorArchitecture
$distributionName = "{0}_{1}_{2}" -f ($pfn, $version, $architecture)
$terminalDir = "terminal-{0}" -f ($version)
########
# Unpacking Terminal and XAML
########
$terminalAppPath = Join-Path $tempdir $terminalDir
If ($TerminalAppX) {
$TerminalAppX = Get-Item $TerminalAppX | Select-Object -Expand FullName
New-Item -ItemType Directory -Path $terminalAppPath | Out-Null
& $MakeAppxPath unpack /p $TerminalAppX /d $terminalAppPath /o | Out-Null
If ($LASTEXITCODE -Ne 0) {
Throw "Unpacking $TerminalAppX failed"
}
} ElseIf ($TerminalLayout) {
Copy-Item -Recurse -Path $TerminalLayout -Destination $terminalAppPath
}
$xamlAppPath = Join-Path $tempdir "xaml"
New-Item -ItemType Directory -Path $xamlAppPath | Out-Null
& $MakeAppxPath unpack /p $XamlAppX /d $xamlAppPath /o | Out-Null
If ($LASTEXITCODE -Ne 0) {
Throw "Unpacking $XamlAppX failed"
}
########
# Some sanity checking
########
$xamlManifest = [xml](Get-Content (Join-Path $xamlAppPath "AppxManifest.xml"))
If ($xamlManifest.Package.Identity.Name -NotLike "Microsoft.UI.Xaml*") {
Throw "$XamlAppX is not a XAML package (instead, it looks like $($xamlManifest.Package.Identity.Name))"
}
If ($xamlManifest.Package.Identity.ProcessorArchitecture -Ne $architecture) {
Throw "$XamlAppX is not built for $architecture (instead, it is built for $($xamlManifest.Package.Identity.ProcessorArchitecture))"
}
########
# Preparation of source files
########
$itemsToRemove = $filesToRemove | ForEach-Object {
Get-Item (Join-Path $terminalAppPath $_) -EA:SilentlyContinue | Where-Object {
$filesToKeep -NotContains $_.Name
}
} | Sort-Object FullName -Unique
$itemsToRemove | Remove-Item -Recurse
$filesToCopyFromXaml | ForEach-Object {
Get-Item (Join-Path $xamlAppPath $_)
} | Copy-Item -Recurse -Destination $terminalAppPath
########
# Resource Management
########
$finalTerminalPriFile = Join-Path $terminalAppPath "resources.pri"
& (Join-Path $PSScriptRoot "Merge-TerminalAndXamlResources.ps1") `
-TerminalRoot $terminalAppPath `
-XamlRoot $xamlAppPath `
-OutputPath $finalTerminalPriFile `
-Verbose:$Verbose | Out-Host
########
# Packaging
########
If ($PSCmdlet.ParameterSetName -Eq "AppX") {
# We only produce a ZIP when we're combining two AppX directories.
New-Item -ItemType Directory -Path $Destination -ErrorAction:SilentlyContinue | Out-Null
$outputZip = (Join-Path $Destination ("{0}.zip" -f ($distributionName)))
& tar -c --format=zip -f $outputZip -C $tempDir $terminalDir
Remove-Item -Recurse -Force $tempDir -EA:SilentlyContinue
Get-Item $outputZip
} ElseIf ($PSCmdlet.ParameterSetName -Eq "Layout") {
Get-Item $terminalAppPath
}

View File

@@ -0,0 +1,14 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
Param(
[string]$NewWindowsVersion = "10.0.22000.0"
)
Get-ChildItem src/cascadia/CascadiaPackage -Recurse -Filter *.appxmanifest | ForEach-Object {
$xml = [xml](Get-Content $_.FullName)
$xml.Package.Dependencies.TargetDeviceFamily | Where-Object Name -Like "Windows*" | ForEach-Object {
$_.MinVersion = $NewWindowsVersion
}
$xml.Save($_.FullName)
}

View File

@@ -8,7 +8,7 @@ Param(
[Parameter(HelpMessage="Path to Windows Kit")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0"
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0"
)
$ErrorActionPreference = "Stop"
@@ -70,24 +70,23 @@ Try {
$dependencies = $Manifest.Package.Dependencies.PackageDependency.Name
$depsHasVclibsDesktop = ("Microsoft.VCLibs.140.00.UWPDesktop" -in $dependencies) -or ("Microsoft.VCLibs.140.00.Debug.UWPDesktop" -in $dependencies)
$depsHasVclibsAppX = ("Microsoft.VCLibs.140.00" -in $dependencies) -or ("Microsoft.VCLibs.140.00.Debug" -in $dependencies)
$depsHasVcLibsAppX = ("Microsoft.VCLibs.140.00" -in $dependencies) -or ("Microsoft.VCLibs.140.00.Debug" -in $dependencies)
$filesHasVclibsDesktop = ($null -ne (Get-Item "$AppxPackageRootPath\vcruntime140.dll" -EA:Ignore)) -or ($null -ne (Get-Item "$AppxPackageRootPath\vcruntime140d.dll" -EA:Ignore))
$filesHasVclibsAppX = ($null -ne (Get-Item "$AppxPackageRootPath\vcruntime140_app.dll" -EA:Ignore)) -or ($null -ne (Get-Item "$AppxPackageRootPath\vcruntime140d_app.dll" -EA:Ignore))
If ($filesHasVclibsDesktop) {
Throw "Package contains the desktop VCLibs"
If ($depsHasVclibsDesktop -Eq $filesHasVclibsDesktop) {
$eitherBoth = if ($depsHasVclibsDesktop) { "both" } else { "neither" }
$neitherNor = if ($depsHasVclibsDesktop) { "and" } else { "nor" }
Throw "Package has $eitherBoth Dependency $neitherNor Integrated Desktop VCLibs"
}
If ($depsHasVclibsDesktop) {
Throw "Package has a dependency on the desktop VCLibs"
}
If ($filesHasVclibsAppX) {
Throw "Package contains the AppX VCLibs"
}
If ($depsHasVclibsAppX) {
Throw "Package has a dependency on the AppX VCLibs"
If ($depsHasVclibsAppx -Eq $filesHasVclibsAppx) {
if ($depsHasVclibsAppx) {
# We've shipped like this forever, so downgrade to warning.
Write-Warning "Package has both Dependency and Integrated AppX VCLibs"
} else {
Throw "Package has neither Dependency nor Integrated AppX VCLibs"
}
}
### Check that we have an App.xbf (which is a proxy for our resources having been merged)
@@ -97,6 +96,11 @@ Try {
Throw "Failed to find App.xbf (TerminalApp project) in resources.pri"
}
If (($null -eq (Get-Item "$AppxPackageRootPath\cpprest142_2_10.dll" -EA:Ignore)) -And
($null -eq (Get-Item "$AppxPackageRootPath\cpprest142_2_10d.dll" -EA:Ignore))) {
Throw "Failed to find cpprest142_2_10.dll -- check the WAP packaging project"
}
If (($null -eq (Get-Item "$AppxPackageRootPath\wtd.exe" -EA:Ignore)) -And
($null -eq (Get-Item "$AppxPackageRootPath\wt.exe" -EA:Ignore))) {
Throw "Failed to find wt.exe/wtd.exe -- check the WAP packaging project"

View File

@@ -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,
@@ -10,4 +10,22 @@
<OpenConsoleDir>$(MSBuildThisFileDirectory)</OpenConsoleDir>
</PropertyGroup>
<PropertyGroup>
<!--
For the Windows 10 build, we're targeting the prerelease version of Microsoft.UI.Xaml.
This version emits every XAML DLL directly into our package.
This is a workaround for us not having deliverable MSFT-21242953 on this version of Windows.
This version should be tracked in all project packages.config files for projects that depend on Xaml.
-->
<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.1</TerminalMUXVersion>
</PropertyGroup>
</Project>

View File

@@ -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/",

View File

@@ -1,11 +1,23 @@
<?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">
<!--
The Windows 11 build is going to have the same package name, so it *must* have a different version.
The easiest way for us to do this is to add 1 to the revision field.
In short, for a given Terminal build 1.11, we will emit two different versions (assume this is build
4 on day 23 of the year):
- 1.11.234.0 for Windows 10
- 1.11.235.0 for Windows 11
This presents a potential for conflicts if we want to ship two builds produced back to back on the
same day... which is terribly unlikely.
-->
<VersionBuildRevision Condition="'$(TerminalTargetWindowsVersion)'=='Win11' and '$(VersionBuildRevision)'!=''">$([MSBuild]::Add($(VersionBuildRevision), 1))</VersionBuildRevision>
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
<XesBaseYearForStoreVersion>2023</XesBaseYearForStoreVersion>
<XesBaseYearForStoreVersion>2022</XesBaseYearForStoreVersion>
<VersionMajor>1</VersionMajor>
<VersionMinor>18</VersionMinor>
<VersionMinor>15</VersionMinor>
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
</PropertyGroup>
</Project>

View File

@@ -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": "5cb3efabce007c3a0230e4cc2e27da491c646b6c"
}
}
"type": "git",
"git": {
"repositoryUrl": "https://github.com/CLIUtils/CLI11",
"commitHash": "dd0d8e4fe729e5b1110232c7a5c9566dad884686"
}
}
}
],
"Version": 1
],
"Version": 1
}

View File

@@ -13,10 +13,6 @@ Licensed under the MIT license.
#define CIS_EVENT_TYPE_FOCUS (1)
#define CIS_EVENT_TYPE_FOCUS_ACK (2)
#define CIS_MSG_TYPE_MAPVIRTUALKEY (0)
#define CIS_MSG_TYPE_VKKEYSCAN (1)
#define CIS_MSG_TYPE_GETKEYSTATE (2)
#define CIS_MSG_TYPE_GETDISPLAYSIZE (3)
#define CIS_MSG_TYPE_GETFONTSIZE (4)
#define CIS_MSG_TYPE_SETCURSOR (5)
@@ -35,22 +31,6 @@ typedef struct {
UCHAR Type;
union {
struct {
UINT Code;
UINT MapType;
UINT ReturnValue;
} MapVirtualKeyParams;
struct {
WCHAR Character;
SHORT ReturnValue;
} VkKeyScanParams;
struct {
int VirtualKey;
SHORT ReturnValue;
} GetKeyStateParams;
struct {
CD_IO_DISPLAY_SIZE DisplaySize;

View File

@@ -2,8 +2,8 @@
[Amalgamated](https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated)
from source commit
[5defb4e](https://github.com/open-source-parsers/jsoncpp/commit/5defb4ed1a4293b8e2bf641e16b156fb9de498cc),
release 1.9.5.
[6aba23f](https://github.com/open-source-parsers/jsoncpp/commit/6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2),
release 1.9.3.
> Generating amalgamated source and header JsonCpp is provided with a script to
> generate a single header and a single source file to ease inclusion into an

View File

@@ -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": "5defb4ed1a4293b8e2bf641e16b156fb9de498cc"
}
}
"type": "git",
"git": {
"repositoryUrl": "https://github.com/open-source-parsers/jsoncpp",
"commitHash": "6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2"
}
}
}
],
"Version": 1
],
"Version": 1
}

View File

@@ -7,28 +7,28 @@
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
@@ -94,10 +94,10 @@ license you like.
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.5"
#define JSONCPP_VERSION_STRING "1.9.3"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 5
#define JSONCPP_VERSION_PATCH 3
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
@@ -162,10 +162,11 @@ public:
* Release memory which was allocated for N items at pointer P.
*
* The memory block is filled with zeroes before being released.
* The pointer argument is tagged as "volatile" to prevent the
* compiler optimizing out this critical step.
*/
void deallocate(pointer p, size_type n) {
// memset_s is used because memset may be optimized away by the compiler
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
void deallocate(volatile pointer p, size_type n) {
std::memset(p, 0, n * sizeof(T));
// free using "global operator delete"
::operator delete(p);
}

View File

@@ -6,28 +6,28 @@
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
@@ -93,10 +93,10 @@ license you like.
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.5"
#define JSONCPP_VERSION_STRING "1.9.3"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 5
#define JSONCPP_VERSION_PATCH 3
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
@@ -161,10 +161,11 @@ public:
* Release memory which was allocated for N items at pointer P.
*
* The memory block is filled with zeroes before being released.
* The pointer argument is tagged as "volatile" to prevent the
* compiler optimizing out this critical step.
*/
void deallocate(pointer p, size_type n) {
// memset_s is used because memset may be optimized away by the compiler
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
void deallocate(volatile pointer p, size_type n) {
std::memset(p, 0, n * sizeof(T));
// free using "global operator delete"
::operator delete(p);
}
@@ -574,7 +575,7 @@ public:
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(push)
#pragma warning(disable : 4251 4275)
#pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma pack(push, 8)
@@ -787,10 +788,10 @@ private:
CZString(ArrayIndex index);
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
CZString(CZString const& other);
CZString(CZString&& other) noexcept;
CZString(CZString&& other);
~CZString();
CZString& operator=(const CZString& other);
CZString& operator=(CZString&& other) noexcept;
CZString& operator=(CZString&& other);
bool operator<(CZString const& other) const;
bool operator==(CZString const& other) const;
@@ -866,15 +867,14 @@ public:
Value(const StaticString& value);
Value(const String& value);
Value(bool value);
Value(std::nullptr_t ptr) = delete;
Value(const Value& other);
Value(Value&& other) noexcept;
Value(Value&& other);
~Value();
/// \note Overwrite existing comments. To preserve comments, use
/// #swapPayload().
Value& operator=(const Value& other);
Value& operator=(Value&& other) noexcept;
Value& operator=(Value&& other);
/// Swap everything.
void swap(Value& other);
@@ -1159,9 +1159,9 @@ private:
public:
Comments() = default;
Comments(const Comments& that);
Comments(Comments&& that) noexcept;
Comments(Comments&& that);
Comments& operator=(const Comments& that);
Comments& operator=(Comments&& that) noexcept;
Comments& operator=(Comments&& that);
bool has(CommentPlacement slot) const;
String get(CommentPlacement slot) const;
void set(CommentPlacement slot, String comment);
@@ -1442,8 +1442,8 @@ public:
* because the returned references/pointers can be used
* to change state of the base class.
*/
reference operator*() const { return const_cast<reference>(deref()); }
pointer operator->() const { return const_cast<pointer>(&deref()); }
reference operator*() { return deref(); }
pointer operator->() { return &deref(); }
};
inline void swap(Value& a, Value& b) { a.swap(b); }
@@ -1506,7 +1506,8 @@ namespace Json {
* \deprecated Use CharReader and CharReaderBuilder.
*/
class JSON_API Reader {
class JSONCPP_DEPRECATED(
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
public:
using Char = char;
using Location = const Char*;
@@ -1523,13 +1524,13 @@ public:
};
/** \brief Constructs a Reader allowing all features for parsing.
* \deprecated Use CharReader and CharReaderBuilder.
*/
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
Reader();
/** \brief Constructs a Reader allowing the specified feature set for parsing.
* \deprecated Use CharReader and CharReaderBuilder.
*/
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
Reader(const Features& features);
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
@@ -1796,9 +1797,6 @@ public:
* - `"allowSpecialFloats": false or true`
* - If true, special float values (NaNs and infinities) are allowed and
* their values are lossfree restorable.
* - `"skipBom": false or true`
* - If true, if the input starts with the Unicode byte order mark (BOM),
* it is skipped.
*
* You can examine 'settings_` yourself to see the defaults. You can also
* write and read them just like any JSON Value.
@@ -2002,8 +2000,6 @@ public:
* - Number of precision digits for formatting of real values.
* - "precisionType": "significant"(default) or "decimal"
* - Type of precision for formatting of real values.
* - "emitUTF8": false or true
* - If true, outputs raw UTF8 strings instead of escaping them.
* You can examine 'settings_` yourself
* to see the defaults. You can also write and read them just like any
@@ -2039,7 +2035,7 @@ public:
/** \brief Abstract class for writers.
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
*/
class JSON_API Writer {
class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
public:
virtual ~Writer();
@@ -2059,7 +2055,7 @@ public:
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSON_API FastWriter
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter
: public Writer {
public:
FastWriter();
@@ -2119,7 +2115,7 @@ private:
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSON_API
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
StyledWriter : public Writer {
public:
StyledWriter();
@@ -2188,7 +2184,7 @@ private:
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSON_API
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
StyledStreamWriter {
public:
/**

View File

@@ -6,28 +6,28 @@
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
@@ -202,18 +202,14 @@ template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
* Return iterator that would be the new end of the range [begin,end), if we
* were to delete zeros in the end of string, but not the last zero before '.'.
*/
template <typename Iter>
Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) {
for (; begin != end; --end) {
if (*(end - 1) != '0') {
return end;
}
// Don't delete the last zero before the decimal point.
if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
if (precision) {
return end;
}
return end - 2;
if (begin != (end - 1) && *(end - 2) == '.') {
return end;
}
}
return end;
@@ -342,7 +338,8 @@ bool Reader::parse(std::istream& is, Value& root, bool collectComments) {
// Since String is reference-counted, this at least does not
// create an extra copy.
String doc(std::istreambuf_iterator<char>(is), {});
String doc;
std::getline(is, doc, static_cast<char> EOF);
return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
}
@@ -1412,11 +1409,8 @@ bool OurReader::readToken(Token& token) {
if (features_.allowSingleQuotes_) {
token.type_ = tokenString;
ok = readStringSingleQuote();
} else {
// If we don't allow single quotes, this is a failure case.
ok = false;
}
break;
break;
} // else fall through
case '/':
token.type_ = tokenComment;
ok = readComment();
@@ -2158,7 +2152,7 @@ bool CharReaderBuilder::validate(Json::Value* invalid) const {
if (valid_keys.count(key))
continue;
if (invalid)
(*invalid)[key] = *si;
(*invalid)[std::move(key)] = *si;
else
return false;
}
@@ -2673,7 +2667,7 @@ Value::CZString::CZString(const CZString& other) {
storage_.length_ = other.storage_.length_;
}
Value::CZString::CZString(CZString&& other) noexcept
Value::CZString::CZString(CZString&& other)
: cstr_(other.cstr_), index_(other.index_) {
other.cstr_ = nullptr;
}
@@ -2699,7 +2693,7 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
return *this;
}
Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
Value::CZString& Value::CZString::operator=(CZString&& other) {
cstr_ = other.cstr_;
index_ = other.index_;
other.cstr_ = nullptr;
@@ -2847,7 +2841,7 @@ Value::Value(const Value& other) {
dupMeta(other);
}
Value::Value(Value&& other) noexcept {
Value::Value(Value&& other) {
initBasic(nullValue);
swap(other);
}
@@ -2862,7 +2856,7 @@ Value& Value::operator=(const Value& other) {
return *this;
}
Value& Value::operator=(Value&& other) noexcept {
Value& Value::operator=(Value&& other) {
other.swap(*this);
return *this;
}
@@ -3326,8 +3320,7 @@ void Value::resize(ArrayIndex newSize) {
if (newSize == 0)
clear();
else if (newSize > oldSize)
for (ArrayIndex i = oldSize; i < newSize; ++i)
(*this)[i];
this->operator[](newSize - 1);
else {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
value_.map_->erase(index);
@@ -3788,15 +3781,14 @@ bool Value::isObject() const { return type() == objectValue; }
Value::Comments::Comments(const Comments& that)
: ptr_{cloneUnique(that.ptr_)} {}
Value::Comments::Comments(Comments&& that) noexcept
: ptr_{std::move(that.ptr_)} {}
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
Value::Comments& Value::Comments::operator=(const Comments& that) {
ptr_ = cloneUnique(that.ptr_);
return *this;
}
Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
Value::Comments& Value::Comments::operator=(Comments&& that) {
ptr_ = std::move(that.ptr_);
return *this;
}
@@ -3812,11 +3804,13 @@ String Value::Comments::get(CommentPlacement slot) const {
}
void Value::Comments::set(CommentPlacement slot, String comment) {
if (slot >= CommentPlacement::numberOfCommentPlacement)
return;
if (!ptr_)
if (!ptr_) {
ptr_ = std::unique_ptr<Array>(new Array());
(*ptr_)[slot] = std::move(comment);
}
// check comments array boundry.
if (slot < CommentPlacement::numberOfCommentPlacement) {
(*ptr_)[slot] = std::move(comment);
}
}
void Value::setComment(String comment, CommentPlacement placement) {
@@ -4130,7 +4124,7 @@ Value& Path::make(Value& root) const {
#if !defined(isnan)
// IEEE standard states that NaN values will not compare to themselves
#define isnan(x) ((x) != (x))
#define isnan(x) (x != x)
#endif
#if !defined(__APPLE__)
@@ -4216,18 +4210,16 @@ String valueToString(double value, bool useSpecialFloats,
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
// strip the zero padding from the right
if (precisionType == PrecisionType::decimalPlaces) {
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
}
// try to ensure we preserve the fact that this was given to us as a double on
// input
if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
buffer += ".0";
}
// strip the zero padding from the right
if (precisionType == PrecisionType::decimalPlaces) {
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end(), precision),
buffer.end());
}
return buffer;
}
} // namespace
@@ -4239,11 +4231,11 @@ String valueToString(double value, unsigned int precision,
String valueToString(bool value) { return value ? "true" : "false"; }
static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
assert(s || !n);
return std::any_of(s, s + n, [](unsigned char c) {
return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
return c == '\\' || c == '"' || !std::isprint(c);
});
}
@@ -4334,12 +4326,12 @@ static void appendHex(String& result, unsigned ch) {
result.append("\\u").append(toHex16Bit(ch));
}
static String valueToQuotedStringN(const char* value, size_t length,
static String valueToQuotedStringN(const char* value, unsigned length,
bool emitUTF8 = false) {
if (value == nullptr)
return "";
if (!doesAnyCharRequireEscaping(value, length))
if (!isAnyCharRequiredQuoting(value, length))
return String("\"") + value + "\"";
// We have to walk value and escape any special characters.
// Appending to String is not efficient, but this should be rare.
@@ -4412,7 +4404,7 @@ static String valueToQuotedStringN(const char* value, size_t length,
}
String valueToQuotedString(const char* value) {
return valueToQuotedStringN(value, strlen(value));
return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
}
// Class Writer
@@ -4461,7 +4453,7 @@ void FastWriter::writeValue(const Value& value) {
char const* end;
bool ok = value.getString(&str, &end);
if (ok)
document_ += valueToQuotedStringN(str, static_cast<size_t>(end - str));
document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str));
break;
}
case booleanValue:
@@ -4484,7 +4476,8 @@ void FastWriter::writeValue(const Value& value) {
const String& name = *it;
if (it != members.begin())
document_ += ',';
document_ += valueToQuotedStringN(name.data(), name.length());
document_ += valueToQuotedStringN(name.data(),
static_cast<unsigned>(name.length()));
document_ += yamlCompatibilityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
@@ -4529,7 +4522,7 @@ void StyledWriter::writeValue(const Value& value) {
char const* end;
bool ok = value.getString(&str, &end);
if (ok)
pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
else
pushValue("");
break;
@@ -4570,7 +4563,7 @@ void StyledWriter::writeValue(const Value& value) {
}
void StyledWriter::writeArrayValue(const Value& value) {
size_t size = value.size();
unsigned size = value.size();
if (size == 0)
pushValue("[]");
else {
@@ -4579,7 +4572,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
writeWithIndent("[");
indent();
bool hasChildValue = !childValues_.empty();
ArrayIndex index = 0;
unsigned index = 0;
for (;;) {
const Value& childValue = value[index];
writeCommentBeforeValue(childValue);
@@ -4602,7 +4595,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
{
assert(childValues_.size() == size);
document_ += "[ ";
for (size_t index = 0; index < size; ++index) {
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
document_ += ", ";
document_ += childValues_[index];
@@ -4747,7 +4740,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
char const* end;
bool ok = value.getString(&str, &end);
if (ok)
pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
else
pushValue("");
break;
@@ -5021,8 +5014,8 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
char const* end;
bool ok = value.getString(&str, &end);
if (ok)
pushValue(
valueToQuotedStringN(str, static_cast<size_t>(end - str), emitUTF8_));
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str),
emitUTF8_));
else
pushValue("");
break;
@@ -5045,8 +5038,8 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
String const& name = *it;
Value const& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(
valueToQuotedStringN(name.data(), name.length(), emitUTF8_));
writeWithIndent(valueToQuotedStringN(
name.data(), static_cast<unsigned>(name.length()), emitUTF8_));
*sout_ << colonSymbol_;
writeValue(childValue);
if (++it == members.end()) {
@@ -5280,7 +5273,7 @@ bool StreamWriterBuilder::validate(Json::Value* invalid) const {
if (valid_keys.count(key))
continue;
if (invalid)
(*invalid)[key] = *si;
(*invalid)[std::move(key)] = *si;
else
return false;
}

View File

@@ -2,19 +2,21 @@
<!-- The packages.config acts as the global version for all of the NuGet packages contained within. -->
<packages>
<!-- Native packages -->
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="vcpkg-cpprestsdk" version="2.10.14" targetFramework="native" />
<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.8.3" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" 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>

View File

@@ -59,7 +59,7 @@ To modify settings specific to the current application, invoke the `Properties`
When console applications are launched, the Windows Console Host determines which settings to use by overlaying settings from the above locations.
1. Initialize settings based on hard-coded defaults
1. Initialize settings based on hardcoded defaults
2. Overlay settings specified by the user's configured defaults
3. Overlay application-specific settings from either the registry or the shortcut file, depending on how the application was launched

View File

@@ -145,7 +145,7 @@ Our only backport successes really come from corporations with massive addressab
It's also costly in terms of time, effort, and testing for us to validate a modification to a released OS. We have a mindbogglingly massive amount of automated machinery dedicated to processing and validating the things that we check in while developing the current OS builds. But it's a special costly ask to spin up some to all of those activities to validate backported fixes. We do it all the time for Patch Tuesday, but in those patches, they only pass through the minimum number of fixes required to maximize the restoration of productivity/security/revenue/etc. because every additional fix adds additional complexity and additional risk.
So from our little team working hard to make developers happy, we virtually never make the cut for servicing. We're sorry, but we hope you can understand. It's just the reality of the situation to say "nope" when people ask for a backport. In our team's ideal world, you would all be running the latest console bits everywhere every time we make a change. But that's just not how it is today.
So from our little team working hard to make developers happy, we virtually never make the cut for servicing. We're sorry, but we hope you can understand. It's just the reality of the situation to say "nope" when people ask for a backport. In our team's ideal world, you would all be running the latest console bits everywhere everytime we make a change. But that's just not how it is today.
Original Source: https://github.com/microsoft/terminal/issues/279#issuecomment-439179675

View File

@@ -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.

View File

@@ -380,7 +380,7 @@ Here's the AppxManifest we're using:
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22621.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>
@@ -517,7 +517,7 @@ This is because of a few key lines we already put in the appxmanifest:
```xml
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22621.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>

View File

@@ -14,23 +14,10 @@
"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"
},
"CSSLengthPercentage": {
"pattern": "^[+-]?\\d+(?:\\.\\d+)?(?:%|ch|pt|px)?$",
"type": [
"string",
"null"
]
},
"DynamicProfileSource": {
"enum": [
"Windows.Terminal.Wsl",
@@ -71,32 +58,25 @@
"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": {
"description": "The name of a color scheme to use when unfocused.",
"oneOf": [
{
"$ref": "#/$defs/SchemePair"
},
{
"type": "string"
}
]
"type": "string"
},
"foreground": {
"$ref": "#/$defs/Color",
@@ -217,7 +197,7 @@
},
"intenseTextStyle": {
"default": "bright",
"description": "Controls how 'intense' text is rendered when unfocused. Values are \"bold\", \"bright\", \"all\" and \"none\"",
"description": "Controls how 'intense' text is rendered. Values are \"bold\", \"bright\", \"all\" and \"none\"",
"enum": [
"none",
"bold",
@@ -227,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.",
@@ -247,21 +221,6 @@
},
"type": "object"
},
"SchemePair": {
"description": "Contains both a light and dark color scheme for the Terminal to use, depending on the theme of the application.",
"properties": {
"light": {
"default": "Campbell",
"description": "Name of the scheme to use when the app is using light theme",
"type": "string"
},
"dark": {
"default": "Campbell",
"description": "Name of the scheme to use when the app is using dark theme",
"type": "string"
}
}
},
"FontConfig": {
"properties": {
"face": {
@@ -273,7 +232,7 @@
"default": 12,
"description": "Size of the font in points.",
"minimum": 1,
"type": "number"
"type": "integer"
},
"weight": {
"default": "normal",
@@ -321,14 +280,6 @@
}
},
"additionalProperties": false
},
"cellWidth": {
"$ref": "#/$defs/CSSLengthPercentage",
"description": "Override the width of the terminal's cells. The override works similar to CSS' letter-spacing. It defaults to the natural glyph advance width of the primary font rounded to the nearest pixel."
},
"cellHeight": {
"$ref": "#/$defs/CSSLengthPercentage",
"description": "Override the height of the terminal's cells. The override works similar to CSS' line-height. Defaults to the sum of the natural glyph ascend, descend and line-gap of the primary font rounded to the nearest pixel. The default is usually quite close to setting this to 1.2."
}
},
"type": "object"
@@ -349,7 +300,6 @@
"enum": [
"adjustFontSize",
"clearBuffer",
"closeOtherPanes",
"closeOtherTabs",
"closePane",
"closeTab",
@@ -358,7 +308,6 @@
"commandPalette",
"copy",
"duplicateTab",
"expandSelectionToWord",
"exportBuffer",
"find",
"findMatch",
@@ -401,11 +350,9 @@
"switchToTab",
"tabSearch",
"toggleAlwaysOnTop",
"toggleBlockSelection",
"toggleFocusMode",
"selectAll",
"setFocusMode",
"switchSelectionEndpoint",
"toggleFullscreen",
"setFullScreen",
"setMaximized",
@@ -417,11 +364,6 @@
"quit",
"adjustOpacity",
"restoreLastClosed",
"addMark",
"scrollToMark",
"clearMark",
"clearAllMarks",
"experimental.colorSelection",
"unbound"
],
"type": "string"
@@ -441,15 +383,6 @@
],
"type": "string"
},
"ScrollToMarkDirection": {
"enum": [
"previous",
"next",
"first",
"last"
],
"type": "string"
},
"ResizeDirection": {
"enum": [
"left",
@@ -576,160 +509,6 @@
},
"type": "object"
},
"NewTabMenuEntryType": {
"enum": [
"source",
"profile",
"folder",
"separator",
"remainingProfiles",
"matchProfiles"
]
},
"NewTabMenuEntry": {
"properties": {
"type": {
"description": "The type of menu entry",
"$ref": "#/$defs/NewTabMenuEntryType"
}
},
"required": [
"type"
],
"type": "object"
},
"FolderEntryInlining": {
"enum": [
"never",
"auto"
]
},
"FolderEntry": {
"description": "A folder entry in the new tab dropdown",
"allOf": [
{
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"properties": {
"type": {
"type": "string",
"const": "folder"
},
"name": {
"type": "string",
"default": "",
"description": "The name of the folder to show in the menu"
},
"icon": {
"$ref": "#/$defs/Icon"
},
"entries": {
"type": "array",
"description": "The entries to put inside this folder",
"minItems": 1,
"items": {
"$ref": "#/$defs/NewTabMenuEntry"
}
},
"inline": {
"description": "When set to auto and the folder only has a single entry, the entry will show directly and no folder will be rendered",
"default": "never",
"$ref": "#/$defs/FolderEntryInlining"
},
"allowEmpty": {
"description": "Whether to render a folder without entries, or to hide it",
"default": "false",
"type": "boolean"
}
}
}
]
},
"SeparatorEntry": {
"description": "A separator in the new tab dropdown",
"allOf": [
{
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"properties": {
"type": {
"type": "string",
"const": "separator"
}
}
}
]
},
"ProfileEntry": {
"description": "A profile in the new tab dropdown",
"allOf": [
{
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"properties": {
"type": {
"type": "string",
"const": "profile"
},
"profile": {
"type": "string",
"default": "",
"description": "The name or GUID of the profile to show in this entry"
}
}
}
]
},
"RemainingProfilesEntry": {
"description": "The set of profiles that are not yet explicitly included in another entry, such as the profile or source entries. This entry can be used at most one time!",
"allOf": [
{
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"properties": {
"type": {
"type": "string",
"const": "remainingProfiles"
}
}
}
]
},
"MatchProfilesEntry": {
"description": "A set of profiles all matching the given name, source, or command line, to show in the new tab dropdown",
"allOf": [
{
"$ref": "#/$defs/NewTabMenuEntry"
},
{
"properties": {
"type": {
"type": "string",
"const": "matchProfiles"
},
"name": {
"type": "string",
"default": "",
"description": "The name of the profiles to match"
},
"source": {
"type": "string",
"default": "",
"description": "The source of the profiles to match"
},
"commandline": {
"type": "string",
"default": "",
"description": "The command line of the profiles to match"
}
}
}
]
},
"SwitchToAdjacentTabArgs": {
"oneOf": [
{
@@ -953,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": [
@@ -1036,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": [
@@ -1121,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": [
@@ -1737,145 +1434,6 @@
}
]
},
"ShowCloseButton": {
"enum": [
"always",
"hover",
"never"
],
"type": "string"
},
"ThemeColor": {
"description": "A special kind of color for use in themes. Can be an #rrggbb color, #rrggbbaa color, or a special value. 'accent' is evaluated as the user's selected Accent color in the OS, and 'terminalBackground' will be evaluated as the background color of the active terminal pane.",
"oneOf": [
{
"pattern": "^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{2})?)?$",
"type": "string",
"format": "color",
"default": "#000000ff"
},
{
"const": "accent",
"type": "string"
},
{
"const": "terminalBackground",
"type": "string"
},
{
"type": "null"
}
]
},
"TabTheme": {
"additionalProperties": false,
"description": "A set of properties for customizing the appearance of the tabs",
"properties": {
"background": {
"description": "The color of a tab when it is the active tab",
"$ref": "#/$defs/ThemeColor"
},
"unfocusedBackground": {
"description": "The color of a tab when it is not the active tab",
"$ref": "#/$defs/ThemeColor"
},
"showCloseButton": {
"description": "Controls the visibility of the close button on the tab",
"$ref": "#/$defs/ShowCloseButton"
}
}
},
"TabRowTheme": {
"additionalProperties": false,
"description": "A set of properties for customizing the appearance of the tab row",
"properties": {
"background": {
"description": "The color of the tab row when the window is the foreground window.",
"$ref": "#/$defs/ThemeColor"
},
"unfocusedBackground": {
"description": "The color of the tab row when the window is inactive",
"$ref": "#/$defs/ThemeColor"
}
}
},
"WindowTheme": {
"additionalProperties": false,
"description": "A set of properties for customizing the appearance of the window itself",
"properties": {
"applicationTheme": {
"description": "Which UI theme the Terminal should use for controls",
"enum": [ "light", "dark", "system" ],
"type": "string"
},
"useMica": {
"description": "True if the Terminal should use a Mica backdrop for the window. This will apply underneath all controls (including the terminal panes and the titlebar)",
"type": "boolean",
"default": false
}
}
},
"Theme": {
"additionalProperties": false,
"description": "A set of properties for customizing the appearance of the window. This controls things like the titlebar, the tabs, the application theme.",
"properties": {
"name": {
"type": "string",
"description": "The name of the theme. This will be displayed in the settings UI.",
"not": {
"enum": [ "light", "dark", "system" ]
}
},
"tab": {
"$ref": "#/$defs/TabTheme"
},
"tabRow": {
"$ref": "#/$defs/TabRowTheme"
},
"window": {
"$ref": "#/$defs/WindowTheme"
}
}
},
"ThemePair": {
"additionalProperties": false,
"description": "A pair of Theme names, to allow the Terminal to switch theme based on the OS theme",
"properties": {
"light": {
"type": "string",
"description": "The name of the theme to use when the OS is in Light theme",
"default": "light"
},
"dark": {
"type": "string",
"description": "The name of the theme to use when the OS is in Dark theme",
"default": "dark"
}
}
},
"NewTabMenu": {
"description": "Defines the order and structure of the 'new tab' menu. It can consist of e.g. profiles, folders, and separators.",
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/$defs/FolderEntry"
},
{
"$ref": "#/$defs/SeparatorEntry"
},
{
"$ref": "#/$defs/ProfileEntry"
},
{
"$ref": "#/$defs/MatchProfilesEntry"
},
{
"$ref": "#/$defs/RemainingProfilesEntry"
}
]
}
},
"Keybinding": {
"additionalProperties": false,
"properties": {
@@ -1987,9 +1545,6 @@
{
"$ref": "#/$defs/AdjustOpacityAction"
},
{
"$ref": "#/$defs/ColorSelectionAction"
},
{
"type": "null"
}
@@ -2092,11 +1647,6 @@
"description": "When set to true, the terminal will focus the pane on mouse hover.",
"type": "boolean"
},
"compatibility.isolatedMode": {
"default": false,
"description": "When set to true, Terminal windows will not be able to interact with each other (including global hotkeys, tab drag/drop, running commandlines in existing windows, etc.). This is a compatibility escape hatch for users who are running into certain windowing issues.",
"type": "boolean"
},
"copyFormatting": {
"default": true,
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.",
@@ -2117,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.",
@@ -2169,11 +1714,6 @@
"description": "When set to true, the background image for the currently focused profile is expanded to encompass the entire window, beneath other panes.",
"type": "boolean"
},
"compatibility.reloadEnvironmentVariables": {
"default": true,
"description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.",
"type": "boolean"
},
"initialCols": {
"default": 120,
"description": "The number of columns displayed in the window upon first load. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), this property is ignored.",
@@ -2264,32 +1804,20 @@
},
"type": "array"
},
"newTabMenu": {
"$ref": "#/$defs/NewTabMenu"
},
"language": {
"default": "",
"description": "Sets an override for the app's preferred language, expressed as a BCP-47 language tag like en-US.",
"type": "string"
},
"theme": {
"default": "dark",
"description": "Sets the theme of the application. This value should be the name of one of the themes defined in `themes`. The Terminal also includes the themes `dark`, `light`, and `system`.",
"oneOf": [
{
"type": "string"
},
{
"$ref": "#/$defs/ThemePair"
}
]
},
"themes": {
"description": "The list of available themes",
"items": {
"$ref": "#/$defs/Theme"
},
"type": "array"
"default": "system",
"description": "Sets the theme of the application. The special value \"system\" refers to the active Windows system theme.",
"enum": [
"light",
"dark",
"system"
],
"type": "string"
},
"showTabsInTitlebar": {
"default": true,
@@ -2370,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": [
@@ -2497,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"
},
@@ -2522,14 +2031,7 @@
"colorScheme": {
"default": "Campbell",
"description": "Name of the terminal color scheme to use. Color schemes are defined under \"schemes\".",
"oneOf": [
{
"$ref": "#/$defs/SchemePair"
},
{
"type": "string"
}
]
"type": "string"
},
"commandline": {
"description": "Executable used in the profile.",
@@ -2574,18 +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."
},
"environment": {
"description": "Key-value pairs representing environment variables to set. Environment variable names are not case sensitive. You can reference existing environment variable names by enclosing them in literal percent characters (e.g. %PATH%).",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"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"
@@ -2594,19 +2084,14 @@
"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"
},
"useAtlasEngine": {
"description": "Windows Terminal 1.16 and later ship with a new, performant text renderer. Set this to false to revert back to the old text renderer.",
"experimental.useAtlasEngine": {
"description": "Enable using the experimental new rendering engine for this profile. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "boolean",
"default": true
"default": false
},
"fontFace": {
"default": "Cascadia Mono",
@@ -2618,7 +2103,7 @@
"default": 12,
"description": "[deprecated] Define 'size' within the 'font' object instead.",
"minimum": 1,
"type": "number",
"type": "integer",
"deprecated": true
},
"fontWeight": {
@@ -2649,17 +2134,6 @@
],
"deprecated": true
},
"intenseTextStyle": {
"default": "bright",
"description": "Controls how 'intense' text is rendered. Values are \"bold\", \"bright\", \"all\" and \"none\"",
"enum": [
"none",
"bold",
"bright",
"all"
],
"type": "string"
},
"foreground": {
"$ref": "#/$defs/Color",
"default": "#cccccc",
@@ -2713,22 +2187,15 @@
]
},
"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",
"description": "Defines the visibility of the scrollbar.",
"enum": [
"visible",
"hidden",
"always"
"hidden"
],
"type": "string"
},
@@ -2762,10 +2229,7 @@
},
"startingDirectory": {
"description": "The directory the shell starts in when it is loaded.",
"type": [
"string",
"null"
]
"type": "string"
},
"suppressApplicationTitle": {
"description": "When set to true, tabTitle overrides the default title of the tab and any title change messages from the application will be suppressed. When set to false, tabTitle behaves as normal.",

View File

@@ -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) -->

View File

@@ -1,7 +1,7 @@
---
author: Mike Griese @zadjii-msft
created on: 2020-5-13
last updated: 2022-11-18
last updated: 2020-08-04
issue id: 1571
---
@@ -76,34 +76,6 @@ There are five `type`s of objects in this menu:
- The `"entries"` property specifies a list of menu entries that will appear
nested under this entry. This can contain other `"type":"folder"` groups as
well!
- The `"inline"` property accepts two values
- `auto`: When the folder only has one entry in it, don't actually create a
nested layer to then menu. Just place the single entry in the layer that
folder would occupy. (Useful for dynamic profile sources with only a
single entry).
- `never`: (**default**) Always create a nested entry, even for a single
sub-item.
- The `allowEmpty` property will force this entry to show up in the menu, even
if it doesn't have any profiles in it. This defaults to `false`, meaning
that folders without any entries in them will just be ignored when
generating the menu. This will be more useful with the `matchProfile` entry,
below.
When this is true, and the folder is empty, we should add a
placeholder `<empty>` entry to the menu, to indicate that no profiles were
in that folder.
- _This setting is probably pretty niche, and not a requirement_. More of a
theoretical suggestion than anything.
- In the case of no entries for this folder, we should make sure to also
reflect the `inline` property:
- `allowEmpty:true`, `inline:auto`: just ignore the entry at all. Don't
add a placeholder to the parent list.
- `allowEmpty:true`, `inline:never`: Add a nested entry, with an
`<empty>` placeholder.
- `allowEmpty:false`, `inline:auto`: just ignore the entry at all. Don't
add a placeholder to the parent list.
- `allowEmpty:false`, `inline:never`: just ignore the entry at all. Don't
add a placeholder to the parent list.
* `"type":"action"`: This represents a menu entry that should execute a specific
`ShortcutAction`.
- the `id` property will specify the global action ID (see [#6899], [#7175])
@@ -125,16 +97,6 @@ There are five `type`s of objects in this menu:
enabling all other profiles to also be accessible.
- The "name" of these entries will simply be the name of the profile
- The "icon" of these entries will simply be the profile's icon
- This won't include any profiles that have been included via `matchProfile`
entries (below)
* `"type": "matchProfile"`: Expands to all the profiles that match a given
string. This lets the user easily specify a whole collection of profiles for a
folder, without needing to add them all manually.
- `"name"`, `"commandline"` or `"source"`: These three properties are used to
filter the list of profiles, based on the matching property in the profile
itself. The value is a string to compare with the corresponding property in
the profile. A full string comparison is done - not a regex or partial
string match.
The "default" new tab menu could be imagined as the following blob of json:
@@ -146,42 +108,6 @@ The "default" new tab menu could be imagined as the following blob of json:
}
```
Alternatively, we could consider something like the following. This would place
CMD, PowerShell, and all PowerShell cores in the root at the top, followed by
nested entries for each subsequent dynamic profile generator.
```jsonc
{
"newTabMenu": [
{ "type":"profile", "profile": "cmd" },
{ "type":"profile", "profile": "Windows PowerShell" },
{ "type": "matchProfile", "source": "Microsoft.Terminal.PowerShellCore" }
{
"type": "folder",
"name": "WSL",
"entries": [ { "type": "matchProfile", "source": "Microsoft.Terminal.Wsl" } ]
},
{
"type": "folder",
"name": "Visual Studio",
"entries": [ { "type": "matchProfile", "source": "Microsoft.Terminal.VisualStudio" } ]
},
// ... etc for other profile generators
{ "type": "remainingProfiles" }
]
}
```
I might only recommend that for `userDefaults.json`, which is the json files
used as a template for a user's new settings file. This would prevent us from
moving the user's cheese too much, if they're already using the Terminal and
happy with their list as is. Especially consider someone who's default profile
is a WSL distro, which would now need two clicks to get to.
> _note_: We will also want to support the same `{ "key": "SomeResourceString"}`
> syntax used by the Command Palette commands
> for specifying localizable names, if we chose to pursue this route.
### Other considerations
Also considered during the investigation for this feature was re-using the list
@@ -228,42 +154,6 @@ The design chosen in this spec more cleanly separates the responsibilities of
the list of profiles and the contents of the new tab menu. This way, each object
can be defined independent of the structure of the other.
Regarding implementation of `matchProfile` entries: In order to build the menu,
we'll evaluate the entries in the following order:
* all explicit `profile` entries
* then all `matchProfile` entries, using profiles not already specified
* then expand out `remainingProfiles` with anything not found above.
As an example:
```jsonc
{
"newTabMenu": [
{ "type": "matchProfile", "source": "Microsoft.Terminal.Wsl" }
{
"type": "folder",
"name": "WSLs",
"entries": [ { "type": "matchProfile", "source": "Microsoft.Terminal.Wsl" } ]
},
{ "type": "remainingProfiles" }
]
}
```
For profiles { "Profile A", "Profile B (WSL)", "Profile C (WSL)" }, This would
expand to:
```
New Tab Button ▽
├─ Profile A
├─ Profile B (WSL)
├─ Profile C (WSL)
└─ WSLs
└─ Profile B (WSL)
└─ Profile C (WSL)
```
## UI/UX Design
See the above _figure 1_.
@@ -399,39 +289,7 @@ And assuming the user has bound:
- Close Tab: `{ "action": "closeTab", "index": "${selectedTab.index}" }`
- Close Other Tabs: `{ "action": "closeTabs", "otherThan": "${selectedTab.index}" }`
- Close Tabs to the Right: `{ "action": "closeTabs", "after": "${selectedTab.index}" }`
* We may want to consider regex, tag-based, or some other type of matching for
`matchProfile` entries in the future. We originally considered using regex for
`matchProfile` by default, but decided instead on full string matches to leave
room for regex matching in the future. Should we chose to pursue something
like that, we should use a settings structure like:
```json
"type": "profileMatch",
"source": { "type": "regex", "value": ".*wsl.*" }
```
* We may want to expand `matchProfile` to match on other properties too. (`title`?)
* We may want to consider adding support for capture groups, e.g.
```json
{
"type": "profileMatch",
"name": { "type": "regex", "value": "^ssh: (.*)" }
}
```
for matching to all your `ssh: ` profiles, but populate the name in the entry
with that first capture group. So, ["ssh: foo", "ssh: bar"] would just expand
to a "foo" and "bar" entry.
## Updates
_February 2022_: Doc updated in response to some discussion in [#11326] and
[#7774]. In those PRs, it became clear that there needs to be a simple way of
collecting up a whole group of profiles automatically for sorting in these
menus. Although discussion centered on how hard it would be for extensions to
provide that customization themselves, the `match` statement was added as a way
to allow the user to easily filter those profiles themselves.
This was something we had originally considered as a "future consideration", but
ultimately deemed it to be out of scope for the initial spec review.
<!-- Footnotes -->
[#2046]: https://github.com/microsoft/terminal/issues/2046
@@ -440,5 +298,3 @@ ultimately deemed it to be out of scope for the initial spec review.
[#3337]: https://github.com/microsoft/terminal/issues/3337
[#6899]: https://github.com/microsoft/terminal/issues/6899
[#7175]: https://github.com/microsoft/terminal/issues/7175
[#11326]: https://github.com/microsoft/terminal/issues/11326
[#7774]: https://github.com/microsoft/terminal/issues/7774

View File

@@ -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

View File

@@ -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
@@ -201,7 +201,7 @@ Concerns:
### Accessibility
Accessibility applications are the most likely to resort to a method of spelunking the process tree or window handles to attempt to find content to read out. Presuming they have hard-coded rules for console-type applications, these algorithms could be surprised by the substitution of another terminal environment.
Accessibility applications are the most likely to resort to a method of spelunking the process tree or window handles to attempt to find content to read out. Presuming they have hardcoded rules for console-type applications, these algorithms could be surprised by the substitution of another terminal environment.
The major players here that I am considering are NVDA, JAWS, and Narrator. As far as I am aware, all of these applications attempt to drive their interactivity through UI Automation where possible. And we have worked with all of these applications in the past in improving their support for both `conhost.exe` and the Windows Terminal product. I have relatively high confidence that we will be able to work with them again to help update these assistive products to understand the new UI delegation, if necessary.

View File

@@ -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 hard-coded <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.
![Y-Beam Example](./images/Y-Beam.png)
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.
![Separated Y-Beam Example](./images/Half-Y-Beam.png)
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.
![Both Separated Y-Beams Example](./images/Split-Y-Beam.png)
### 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/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

View File

@@ -115,7 +115,7 @@ greater detail below:
### Default Settings
We'll have a static version of the "Default" file **hard-coded within the
We'll have a static version of the "Default" file **hardcoded within the
application package**. This `defaults.json` file will live within the
application's package, which will prevent users from being able to edit it.
@@ -128,19 +128,19 @@ won't actually be generated, but because it's shipped with our app, it'll be
overridden each time the app is updated. "Auto-generated" should be good enough
to indicate to users that it should not be modified.
Because the `defaults.json` file is hard-coded within our application, we can use
Because the `defaults.json` file is hardcoded within our application, we can use
its text directly, without loading the file from disk. This should help save
some startup time, as we'll only need to load the user settings from disk.
When we make changes to the default settings, or we make changes to the settings
schema, we should make sure that we update the hard-coded `defaults.json` with
schema, we should make sure that we update the hardcoded `defaults.json` with
the new values. That way, the `defaults.json` file will always have the complete
set of settings in it.
### Layering settings
When we load the settings, we'll do it in three stages. First, we'll deserialize
the default settings that we've hard-coded. We'll then generate any profiles that
the default settings that we've hardcoded. We'll then generate any profiles that
might come from dynamic profile sources. Then, we'll intelligently layer the
user's setting upon those we've already loaded. If a user wants to make changes
to some objects, like the default profiles, we'll need to make sure to load from
@@ -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.

View File

@@ -158,7 +158,7 @@ For `settings.json`, `_globals` will only hold the values set in `settings.json`
This process becomes a bit more complex for `Profile` because it can fallback in the following order:
1. `settings.json` profile
2. `settings.json` `profiles.defaults`
3. (if a dynamic profile) the hard-coded value in the dynamic profile generator
3. (if a dynamic profile) the hardcoded value in the dynamic profile generator
4. `defaults.json` profile
`CascadiaSettings` must do the following...
@@ -280,7 +280,7 @@ TerminalApp will construct and reference a `CascadiaSettings settings` as follow
and layers the settings.json data on top of it.
- check for errors/warnings, and handle them appropriately
This will be different from the current model which has the settings.json path hard-coded, and is simplified
This will be different from the current model which has the settings.json path hardcoded, and is simplified
to a `LoadAll()` call wrapped in error handlers.
**NOTE:** This model allows us to layer even more settings files on top of the existing Terminal Settings

View File

@@ -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

View 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/

View File

@@ -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

View File

@@ -1,410 +0,0 @@
---
author: Mike Griese @zadjii-msft
created on: 2021-03-03
last updated: 2022-11-04
issue id: #2634
---
# Broadcast Input
## Abstract
"Broadcast Input" is a feature present on other terminals which allows the user
to send the same input to multiple tabs or panes at the same time. This can make
it simpler for the user to run the same command in multiple directories or
servers at the same time.
With a viable prototype in [#9222], it's important that we have a well-defined
plan for how we want this feature to be exposed before merging that PR. This
spec is intended to be a lighter-than-usual spec to build consensus on the
design of how the actions should be expressed.
## Background
### Inspiration
This spec is heavily inspired by the [iTerm2 implementation]. @carlos-zamora did
a great job of breaking down how iTerm2 works in [this comment].
SecureCRT also implements a similar feature using a "chat window" that can send
the input in the chat window to all tabs. This seemed like a less ergonomic
solution, so it was not seriously considered.
Additionally, Terminator (on \*nix) allows for a similar feature through the use
of "groups". From [@zljubisic]:
> In Linux terminator you can define groups, and than put each pane in one of
> defined groups. Afterwards, you can choose broadcasting to all panes, only
> certain group or no broadcast at all.
This also seemed like a less powerful version of broadcast input than the
iterm2-like version, so it was also not further investigated.
### User Stories
iTerm2 supports the following actions:
* **Story A:** _Send input to current session only_: The default setting.
* **Story B:** _Broadcast to all panes in all tabs_: Anything you type on the
keyboard goes to all sessions in this window.
* **Story C:** _Broadcast to all panes in current tab_: Anything you type on the
keyboard goes to all sessions in this tab.
* **Story D:** _Toggle broadcast input to current session_: Toggles whether this
session receives broadcasted keystrokes within this window.
## Solution Design
### Proposal 1: iTerm2-like Modal Input Broadcast
iTerm2 implements broadcast input as a type of "modal" system. The user is in
one of the following modes:
* Broadcast to all panes in all tabs
* Broadcast to all panes in the current tab
* Broadcast to some set of panes within the current tab
* Don't broadcast input at all (the default behavior)
These modes are vaguely per-tab state. There's a global "broadcast to all tabs &
panes" property. Then, each tab also has a pair of values:
* Should input be sent to all panes in this tab?
* If not, which panes should input be sent to?
It's not possible to send input to one pane in tab A, then another pane in tab
B, without enabling the global "broadcast to everyone" mode.
This seems to break down into the following actions:
```json
{ "action": "toggleBroadcastInput", "scope": "window" },
{ "action": "toggleBroadcastInput", "scope": "tab" },
{ "action": "toggleBroadcastInput", "scope": "pane" },
{ "action": "disableBroadcastInput" },
```
Which would be accompanied by the following internal properties:
* A window (`TerminalPage`-level) property for `broadcastToAllPanesAndTabs`
* A per-tab property for `broadcastToAllPanes`
* A per-tab set of panes to broadcast to
The scopes would work as follows:
* `"scope": "window"`: Toggle the window's "broadcast to all tabs and panes"
setting.
* `"scope": "tab"`: Toggle the tab's "broadcast to all panes in this tab"
setting.
- This does not modify the set of panes that the user is broadcasting to in
the tab, merely toggles the tab's setting. If the user has a set of panes
they're broadcasting to in this tab, then toggles this setting on and off,
we'll return to broadcasting to that set.
* `"scope": "pane"`: Add this pane to the set of panes being broadcasted to in
this tab.
- **TODO!: FOR DISCUSSION**: Should this disable the tab's
"broadcastToAllPanes" setting? Or should it leave that alone?
* `"disableBroadcastInput"`: Set the global setting to false, the tab's setting
to false, and clear the set of panes being broadcasted to for this tab.
- **TODO!** This could also just be `"action": "toggleBroadcastInput",
"scope": "none"`
#### Pros
* This is exactly how iTerm2 does it, so there's prior art.
* If you're not globally broadcasting, then you're only ever broadcasting to
some (sub)set of the panes in the current tab. So global broadcast mode is
the only time a user would need to worry about input being to be sent to
an inactive tab.
* You can have a set of panes to broadcast to in the first tab, then a
_separate_ set to broadcast to in a second tab. Broadcasting in one tab
does not affect the other.
#### Cons
* I frankly think the `tab`/`pane` interaction can be a little weird. Like for
this scenario:
- enable broadcast input for tab 1
- switch to tab 2
- enable broadcast input for a pane in tab 2
There's valid confusion to be had between the following two behaviors:
1. input goes to all of tab 1 _and_ the pane in tab 2
2. input only goes to the pane in tab 2
* You can't broadcast to a subset of panes in inactive tabs, in addition to
the active tab. All panes you want to broadcast to must be in the active
tab.
* Does creating a new split in a pane that's being broadcast to add that pane to
the broadcast set?
#### What would this mean for PR #9222?
The prototype PR [#9222] basically just implemented `{ "action":
"toggleBroadcastInput", "scope": "tab" }`. We could make `tab` the default
`scope` if no other one is specified, and then the PR would need basically no
modifications. Future PRs could add args to the `toggleBroadcastInput` action,
without breaking users who bind a key to that action now.
### Proposal 2: Broadcast Set
This was the design I had originally came up with before investigating iTerm2
much closer. This design involves a "broadcast set" of panes. All the panes in
the broadcast set would also get the `KeySent` and `CharSent` events, in
addition to the active pane. (The active pane may be a part of the broadcast
set). If a pane is read-only in the broadcast set, then it won't handle those
broadcasted events (obviously).
As far as actions, we're looking at something like:
* **A** Only send input to the active pane
* Remove all the panes from the broadcast set
* **B** send input to all panes in all tabs
* If all the panes are in the broadcast set, remove them all. Otherwise, add
all panes in all tabs to the broadcast set.
* **C** send input to all panes in the current tab
* If all the panes in the current tab are in the broadcast set, remove them
from the broadcast set. Otherwise, add all the panes from this tab to the
broadcast set.
* **D** toggle sending input to the current pane
* If this pane is in the broadcast set, remove it. Otherwise add it.
This seems to break down into the following actions:
```json
{ "action": "disableBroadcastInput" },
{ "action": "toggleBroadcastInput", "scope": "window" },
{ "action": "toggleBroadcastInput", "scope": "tab" },
{ "action": "toggleBroadcastInput", "scope": "pane" },
```
Which would be accompanied by the following internal properties:
* A window (`TerminalPage`-level) set of panes to broadcast to.
#### Pros:
* Mentally, you're either adding panes to the set of panes to broadcast to, or
removing them.
* You can broadcast to panes in multiple tabs, without broadcasting to _all_
panes in all tabs.
#### Cons:
* is _slightly_ different from iTerm2.
* Does creating a new split in a pane that's being broadcast to add that pane to
the broadcast set?
* You can't have a set of panes to broadcast to in the one tab, and a different
set in another tab. As an example:
1. in tab 1, you add panes A and B to the broadcast set. Typing in either one
goes to both A and B.
2. in tab 1, switch to pane C. Now input goes to A, B and C.
3. in tab 1, switch to pane D. Now input goes to A, B and D.
4. switch to tab 2, pane E. Now input goes to A, B and E.
You can't have like, a set with A & B (in 1), then E & F (in 2). So if someone
wants to type to both panes in 1, then both panes in 2, then both panes in 1,
they need to keep toggling which panes are in the broadcast set.
#### What would this mean for PR #9222?
Similar to Proposal 1, we'd use `tab` as the default value for `scope`. In the
future, when we add support for the other scopes, we'd change how the
broadcasting works, to use a set of panes to broadcast to, instead of just the
tab-level property.
### Proposal 3: It's iTerm2, but slightly different
While typing this up, I thought maybe it might make more sense if we took the
iTerm2 version, and changed it slightly:
* `"scope": "tab"`: If all the panes are in the broadcast set for this tab, then
remove them all. Otherwise, add all the panes in this tab to this tab's
broadcast set.
* `"scope": "pane"`: If this pane is in the broadcast set for a tab, then remove
it. Otherwise, add it.
With this, we get rid of the tab-level setting for "broadcast to all the panes
in this tab", and rely only on the broadcast set for that tab.
#### Pros:
* All the pros from proposal A
* Does away with the seemingly weird toggling between "all the panes in a tab"
and "some of the panes in a tab" that's possible with proposal A
#### Cons:
* You can't broadcast to a subset of panes in inactive tabs, in addition to
the active tab. All panes you want to broadcast to must be in the active
tab.
* is _slightly_ different from iTerm2. Just _slightly_.
* Does creating a new split in a pane that's being broadcast to add that pane to
the broadcast set?
#### What would this mean for PR #9222?
Same as with proposal A, we wouldn't change anything in the current PR. A future
PR that would add the other scope's to that action would need to change how the
broadcasting within a tab works, to use a set of panes to broadcast to, instead
of just the tab-level property.
## Conclusion
I'm proposing these settings for broader discussion. I'm not really sure which I
like most at this point. 1 & 3 have the advantage of being most similar to the
prior art, but 2 is more easily extendable to "groups" (see [Future
Considerations](#Future-Considerations)).
**TODO!**: Make a decision.
_**Fortunately**_: All these proposals actually use the same set of actions. So
it doesn't _really_ matter which we pick right now. We can unblock [#9222] as
the implementation of the `"tab"` scope, and address other scopes in the future.
We should still decide long-term which of these we'd like, but the actions seem
universal.
## UI/UX Design
This is supposed to be a quick & dirty spec, so I'm LARGELY skipping this.
As far as indicators go, we'll throw something like:
![NetworkTower Segoe UI Icon](broadcast-segoe-icon.png)
in the tab when a pane is being broadcasted to. If all tabs are being
broadcasted to, then they'll all have that icon. If a tab is inactive, and any
pane in that tab is being broadcast to, then show the icon in the tab.
It probably makes the most sense to have pane titlebars ([#4998]) also display
that icon.
In the original PR, it was suggested to use some variant of the [accent color]
to on the borders of panes that are currently receiving broadcasted input. We're
already using the accent color on the borders of the active pane.
`SystemAccentColorLight*`/`SystemAccentColorDark*` would provide a way of using
a similar hue with different lightness/saturation. This would be a decent visual
indicator that they're _not_ the active pane, but they are going to receive
input. Something a bit like:
![A sample of using the border to indicate the broadcasted-to panes](broadcast-input-borders.gif)
This should obviously be able to be overridden in the user's theme, similar to
the pane border colors.
iTerm2 also supports displaying "stripes" in the background of all the panes
that are being broadcast too. That's certainly another way of indicating this
feature to the user. I'm not sure how we'd layer it with the background image
though. **I recommend we ignore this for now, and leave this as a follow-up**.
### Tab context menu items
For reference, refer to the following from iTerm2:
![image](https://user-images.githubusercontent.com/2578976/64075757-fa971980-ccee-11e9-9e44-47aaf3bca76c.png)
We don't have a menu bar like on MacOS, but we do have a tab context menu. We
could add these items as a nested entry under each tab. If we wanted to do this,
we should also make sure to dynamically change the icon of the MenuItem to
reflect the current broadcast state.
## Potential Issues
<table>
<tr>
<td><strong>Compatibility</strong></td>
<td>
[comment]: # Will the proposed change break existing code/behaviors? If so, how, and is the breaking change "worth it"?
</td>
</tr>
</table>
[comment]: # If there are any other potential issues, make sure to include them here.
## Implementation plan
* [ ] Resurrect [#9222], and use that to implement `"scope": "tab"`. This is
implemented the same, regardless of which proposal we chose.
* [ ] Add a tab context menu entry for toggling broadcast input, with a dynamic
icon based on the current state.
* [ ] Implement `"scope": "window"`. Again, this is implemented the same regardless
of which proposal we pursue.
* [ ] Decide between the two proposals here.
* [ ] Implement `"scope": "pane"`.
Doing the first element here is probably the most important one for most users,
and can be done regardless of the proposal chosen here. As such, we could even
suggest the default value of `scope` be `tab`. If we did that, then we wouldn't
need to do any args at all in the initial version.
## Future Considerations
Let's look to iTerm2, who's supported this feature for years, for some
inspiration of future things we should be worried about. If their users have
asked for these features, then it's inevitable that our users will too 😉
* [iterm2#6709] - Broadcast Input to multiple windows
- This is pretty straightforward. Would require coordination with the Monarch
though, and I'm worried about the perf hit of tossing every keystroke across
the process boundary.
- I suppose this would be `{ "action": "toggleBroadcastInput", "scope":
"global" }`
* [iterm2#6451], [iterm2#5563] - "Broadcast commands"
- iTerm2 has an action that lets the user manually clear the terminal-side
buffer. (This is tracked on the Windows Terminal as [#1882]). It might make
sense for there to be a mode where some _actions_ are also broadcast to
panes, not just key strokes. But which actions would those be? Moving the
selection anchors? Copy doesn't really make sense. Paste _does_ though.
Maybe the open find dialog / next&prev search match actions?
- This probably would require it's own spec.
* [iterm2#6007] - Different stripe color for different broadcast modes
- Have one color to indicate when broadcasting in `global` scope, another in
`tab` scope, a third in `pane` scope.
- This might mesh well with theming ([#3327]), for properties like
`pane.broadcastBorderColor.globalScope`,
`pane.broadcastBorderColor.paneScope`. Don't love those names, but you get
the idea.
* **[iterm2#5639]: Broadcast groups**, [iterm2#3372] - Broadcast Input to
multiple but not all tabs
- This is probably the most interesting request. I think this one identifies a
major shortcoming of the above proposals. With proposal 2, there's only ever
one top-level broadcast group. With proposals 1 & 3, there's per-tab
broadcast groups. In neither proposal can you have multiple concurrent
side-by-side broadcast groups.
- Groups should probably work across tabs. This would suggest that Proposal 2
is closer to how groups would work. Instead of there being one top-level
set, there would be multiple. **I'm not sure how proposals 1&3 would
seamlessly transition into also supporting groups**.
- The major trick here is: how do we differentiate these different groups to
the user? If we used the broadcast icon with a number, maybe in the corner
of the tab? Like [📡: 1]? Can a pane be in multiple broadcast sets at the
same time?
- The natural arg idea would be `{ "action": "toggleBroadcastInput", "scope":
"tab", "group": 1 }` to say "add all panes in the tab to broadcast group 1",
or "remove all panes in the tab from broadcast group 1". If panes are in
another group, they'd be moved to the specified group. If all panes are in
that group, then remove them all.
- The UI for this would certainly get complex fast.
- This also matches the Terminator-style broadcasting to groups.
* Re: stripes in the background of the tab. We could expose a pane's current
broadcast state to the pixel shader, and a user could use a custom pixel
shader to add stripes behind the text in the shader code. That's one possible
solution.
## Resources
[comment]: # Be sure to add links to references, resources, footnotes, etc.
### Footnotes
<a name="footnote-1"><a>[1]:
[#1882]: https://github.com/microsoft/terminal/issues/1882
[#2634]: https://github.com/microsoft/terminal/issues/2634
[#4998]: https://github.com/microsoft/terminal/issues/4998
[#3327]: https://github.com/microsoft/terminal/issues/3327
[#9222]: https://github.com/microsoft/terminal/pull/9222
[this comment]: https://github.com/microsoft/terminal/issues/2634#issuecomment-789116413
[iTerm2 implementation]: https://iterm2.com/documentation-one-page.html#documentation-menu-items.html
[@zljubisic]: https://github.com/microsoft/terminal/pull/9222#issuecomment-789143189
[accent color]: https://docs.microsoft.com/en-us/windows/uwp/design/style/color#accent-color-palette
[iterm2#6709]: https://gitlab.com/gnachman/iterm2/-/issues/6709
[iterm2#6451]: https://gitlab.com/gnachman/iterm2/-/issues/6451
[iterm2#6007]: https://gitlab.com/gnachman/iterm2/-/issues/6007
[iterm2#5639]: https://gitlab.com/gnachman/iterm2/-/issues/5639
[iterm2#5563]: https://gitlab.com/gnachman/iterm2/-/issues/5563
[iterm2#3372]: https://gitlab.com/gnachman/iterm2/-/issues/3372

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -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 TermControl](./mica-in-control-000.png)
### 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

View File

@@ -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.
![Tab matches Terminal background](Tab-Matches-Terminal-Color-000.png)
_fig 1_: Using a tab color set to "terminalBackground". The Windows PowerShell
tab has also set its color with the color picker.
![Acrylic in the titlebar](AcrylicInTitlebar.png)
_fig 2_: Using an acrylic titlebar color, with a tab color set to
"terminalBackground"
![Titlebar matches Terminal background](AcrylicTerminalBackgroundInTitlebar.png)
_fig 3_: Using an acrylic terminal background, and the titlebar color is set to
"terminalBackground"
![Whole window background image](whole-window-background-000.png) _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)
![Tabs with bottom corner radius set](tab-buttons-000.png) _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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 779 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Some files were not shown because too many files have changed in this diff Show More