Compare commits
19 commits
main
...
dev/miniks
Author | SHA1 | Date | |
---|---|---|---|
466b80496d | |||
af2712b09e | |||
d2372342e2 | |||
e59f2b8477 | |||
60ef914956 | |||
cdc5a6a747 | |||
9b8c9d4f51 | |||
69538c4ab3 | |||
324c0942c8 | |||
c65161d60e | |||
b591355103 | |||
a1c1d5cc09 | |||
67d591b11d | |||
a692bb2f0f | |||
f00ffb0291 | |||
33e9a9b22a | |||
8114fa0dd0 | |||
00ca3f204c | |||
1ed8ef0847 |
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"XamlStyler.Console": {
|
||||
"version": "3.2008.4",
|
||||
"commands": [
|
||||
"xstyler"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
|
|
2
.gitattributes
vendored
|
@ -3,8 +3,6 @@
|
|||
###############################################################################
|
||||
* -text
|
||||
|
||||
*.inc linguist-language=cpp
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
|
|
27
.github/ISSUE_TEMPLATE/Bug_Report.yml
vendored
|
@ -1,30 +1,27 @@
|
|||
name: "Bug report 🐛"
|
||||
description: Report errors or unexpected behavior
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
issue_body: true
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please make sure to [search for existing issues](https://github.com/microsoft/terminal/issues) and [check the FAQ](https://github.com/microsoft/terminal/wiki/Frequently-Asked-Questions-(FAQ)) before filing a new one!
|
||||
Please make sure to [search for existing issues](https://github.com/microsoft/terminal/issues) before filing a new one!
|
||||
|
||||
If this is an application crash, please also provide a [Feedback Hub](https://aka.ms/terminal-feedback-hub) submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal" and choose "Share My Feedback" after submission to get the link.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Windows Terminal version
|
||||
placeholder: "1.7.3651.0"
|
||||
label: Windows Terminal version (or Windows build number)
|
||||
placeholder: "10.0.19042.0, 1.7.3651.0"
|
||||
description: |
|
||||
You can find the version in the about dialog, or by running `wt -v` at the commandline.
|
||||
If you are reporting an issue in Windows Terminal, you can find the version in the about dialog.
|
||||
|
||||
If you are reporting an issue with the Windows Console, please run `ver` or `[Environment]::OSVersion`.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Windows build number
|
||||
placeholder: "10.0.19042.0"
|
||||
description: |
|
||||
Please run `ver` or `[Environment]::OSVersion`.
|
||||
validations:
|
||||
required: false
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
@ -47,7 +44,7 @@ body:
|
|||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: If you want to include screenshots, paste them into the markdown editor below.
|
||||
description: If you want to include screenshots, paste them into the markdown editor below the form or follow up with a separate comment.
|
||||
placeholder: What were you expecting?
|
||||
validations:
|
||||
required: false
|
||||
|
|
14
.github/actions/spelling/allow/allow.txt
vendored
|
@ -1,14 +1,12 @@
|
|||
admins
|
||||
apc
|
||||
Apc
|
||||
bsd
|
||||
calt
|
||||
ccmp
|
||||
changelog
|
||||
cybersecurity
|
||||
Apc
|
||||
clickable
|
||||
clig
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
dcs
|
||||
Dcs
|
||||
|
@ -32,22 +30,20 @@ hyperlink
|
|||
hyperlinking
|
||||
hyperlinks
|
||||
img
|
||||
inlined
|
||||
It'd
|
||||
kje
|
||||
liga
|
||||
lje
|
||||
Llast
|
||||
Lmid
|
||||
locl
|
||||
lorem
|
||||
Llast
|
||||
Lmid
|
||||
Lorigin
|
||||
maxed
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
nje
|
||||
noreply
|
||||
nje
|
||||
ogonek
|
||||
ok'd
|
||||
overlined
|
||||
|
|
12
.github/actions/spelling/allow/apis.txt
vendored
|
@ -1,7 +1,5 @@
|
|||
ACCEPTFILES
|
||||
ACCESSDENIED
|
||||
acl
|
||||
aclapi
|
||||
alignas
|
||||
alignof
|
||||
APPLYTOSUBMENUS
|
||||
|
@ -11,7 +9,6 @@ BUILDBRANCH
|
|||
BUILDMSG
|
||||
BUILDNUMBER
|
||||
BYPOSITION
|
||||
BYCOMMAND
|
||||
charconv
|
||||
CLASSNOTAVAILABLE
|
||||
cmdletbinding
|
||||
|
@ -19,11 +16,9 @@ COLORPROPERTY
|
|||
colspan
|
||||
COMDLG
|
||||
comparand
|
||||
commandlinetoargv
|
||||
cstdint
|
||||
CXICON
|
||||
CYICON
|
||||
Dacl
|
||||
dataobject
|
||||
dcomp
|
||||
DERR
|
||||
|
@ -90,7 +85,6 @@ LSHIFT
|
|||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
memicmp
|
||||
mptt
|
||||
mov
|
||||
|
@ -120,19 +114,15 @@ OSVERSIONINFOEXW
|
|||
otms
|
||||
OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
ptstr
|
||||
rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
schandle
|
||||
semver
|
||||
serializer
|
||||
|
@ -169,8 +159,6 @@ toupper
|
|||
TTask
|
||||
TVal
|
||||
UChar
|
||||
UFIELD
|
||||
ULARGE
|
||||
UPDATEINIFILE
|
||||
userenv
|
||||
wcsstr
|
||||
|
|
1
.github/actions/spelling/allow/names.txt
vendored
|
@ -9,7 +9,6 @@ Diviness
|
|||
dsafa
|
||||
duhowett
|
||||
ekg
|
||||
eryksun
|
||||
ethanschoonover
|
||||
Firefox
|
||||
Gatta
|
||||
|
|
2
.github/actions/spelling/excludes.txt
vendored
|
@ -61,14 +61,12 @@ SUMS$
|
|||
^src/host/runft\.bat$
|
||||
^src/host/runut\.bat$
|
||||
^src/interactivity/onecore/BgfxEngine\.
|
||||
^src/renderer/atlas/
|
||||
^src/renderer/wddmcon/WddmConRenderer\.
|
||||
^src/terminal/adapter/ut_adapter/run\.bat$
|
||||
^src/terminal/parser/delfuzzpayload\.bat$
|
||||
^src/terminal/parser/ft_fuzzer/run\.bat$
|
||||
^src/terminal/parser/ft_fuzzer/VTCommandFuzzer\.cpp$
|
||||
^src/terminal/parser/ft_fuzzwrapper/run\.bat$
|
||||
^src/terminal/parser/ut_parser/Base64Test.cpp$
|
||||
^src/terminal/parser/ut_parser/run\.bat$
|
||||
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
|
||||
^src/tools/lnkd/lnkd\.bat$
|
||||
|
|
4
.github/actions/spelling/expect/expect.txt
vendored
|
@ -508,7 +508,6 @@ dealloc
|
|||
Debian
|
||||
debolden
|
||||
debugtype
|
||||
DECAC
|
||||
DECALN
|
||||
DECANM
|
||||
DECAUPSS
|
||||
|
@ -939,7 +938,6 @@ GTP
|
|||
guc
|
||||
gui
|
||||
guidatom
|
||||
guiddef
|
||||
GValue
|
||||
GWL
|
||||
GWLP
|
||||
|
@ -1537,7 +1535,6 @@ NOCOLOR
|
|||
NOCOMM
|
||||
NOCONTEXTHELP
|
||||
NOCOPYBITS
|
||||
nodefaultlib
|
||||
nodiscard
|
||||
NODUP
|
||||
noexcept
|
||||
|
@ -2235,7 +2232,6 @@ STARTWPARMSW
|
|||
Statusline
|
||||
stdafx
|
||||
STDAPI
|
||||
stdc
|
||||
stdcall
|
||||
stdcpp
|
||||
stderr
|
||||
|
|
|
@ -4,7 +4,7 @@ https://www\.itscj\.ipsj\.or\.jp/iso-ir/[-0-9]+\.pdf
|
|||
https://www\.vt100\.net/docs/[-a-zA-Z0-9#_\/.]*
|
||||
https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
|
||||
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.+]*
|
||||
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.]*
|
||||
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
|
||||
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="vswhere" version="2.6.7" />
|
||||
</packages>
|
||||
</packages>
|
77
.vscode/settings.json
vendored
|
@ -21,85 +21,12 @@
|
|||
"xloctime": "cpp",
|
||||
"multi_span": "cpp",
|
||||
"pointers": "cpp",
|
||||
"vector": "cpp",
|
||||
"bitset": "cpp",
|
||||
"deque": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"list": "cpp",
|
||||
"queue": "cpp",
|
||||
"random": "cpp",
|
||||
"regex": "cpp",
|
||||
"stack": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xtree": "cpp",
|
||||
"xutility": "cpp",
|
||||
"span": "cpp",
|
||||
"string_span": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"cctype": "cpp",
|
||||
"charconv": "cpp",
|
||||
"chrono": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"complex": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"exception": "cpp",
|
||||
"filesystem": "cpp",
|
||||
"fstream": "cpp",
|
||||
"functional": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"ios": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"iterator": "cpp",
|
||||
"limits": "cpp",
|
||||
"locale": "cpp",
|
||||
"map": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ratio": "cpp",
|
||||
"set": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"string": "cpp",
|
||||
"system_error": "cpp",
|
||||
"thread": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"xfacet": "cpp",
|
||||
"xiosbase": "cpp",
|
||||
"xlocale": "cpp",
|
||||
"xlocbuf": "cpp",
|
||||
"xlocinfo": "cpp",
|
||||
"xmemory": "cpp",
|
||||
"xstddef": "cpp",
|
||||
"xtr1common": "cpp"
|
||||
"vector": "cpp"
|
||||
},
|
||||
"files.exclude": {
|
||||
"**/bin/**": true,
|
||||
"**/obj/**": true,
|
||||
"**/packages/**": true,
|
||||
"**/Generated Files/**": true
|
||||
"**/generated files/**": true
|
||||
}
|
||||
}
|
24
.vscode/tasks.json
vendored
|
@ -9,16 +9,14 @@
|
|||
"-Command",
|
||||
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
|
||||
"Set-MsBuildDevEnvironment;",
|
||||
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"} TermControl{\"Terminal\\TerminalControl\"}};",
|
||||
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"}};",
|
||||
"$target = switch(\"${input:buildModeChoice}\"){Build{\"\"} Rebuild{\":Rebuild\"} Clean{\":Clean\"}};",
|
||||
"$target = $project + $target;",
|
||||
"msbuild",
|
||||
"${workspaceFolder}\\OpenConsole.sln",
|
||||
"/p:Configuration=${input:configChoice}",
|
||||
"/p:Platform=${input:platformChoice}",
|
||||
"/p:AppxSymbolPackageEnabled=false", // This takes a long time, so false if we don't really need it.
|
||||
"/t:$target",
|
||||
"/m", // Parallel builds
|
||||
"/verbosity:minimal"
|
||||
],
|
||||
"problemMatcher": ["$msCompile"],
|
||||
|
@ -48,7 +46,8 @@
|
|||
],
|
||||
"problemMatcher": ["$msCompile"],
|
||||
"group": {
|
||||
"kind": "build"
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -58,18 +57,6 @@
|
|||
"args": [
|
||||
],
|
||||
"problemMatcher": ["$msCompile"],
|
||||
},
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Run Code Format",
|
||||
"command": "powershell.exe",
|
||||
"args": [
|
||||
"-Command",
|
||||
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
|
||||
"Set-MsBuildDevEnvironment;",
|
||||
"Invoke-CodeFormat",
|
||||
],
|
||||
"problemMatcher": ["$msCompile"],
|
||||
}
|
||||
],
|
||||
"inputs":[
|
||||
|
@ -111,11 +98,10 @@
|
|||
"description": "OpenConsole or Terminal?",
|
||||
"options":[
|
||||
"OpenConsole",
|
||||
"Terminal",
|
||||
"TermControl"
|
||||
"Terminal"
|
||||
],
|
||||
"default": "Terminal"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
"Microsoft.Net.Component.4.5.TargetingPack",
|
||||
"Microsoft.VisualStudio.Component.DiagnosticTools",
|
||||
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.22000",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.18362",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
|
||||
"Microsoft.VisualStudio.Component.VC.CoreIde",
|
||||
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
|
||||
|
|
|
@ -43,7 +43,7 @@ If no existing item describes your issue/feature, great - please file a new issu
|
|||
* Have a question that you don't see answered in docs, videos, etc.? File an issue
|
||||
* Want to know if we're planning on building a particular feature? File an issue
|
||||
* Got a great idea for a new feature? File an issue/request/idea
|
||||
* Don't understand how to do something? File an issue
|
||||
* Don't understand how to do something? File an issue/Community Guidance Request
|
||||
* Found an existing issue that describes yours? Great - upvote and add additional commentary / info / repro-steps / etc.
|
||||
|
||||
When you hit "New Issue", select the type of issue closest to what you want to report/ask/request:
|
||||
|
@ -99,39 +99,25 @@ If you don't have any additional info/context to add but would like to indicate
|
|||
|
||||
## Contributing fixes / features
|
||||
|
||||
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 ["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.
|
||||
* ["Tasks"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Task%22+) are usually new pieces of functionality that aren't yet implemented for the Terminal/Console. These are usually smaller features, which we believe
|
||||
- could be a single, atomic PR
|
||||
- Don't require much design consideration, or we've already written the spec for the larger feature they belong to.
|
||||
* ["Features"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Feature%22+) are larger pieces of new functionality. These are usually things we believe would require larger discussion of how they should be implemented, or they'll require some complicated new settings. They might just be features that are composed of many individual tasks. Often times, with features, we like to have a spec written before development work is started, to make sure we're all on the same page (see below).
|
||||
|
||||
Bugs and tasks are obviously the easiest to get started with, but don't feel afraid of features either! We've had some community members contribute some amazing "feature"-level work to the Terminal (albeit, with lots of discussion 😄).
|
||||
|
||||
|
||||
Often, we like to assign issues that generally belong to somebody's area of expertise to the team member that owns that area. This doesn't mean the community can't jump in -- they should reach out and have a chat with the assignee to see if it'd okay to take. If an issue's been assigned more than a month ago, there's a good chance it's fair game to try yourself.
|
||||
For those able & willing to help fix issues and/or implement features ...
|
||||
|
||||
### To Spec or not to Spec
|
||||
|
||||
Some issues/features may be quick and simple to describe and understand. For such scenarios, once a team member has agreed with your approach, skip ahead to the section headed "Fork, Branch, and Create your PR", below.
|
||||
|
||||
Small issues that do not require a spec will be labelled `Issue-Bug` or `Issue-Task`.
|
||||
Small issues that do not require a spec will be labelled Issue-Bug or Issue-Task.
|
||||
|
||||
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled `Issue-Feature`. More often than not, we'll add such features to the ["Specification Tracker" project](https://github.com/microsoft/terminal/projects/1).
|
||||
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled Issue-Feature.
|
||||
|
||||
Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.
|
||||
|
||||
Specs will be managed in a very similar manner as code contributions so please follow the "[Fork, Branch and Create your PR](CONTRIBUTING.md#fork-clone-branch-and-create-your-pr)" section below.
|
||||
Specs will be managed in a very similar manner as code contributions so please follow the "Fork, Branch and Create your PR" below.
|
||||
|
||||
### Writing / Contributing-to a Spec
|
||||
|
||||
To write/contribute to a spec: fork, branch and commit via PRs, as you would with any code changes.
|
||||
|
||||
Specs are written in markdown, stored under the [`\doc\specs`](./doc/specs) folder and named `[issue id] - [spec description].md`.
|
||||
Specs are written in markdown, stored under the `\doc\spec` folder and named `[issue id] - [spec description].md`.
|
||||
|
||||
👉 **It is important to follow the spec templates and complete the requested information**. The available spec templates will help ensure that specs contain the minimum information & decisions necessary to permit development to begin. In particular, specs require you to confirm that you've already discussed the issue/idea with the team in an issue and that you provide the issue ID for reference.
|
||||
|
||||
|
@ -139,7 +125,7 @@ Team members will be happy to help review specs and guide them to completion.
|
|||
|
||||
### Help Wanted
|
||||
|
||||
Once the team has approved an issue/spec, development can proceed. If no developers are immediately available, the spec can be parked ready for a developer to get started. Parked specs' issues will be labeled "Help Wanted". To find a list of development opportunities waiting for developer involvement, visit the Issues and filter on [the Help-Wanted label](https://github.com/microsoft/terminal/labels/Help%20Wanted).
|
||||
Once the team have approved an issue/spec, development can proceed. If no developers are immediately available, the spec can be parked ready for a developer to get started. Parked specs' issues will be labeled "Help Wanted". To find a list of development opportunities waiting for developer involvement, visit the Issues and filter on [the Help-Wanted label](https://github.com/microsoft/terminal/labels/Help%20Wanted).
|
||||
|
||||
---
|
||||
|
||||
|
|
113
NOTICE.md
|
@ -117,6 +117,7 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
```
|
||||
|
||||
## dynamic_bitset
|
||||
|
@ -147,6 +148,7 @@ AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
|
||||
```
|
||||
|
||||
## \{fmt\}
|
||||
|
@ -213,6 +215,7 @@ AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
@ -246,115 +249,5 @@ 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)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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 OR COPYRIGHT HOLDERS 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.
|
||||
```
|
||||
|
||||
## ConEmu
|
||||
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2009-2017, Maximus5 <ConEmu.Maximus5@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
# Microsoft Open Source
|
||||
|
||||
This product also incorporates source code from other Microsoft open source projects, all licensed under the MIT license.
|
||||
|
||||
## `GSL`
|
||||
|
||||
**Source**: [https://github.com/microsoft/GSL](https://github.com/microsoft/GSL)
|
||||
|
||||
## `Microsoft-UI-XAML`
|
||||
|
||||
**Source**: [https://github.com/microsoft/Microsoft-UI-XAML](https://github.com/microsoft/Microsoft-UI-XAML)
|
||||
|
||||
## `VirtualDesktopUtils`
|
||||
|
||||
**Source**: [https://github.com/microsoft/PowerToys](https://github.com/microsoft/PowerToys)
|
||||
|
||||
## `wil`
|
||||
|
||||
**Source**: [https://github.com/microsoft/wil](https://github.com/microsoft/wil)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
The MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
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 OR COPYRIGHT HOLDERS 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.
|
||||
```
|
||||
|
|
852
OpenConsole.sln
|
@ -1,5 +1,3 @@
|
|||
![terminal-logos](https://user-images.githubusercontent.com/48369326/115790869-4c852b00-a37c-11eb-97f1-f61972c7800c.png)
|
||||
|
||||
# Welcome to the Windows Terminal, Console and Command-Line repo
|
||||
|
||||
This repository contains the source code for:
|
||||
|
@ -214,7 +212,7 @@ resources useful and interesting:
|
|||
* Windows Terminal Launch: [Build 2019
|
||||
Session](https://www.youtube.com/watch?v=KMudkRcwjCw)
|
||||
* Run As Radio: [Show 645 - Windows Terminal with Richard
|
||||
Turner](https://www.runasradio.com/Shows/Show/645)
|
||||
Turner](http://www.runasradio.com/Shows/Show/645)
|
||||
* Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps
|
||||
on the Windows
|
||||
Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54)
|
||||
|
@ -243,7 +241,7 @@ Visual Studio.
|
|||
|
||||
## Documentation
|
||||
|
||||
All project documentation is located at [aka.ms/terminal-docs](https://aka.ms/terminal-docs). If you would like
|
||||
All project documentation is located at aka.ms/terminal-docs. If you would like
|
||||
to contribute to the documentation, please submit a pull request on the [Windows
|
||||
Terminal Documentation repo](https://github.com/MicrosoftDocs/terminal).
|
||||
|
||||
|
@ -278,7 +276,6 @@ If you would like to ask a question that you feel doesn't warrant an issue
|
|||
* Carlos Zamora, Developer: [@cazamor_msft](https://twitter.com/cazamor_msft)
|
||||
* Leon Liang, Developer: [@leonmsft](https://twitter.com/leonmsft)
|
||||
* Pankaj Bhojwani, Developer
|
||||
* Leonard Hecker, Developer: [@LeonardHecker](https://twitter.com/LeonardHecker)
|
||||
|
||||
## Developer Guidance
|
||||
|
||||
|
@ -289,7 +286,6 @@ If you would like to ask a question that you feel doesn't warrant an issue
|
|||
* You must [enable Developer Mode in the Windows Settings
|
||||
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 10 1903
|
||||
SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
|
||||
installed
|
||||
|
|
221
Scratch.sln
|
@ -1,221 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31205.134
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Package", "scratch\ScratchIslandApp\Package\Package.wapproj", "{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleAppLib", "scratch\ScratchIslandApp\SampleApp\SampleAppLib.vcxproj", "{A4394404-37F7-41C1-802B-49788D3720E3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleApp", "scratch\ScratchIslandApp\SampleApp\dll\SampleApp.vcxproj", "{26C51792-41A3-4FE0-AB5E-8B69D557BF91}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3} = {A4394404-37F7-41C1-802B-49788D3720E3}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowExe", "scratch\ScratchIslandApp\WindowExe\WindowExe.vcxproj", "{B4427499-9FDE-4208-B456-5BC580637633}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91} = {26C51792-41A3-4FE0-AB5E-8B69D557BF91}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common Props", "Common Props", "{53DD5520-E64C-4C06-B472-7CE62CA539C9}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\common.build.post.props = src\common.build.post.props
|
||||
src\common.build.pre.props = src\common.build.pre.props
|
||||
src\common.build.tests.props = src\common.build.tests.props
|
||||
common.openconsole.props = common.openconsole.props
|
||||
src\cppwinrt.build.post.props = src\cppwinrt.build.post.props
|
||||
src\cppwinrt.build.pre.props = src\cppwinrt.build.pre.props
|
||||
src\wap-common.build.post.props = src\wap-common.build.post.props
|
||||
src\wap-common.build.pre.props = src\wap-common.build.pre.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxproj", "{6BAE5851-50D5-4934-8D5E-30361A8A40F3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types", "src\types\lib\types.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820263}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
AuditMode|ARM64 = AuditMode|ARM64
|
||||
AuditMode|x64 = AuditMode|x64
|
||||
AuditMode|x86 = AuditMode|x86
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Fuzzing|ARM64 = Fuzzing|ARM64
|
||||
Fuzzing|x64 = Fuzzing|x64
|
||||
Fuzzing|x86 = Fuzzing|x86
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.ActiveCfg = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Build.0 = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Deploy.0 = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.ActiveCfg = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Build.0 = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Deploy.0 = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.ActiveCfg = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Build.0 = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Deploy.0 = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Build.0 = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Build.0 = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Build.0 = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Deploy.0 = Debug|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.ActiveCfg = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Build.0 = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Deploy.0 = Debug|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.ActiveCfg = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Build.0 = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Deploy.0 = Debug|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.ActiveCfg = Release|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Build.0 = Release|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Deploy.0 = Release|x64
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.ActiveCfg = Release|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Build.0 = Release|x86
|
||||
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Deploy.0 = Release|x86
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.Build.0 = Debug|x64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.ActiveCfg = Release|x64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.Build.0 = Release|x64
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.Build.0 = Release|Win32
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.Build.0 = Debug|x64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.Build.0 = Debug|Win32
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.ActiveCfg = Release|x64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.Build.0 = Release|x64
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.ActiveCfg = Release|Win32
|
||||
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.Build.0 = Release|Win32
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.Build.0 = Debug|x64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.Build.0 = Debug|Win32
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.ActiveCfg = Release|x64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.Build.0 = Release|x64
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.Build.0 = Release|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.Build.0 = Debug|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.ActiveCfg = Release|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.Build.0 = Release|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.Build.0 = Release|Win32
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.Build.0 = Debug|x64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.Build.0 = Debug|Win32
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.ActiveCfg = Release|x64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.Build.0 = Release|x64
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.ActiveCfg = Release|Win32
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {05EAE315-9188-4D7B-B889-7D5F480A8915}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"AttributesTolerance": 1,
|
||||
"KeepFirstAttributeOnSameLine": true,
|
||||
"MaxAttributeCharactersPerLine": 0,
|
||||
"MaxAttributesPerLine": 1,
|
||||
"NewlineExemptionElements": "RadialGradientBrush, GradientStop, LinearGradientBrush, ScaleTransform, SkewTransform, RotateTransform, TranslateTransform, Trigger, Condition, Setter",
|
||||
"SeparateByGroups": false,
|
||||
"AttributeIndentation": 0,
|
||||
"AttributeIndentationStyle": 1,
|
||||
"RemoveDesignTimeReferences": false,
|
||||
"EnableAttributeReordering": true,
|
||||
"AttributeOrderingRuleGroups": [
|
||||
"x:Class",
|
||||
"xmlns, xmlns:x",
|
||||
"xmlns:*",
|
||||
"x:Key, Key, x:Name, Name, x:Uid, Uid, Title",
|
||||
"Grid.Row, Grid.RowSpan, Grid.Column, Grid.ColumnSpan, Canvas.Left, Canvas.Top, Canvas.Right, Canvas.Bottom",
|
||||
"Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight",
|
||||
"Margin, Padding, HorizontalAlignment, VerticalAlignment, HorizontalContentAlignment, VerticalContentAlignment, Panel.ZIndex",
|
||||
"*:*, *",
|
||||
"PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
|
||||
"mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText",
|
||||
"Storyboard.*, From, To, Duration"
|
||||
],
|
||||
"FirstLineAttributes": "",
|
||||
"OrderAttributesByName": true,
|
||||
"PutEndingBracketOnNewLine": false,
|
||||
"RemoveEndingTagOfEmptyElement": true,
|
||||
"SpaceBeforeClosingSlash": true,
|
||||
"RootElementLineBreakRule": 0,
|
||||
"ReorderVSM": 2,
|
||||
"ReorderGridChildren": false,
|
||||
"ReorderCanvasChildren": false,
|
||||
"ReorderSetters": 0,
|
||||
"FormatMarkupExtension": true,
|
||||
"NoNewLineMarkupExtensions": "x:Bind, Binding",
|
||||
"ThicknessSeparator": 2,
|
||||
"ThicknessAttributes": "Margin, Padding, BorderThickness, ThumbnailClipMargin",
|
||||
"FormatOnSave": true,
|
||||
"CommentPadding": 2,
|
||||
}
|
|
@ -29,147 +29,4 @@ function GetQueryTestRunsUri
|
|||
$baseUri = GetAzureDevOpsBaseUri -CollectionUri $CollectionUri -TeamProject $TeamProject
|
||||
$queryUri = "$baseUri/_apis/test/runs?buildUri=$BuildUri$includeRunDetailsParameter&api-version=5.0"
|
||||
return $queryUri
|
||||
}
|
||||
|
||||
function Get-HelixJobTypeFromTestRun
|
||||
{
|
||||
Param ($testRun)
|
||||
|
||||
$testRunSingleResultUri = "$($testRun.url)/results?`$top=1&`$skip=0&api-version=5.1"
|
||||
$singleTestResult = Invoke-RestMethod -Uri $testRunSingleResultUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
$count = $singleTestResult.value.Length
|
||||
if($count -eq 0)
|
||||
{
|
||||
# If the count is 0, then results have not yet been reported for this run.
|
||||
# We only care about completed runs with results, so it is ok to just return 'UNKNOWN' for this run.
|
||||
return "UNKNOWN"
|
||||
}
|
||||
else
|
||||
{
|
||||
$info = ConvertFrom-Json $singleTestResult.value.comment
|
||||
$helixJobId = $info.HelixJobId
|
||||
$job = Invoke-RestMethodWithRetries "https://helix.dot.net/api/2019-06-17/jobs/${helixJobId}?access_token=${HelixAccessToken}"
|
||||
return $job.Type
|
||||
}
|
||||
}
|
||||
|
||||
function Append-HelixAccessTokenToUrl
|
||||
{
|
||||
Param ([string]$url, [string]$token)
|
||||
if($url.Contains("?"))
|
||||
{
|
||||
$url = "$($url)&access_token=$($token)"
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = "$($url)?access_token=$($token)"
|
||||
}
|
||||
return $url
|
||||
}
|
||||
|
||||
|
||||
# The Helix Rest api is sometimes unreliable. So we call these apis with retry logic.
|
||||
# Note: The Azure DevOps apis are stable and do not need to be called with this retry logic.
|
||||
$helixApiRetries = 0
|
||||
$helixApiRetriesMax = 10
|
||||
|
||||
function Download-StringWithRetries
|
||||
{
|
||||
Param ([string]$fileName, [string]$url)
|
||||
|
||||
$result = ""
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
Write-Host "Downloading $fileName"
|
||||
$result = (New-Object System.Net.WebClient).DownloadString($url)
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to download $fileName $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry download of $fileName"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to download $fileName"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
function Invoke-RestMethodWithRetries
|
||||
{
|
||||
Param ([string]$url,$Headers)
|
||||
|
||||
$result = @()
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
$result = Invoke-RestMethod -Uri $url -Method Get -Headers $Headers
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to invoke Rest method $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry invoke"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to invoke Rest method"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
function Download-FileWithRetries
|
||||
{
|
||||
Param ([string]$fileurl, [string]$destination)
|
||||
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
Write-Host "Downloading $destination"
|
||||
$webClient.DownloadFile($fileurl, $destination)
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to download $destination $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry download of $destination"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to download $destination"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ Write-Host "Checking test results..."
|
|||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
|
||||
$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
[System.Collections.Generic.List[string]]$failingTests = @()
|
||||
[System.Collections.Generic.List[string]]$unreliableTests = @()
|
||||
[System.Collections.Generic.List[string]]$unexpectedResultTest = @()
|
||||
|
@ -50,7 +50,7 @@ foreach ($testRun in ($testRuns.value | Sort-Object -Property "completedDate" -D
|
|||
$totalTestsExecutedCount += $testRun.totalTests
|
||||
|
||||
$testRunResultsUri = "$($testRun.url)/results?api-version=5.0"
|
||||
$testResults = Invoke-RestMethodWithRetries "$($testRun.url)/results?api-version=5.0" -Headers $azureDevOpsRestApiHeaders
|
||||
$testResults = Invoke-RestMethod -Uri "$($testRun.url)/results?api-version=5.0" -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ $payloadDir = "HelixPayload\$Configuration\$Platform"
|
|||
|
||||
$repoDirectory = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "..\..\"
|
||||
$nugetPackagesDir = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "packages"
|
||||
|
||||
|
||||
# Create the payload directory. Remove it if it already exists.
|
||||
If(test-path $payloadDir)
|
||||
{
|
||||
|
@ -19,13 +19,11 @@ New-Item -ItemType Directory -Force -Path $payloadDir
|
|||
|
||||
# Copy files from nuget packages
|
||||
Copy-Item "$nugetPackagesDir\microsoft.windows.apps.test.1.0.181203002\lib\netcoreapp2.1\*.dll" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\NetFx4.5\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$Platform\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$Platform\CoreClr\*" $payloadDir
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\"
|
||||
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\"
|
||||
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\"
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir\content\"
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.1\content\*" "$payloadDir\content\"
|
||||
|
||||
function Copy-If-Exists
|
||||
{
|
||||
|
@ -54,13 +52,3 @@ Copy-Item "build\helix\HelixTestHelpers.cs" "$payloadDir"
|
|||
Copy-Item "build\helix\runtests.cmd" $payloadDir
|
||||
Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir"
|
||||
Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
|
||||
|
||||
# Copy the APPX package from the 'drop' artifact dir
|
||||
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
|
||||
|
|
|
@ -9,6 +9,11 @@ Param(
|
|||
|
||||
$helixLinkFile = "$OutputFolder\LinksToHelixTestFiles.html"
|
||||
|
||||
$accessTokenParam = ""
|
||||
if($HelixAccessToken)
|
||||
{
|
||||
$accessTokenParam = "?access_token=$HelixAccessToken"
|
||||
}
|
||||
|
||||
function Generate-File-Links
|
||||
{
|
||||
|
@ -20,31 +25,13 @@ function Generate-File-Links
|
|||
Out-File -FilePath $helixLinkFile -Append -InputObject "<ul>"
|
||||
foreach($file in $files)
|
||||
{
|
||||
$url = Append-HelixAccessTokenToUrl $file.Link "{Your-Helix-Access-Token-Here}"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<li>$($url)</li>"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<li><a href=$($file.Link)>$($file.Name)</a></li>"
|
||||
}
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "</ul>"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "</div>"
|
||||
}
|
||||
}
|
||||
|
||||
function Append-HelixAccessTokenToUrl
|
||||
{
|
||||
Param ([string]$url, [string]$token)
|
||||
if($token)
|
||||
{
|
||||
if($url.Contains("?"))
|
||||
{
|
||||
$url = "$($url)&access_token=$($token)"
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = "$($url)?access_token=$($token)"
|
||||
}
|
||||
}
|
||||
return $url
|
||||
}
|
||||
|
||||
#Create output directory
|
||||
New-Item $OutputFolder -ItemType Directory
|
||||
|
||||
|
@ -58,71 +45,66 @@ $azureDevOpsRestApiHeaders = @{
|
|||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
|
||||
$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
$webClient = New-Object System.Net.WebClient
|
||||
[System.Collections.Generic.List[string]]$workItems = @()
|
||||
|
||||
foreach ($testRun in $testRuns.value)
|
||||
{
|
||||
Write-Host "testRunUri = $testRun.url"
|
||||
$testResults = Invoke-RestMethodWithRetries "$($testRun.url)/results?api-version=5.0" -Headers $azureDevOpsRestApiHeaders
|
||||
$testResults = Invoke-RestMethod -Uri "$($testRun.url)/results?api-version=5.0" -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
$isTestRunNameShown = $false
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
$info = ConvertFrom-Json $testResult.comment
|
||||
$helixJobId = $info.HelixJobId
|
||||
$helixWorkItemName = $info.HelixWorkItemName
|
||||
|
||||
$workItem = "$helixJobId-$helixWorkItemName"
|
||||
|
||||
Write-Host "Helix Work Item = $workItem"
|
||||
|
||||
if (-not $workItems.Contains($workItem))
|
||||
if ("comment" -in $testResult)
|
||||
{
|
||||
$workItems.Add($workItem)
|
||||
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files"
|
||||
$filesQueryUri = Append-HelixAccessTokenToUrl $filesQueryUri $helixAccessToken
|
||||
$files = Invoke-RestMethodWithRetries $filesQueryUri
|
||||
$info = ConvertFrom-Json $testResult.comment
|
||||
$helixJobId = $info.HelixJobId
|
||||
$helixWorkItemName = $info.HelixWorkItemName
|
||||
|
||||
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
|
||||
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
|
||||
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
|
||||
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
|
||||
$workItem = "$helixJobId-$helixWorkItemName"
|
||||
|
||||
if (-not $workItems.Contains($workItem))
|
||||
{
|
||||
if(-Not $isTestRunNameShown)
|
||||
$workItems.Add($workItem)
|
||||
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam"
|
||||
$files = Invoke-RestMethod -Uri $filesQueryUri -Method Get
|
||||
|
||||
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
|
||||
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
|
||||
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
|
||||
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
|
||||
{
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
|
||||
$isTestRunNameShown = $true
|
||||
}
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
|
||||
Generate-File-Links $screenShots "Screenshots"
|
||||
Generate-File-Links $dumps "CrashDumps"
|
||||
Generate-File-Links $pgcFiles "PGC files"
|
||||
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
|
||||
Generate-File-Links $misc "Misc"
|
||||
|
||||
foreach($pgcFile in $pgcFiles)
|
||||
{
|
||||
$flavorPath = $testResult.automatedTestName.Split('.')[0]
|
||||
$archPath = $testResult.automatedTestName.Split('.')[1]
|
||||
$fileName = $pgcFile.Name
|
||||
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
|
||||
$destination = "$fullPath\$fileName"
|
||||
|
||||
Write-Host "Copying $($pgcFile.Name) to $destination"
|
||||
|
||||
if (-Not (Test-Path $fullPath))
|
||||
if(-Not $isTestRunNameShown)
|
||||
{
|
||||
New-Item $fullPath -ItemType Directory
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
|
||||
$isTestRunNameShown = $true
|
||||
}
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
|
||||
Generate-File-Links $screenShots "Screenshots"
|
||||
Generate-File-Links $dumps "CrashDumps"
|
||||
Generate-File-Links $pgcFiles "PGC files"
|
||||
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
|
||||
Generate-File-Links $misc "Misc"
|
||||
|
||||
$link = $pgcFile.Link
|
||||
foreach($pgcFile in $pgcFiles)
|
||||
{
|
||||
$flavorPath = $pgcFile.Name.Split('.')[0]
|
||||
$archPath = $pgcFile.Name.Split('.')[1]
|
||||
$fileName = $pgcFile.Name.Remove(0, $flavorPath.length + $archPath.length + 2)
|
||||
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
|
||||
$destination = "$fullPath\$fileName"
|
||||
|
||||
Write-Host "Downloading $link to $destination"
|
||||
Write-Host "Copying $($pgcFile.Name) to $destination"
|
||||
|
||||
$link = Append-HelixAccessTokenToUrl $link $HelixAccessToken
|
||||
Download-FileWithRetries $link $destination
|
||||
if (-Not (Test-Path $fullPath))
|
||||
{
|
||||
New-Item $fullPath -ItemType Directory
|
||||
}
|
||||
|
||||
$link = "$($pgcFile.Link)$accessTokenParam"
|
||||
$webClient.DownloadFile($link, $destination)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
</ItemGroup>
|
||||
|
||||
<!-- These .proj files are generated by the build machine prior to running tests via GenerateTestProjFile.ps1. -->
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-SettingsModelLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-WindowsTerminalUIATests.proj" Condition=" '$(TestSuite)'=='PgoInstrumentationSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
</Project>
|
|
@ -23,7 +23,7 @@ Write-Host "queryUri = $queryUri"
|
|||
# To account for unreliable tests, we'll iterate through all of the tests associated with this build, check to see any tests that were unreliable
|
||||
# (denoted by being marked as "skipped"), and if so, we'll instead mark those tests with a warning and enumerate all of the attempted runs
|
||||
# with their pass/fail states as well as any relevant error messages for failed attempts.
|
||||
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
|
||||
$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
$timesSeenByRunName = @{}
|
||||
|
||||
|
@ -32,10 +32,10 @@ foreach ($testRun in $testRuns.value)
|
|||
$testRunResultsUri = "$($testRun.url)/results?api-version=5.0"
|
||||
|
||||
Write-Host "Marking test run `"$($testRun.name)`" as in progress so we can change its results to account for unreliable tests."
|
||||
Invoke-RestMethod "$($testRun.url)?api-version=5.0" -Method Patch -Body (ConvertTo-Json @{ "state" = "InProgress" }) -Headers $azureDevOpsRestApiHeaders -ContentType "application/json" | Out-Null
|
||||
Invoke-RestMethod -Uri "$($testRun.url)?api-version=5.0" -Method Patch -Body (ConvertTo-Json @{ "state" = "InProgress" }) -Headers $azureDevOpsRestApiHeaders -ContentType "application/json" | Out-Null
|
||||
|
||||
Write-Host "Retrieving test results..."
|
||||
$testResults = Invoke-RestMethodWithRetries $testRunResultsUri -Headers $azureDevOpsRestApiHeaders
|
||||
$testResults = Invoke-RestMethod -Uri $testRunResultsUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
|
@ -54,8 +54,7 @@ foreach ($testRun in $testRuns.value)
|
|||
Write-Host " Test $($testResult.testCaseTitle) was detected as unreliable. Updating..."
|
||||
|
||||
# The errorMessage field contains a link to the JSON-encoded rerun result data.
|
||||
$resultsJson = Download-StringWithRetries "Error results" $testResult.errorMessage
|
||||
$rerunResults = ConvertFrom-Json $resultsJson
|
||||
$rerunResults = ConvertFrom-Json (New-Object System.Net.WebClient).DownloadString($testResult.errorMessage)
|
||||
[System.Collections.Generic.List[System.Collections.Hashtable]]$rerunDataList = @()
|
||||
$attemptCount = 0
|
||||
$passCount = 0
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.TestContent" version="1.0.1" />
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="TAEF.Redist.Wlk" version="10.57.200731005-develop" targetFramework="native" />
|
||||
<package id="microsoft.windows.apps.test" version="1.0.181203002" targetFramework="native" />
|
||||
<package id="runtime.win-x86.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
|
||||
<package id="runtime.win-x64.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
|
||||
|
|
|
@ -28,7 +28,7 @@ echo %TIME%
|
|||
powershell -ExecutionPolicy Bypass .\InstallTestAppDependencies.ps1
|
||||
echo %TIME%
|
||||
|
||||
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll WindowsTerminal.UIA.Tests.dll
|
||||
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll
|
||||
set testBinaries=
|
||||
for %%B in (%testBinaryCandidates%) do (
|
||||
if exist %%B (
|
||||
|
@ -46,6 +46,7 @@ move te.wtl te_original.wtl
|
|||
|
||||
copy /y te_original.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
for /f "tokens=* delims=" %%a in ('dir /b *.pgc') do ren "%%a" "%testnameprefix%.%%~na.pgc"
|
||||
copy /y *.pgc %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
|
||||
set FailedTestQuery=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="TAEF.Redist.Wlk" version="10.57.200731005-develop" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
trigger: none
|
||||
pr: none
|
||||
|
||||
variables:
|
||||
- name: runCodesignValidationInjectionBG
|
||||
value: false
|
||||
|
||||
# 0.0.yyMM.dd##
|
||||
# 0.0.1904.0900
|
||||
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
|
||||
|
||||
stages:
|
||||
- stage: Build_x64
|
||||
displayName: Build x64
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/build-console-pgo.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- stage: Publish_PGO_Databases
|
||||
displayName: Publish PGO databases
|
||||
dependsOn: ['Build_x64']
|
||||
jobs:
|
||||
- template: ./templates/pgo-build-and-publish-nuget-job.yml
|
||||
parameters:
|
||||
pgoArtifact: 'PGO'
|
|
@ -1,487 +1,48 @@
|
|||
# This build should never run as CI or against a pull request.
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
pool:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
parameters:
|
||||
- name: branding
|
||||
displayName: "Branding (Build Type)"
|
||||
type: string
|
||||
default: Release
|
||||
values:
|
||||
- Release
|
||||
- Preview
|
||||
- name: buildTerminal
|
||||
displayName: "Build Windows Terminal MSIX"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildTerminalVPack
|
||||
displayName: "Build Windows Terminal VPack"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildWPF
|
||||
displayName: "Build Terminal WPF Control"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pgoBuildMode
|
||||
displayName: "PGO Build Mode"
|
||||
type: string
|
||||
default: Optimize
|
||||
values:
|
||||
- Optimize
|
||||
- Instrument
|
||||
- None
|
||||
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
default:
|
||||
- Release
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- x86
|
||||
- arm64
|
||||
|
||||
variables:
|
||||
TerminalInternalPackageVersion: "0.0.7"
|
||||
baseYearForVersioning: 2019 # Used by build-console-int
|
||||
versionMajor: 0
|
||||
versionMinor: 1
|
||||
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
resources:
|
||||
repositories:
|
||||
- repository: self
|
||||
type: git
|
||||
ref: main
|
||||
# When we move off PackageES for Versioning, we'll need to switch
|
||||
# name to this format. For now, though, we need to use DayOfYear.Rev
|
||||
# to unique our builds, as mandated by PackageES's Setup task.
|
||||
# name: '$(versionMajor).$(versionMinor).$(DayOfYear)$(Rev:r).0'
|
||||
#
|
||||
# Build name/version number above must end with .0 to make the
|
||||
# store publication machinery happy.
|
||||
name: 'Terminal_$(date:yyMM).$(date:dd)$(rev:rrr)'
|
||||
|
||||
# Build Arguments:
|
||||
# WindowsTerminalOfficialBuild=[true,false]
|
||||
# true - this is running on our build agent
|
||||
# false - running locally
|
||||
# WindowsTerminalBranding=[Dev,Preview,Release]
|
||||
# <none> - Development build resources (default)
|
||||
# Preview - Preview build resources
|
||||
# Release - regular build resources
|
||||
jobs:
|
||||
- job: Build
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ each platform in parameters.buildPlatforms }}:
|
||||
${{ config }}_${{ platform }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
BuildPlatform: ${{ platform }}
|
||||
displayName: Build
|
||||
cancelTimeoutInMinutes: 1
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- task: PowerShell@2
|
||||
displayName: Rationalize Build Platform
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Arch = "$(BuildPlatform)"
|
||||
- template: ./templates/build-console-audit-job.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
|
||||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
- template: ./templates/build-console-int.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
|
||||
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Use NuGet 5.10
|
||||
inputs:
|
||||
versionSpec: 5.10
|
||||
- task: NuGetCommand@2
|
||||
displayName: NuGet custom
|
||||
inputs:
|
||||
command: custom
|
||||
selectOrConfig: config
|
||||
nugetConfigPath: NuGet.Config
|
||||
arguments: restore OpenConsole.sln -SolutionDirectory $(Build.SourcesDirectory)
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
|
||||
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
|
||||
versionListDownload: $(TerminalInternalPackageVersion)
|
||||
- task: TouchdownBuildTask@1
|
||||
displayName: Download Localization Files
|
||||
inputs:
|
||||
teamId: 7105
|
||||
authId: $(TouchdownAppId)
|
||||
authKey: $(TouchdownAppKey)
|
||||
resourceFilePath: >-
|
||||
src\cascadia\TerminalApp\Resources\en-US\Resources.resw
|
||||
- template: ./templates/build-console-int.yml
|
||||
parameters:
|
||||
platform: x86
|
||||
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
|
||||
|
||||
src\cascadia\TerminalControl\Resources\en-US\Resources.resw
|
||||
- template: ./templates/build-console-int.yml
|
||||
parameters:
|
||||
platform: arm64
|
||||
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
|
||||
|
||||
src\cascadia\TerminalConnection\Resources\en-US\Resources.resw
|
||||
- template: ./templates/check-formatting.yml
|
||||
|
||||
src\cascadia\TerminalSettingsModel\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\WindowsTerminalUniversal\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw
|
||||
appendRelativeDir: true
|
||||
localizationTarget: false
|
||||
pseudoSetting: Included
|
||||
- task: PowerShell@2
|
||||
displayName: Move Loc files one level up
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw'
|
||||
|
||||
$Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore }
|
||||
pwsh: true
|
||||
- task: PowerShell@2
|
||||
displayName: Generate NOTICE.html from NOTICE.md
|
||||
inputs:
|
||||
filePath: .\build\scripts\Generate-ThirdPartyNotices.ps1
|
||||
arguments: -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
|
||||
pwsh: true
|
||||
- ${{ if eq(parameters.pgoBuildMode, 'Optimize') }}:
|
||||
- task: PowerShell@2
|
||||
displayName: Restore PGO Database
|
||||
inputs:
|
||||
filePath: tools/PGODatabase/restore-pgodb.ps1
|
||||
workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /t:Terminal\CascadiaPackage;Terminal\WindowsTerminalUniversal /p:WindowsTerminalReleaseBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: true
|
||||
maximumCpuCount: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: binlog'
|
||||
condition: failed()
|
||||
continueOnError: True
|
||||
inputs:
|
||||
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
|
||||
ArtifactName: binlog-$(BuildPlatform)
|
||||
- ${{ if eq(parameters.pgoBuildMode, 'Optimize') }}:
|
||||
- task: PowerShell@2
|
||||
displayName: Validate binaries are optimized
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll'
|
||||
|
||||
foreach ($BinFile in $Binaries) {
|
||||
|
||||
& "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/src/cascadia/CascadiaPackage/bin/$(BuildPlatform)/$(BuildConfiguration)/$BinFile"
|
||||
|
||||
}
|
||||
- task: PowerShell@2
|
||||
displayName: Check MSIX for common regressions
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix"
|
||||
|
||||
.\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName
|
||||
pwsh: true
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln for PublicTerminalCore
|
||||
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
|
||||
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)
|
||||
- task: PowerShell@2
|
||||
displayName: Source Index PDBs
|
||||
inputs:
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
|
||||
errorActionPreference: silentlyContinue
|
||||
- task: ComponentGovernanceComponentDetection@0
|
||||
displayName: Component Detection
|
||||
- task: PowerShell@2
|
||||
displayName: Run Unit Tests
|
||||
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
enabled: False
|
||||
inputs:
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
|
||||
- task: PowerShell@2
|
||||
displayName: Run Feature Tests
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
|
||||
enabled: False
|
||||
inputs:
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy *.appx/*.msix to Artifacts
|
||||
inputs:
|
||||
Contents: >-
|
||||
**/*.appx
|
||||
|
||||
**/*.msix
|
||||
|
||||
**/*.appxsym
|
||||
|
||||
!**/Microsoft.VCLibs*.appx
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (appx)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
|
||||
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy PublicTerminalCore.dll to Artifacts
|
||||
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
|
||||
inputs:
|
||||
Contents: >-
|
||||
**/PublicTerminalCore.dll
|
||||
|
||||
**/api-ms-win-core-synch-l1-2-0.dll
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/wpf
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (PublicTerminalCore)
|
||||
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)/wpf
|
||||
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)
|
||||
- task: PublishSymbols@2
|
||||
displayName: Publish symbols path
|
||||
continueOnError: True
|
||||
inputs:
|
||||
SearchPattern: '**/*.pdb'
|
||||
IndexSources: false
|
||||
SymbolServerType: TeamServices
|
||||
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- job: BundleAndSign
|
||||
displayName: Create and sign AppX/MSIX bundles
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Artifacts (*.appx, *.msix)
|
||||
inputs:
|
||||
downloadType: specific
|
||||
itemPattern: >-
|
||||
**/*.msix
|
||||
|
||||
**/*.appx
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Create WindowsTerminal*.msixbundle
|
||||
inputs:
|
||||
filePath: build\scripts\Create-AppxBundle.ps1
|
||||
arguments: -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion 0.0.0.0 -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminal_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
- task: PowerShell@2
|
||||
displayName: Create WindowsTerminalUniversal*.msixbundle
|
||||
inputs:
|
||||
filePath: build\scripts\Create-AppxBundle.ps1
|
||||
arguments: -InputPath "$(System.ArtifactsDirectory)" -ProjectName WindowsTerminalUniversal -BundleVersion $(XES_APPXMANIFESTVERSION) -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminalUniversal_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.msixbundle to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(System.ArtifactsDirectory)
|
||||
Pattern: Microsoft.WindowsTerminal*.msixbundle
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "Dynamic",
|
||||
"CertTemplateName": "WINMSAPP1ST",
|
||||
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
|
||||
"OperationCode": "SigntoolSign",
|
||||
"Parameters": {
|
||||
"OpusName": "Microsoft",
|
||||
"OpusInfo": "http://www.microsoft.com",
|
||||
"FileDigest": "/fd \"SHA256\"",
|
||||
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "Dynamic",
|
||||
"CertTemplateName": "WINMSAPP1ST",
|
||||
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
|
||||
"OperationCode": "SigntoolVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: appxbundle-signed'
|
||||
inputs:
|
||||
PathtoPublish: $(System.ArtifactsDirectory)
|
||||
ArtifactName: appxbundle-signed
|
||||
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- job: PackageAndSignWPF
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ config }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
displayName: Create NuGet Package (WPF Terminal Control)
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download x86 PublicTerminalCore
|
||||
inputs:
|
||||
artifactName: wpf-dll-x86-$(BuildConfiguration)
|
||||
itemPattern: '**/*.dll'
|
||||
downloadPath: bin\Win32\$(BuildConfiguration)\
|
||||
extractTars: false
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download x64 PublicTerminalCore
|
||||
inputs:
|
||||
artifactName: wpf-dll-x64-$(BuildConfiguration)
|
||||
itemPattern: '**/*.dll'
|
||||
downloadPath: bin\x64\$(BuildConfiguration)\
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Move downloaded artifacts up a level
|
||||
inputs:
|
||||
targetType: inline
|
||||
# Find all artifact files and move them up a directory. Ugh.
|
||||
script: >-
|
||||
Get-ChildItem bin -Recurse -Directory -Filter wpf-dll-* | % {
|
||||
$_ | Get-ChildItem -Recurse -File | % {
|
||||
Move-Item -Verbose $_.FullName $_.Directory.Parent.FullName
|
||||
}
|
||||
}
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Use NuGet 5.10.0
|
||||
inputs:
|
||||
versionSpec: 5.10.0
|
||||
- task: NuGetCommand@2
|
||||
displayName: NuGet restore copy
|
||||
inputs:
|
||||
selectOrConfig: config
|
||||
nugetConfigPath: NuGet.Config
|
||||
- task: VSBuild@1
|
||||
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)
|
||||
maximumCpuCount: true
|
||||
- task: PublishSymbols@2
|
||||
displayName: Publish symbols path
|
||||
continueOnError: True
|
||||
inputs:
|
||||
SearchPattern: '**/*.pdb'
|
||||
IndexSources: false
|
||||
SymbolServerType: TeamServices
|
||||
SymbolsArtifactName: Symbols_WPF_$(BuildConfiguration)
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy *.nupkg to Artifacts
|
||||
inputs:
|
||||
Contents: '**/*Wpf*.nupkg'
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.nupkg to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
Pattern: '*.nupkg'
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetSign",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (nupkg)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)\nupkg
|
||||
ArtifactName: wpf-nupkg-$(BuildConfiguration)
|
||||
|
||||
- ${{ if eq(parameters.buildTerminalVPack, true) }}:
|
||||
- job: VPack
|
||||
displayName: Create Windows vPack
|
||||
dependsOn: BundleAndSign
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Build Artifacts
|
||||
inputs:
|
||||
artifactName: appxbundle-signed
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Rename and stage packages for vpack
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
# Rename to known/fixed name for Windows build system
|
||||
|
||||
Get-ChildItem Microsoft.WindowsTerminal_*.msixbundle | Rename-Item -NewName { 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle' }
|
||||
|
||||
|
||||
# Create vpack directory and place item inside
|
||||
|
||||
mkdir WindowsTerminal.app
|
||||
|
||||
mv Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle .\WindowsTerminal.app\
|
||||
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed
|
||||
- task: PkgESVPack@12
|
||||
displayName: 'Package ES - VPack'
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed\WindowsTerminal.app
|
||||
description: Windows Terminal pre-install application
|
||||
pushPkgName: WindowsTerminal.app
|
||||
owner: condev
|
||||
...
|
||||
- template: ./templates/release-sign-and-bundle.yml
|
||||
|
|
|
@ -8,12 +8,9 @@ jobs:
|
|||
variables:
|
||||
BuildConfiguration: AuditMode
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
|
|
@ -11,32 +11,21 @@ jobs:
|
|||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
parameters:
|
||||
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
|
||||
|
||||
# It appears that the Component Governance build task that gets automatically injected stopped working
|
||||
# when we renamed our main branch.
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: 'Component Detection'
|
||||
condition: and(succeededOrFailed(), not(eq(variables['Build.Reason'], 'PullRequest')))
|
||||
|
||||
- template: helix-runtests-job.yml
|
||||
parameters:
|
||||
name: 'RunTestsInHelix'
|
||||
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
condition: and(succeeded(), and(eq('${{ parameters.platform }}', 'x64'), not(eq(variables['Build.Reason'], 'PullRequest'))))
|
||||
testSuite: 'DevTestSuite'
|
||||
platform: ${{ parameters.platform }}
|
||||
configuration: ${{ parameters.configuration }}
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
|
||||
- template: helix-processtestresults-job.yml
|
||||
|
|
30
build/pipelines/templates/build-console-int.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
parameters:
|
||||
configuration: 'Release'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
|
||||
pool:
|
||||
name: Package ES Lab E
|
||||
demands:
|
||||
- msbuild
|
||||
- visualstudio
|
||||
- vstest
|
||||
|
||||
steps:
|
||||
- task: PkgESSetupBuild@10
|
||||
displayName: 'Package ES - Setup Build'
|
||||
inputs:
|
||||
useDfs: false
|
||||
productName: WindowsTerminal
|
||||
disableOutputRedirect: true
|
||||
|
||||
- template: build-console-steps.yml
|
||||
parameters:
|
||||
additionalBuildArguments: "/p:XesUseOneStoreVersioning=true;XesBaseYearForStoreVersion=$(baseYearForVersioning) ${{ parameters.additionalBuildArguments }}"
|
|
@ -1,54 +0,0 @@
|
|||
parameters:
|
||||
configuration: 'Release'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
minimumExpectedTestsExecutedCount: 1 # Sanity check for minimum expected tests to be reported
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Instrument'
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
parameters:
|
||||
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
|
||||
|
||||
- template: helix-runtests-job.yml
|
||||
parameters:
|
||||
name: 'RunTestsInHelix'
|
||||
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
condition: succeeded()
|
||||
testSuite: 'PgoInstrumentationSuite'
|
||||
taefQuery: '@IsPgo=true'
|
||||
configuration: ${{ parameters.configuration }}
|
||||
platform: ${{ parameters.platform }}
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
|
||||
- template: helix-processtestresults-job.yml
|
||||
parameters:
|
||||
name: 'ProcessTestResults'
|
||||
pgoArtifact: 'PGO'
|
||||
dependsOn:
|
||||
- RunTestsInHelix
|
||||
condition: succeededOrFailed()
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}
|
||||
|
||||
- template: pgo-merge-pgd-job.yml
|
||||
parameters:
|
||||
name: 'MergePGD'
|
||||
dependsOn:
|
||||
- ProcessTestResults
|
||||
pgoArtifact: 'PGO'
|
||||
platform: ${{ parameters.platform }}
|
|
@ -22,7 +22,7 @@ steps:
|
|||
configPath: NuGet.config
|
||||
restoreSolution: OpenConsole.sln
|
||||
restoreDirectory: '$(Build.SourcesDirectory)\packages'
|
||||
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: Restore NuGet packages for extraneous build actions
|
||||
inputs:
|
||||
|
@ -32,29 +32,6 @@ steps:
|
|||
restoreSolution: build/packages.config
|
||||
restoreDirectory: '$(Build.SourcesDirectory)\packages'
|
||||
|
||||
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
|
||||
- script: |
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
|
||||
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
|
||||
del %TEMP%\vsinstalldir.txt
|
||||
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display build machine environment variables'
|
||||
inputs:
|
||||
filename: 'set'
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'Restore PGO database'
|
||||
condition: eq(variables['PGOBuildMode'], 'Optimize')
|
||||
inputs:
|
||||
targetType: filePath
|
||||
workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase
|
||||
filePath: $(Build.SourcesDirectory)\tools\PGODatabase\restore-pgodb.ps1
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 'Build solution **\OpenConsole.sln'
|
||||
inputs:
|
||||
|
@ -68,9 +45,6 @@ steps:
|
|||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Check MSIX for common regressions'
|
||||
# PGO runtime needs its own CRT and it's in the package for convenience.
|
||||
# That will make this script mad so skip since we're not shipping the PGO Instrumentation one anyway.
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
|
@ -79,7 +53,6 @@ steps:
|
|||
|
||||
- task: powershell@2
|
||||
displayName: 'Source Index PDBs'
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
|
@ -95,25 +68,13 @@ steps:
|
|||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Validate binaries are optimized'
|
||||
condition: eq(variables['pgoBuildMode'], 'Optimize')
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
$Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll'
|
||||
foreach ($BinFile in $Binaries)
|
||||
{
|
||||
& "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/$BinFile"
|
||||
}
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run Unit Tests'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
|
||||
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run Feature Tests (x64 only)'
|
||||
|
@ -121,7 +82,7 @@ steps:
|
|||
targetType: filePath
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
|
||||
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), eq(variables['BuildPlatform'], 'x64'))
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Convert Test Logs from WTL to xUnit format'
|
||||
|
@ -129,14 +90,13 @@ steps:
|
|||
targetType: filePath
|
||||
filePath: build\Helix\ConvertWttLogToXUnit.ps1
|
||||
arguments: -WttInputPath '${{ parameters.testLogPath }}' -WttSingleRerunInputPath 'unused.wtl' -WttMultipleRerunInputPath 'unused2.wtl' -XUnitOutputPath 'onBuildMachineResults.xml' -TestNamePrefix '$(BuildConfiguration).$(BuildPlatform)'
|
||||
condition: and(ne(variables['PGOBuildMode'], 'Instrument'),or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
condition: or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86'))
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Upload converted test logs'
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
testResultsFormat: 'xUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest
|
||||
testResultsFiles: '**/onBuildMachineResults.xml'
|
||||
testResultsFiles: '**/onBuildMachineResults.xml'
|
||||
#searchFolder: '$(System.DefaultWorkingDirectory)' # Optional
|
||||
#mergeTestResults: false # Optional
|
||||
#failTaskOnFailedTests: false # Optional
|
||||
|
@ -167,47 +127,24 @@ steps:
|
|||
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: succeeded()
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy outputs needed for test runs to Artifacts'
|
||||
inputs:
|
||||
Contents: |
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.exe
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml
|
||||
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.exe
|
||||
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.dll
|
||||
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.xml
|
||||
**/Microsoft.VCLibs.*.appx
|
||||
**/TestHostApp/*.exe
|
||||
**/TestHostApp/*.dll
|
||||
**/TestHostApp/*.xml
|
||||
!**/*.pdb
|
||||
!**/*.ipdb
|
||||
!**/*.obj
|
||||
!**/*.pch
|
||||
**/TestHostApp/*
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: succeeded()
|
||||
condition: and(and(succeeded(), eq(variables['BuildPlatform'], 'x64')), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish All Build Artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'drop'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy PGO databases needed for PGO instrumentation run'
|
||||
inputs:
|
||||
Contents: |
|
||||
**/*.pgd
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO/$(BuildPlatform)'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish All PGO Artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO'
|
||||
ArtifactName: 'PGO'
|
||||
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
|
||||
ArtifactName: 'drop'
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
clean: true
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Code Formatting Check'
|
||||
displayName: 'Code Formattting Check'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: '.\build\scripts\Invoke-FormattingCheck.ps1'
|
||||
|
|
|
@ -12,4 +12,4 @@ steps:
|
|||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\GenerateTestProjFile.ps1
|
||||
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
|
||||
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\taef.redist.wlk.10.57.200731005-develop\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
|
|
@ -22,7 +22,6 @@ jobs:
|
|||
condition: succeededOrFailed()
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
HelixAccessToken: $(HelixApiAccessToken)
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\UpdateUnreliableTests.ps1
|
||||
|
@ -33,7 +32,6 @@ jobs:
|
|||
condition: succeededOrFailed()
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
HelixAccessToken: $(HelixApiAccessToken)
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\OutputTestResults.ps1
|
||||
|
|
|
@ -10,12 +10,19 @@ parameters:
|
|||
maxParallel: 4
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
taefQuery: ''
|
||||
configuration: ''
|
||||
platform: ''
|
||||
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
|
||||
useBuildOutputFromPipeline: $(System.DefinitionId)
|
||||
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
|
||||
closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
|
||||
matrix:
|
||||
# Release_x86:
|
||||
# buildPlatform: 'x86'
|
||||
# buildConfiguration: 'release'
|
||||
# openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
|
||||
# closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
|
||||
Release_x64:
|
||||
buildPlatform: 'x64'
|
||||
buildConfiguration: 'release'
|
||||
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
|
||||
closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
|
@ -26,15 +33,13 @@ jobs:
|
|||
timeoutInMinutes: 120
|
||||
strategy:
|
||||
maxParallel: ${{ parameters.maxParallel }}
|
||||
matrix: ${{ parameters.matrix }}
|
||||
variables:
|
||||
buildConfiguration: ${{ parameters.configuration }}
|
||||
buildPlatform: ${{ parameters.platform }}
|
||||
openHelixTargetQueues: ${{ parameters.openHelixTargetQueues }}
|
||||
closedHelixTargetQueues: ${{ parameters.closedHelixTargetQueues }}
|
||||
artifactsDir: $(Build.SourcesDirectory)\Artifacts
|
||||
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\$(buildPlatform)
|
||||
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$(buildPlatform)
|
||||
helixCommonArgs: '/binaryLogger:$(Build.SourcesDirectory)/${{parameters.name}}.$(buildPlatform).$(buildConfiguration).binlog /p:HelixBuild=$(Build.BuildId).$(buildPlatform).$(buildConfiguration) /p:Platform=$(buildPlatform) /p:Configuration=$(buildConfiguration) /p:HelixType=${{parameters.helixType}} /p:TestSuite=${{parameters.testSuite}} /p:ProjFilesPath=$(Build.ArtifactStagingDirectory) /p:rerunPassesRequiredToAvoidFailure=${{parameters.rerunPassesRequiredToAvoidFailure}}'
|
||||
|
||||
|
||||
steps:
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display build machine environment variables'
|
||||
|
@ -92,17 +97,9 @@ jobs:
|
|||
filename: 'dir'
|
||||
arguments: '/s $(Build.SourcesDirectory)\HelixPayload'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Make artifact directories'
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\"
|
||||
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\"
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.LocalTests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-TerminalAppLocalTests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
|
@ -110,7 +107,7 @@ jobs:
|
|||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\SettingsModel.LocalTests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-SettingsModelLocalTests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
|
@ -119,20 +116,12 @@ jobs:
|
|||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\Conhost.UIA.Tests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-HostTestsUIA.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),or(eq('${{ parameters.testSuite }}','PgoInstrumentationSuite'),eq('${{ parameters.testSuite }}','DevTestSuite')))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\WindowsTerminal.UIA.Tests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-WindowsTerminalUIATests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish generated .proj files'
|
||||
inputs:
|
||||
|
@ -141,7 +130,6 @@ jobs:
|
|||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Run tests in Helix (open queues)'
|
||||
condition: and(succeeded(),eq(variables['System.CollectionUri'],'https://dev.azure.com/ms/'))
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
|
@ -150,14 +138,3 @@ jobs:
|
|||
custom: msbuild
|
||||
arguments: '$(helixCommonArgs) /p:IsExternal=true /p:Creator=Terminal /p:HelixTargetQueues=$(openHelixTargetQueues)'
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Run tests in Helix (closed queues)'
|
||||
condition: and(succeeded(),ne(variables['System.CollectionUri'],'https://dev.azure.com/ms/'))
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
HelixAccessToken: $(HelixApiAccessToken)
|
||||
inputs:
|
||||
command: custom
|
||||
projects: build\Helix\RunTestsInHelix.proj
|
||||
custom: msbuild
|
||||
arguments: '$(helixCommonArgs) /p:HelixTargetQueues=$(closedHelixTargetQueues)'
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
# From our friends at MUX: https://github.com/microsoft/microsoft-ui-xaml/blob/main/build/AzurePipelinesTemplates/MUX-BuildAndPublishPGONuGet-Job.yml
|
||||
|
||||
parameters:
|
||||
dependsOn: ''
|
||||
pgoArtifact: PGO
|
||||
|
||||
jobs:
|
||||
- job: BuildAndPublishPGONuGet
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
artifactsPath: $(Build.SourcesDirectory)\Artifacts
|
||||
pgoToolsPath: $(Build.SourcesDirectory)\tools\PGODatabase
|
||||
nuspecPath: $(pgoToolsPath)\NuSpecs
|
||||
nuspecFilename: PGO.nuspec
|
||||
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
inputs:
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
downloadPath: $(artifactsPath)
|
||||
|
||||
- task: NuGetAuthenticate@0
|
||||
inputs:
|
||||
nuGetServiceConnections: 'Terminal Public Artifact Feed'
|
||||
|
||||
- task: NuGetToolInstaller@0
|
||||
displayName: 'Use NuGet 5.8.0'
|
||||
inputs:
|
||||
versionSpec: 5.8.0
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy pgd files to NuGet build directory'
|
||||
inputs:
|
||||
sourceFolder: $(artifactsPath)\${{ parameters.pgoArtifact }}
|
||||
contents: '**\*.pgd'
|
||||
targetFolder: $(nuspecPath)\tools
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'Generate NuSpec file'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: $(pgoToolsPath)\generate-nuspec.ps1
|
||||
workingDirectory: $(pgoToolsPath)
|
||||
arguments: $(nuspecPath)\$(nuspecFilename).template $(nuspecPath)\$(nuspecFilename)
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: 'NuGet pack'
|
||||
inputs:
|
||||
command: pack
|
||||
packagesToPack: '$(nuspecPath)\$(nuspecFilename)'
|
||||
basePath: '$(nuspecPath)'
|
||||
packDestination: '$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathToPublish: $(Build.ArtifactStagingDirectory)
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: 'NuGet push'
|
||||
inputs:
|
||||
command: push
|
||||
nuGetFeedType: external
|
||||
packagesToPush: $(Build.ArtifactStagingDirectory)/*.nupkg
|
||||
# The actual URL and PAT for this feed is configured at
|
||||
# https://microsoft.visualstudio.com/Dart/_settings/adminservices
|
||||
# This is the name of that connection
|
||||
publishFeedCredentials: 'Terminal Public Artifact Feed'
|
||||
feedsToUse: config
|
||||
nugetConfigPath: '$(Build.SourcesDirectory)/NuGet.config'
|
|
@ -1,90 +0,0 @@
|
|||
parameters:
|
||||
dependsOn: ''
|
||||
pgoArtifact: PGO
|
||||
platform: ''
|
||||
|
||||
jobs:
|
||||
- job: MergePGD
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
artifactsPath: $(Build.SourcesDirectory)\Artifacts
|
||||
pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }}
|
||||
buildPlatform: ${{ parameters.platform }}
|
||||
|
||||
steps:
|
||||
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
|
||||
- script: |
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
|
||||
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
|
||||
del %TEMP%\vsinstalldir.txt
|
||||
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
inputs:
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
downloadPath: $(artifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge WindowsTerminal*.pgc WindowsTerminal.pgd
|
||||
displayName: 'Merge Terminal pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge OpenConsole*.pgc OpenConsole.pgd
|
||||
displayName: 'Merge OpenConsole pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Control*.pgc Microsoft.Terminal.Control.pgd
|
||||
displayName: 'Merge Microsoft.Terminal.Control pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Remoting*.pgc Microsoft.Terminal.Remoting.pgd
|
||||
displayName: 'Merge Microsoft.Terminal.Remoting pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Editor*.pgc Microsoft.Terminal.Settings.Editor.pgd
|
||||
displayName: 'Merge Microsoft.Terminal.Settings.Editor pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Model*.pgc Microsoft.Terminal.Settings.Model.pgd
|
||||
displayName: 'Merge Microsoft.Terminal.Settings.Model pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalApp*.pgc TerminalApp.pgd
|
||||
displayName: 'Merge TerminalApp pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalConnection*.pgc TerminalConnection.pgd
|
||||
displayName: 'Merge TerminalConnection pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy merged pgd to artifact staging'
|
||||
inputs:
|
||||
sourceFolder: $(pgoArtifactsPath)
|
||||
contents: '**\$(buildPlatform)\*.pgd'
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathToPublish: $(Build.ArtifactStagingDirectory)
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
74
build/pipelines/templates/release-sign-and-bundle.yml
Normal file
|
@ -0,0 +1,74 @@
|
|||
parameters:
|
||||
configuration: 'Release'
|
||||
|
||||
jobs:
|
||||
- job: SignDeploy${{ parameters.configuration }}
|
||||
displayName: Sign and Deploy for ${{ parameters.configuration }}
|
||||
|
||||
dependsOn:
|
||||
- Buildx64AuditMode
|
||||
- Buildx64Release
|
||||
- Buildx86Release
|
||||
- Buildarm64Release
|
||||
- CodeFormatCheck
|
||||
condition: |
|
||||
and
|
||||
(
|
||||
in(dependencies.Buildx64AuditMode.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
|
||||
in(dependencies.Buildx64Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
|
||||
in(dependencies.Buildx86Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
|
||||
in(dependencies.Buildarm64Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
|
||||
in(dependencies.CodeFormatCheck.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
|
||||
)
|
||||
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
AppxProjectName: CascadiaPackage
|
||||
AppxBundleName: Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle
|
||||
|
||||
pool:
|
||||
name: Package ES Lab E
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
|
||||
- task: PkgESSetupBuild@10
|
||||
displayName: 'Package ES - Setup Build'
|
||||
inputs:
|
||||
useDfs: false
|
||||
productName: WindowsTerminal
|
||||
disableOutputRedirect: true
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: 'Component Detection'
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download AppX artifacts
|
||||
inputs:
|
||||
artifactName: 'appx-$(BuildConfiguration)'
|
||||
itemPattern: |
|
||||
**/*.appx
|
||||
**/*.msix
|
||||
downloadPath: '$(Build.ArtifactStagingDirectory)\appx'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Create $(AppxBundleName)'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: '.\build\scripts\Create-AppxBundle.ps1'
|
||||
arguments: |
|
||||
-InputPath "$(Build.ArtifactStagingDirectory)\appx" -ProjectName $(AppxProjectName) -BundleVersion 0.0.0.0 -OutputPath "$(Build.ArtifactStagingDirectory)\$(AppxBundleName)"
|
||||
|
||||
- task: PkgESCodeSign@10
|
||||
displayName: 'Package ES - SignConfig.WindowsTerminal.xml'
|
||||
inputs:
|
||||
signConfigXml: 'build\config\SignConfig.WindowsTerminal.xml'
|
||||
inPathRoot: '$(Build.ArtifactStagingDirectory)'
|
||||
outPathRoot: '$(Build.ArtifactStagingDirectory)\signed'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Signed AppX'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)\signed'
|
||||
ArtifactName: 'appxbundle-signed-$(BuildConfiguration)'
|
|
@ -1,103 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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')" />
|
||||
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|Any CPU">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>AnyCPU</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Fuzzing|Any CPU">
|
||||
<Configuration>Fuzzing</Configuration>
|
||||
<Platform>AnyCPU</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="AuditMode|Any CPU">
|
||||
<Configuration>AuditMode</Configuration>
|
||||
<Platform>AnyCPU</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Any CPU">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>AnyCPU</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>d97c3c61-53cd-4e72-919b-9a0940e038f9</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<IntermediateOutputPath>$(SolutionDir)obj\$(Configuration)\GenerateFeatureFlags\</IntermediateOutputPath>
|
||||
<OpenConsoleCommonOutDir>$(SolutionDir)bin\$(Configuration)\</OpenConsoleCommonOutDir>
|
||||
|
||||
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Preview'">Preview</_WTBrandingName>
|
||||
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Release'">Release</_WTBrandingName>
|
||||
<_WTBrandingName Condition="'$(_WTBrandingName)'==''">Dev</_WTBrandingName>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_GenerateBranchAndBrandingCache">
|
||||
<Exec Command="git.exe rev-parse --abbrev-ref HEAD"
|
||||
CustomWarningRegularExpression="^fatal:.*"
|
||||
ConsoleToMsBuild="true"
|
||||
IgnoreExitCode="true">
|
||||
<Output TaskParameter="ConsoleOutput" ItemName="_GitBranchLines" />
|
||||
</Exec>
|
||||
|
||||
<ItemGroup>
|
||||
<_BrandingLines Include="$(_WTBrandingName)" />
|
||||
</ItemGroup>
|
||||
|
||||
<WriteLinesToFile File="$(IntermediateOutputPath)branch_branding_cache.txt"
|
||||
Lines="@(_GitBranchLines);@(_BrandingLines)"
|
||||
Overwrite="true"
|
||||
WriteOnlyWhenDifferent="true" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="$(IntermediateOutputPath)branch_branding_cache.txt" />
|
||||
<_BranchBrandingCacheFiles Include="$(IntermediateOutputPath)branch_branding_cache.txt" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_RunFeatureFlagScript"
|
||||
Inputs="@(FeatureFlagFile);@(_BranchBrandingCacheFiles)"
|
||||
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
|
||||
DependsOnTargets="_GenerateBranchAndBrandingCache">
|
||||
<MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" />
|
||||
<!-- This commandline is escaped like:
|
||||
|
||||
powershell -Command "&'$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1' -Path '%(FeatureFlagFile.FullPath)'' -Branding $(_WTBrandingName)"
|
||||
|
||||
which was the only way I could find to get it to obey spaces in the SolutionDir
|
||||
-->
|
||||
<Exec
|
||||
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command "&'$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1' -Path '%(FeatureFlagFile.FullPath)' -Branding $(_WTBrandingName)""
|
||||
ConsoleToMsBuild="true"
|
||||
StandardOutputImportance="low">
|
||||
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />
|
||||
</Exec>
|
||||
|
||||
<!--
|
||||
We gather the feature flag output in MSBuild and emit the file so that we can take advantage of
|
||||
WriteOnlyWhenDifferent. Doing this ensures that we don't rebuild the world when the branch changes
|
||||
(if it results in a new TilFeatureStaging.h that would have had the same content/features as the previous one)
|
||||
-->
|
||||
|
||||
<WriteLinesToFile File="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
|
||||
Lines="@(_FeatureFlagFileLines)"
|
||||
Overwrite="true"
|
||||
WriteOnlyWhenDifferent="true" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="Build" DependsOnTargets="_RunFeatureFlagScript" />
|
||||
<Target Name="Clean">
|
||||
<Delete Files="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<FeatureFlagFile Include="$(SolutionDir)\src\features.xml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -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.22000.0\x86\MakeAppx.exe"
|
||||
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\MakeAppx.exe"
|
||||
)
|
||||
|
||||
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {
|
||||
|
|
|
@ -3,24 +3,12 @@
|
|||
# Checks for code formatting errors. Will throw exception if any are found.
|
||||
function Invoke-CheckBadCodeFormatting() {
|
||||
Import-Module ./tools/OpenConsole.psm1
|
||||
|
||||
# Don't run the XAML formatter in this step - even if it changes nothing,
|
||||
# it'll still touch all the .xaml files.
|
||||
Invoke-CodeFormat -IgnoreXaml
|
||||
|
||||
Invoke-CodeFormat
|
||||
# returns a non-zero exit code if there are any diffs in the tracked files in the repo
|
||||
git diff-index --quiet HEAD --
|
||||
if ($lastExitCode -eq 1) {
|
||||
|
||||
# Write the list of files that need updating to the log
|
||||
git diff-index --name-only HEAD
|
||||
|
||||
throw "code formatting bad, run Invoke-CodeFormat on branch"
|
||||
}
|
||||
|
||||
# Manually check the formatting of our .xaml files, without touching them.
|
||||
Test-XamlFormat
|
||||
|
||||
}
|
||||
|
||||
Invoke-CheckBadCodeFormatting
|
||||
|
|
|
@ -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.22000.0"
|
||||
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
|
|
@ -19,13 +19,10 @@
|
|||
"/.github/",
|
||||
"/samples/",
|
||||
"/res/terminal/",
|
||||
"/res/fonts/",
|
||||
"/doc/specs/",
|
||||
"/doc/cascadia/",
|
||||
"/doc/user-docs/",
|
||||
"/src/tools/MonarchPeasantSample/",
|
||||
"/scratch/",
|
||||
"Scratch.sln",
|
||||
],
|
||||
"SuffixFilters": [
|
||||
".dbb",
|
||||
|
@ -41,7 +38,6 @@
|
|||
".wrn",
|
||||
".rec",
|
||||
".err",
|
||||
"XamlStyler.json",
|
||||
".xlsx"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2021</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>13</VersionMinor>
|
||||
<VersionMinor>8</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
2
dep/wil
|
@ -1 +1 @@
|
|||
Subproject commit 2e225973d6c2ecf17fb4d376ddbeedb6db7dd82f
|
||||
Subproject commit 3c00e7f1d8cf9930bbb8e5be3ef0df65c84e8928
|
|
@ -4,7 +4,7 @@
|
|||
Introducing exceptions to an existing non-exception-based codebase can be perilous. The console was originally written
|
||||
in C at a time when C++ was relatively unused in the Windows operating system. As part of our project to modernize the
|
||||
Windows console, we converted to use C++, but still had an aversion to using exception-based error handling in
|
||||
our code for fear that it might introduce unexpected failures. However, the STL and other libraries like it are so useful that
|
||||
our code for fear that it introduce unexpected failures. However, the STL and other libraries like it are so useful that
|
||||
sometimes it's significantly simpler to use them. Given that, we have a set of rules that we follow when considering
|
||||
exception use.
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ I think there might be a bit of a misunderstanding here - there are two differen
|
|||
* shell applications, like `cmd.exe`, `powershell`, `zsh`, etc. These are text-only applications that emit streams of characters. They don't care at all about how they're eventually rendered to the user. These are also sometimes referred to as "commandline client" applications.
|
||||
* terminal applications, like the Windows Terminal, gnome-terminal, xterm, iterm2, hyper. These are graphical applications that can be used to render the output of commandline clients.
|
||||
|
||||
On Windows, if you just run `cmd.exe` directly, the OS will create an instance of `conhost.exe` as the _terminal_ for `cmd.exe`. The same thing happens for `powershell.exe`, the system will create a new conhost window for any client that's not already connected to a terminal of some sort. This has lead to an enormous amount of confusion for people thinking that a conhost window is actually a "`cmd` window". `cmd` can't have a window, it's just a commandline application. Its window is always some other terminal.
|
||||
On Windows, if you just run `cmd.exe` directly, the OS will create an instance of `conhost.exe` as the _terminal_ for `cmd.exe`. The same thing happens for `powershell.exe`, the system will creates a new conhost window for any client that's not already connected to a terminal of some sort. This has lead to an enormous amount of confusion for people thinking that a conhost window is actually a "`cmd` window". `cmd` can't have a window, it's just a commandline application. Its window is always some other terminal.
|
||||
|
||||
Any terminal can run any commandline client application. So you can use the Windows Terminal to run whatever shell you want. I use mine for both `cmd` and `powershell`, and also WSL:
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ Use the [TAEF Verify Macros for C++](https://docs.microsoft.com/en-us/windows-ha
|
|||
|
||||
### Running Tests
|
||||
|
||||
If you have Visual Studio and related C++ components installed, and you have successfully restored NuGets, you should have the TAEF test runner `te.exe` available locally as part of the `Microsoft.Taef` package.
|
||||
If you have Visual Studio and related C++ components installed, and you have successfully restored NuGets, you should have the TAEF test runner `te.exe` available locally as part of the `Taef.Redist.Wlk` package.
|
||||
|
||||
> Note that you cannot easily run TAEF tests directly through Visual Studio. The `Microsoft.Taef` NuGet package comes with an adapter that will let you browse and execute TAEF tests inside of Visual Studio, but its performance and reliability prevent us from recommending it here.
|
||||
> Note that you cannot easily run TAEF tests directly through Visual Studio. The `Taef.Redist.Wlk` NuGet package comes with an adapter that will let you browse and execute TAEF tests inside of Visual Studio, but its performance and reliability prevent us from recommending it here.
|
||||
|
||||
In a "normal" CMD environment, `te.exe` may not be directly available. Try the following command to set up the development environment first:
|
||||
In a "normal" CMD environment, `te.exe` may not be directly available. Try the following command to set up the development enviroment first:
|
||||
|
||||
```shell
|
||||
.\tools\razzle.cmd
|
||||
|
|
|
@ -127,4 +127,4 @@ When a release is created, if the PR ID number is linked inside the release desc
|
|||
- Issue message: 🎉This issue was addressed in #{pull request ID}, which has now been successfully released as {release name} {release version}.🎉"
|
||||
|
||||
## Admin Panel
|
||||
[Here](https://portal.fabricbot.ms/bot/?repo=microsoft/terminal)
|
||||
[Here](https://fabric-cp.azurewebsites.net/bot/)
|
||||
|
|
|
@ -9,13 +9,7 @@ git submodule update --init --recursive
|
|||
|
||||
OpenConsole.sln may be built from within Visual Studio or from the command-line using a set of convenience scripts & tools in the **/tools** directory:
|
||||
|
||||
When using Visual Studio, be sure to set up the path for code formatting. To download the required clang-format.exe file, follow one of the building instructions below and run:
|
||||
```powershell
|
||||
Import-Module .\tools\OpenConsole.psm1
|
||||
Set-MsBuildDevEnvironment
|
||||
Get-Format
|
||||
```
|
||||
After, go to Tools > Options > Text Editor > C++ > Formatting and check "Use custom clang-format.exe file" in Visual Studio and choose the clang-format.exe in the repository at /packages/clang-format.win-x86.10.0.0/tools/clang-format.exe by clicking "browse" right under the check box.
|
||||
When using Visual Studio, be sure to set up the path for code formatting. This can be done in Visual Studio by going to Tools > Options > Text Editor > C++ > Formatting and checking "Use custom clang-format.exe file" and choosing the clang-format.exe in the repository at /dep/llvm/clang-format.exe by clicking "browse" right under the check box.
|
||||
|
||||
### Building in PowerShell
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ Adding a setting to Windows Terminal is fairly straightforward. This guide serve
|
|||
|
||||
The Terminal Settings Model (`Microsoft.Terminal.Settings.Model`) is responsible for (de)serializing and exposing settings.
|
||||
|
||||
### `INHERITABLE_SETTING` macro
|
||||
### `GETSET_SETTING` macro
|
||||
|
||||
The `INHERITABLE_SETTING` macro can be used to implement inheritance for your new setting and store the setting in the settings model. It takes three parameters:
|
||||
The `GETSET_SETTING` macro can be used to implement inheritance for your new setting and store the setting in the settings model. It takes three parameters:
|
||||
- `type`: the type that the setting will be stored as
|
||||
- `name`: the name of the variable for storage
|
||||
- `defaultValue`: the value to use if the user does not define the setting anywhere
|
||||
|
@ -20,7 +20,7 @@ This tutorial will add `CloseOnExitMode CloseOnExit` as a profile setting.
|
|||
1. In `Profile.h`, declare/define the setting:
|
||||
|
||||
```c++
|
||||
INHERITABLE_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
|
||||
GETSET_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
|
||||
```
|
||||
|
||||
2. In `Profile.idl`, expose the setting via WinRT:
|
||||
|
@ -141,7 +141,7 @@ struct OpenSettingsArgs : public OpenSettingsArgsT<OpenSettingsArgs>
|
|||
OpenSettingsArgs() = default;
|
||||
|
||||
// adds a getter/setter for your argument, and defines the json key
|
||||
WINRT_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
|
||||
GETSET_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
|
||||
static constexpr std::string_view TargetKey{ "target" };
|
||||
|
||||
public:
|
||||
|
@ -213,9 +213,9 @@ Terminal-level settings are settings that affect a shell session. Generally, the
|
|||
- Declare the setting in `IControlSettings.idl` or `ICoreSettings.idl` (whichever is relevant to your setting). If your setting is an enum setting, declare the enum here instead of in the `TerminalSettingsModel` project.
|
||||
- In `TerminalSettings.h`, declare/define the setting...
|
||||
```c++
|
||||
// The WINRT_PROPERTY macro declares/defines a getter setter for the setting.
|
||||
// Like INHERITABLE_SETTING, it takes in a type, name, and defaultValue.
|
||||
WINRT_PROPERTY(bool, UseAcrylic, false);
|
||||
// The GETSET_PROPERTY macro declares/defines a getter setter for the setting.
|
||||
// Like GETSET_SETTING, it takes in a type, name, and defaultValue.
|
||||
GETSET_PROPERTY(bool, UseAcrylic, false);
|
||||
```
|
||||
- In `TerminalSettings.cpp`...
|
||||
- update `_ApplyProfileSettings` for profile settings
|
||||
|
|
|
@ -166,7 +166,7 @@ should be working just the same as before.
|
|||
Now that you have a static library project, you can start building your unittest
|
||||
dll. Start by creating a new directory for your unittest code, and creating a
|
||||
`.vcxproj` for a TAEF unittest dll. For the Terminal solution, we use the TAEF
|
||||
nuget package `Microsoft.Taef`.
|
||||
nuget package `Taef.Redist.Wlk`.
|
||||
|
||||
### Referencing your C++/WinRT static lib
|
||||
|
||||
|
@ -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.22000.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.18362.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.22000.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.18362.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>
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
# til::feature
|
||||
|
||||
Feature flags are controlled by an XML document stored at `src/features.xml`.
|
||||
|
||||
## Example Document
|
||||
|
||||
```xml
|
||||
<?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) -->
|
||||
<name>Feature_XYZ</name>
|
||||
|
||||
<description>Does a cool thing</description>
|
||||
|
||||
<!-- GitHub deliverable number; optional -->
|
||||
<id>1234</id>
|
||||
|
||||
<!-- Whether the feature defaults to enabled or disabled -->
|
||||
<stage>AlwaysEnabled|AlwaysDisabled</stage>
|
||||
|
||||
<!-- Branch wildcards where the feature should be *DISABLED* -->
|
||||
<alwaysDisabledBranchTokens>
|
||||
<branchToken>branch/with/wildcard/*</branchToken>
|
||||
<!-- ... more branchTokens ... -->
|
||||
</alwaysDisabledBranchTokens>
|
||||
|
||||
<!-- Just like alwaysDisabledBranchTokens, but for *ENABLING* the feature. -->
|
||||
<alwaysEnabledBranchTokens>
|
||||
<branchToken>...</branchToken>
|
||||
</alwaysEnabledBranchTokens>
|
||||
|
||||
<!-- Brandings where the feature should be *DISABLED* -->
|
||||
<alwaysDisabledBrandingTokens>
|
||||
<!-- Valid brandings include Dev, Preview, Release, WindowsInbox -->
|
||||
<brandingToken>Release</brandingToken>
|
||||
<!-- ... more brandingTokens ... -->
|
||||
</alwaysDisabledBrandingTokens>
|
||||
|
||||
<!-- Just like alwaysDisabledBrandingTokens, but for *ENABLING* the feature -->
|
||||
<alwaysEnabledBrandingTokens>
|
||||
<branchToken>...</branchToken>
|
||||
</alwaysEnabledBrandingTokens>
|
||||
|
||||
<!-- Unequivocally disable this feature in Release -->
|
||||
<alwaysDisabledReleaseTokens />
|
||||
</feature>
|
||||
</featureStaging>
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
Features that are disabled for Release using `alwaysDisabledReleaseTokens` are
|
||||
*always* disabled in Release, even if they come from a branch that would have
|
||||
been enabled by the wildcard.
|
||||
|
||||
### Precedence
|
||||
|
||||
1. `alwaysDisabledReleaseTokens`
|
||||
2. Enabled branches
|
||||
3. Disabled branches
|
||||
* The longest branch token that matches your branch will win.
|
||||
3. Enabled brandings
|
||||
4. Disabled brandings
|
||||
5. The feature's default state
|
|
@ -9,7 +9,7 @@ issue id: #1043
|
|||
|
||||
## Abstract
|
||||
|
||||
This spec is for task #1043 “Be able to set an initial position for the terminal”. It goes over the details of a new feature that allows users to set the initial position and size of the terminal. Expected behavior and design of this feature is included. Besides, future possible follow-up works are also addressed.
|
||||
This spec is for task #1043 “Be able to set an initial position for the terminal”. It goes over the details of a new feature that allows users to set the initial position and size of the terminal. Expected behavior and design of this feature is included. Besides, future possible follow-up works are also addressed.
|
||||
|
||||
## Inspiration
|
||||
|
||||
|
@ -17,7 +17,7 @@ The idea is to allow users to set the initial position of the Terminal when they
|
|||
|
||||
## Solution Design
|
||||
|
||||
For now, the Terminal window is put on a default initial position. The program uses CW_USEDEFAULT in the screen coordinates for top-left corner. We have two different types of window – client window and non-client window. However, code path for window creation (WM_CREATE message is shared by the two types of windows) are almost the same for the two types of windows, except that there are some differences in calculation of the width and height of the window.
|
||||
For now, the Terminal window is put on a default initial position. The program uses CW_USEDEFAULT in the screen coordinates for top-left corner. We have two different types of window – client window and non-client window. However, code path for window creation (WM_CREATE message is shared by the two types of windows) are almost the same for the two types of windows, except that there are some differences in calculation of the width and height of the window.
|
||||
|
||||
Two new properties should be added in the json settings file:
|
||||
|
||||
|
@ -92,9 +92,9 @@ For now, this feature only allows the user to set initial position and choose wh
|
|||
|
||||
3. We may also consider more launch modes. Like full screen mode and minimized mode.
|
||||
|
||||
GitHub issue for future follow-ups: https://github.com/microsoft/terminal/issues/766
|
||||
Github issue for future follow-ups: https://github.com/microsoft/terminal/issues/766
|
||||
|
||||
## Resources
|
||||
|
||||
GitHub issue:
|
||||
Github issue:
|
||||
https://github.com/microsoft/terminal/issues/1043
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
---
|
||||
author: Pankaj Bhojwani, pabhojwa@microsoft.com
|
||||
created on: 2021-6-17
|
||||
last updated: 2021-6-23
|
||||
issue id: #1790
|
||||
---
|
||||
|
||||
# Font features and axes of variation
|
||||
|
||||
## Abstract
|
||||
|
||||
This spec outlines how we can allow users to specify font features and axes of variation for fonts in Windows Terminal. Font features include things like being able to specify whether ligatures should be used as well as the specific stylistic set used for a font. Axes of variation commonly include things like weight and slant but can also include fancier things like shadow distance, depending on the font.
|
||||
|
||||
## Inspiration
|
||||
|
||||
Reference: [#1790](https://github.com/microsoft/terminal/issues/1790)
|
||||
|
||||
Currently, if a font has ligatures, we offer no way for a user to disable them. Many users would like the option to do so, and would also like the ability to choose stylistic sets for fonts - for example, at the time of this writing, Cascadia Code offers 4 stylistic sets but we offer no way for users to specify any of them.
|
||||
|
||||
In a similar vein, many fonts allow for setting variations on the font along certain attributes, commonly referred to as 'axes of variation'. We can offer users more font customization options by allowing them to configure these font variations.
|
||||
|
||||
## Solution Design
|
||||
|
||||
### Font features
|
||||
|
||||
It is already possible to pass in a list of [font feature structs](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature) to DWrite for it to handle. A font feature struct contains only 2 things:
|
||||
|
||||
1. A font feature tag
|
||||
2. A parameter value
|
||||
|
||||
A font feature tag is constructed using a 4-character feature tag and the parameter value defines how the feature is applied. For most features, the parameter value is simply treated as a binary value - a value of 0 means the feature is not applied and a non-zero value means the feature is applied. For example, a font feature struct like {'ss03', 1} enables stylistic set 3 for the font and a font feature struct like {'liga', 0} disables ligatures. (Technically, the feature tag is _constructed_ with the 4-character tag and is not the 4-character tag itself, but they are treated the same in the example here for brevity's sake).
|
||||
|
||||
Currently, we pass in to DWrite a null value for the list of features to apply to the font. This causes DWrite to automatically apply a ['standard' list](https://github.com/fdwr/TextLayoutSampler/blob/master/DrawableObject.ixx#L802) of font features to the font. Naturally, passing in our own list of font features to DWrite means DWrite will _only_ apply the features we defined, and no longer apply the standard list. Since the standard list contains 11 features, we need to consider how we can allow users to specify 1 additional feature or delete 1 of the standard features without needing to redefine all the others.
|
||||
|
||||
We will do this by allowing users to define a dictionary in their settings.json file, where the keys are the 4-character feature tags and the values are the parameter values. This dictionary will then get applied to our internal dictionary (which will contain the standard list of 11 features with their parameter values), meaning that any new key-value pairs will get added to our dictionary and any existing key-value pairs will get updated. Finally, this 'merged' dictionary will be what we use to construct the list of features to pass into DWrite.
|
||||
|
||||
### Axes of variation
|
||||
|
||||
Specifying axes of variation is done in an extremely similar manner to the way font features are specified - a 4-character tag is used to specify which font axis is being modified and a numerical value is provided to specify the value the axis should be set to. For example, {'slnt', 20} specifies that the 'slant' axis should be set to 20.
|
||||
|
||||
There is also a standard list of axes of variation, and each axis has its own default. We will approach this the same way we approached font features, by allowing users to specify additional features or omit features without needing to redefine the defaults.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
Users will be able to add a new setting to their font objects (added in [#10433](https://github.com/microsoft/terminal/pull/10433)). The resultant font object may look something like this
|
||||
|
||||
```json
|
||||
"font": {
|
||||
"face": "Cascadia Code",
|
||||
"size": 12,
|
||||
"features": {
|
||||
"ss03": 1,
|
||||
"liga": 0
|
||||
},
|
||||
"axes": {
|
||||
"slnt": 20.5
|
||||
}
|
||||
}
|
||||
```
|
||||
There is one point to note here about clashing. For example, if a user has the old "weight" setting defined _as well as_ a "wght" axis defined, we will only use the "wght" axis value. We prioritize that value for a few reasons:
|
||||
|
||||
1. It is the more recent addition to our settings model. Thus, it is likely that a user that has defined both values probably just forgot to remove the old value.
|
||||
2. It is the more precise value, it is a specific float value whereas the the old "weight" setting is an enum (that eventually gets mapped to a float value).
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Accessibility
|
||||
|
||||
Should not affect accessibility.
|
||||
|
||||
### Security
|
||||
|
||||
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/non-existant 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
|
||||
|
||||
Older versions of Windows may not have the DWrite updates that allow for defining font features and axes of variation. We must make sure to fallback to the current implementation in these cases.
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
Currently when rendering a run of text, if we detect that the given run is simple we will use a shortcut to obtain the glyphs needed, skipping over an expensive `GetGlyphs` call to DWrite. However, when the default feature list is changed in any way (either by adding a new feature or removing one of the defaults), there is no way for us to detect beforehand how the font glyphs would change.
|
||||
|
||||
This means that as long as the user requests a change to the default font feature list, we will _always_ skip the shortcut and call the expensive `GetGlyphs` function for every run of text.
|
||||
|
||||
This will naturally cause a performance cost that we will have to bear for this feature. However, it is worth noting that there are a fair number of glyphs that will cause a run of text to be deemed "not simple" (and thus cause us to call `GetGlyphs` anyway), for example when using Cascadia Code, any run of text that has the letters 'i', 'j', 'l', 'n', 'w' or 'x' is not considered simple (because those glyphs have localized variants).
|
||||
|
||||
## Potential Issues
|
||||
|
||||
See performance issues above.
|
||||
|
||||
## Future considerations
|
||||
|
||||
DWrite additionally offers the ability to vary the font features across runs of text. However, for our initial implementation of this feature, we will only apply font features to the entire buffer. If/when we decide to allow specifying font features for particular runs of text, we can lean into our existing mechanisms of splitting up runs of text to implement that.
|
||||
|
||||
We will also need to consider how we want to represent this in the settings UI. This is slightly more complex than other settings since users should be allowed to manually input 4-character tags.
|
||||
|
||||
## Resources
|
||||
|
||||
[DWRITE_FONT_FEATURE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature)
|
||||
|
||||
[DWRITE_FONT_AXIS_VALUE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite_3/ns-dwrite_3-dwrite_font_axis_value)
|
|
@ -1,619 +0,0 @@
|
|||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2020-11-20
|
||||
last updated: 2021-08-17
|
||||
issue id: #1032
|
||||
---
|
||||
|
||||
# Elevation Quality of Life Improvements
|
||||
|
||||
## Abstract
|
||||
|
||||
For a long time, we've been researching adding support to the Windows Terminal
|
||||
for running both unelevated and elevated (admin) tabs side-by-side, in the same
|
||||
window. However, after much research, we've determined that there isn't a safe
|
||||
way to do this without opening the Terminal up as a potential
|
||||
escalation-of-privilege vector.
|
||||
|
||||
Instead, we'll be adding a number of features to the Terminal to improve the
|
||||
user experience of working in elevated scenarios. These improvements include:
|
||||
|
||||
* A visible indicator that the Terminal window is elevated ([#1939])
|
||||
* Configuring the Terminal to always run elevated ([#632])
|
||||
* Configuring a specific profile to always open elevated ([#632])
|
||||
* Allowing new tabs, panes to be opened elevated directly from an unelevated
|
||||
window
|
||||
* Dynamic profile appearance that changes depending on if the Terminal is
|
||||
elevated or not. ([#1939], [#8311])
|
||||
|
||||
## Background
|
||||
|
||||
_This section was originally authored in the [Process Model 2.0 Spec]. Please
|
||||
refer to it there for its original context._
|
||||
|
||||
Let's presume that you're a user who wants to be able to open an elevated tab
|
||||
within an otherwise unelevated Terminal window. We call this scenario "mixed
|
||||
elevation" - the tabs within the Terminal can be running either unelevated _or_
|
||||
elevated client applications.
|
||||
|
||||
It wouldn't be terribly difficult for the unelevated Terminal to request the
|
||||
permission of the user to spawn an elevated client application. The user would
|
||||
see a UAC prompt, they'd accept, and then they'd be able to have an elevated
|
||||
shell alongside their unelevated tabs.
|
||||
|
||||
However, this creates an escalation of privilege vector. Now, there's an
|
||||
unelevated window which is connected directly to an elevated process. At this
|
||||
point, **any other unelevated application could send input to the Terminal's
|
||||
`HWND`**. This would make it possible for another unelevated process to "drive"
|
||||
the Terminal window, and send commands to the elevated client application.
|
||||
|
||||
It was initially theorized that the window/content model architecture would also
|
||||
help enable "mixed elevation". With mixed elevation, tabs could run at different
|
||||
integrity levels within the same terminal window. However, after investigation
|
||||
and research, it has become apparent that this scenario is not possible to do
|
||||
safely after all. There are numerous technical difficulties involved, and each
|
||||
with their own security risks. At the end of the day, the team wouldn't be
|
||||
comfortable shipping a mixed-elevation solution, because there's simply no way
|
||||
for us to be confident that we haven't introduced an escalation-of-privilege
|
||||
vector utilizing the Terminal. No matter how small the attack surface might be,
|
||||
we wouldn't be confident that there are _no_ vectors for an attack.
|
||||
|
||||
Some things we considered during this investigation:
|
||||
|
||||
* If a user requests a new elevated tab from an otherwise unelevated window, we
|
||||
could use UAC to create a new, elevated window process, and "move" all the
|
||||
current tabs to that window process, as well as the new elevated client. Now,
|
||||
the window process would be elevated, preventing it from input injection, and
|
||||
it would still contains all the previously existing tabs. The original window
|
||||
process could now be discarded, as the new elevated window process will
|
||||
pretend to be the original window.
|
||||
- However, it is unfortunately not possible with COM to have an elevated
|
||||
client attach to an unelevated server that's registered at runtime. Even in
|
||||
a packaged environment, the OS will reject the attempt to `CoCreateInstance`
|
||||
the content process object. this will prevent elevated windows from
|
||||
re-connecting to unelevated client processes.
|
||||
- We could theoretically build an RPC tunnel between content and window
|
||||
processes, and use the RPC connection to marshal the content process to the
|
||||
elevated window. However, then _we_ would need to be responsible for
|
||||
securing access the the RPC endpoint, and we feel even less confident doing
|
||||
that.
|
||||
- Attempts were also made to use a window-broker-content architecture, with
|
||||
the broker process having a static CLSID in the registry, and having the
|
||||
window and content processes at mixed elevation levels `CoCreateInstance`
|
||||
that broker. This however _also_ did not work across elevation levels. This
|
||||
may be due to a lack of Packaged COM support for mixed elevation levels.
|
||||
|
||||
It's also possible that the author forgot that packaged WinRT doesn't play
|
||||
nicely with creating objects in an elevated context. The Terminal has
|
||||
previously needed to manually manifest all its classes in a SxS manifest for
|
||||
Unpackaged WinRT to allow the classes to be activated, rather than relying
|
||||
on the packaged catalog. It's theoretically possible that doing that would
|
||||
have allowed the broker to be activated across integrity levels.
|
||||
|
||||
Even if this approach did end up working, we would still need to be
|
||||
responsible for securing the elevated windows so that an unelevated attacker
|
||||
couldn't hijack a content process and trigger unexpected code in the window
|
||||
process. We didn't feel confident that we could properly secure this channel
|
||||
either.
|
||||
|
||||
We also considered allowing mixed content in windows that were _originally_
|
||||
elevated. If the window is already elevated, then it can launch new unelevated
|
||||
processes. We could allow elevated windows to still create unelevated
|
||||
connections. However, we'd want to indicate per-pane what the elevation state
|
||||
of each connection is. The user would then need to keep track themselves of
|
||||
which terminal instances are elevated, and which are not.
|
||||
|
||||
This also marks a departure from the current behavior, where everything in an
|
||||
elevated window would be elevated by default. The user would need to specify for
|
||||
each thing in the elevated window that they'd want to create it elevated. Or the
|
||||
Terminal would need to provide some setting like
|
||||
`"autoElevateEverythingInAnElevatedWindow"`.
|
||||
|
||||
We cannot support mixed elevation when starting in a unelevated window.
|
||||
Therefore, it doesn't make a lot of UX sense to support it in the other
|
||||
direction. It's a cleaner UX story to just have everything in a single window at
|
||||
the same elevation level.
|
||||
|
||||
## Solution Design
|
||||
|
||||
Instead of supporting mixed elevation in the same window, we'll introduce the
|
||||
following features to the Terminal. These are meant as a way of improving the
|
||||
quality of life for users who work in mixed-elevation (or even just elevated)
|
||||
environments.
|
||||
|
||||
### Visible indicator for elevated windows
|
||||
|
||||
As requested in [#1939], it would be nice if it was easy to visibly identify if
|
||||
a Terminal window was elevated or not.
|
||||
|
||||
One easy way of doing this is by adding a simple UAC shield to the left of the
|
||||
tabs for elevated windows. This shield could be configured by the theme (see
|
||||
[#3327]). We could provide the following states:
|
||||
* Colored (the default)
|
||||
* Monochrome
|
||||
* Hidden, to hide the shield even on elevated windows. This is the current
|
||||
behavior.
|
||||
|
||||
![UAC-shield-in-titlebar](UAC-shield-in-titlebar.png)
|
||||
_figure 1: a monochrome UAC shield in the titlebar of the window, courtesy of @mdtauk_
|
||||
|
||||
We could also simplify this to only allow a boolean true/false for displaying
|
||||
the shield. As we do often with other enums, we could define `true` to be the
|
||||
same as the default appearance, and `false` to be the hidden option. As always,
|
||||
the development of the Terminal is an iterative process, where we can
|
||||
incrementally improve from no setting, to a boolean setting, to a enum-backed
|
||||
one.
|
||||
|
||||
### Configuring a profile to always run elevated
|
||||
|
||||
Oftentimes, users might have a particular tool chain that only works when
|
||||
running elevated. In these scenarios, it would be convenient for the user to be
|
||||
able to identify that the profile should _always_ run elevated. That way, they
|
||||
could open the profile from the dropdown menu of an otherwise unelevated window
|
||||
and have the elevated window open with the profile automatically.
|
||||
|
||||
We'll be adding the `"elevate": true|false` setting as a per-profile setting,
|
||||
with a default value of `false`. When set to `true`, we'll try to auto-elevate
|
||||
the profile whenever it's launched. We'll check to see if this window is
|
||||
elevated before creating the connection for this profile. If the window is not
|
||||
elevated, then we'll create a new window with the requested elevation level to
|
||||
handle the new connection.
|
||||
|
||||
`"elevate": false` will do nothing. If the window is already elevated, then the
|
||||
profile won't open an un-elevated window.
|
||||
|
||||
If the user tries to open an `"elevate": true` profile in a window that's
|
||||
already elevated, then a new tab/split will open in the existing window, rather
|
||||
than spawning an additional elevated window.
|
||||
|
||||
There are three situations where we're creating new terminal instances: new
|
||||
tabs, new splits, and new windows. Currently, these are all actions that are
|
||||
also exposed in the `wt` commandline as subcommands. We can convert from the
|
||||
commandline arguments into these actions already. Therefore, it shouldn't be too
|
||||
challenging to convert these actions back into the equal commandline arguments.
|
||||
|
||||
For the following examples, let's assume the user is currently in an unelevated
|
||||
Terminal window.
|
||||
|
||||
When the user tries to create a new elevated **tab**, we'll need to create a new
|
||||
process, elevated, with the following commandline:
|
||||
|
||||
```
|
||||
wt new-tab [args...]
|
||||
```
|
||||
|
||||
When we create this new `wt` instance, it will obey the glomming rules as
|
||||
specified in [Session Management Spec]. It might end up glomming to another
|
||||
existing window at that elevation level, or possibly create its own window.
|
||||
|
||||
Similarly, for a new elevated **window**, we can make sure to pass the `-w new`
|
||||
arguments to `wt`. These parameters indicate that we definitely want this
|
||||
command to run in a new window, regardless of the current glomming settings.
|
||||
|
||||
```
|
||||
wt -w new new-tab [args...]
|
||||
```
|
||||
|
||||
However, creating a new **pane** is a little trickier. Invoking the `wt
|
||||
split-pane [args...]` is straightforward enough.
|
||||
|
||||
<!-- Discussion notes follow:
|
||||
If the current window doesn't have the same elevation level as the
|
||||
requested profile, do we always want to just create a new split? If the command
|
||||
ends up glomming to an existing window, does that even make sense? That invoking
|
||||
an elevated split in an unelevated window would end up splitting the elevated
|
||||
window? It's very possible that the user wanted a split in the tab they're
|
||||
currently in, in the unelevated window, but they don't want a split in the
|
||||
elevated window.
|
||||
|
||||
What if there's not space in the elevated window to create the split (but there
|
||||
would be in the current window)? That would sure make it seem like nothing
|
||||
happened, silently.
|
||||
|
||||
We could alternatively have cross-elevation splits default to always opening a
|
||||
new tab. That might mitigate some of the odd behaviors. Until we actually have
|
||||
support for running commands in existing windows, we'll always need to make a
|
||||
new window when running elevated. We'll need to make the new window for new tabs
|
||||
and splits, because there's no way to invoke another existing window.
|
||||
|
||||
A third proposal is to pop a warning dialog at the user when they try to open an
|
||||
elevated split from and unelevated window. This dialog could be something like
|
||||
|
||||
> What you requested couldn't be completed. Do you want to:
|
||||
> A. Make me a new tab instead.
|
||||
> B. Forget it and cancel. I'll go fix my config.
|
||||
|
||||
I'm certainly leaning towards proposal 2 - always create a new tab. This is how
|
||||
it's implemented in [#8514]. In that PR, this seems to work sensibly.
|
||||
-->
|
||||
|
||||
After discussing with the team, we have decided that the most sensible approach
|
||||
for handling a cross-elevation `split-pane` is to just create a new tab in the
|
||||
elevated window. The user can always re-attach the pane as a split with the
|
||||
`move-pane` command once the new pane in the elevated window.
|
||||
|
||||
#### Configure the Terminal to _always_ run elevated
|
||||
|
||||
`elevate` is a per-profile property, not a global property. If a user
|
||||
wants to always have all instances of the Terminal run elevated, they
|
||||
could set `"elevate": true` in their profile defaults. That would cause _all_
|
||||
profiles they launch to always spawn as elevated windows.
|
||||
|
||||
#### `elevate` in Actions
|
||||
|
||||
Additionally, we'll add the `elevate` property to the `NewTerminalArgs` used in
|
||||
the `newTab`, `splitPane`, and `newWindow` actions. This is similar to how other
|
||||
properties of profiles can be overridden at launch time. This will allow
|
||||
windows, tabs and panes to all be created specifically as elevated windows.
|
||||
|
||||
In the `NewTerminalArgs`, `elevate` will be an optional boolean, with the
|
||||
following behavior:
|
||||
* `null` (_default_): Don't modify the `elevate` property for this profile
|
||||
* `true`: This launch should act like the profile had `"elevate": true` in its
|
||||
properties.
|
||||
* `false`: This launch should act like the profile had `"elevate": false` in its
|
||||
properties.
|
||||
|
||||
We'll also add an iterable command for opening a profile in an
|
||||
elevated tab, with the following json:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
// New elevated tab...
|
||||
"name": { "key": "NewElevatedTabParentCommandName", "icon": "UAC-Shield.png" },
|
||||
"commands": [
|
||||
{
|
||||
"iterateOn": "profiles",
|
||||
"icon": "${profile.icon}",
|
||||
"name": "${profile.name}",
|
||||
"command": { "action": "newTab", "profile": "${profile.name}", "elevated": true }
|
||||
}
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
#### Elevation from the dropdown
|
||||
|
||||
Currently, the new tab dropdown supports opening a new pane by
|
||||
<kbd>Alt+click</kbd>ing on a profile. We could similarly add support to open a
|
||||
tab elevated with <kbd>Ctrl+click</kbd>. This is similar to the behavior of the
|
||||
Windows taskbar. It supports creating an elevated instance of a program by
|
||||
<kbd>Ctrl+click</kbd>ing on entries as well.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Starting an elevated process from an unelevated process
|
||||
|
||||
It seems that we're able to create an elevated process by passing the `"runas"`
|
||||
verb to
|
||||
[`ShellExecute`](https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutea).
|
||||
So we could use something like
|
||||
|
||||
```c++
|
||||
ShellExecute(nullptr,
|
||||
L"runas",
|
||||
L"wt.exe",
|
||||
L"-w new new-tab [args...]",
|
||||
nullptr,
|
||||
SW_SHOWNORMAL);
|
||||
```
|
||||
|
||||
This will ask the shell to perform a UAC prompt before spawning `wt.exe` as an
|
||||
elevated process.
|
||||
|
||||
> 👉 NOTE: This mechanism won't always work on non-Desktop SKUs of Windows. For
|
||||
> more discussion, see [Elevation on OneCore SKUs](#Elevation-on-OneCore-SKUs).
|
||||
|
||||
## Potential Issues
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><strong>Accessibility</strong></td>
|
||||
<td>
|
||||
|
||||
The set of changes proposed here are not expected to introduce any new
|
||||
accessibility issues. Users can already create elevated Terminal windows. Making
|
||||
it easier to create these windows doesn't really change our accessibility story.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Security</strong></td>
|
||||
<td>
|
||||
|
||||
We won't be doing anything especially unique, so there aren't expected to be any
|
||||
substantial security risks associated with these changes. Users can already
|
||||
create elevated Terminal windows, so we're not really introducing any new
|
||||
functionality, from a security perspective.
|
||||
|
||||
We're relying on the inherent security of the `runas` verb of `ShellExecute` to
|
||||
prevent any sort of unexpected escalation-of-privilege.
|
||||
|
||||
<hr>
|
||||
|
||||
One security concern is the fact that the `settings.json` file is currently a
|
||||
totally unsecured file. It's completely writable by any medium-IL process. That
|
||||
means it's totally possible for a malicious program to change the file. The
|
||||
malicious program could find a user's "Elevated PowerShell" profile, and change
|
||||
the commandline to `malicious.exe`. The user might then think that their
|
||||
"Elevated PowerShell" will run `powershell.exe` elevated, but will actually
|
||||
auto-elevate this attacker.
|
||||
|
||||
If all we expose to the user is the name of the profile in the UAC dialog, then
|
||||
there's no way for the user to be sure that the program that's about to be
|
||||
launched is actually what they expect.
|
||||
|
||||
To help mitigate this, we should _always_ pass the evaluated `commandline` as a
|
||||
part of the call to `ShellExecute`. the arguments that are passed to
|
||||
`ShellExecute` are visible to the user, though they need to click the "More
|
||||
Details" dropdown to reveal them.
|
||||
|
||||
We will need to mitigate this vulnerability regardless of adding support for the
|
||||
auto-elevation of individual terminal tabs/panes. If a user is launching the
|
||||
Terminal elevated (i.e. from the Win+X menu in Windows 11), then it's possible
|
||||
for a malicious program to overwrite the `commandline` of their default profile.
|
||||
The user may now unknowingly invoke this malicious program while thinking they
|
||||
are simply launching the Terminal.
|
||||
|
||||
To deal with this more broadly, we will display a dialog within the Terminal
|
||||
window before creating **any** elevated terminal instance. In that dialog, we'll
|
||||
display the commandline that will be executed, so the user can very easily
|
||||
confirm the commandline.
|
||||
|
||||
This will need to happen for all elevated terminal instances. For an elevated
|
||||
Windows Terminal window, this means _all_ connections made by the Terminal.
|
||||
Every time the user opens a new profile or a new commandline in a pane, we'll
|
||||
need to prompt them first to confirm the commandline. This dialog within the
|
||||
elevated window will also prevent an attacker from editing the `settings.json`
|
||||
file while the user already has an elevated Terminal window open and hijacking a
|
||||
profile.
|
||||
|
||||
The dialog options will certainly be annoying to users who don't want to be
|
||||
taken out of their flow to confirm the commandline that they wish to launch.
|
||||
There's precedent for a similar warning being implemented by VSCode, with their
|
||||
[Workspace Trust] feature. They too faced a similar backlash when the feature
|
||||
first shipped. However, in light of recent global cybersecurity attacks, this is
|
||||
seen as an acceptable UX degradation in the name of application trust. We don't
|
||||
want to provide an avenue that's too easy to abuse.
|
||||
|
||||
When the user confirms the commandline of this profile as something safe to run,
|
||||
we'll add it to an elevated-only version of `state.json`. (see [#7972] for more
|
||||
details). This elevated version of the file will only be accessible by the
|
||||
elevated Terminal, so an attacker cannot hijack the contents of the file. This
|
||||
will help mitigate the UX discomfort caused by prompting on every commandline
|
||||
launched. This should mean that the discomfort is only limited to the first
|
||||
elevated launch of a particular profile. Subsequent launches (without modifying
|
||||
the `commandline`) will work as they always have.
|
||||
|
||||
The dialog for confirming these commandlines should have a link to the docs for
|
||||
"Learn more...". Transparency in the face of this dialog should
|
||||
mitigate some dissatisfaction.
|
||||
|
||||
The dialog will _not_ appear if the user does not have a split token - if the
|
||||
user's PC does not have UAC enabled, then they're _already_ running as an
|
||||
Administrator. Everything they do is elevated, so they shouldn't be prompted in
|
||||
this way.
|
||||
|
||||
The Settings UI should also expose a way of viewing and removing these cached
|
||||
entries. This page should only be populated in the elevated version of the
|
||||
Terminal.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Reliability</strong></td>
|
||||
<td>
|
||||
|
||||
No changes to our reliability are expected as a part of this change.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Compatibility</strong></td>
|
||||
<td>
|
||||
|
||||
There are no serious compatibility concerns expected with this changelist. The
|
||||
new `elevate` property will be unset by default, so users will heed to opt-in
|
||||
to the new auto-elevating behavior.
|
||||
|
||||
There is one minor concern regarding introducing the UAC shield on the window.
|
||||
We're planning on using themes to configure the appearance of the shield. That
|
||||
means we'll need to ship themes before the user will be able to hide the shield
|
||||
again.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Performance, Power, and Efficiency</strong></td>
|
||||
<td>
|
||||
|
||||
No changes to our performance are expected as a part of this change.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Centennial Applications
|
||||
|
||||
In the past, we've had a notoriously rough time with the Centennial app
|
||||
infrastructure and running the Terminal elevated. Notably, we've had to list all
|
||||
our WinRT classes in our SxS manifest so they could be activated using
|
||||
unpackaged WinRT while running elevated. Additionally, there are plenty of
|
||||
issues running the Terminal in an "over the shoulder" elevation (OTS) scenario.
|
||||
|
||||
Specifically, we're concerned with the following scenario:
|
||||
* the current user account has the Terminal installed,
|
||||
* but they aren't an Administrator,
|
||||
* the Administrator account doesn't have the Terminal installed.
|
||||
|
||||
In that scenario, the user can run into issues launching the Terminal in an
|
||||
elevated context (even after entering the Admin's credentials in the UAC
|
||||
prompt).
|
||||
|
||||
This spec proposes no new mitigations for dealing with these issues. It may in
|
||||
fact make them more prevalent, by making elevated contexts more easily
|
||||
accessible.
|
||||
|
||||
Unfortunately, these issues are OS bugs that are largely out of our own control.
|
||||
We will continue to apply pressure to the centennial app team internally as we
|
||||
encounter these issues. They are are team best equipped to resolve these issues.
|
||||
|
||||
### Default Terminal & auto-elevation
|
||||
|
||||
In the future, when we support setting the Terminal as the "default terminal
|
||||
emulator" on Windows. When that lands, we will use the `profiles.defaults`
|
||||
settings to create the tab where we'll be hosting the commandline client. If the user has
|
||||
`"elevate": true` in their `profiles.defaults`, we'd usually try to
|
||||
auto-elevate the profile. In this scenario, however, we can't do that. The
|
||||
Terminal is being invoked on behalf of the client app launching, instead of the
|
||||
Terminal invoking the client application.
|
||||
|
||||
**2021-08-17 edit**: Now that "defterm" has shipped, we're a little more aware
|
||||
of some of the limitations with packaged COM and elevation boundaries. Defterm
|
||||
cannot be used with elevated processes _at all_ currently (see [#10276]). When
|
||||
an elevated commandline application is launched, it will always just appear in
|
||||
`conhost.exe`. Furthermore, An unelevated peasant can't communicate with an
|
||||
elevated monarch so we can't toss the connection to the elevated monarch and
|
||||
have them handle it.
|
||||
|
||||
The simplest solution here is to just _always_ ignore the `elevate` property for
|
||||
incoming defterm connections. This is not an ideal solution, and one that we're
|
||||
willing to revisit if/when [#10276] is ever fixed.
|
||||
|
||||
### Elevation on OneCore SKUs
|
||||
|
||||
This spec proposes using `ShellExecute` to elevate the Terminal window. However,
|
||||
not all Windows SKUs have support for `ShellExecute`. Notably, the non-Desktop
|
||||
SKUs, which are often referred to as "OneCore" SKUs. On these platforms, we
|
||||
won't be able to use `ShellExecute` to elevate the Terminal. There might not
|
||||
even be the concept of multiple elevation levels, or different users, depending
|
||||
on the SKU.
|
||||
|
||||
Fortunately, this is a mostly hypothetical concern for the moment. Desktop is
|
||||
the only publicly supported SKU for the Terminal currently. If the Terminal ever
|
||||
does become available on those SKUs, we can use these proposals as mitigations.
|
||||
|
||||
* If elevation is supported, there must be some other way of elevating a
|
||||
process. We could always use that mechanism instead.
|
||||
* If elevation isn't supported (I'm thinking 10X is one of these), then we could
|
||||
instead display a warning dialog whenever a user tries to open an elevated
|
||||
profile.
|
||||
- We could take the warning a step further. We could add another settings
|
||||
validation step. This would warn the user if they try to mark any profiles
|
||||
or actions as `"elevate":true`
|
||||
|
||||
## Future considerations
|
||||
|
||||
* If we wanted to go even further down the visual differentiation route, we
|
||||
could consider allowing the user to set an entirely different theme ([#3327])
|
||||
based on the elevation state. Something like `elevatedTheme`, to pick another
|
||||
theme from the set of themes. This would allow them to force elevated windows
|
||||
to have a red titlebar, for example.
|
||||
* Over the course of discussion concerning appearance objects ([#8345]), it
|
||||
became clear that having separate "elevated" appearances defined for
|
||||
`profile`s was overly complicated. This is left as a consideration for a
|
||||
possible future extension that could handle this scenario in a cleaner way.
|
||||
* Similarly, we're going to leave [#3637] "different profiles when elevated vs
|
||||
unelevated" for the future. This also plays into the design of "configure the
|
||||
new tab dropdown" ([#1571]), and reconciling those two designs is out-of-scope
|
||||
for this particular release.
|
||||
* Tangentially, we may want to have a separate Terminal icon we ship with the
|
||||
UAC shield present on it. This would be especially useful for the tray icon.
|
||||
Since there will be different tray icon instances for elevated and unelevated
|
||||
windows, having unique icons may help users identify which is which.
|
||||
|
||||
### De-elevating a Terminal
|
||||
|
||||
the original version of this spec proposed that `"elevated":false` from an
|
||||
elevated Terminal window should create a new unelevated Terminal instance. The
|
||||
mechanism for doing this is described in [The Old New Thing: How can I launch an
|
||||
unelevated process from my elevated process, redux].
|
||||
|
||||
This works well when the Terminal is running unpackaged. However, de-elevating a
|
||||
process does not play well with packaged centennial applications. When asking
|
||||
the OS to run the packaged application from an elevated context, the system will
|
||||
still create the child process _elevated_. This means the packaged version of
|
||||
the Terminal won't be able to create a new unelevated Terminal instance.
|
||||
|
||||
From an internal mail thread:
|
||||
|
||||
> App model intercepts the `CreateProcess` call and redirects it to a COM
|
||||
> service. The parent of a packaged app is not the launching app, it’s some COM
|
||||
> service. So none of the parent process nonsense will work because the
|
||||
> parameters you passed to `CreateProcess` aren’t being used to create the
|
||||
> process.
|
||||
|
||||
If this is fixed in the future, we could theoretically re-introduce de-elevating
|
||||
a profile. The original spec proposed a `"elevated": bool?` setting, with the
|
||||
following behaviors:
|
||||
* `null` (_default_): Don't modify the elevation level when running this profile
|
||||
* `true`: If the current window is unelevated, try to create a new elevated
|
||||
window to host this connection.
|
||||
* `false`: If the current window is elevated, try to create a new unelevated
|
||||
window to host this connection.
|
||||
|
||||
We could always re-introduce this setting, to supercede `elevate`.
|
||||
|
||||
### Change profile appearance for elevated windows
|
||||
|
||||
In [#3062] and [#8345], we're planning on allowing users to set different
|
||||
appearances for a profile whether it's focused or not. We could do similar thing
|
||||
to enable a profile to have a different appearance when elevated. In the
|
||||
simplest case, this could allow the user to set `"background": "#ff0000"`. This
|
||||
would make a profile always appear to have a red background when in an elevated
|
||||
window.
|
||||
|
||||
The more specific details of this implementation are left to the spec
|
||||
[Configuration object for profiles].
|
||||
|
||||
In discussion of that spec, we decided that it would be far too complicated to
|
||||
try and overload the `unfocusedAppearance` machinery for differentiating between
|
||||
elevated and unelevated versions of the same profile. Already, that would lead
|
||||
to 4 states: [`appearance`, `unfocusedAppearance`, `elevatedAppearance`,
|
||||
`elevatedUnfocusedAppearance`]. This would lead to a combinatorial explosion if
|
||||
we decided in the future that there should also be other states for a profile.
|
||||
|
||||
This particular QoL improvement is currently being left as a future
|
||||
consideration, should someone come up with a clever way of defining
|
||||
elevated-specific settings.
|
||||
|
||||
<!--
|
||||
Brainstorming notes for future readers:
|
||||
|
||||
You could have a profile that layers on an existing profile, with elevated-specific settings:
|
||||
|
||||
{
|
||||
"name": "foo",
|
||||
"background": "#0000ff",
|
||||
"commandline": "cmd.exe /k echo I am unelevated"
|
||||
},
|
||||
{
|
||||
"inheritsFrom": "foo",
|
||||
"background": "#ff0000",
|
||||
"elevate": true,
|
||||
"commandline": "cmd.exe /k echo I am ELEVATED"
|
||||
}
|
||||
-->
|
||||
|
||||
<!-- Footnotes -->
|
||||
|
||||
[#632]: https://github.com/microsoft/terminal/issues/632
|
||||
[#1032]: https://github.com/microsoft/terminal/issues/1032
|
||||
[#1571]: https://github.com/microsoft/terminal/issues/1571
|
||||
[#1939]: https://github.com/microsoft/terminal/issues/1939
|
||||
[#3062]: https://github.com/microsoft/terminal/issues/3062
|
||||
[#3327]: https://github.com/microsoft/terminal/issues/3327
|
||||
[#3637]: https://github.com/microsoft/terminal/issues/3637
|
||||
[#4472]: https://github.com/microsoft/terminal/issues/4472
|
||||
[#5000]: https://github.com/microsoft/terminal/issues/5000
|
||||
[#7972]: https://github.com/microsoft/terminal/pull/7972
|
||||
[#8311]: https://github.com/microsoft/terminal/issues/8311
|
||||
[#8345]: https://github.com/microsoft/terminal/issues/8345
|
||||
[#8514]: https://github.com/microsoft/terminal/issues/8514
|
||||
[#10276]: https://github.com/microsoft/terminal/issues/10276
|
||||
|
||||
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0.md
|
||||
[Configuration object for profiles]: https://github.com/microsoft/terminal/blob/main/doc/specs/Configuration%20object%20for%20profiles.md
|
||||
[Session Management Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%234472%20-%20Windows%20Terminal%20Session%20Management.md
|
||||
[The Old New Thing: How can I launch an unelevated process from my elevated process, redux]: https://devblogs.microsoft.com/oldnewthing/20190425-00/?p=102443
|
||||
[Workspace Trust]: https://code.visualstudio.com/docs/editor/workspace-trust
|
Before Width: | Height: | Size: 565 KiB |
|
@ -123,4 +123,4 @@ This open issue tracks the phase features of Search: https://github.com/microsof
|
|||
|
||||
## Resources
|
||||
|
||||
GitHub Issue: https://github.com/microsoft/terminal/issues/605
|
||||
Github Issue: https://github.com/microsoft/terminal/issues/605
|
||||
|
|
|
@ -1,736 +0,0 @@
|
|||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2021-02-23
|
||||
last updated: 2021-05-13
|
||||
issue id: #653
|
||||
---
|
||||
|
||||
# Quake Mode
|
||||
|
||||
## Abstract
|
||||
|
||||
Many existing terminals support a feature whereby a user can press a keybinding
|
||||
anywhere in the OS, and summon their terminal application. Oftentimes the act of
|
||||
summoning this window is accompanied by a "dropdown" animation, where the window
|
||||
slides in to view from the top of the screen. This global summon action is often
|
||||
referred to as "quake mode", a reference to the video game Quake, who's console
|
||||
slid in from the top.
|
||||
|
||||
This spec addresses both of the following two issues:
|
||||
* "Quake Mode" ([#653])
|
||||
* "Minimize to tray" ([#5727])
|
||||
|
||||
Readers should make sure to have read the [Process Model 2.0 Spec], for
|
||||
background on Monarch and Peasant processes.
|
||||
|
||||
## Background
|
||||
|
||||
### Inspiration
|
||||
|
||||
For an example of the original Quake console in action, take a look at the
|
||||
following video (noisy video warning): [Quake 3 sample]. Additionally, plenty of
|
||||
existing terminal emulators support similar functionality:
|
||||
|
||||
* **Tilda** allows the user to specify different keys to summon the window on
|
||||
different monitors.
|
||||
* **Guake** alternatively allows the user to either summon the terminal window to
|
||||
a specific monitor, or whichever monitor the mouse is on. Guake only allows
|
||||
one single instance, so pressing the global hotkey always summons the same
|
||||
instance.
|
||||
|
||||
### User Stories
|
||||
|
||||
The original quake mode thread (#653) is absolutely _filled_ with variations on
|
||||
how users want to be able to summon their terminal windows. These include, but
|
||||
are not limited to:
|
||||
|
||||
* **Story A** Press a hotkey anywhere to activate the single Terminal window
|
||||
wherever it was
|
||||
* **Story B** Press a hotkey anywhere to activate the single Terminal window _on
|
||||
the current monitor_. If it wasn't previously on that monitor, move it there.
|
||||
* **Story C** When the Terminal is summoned using the hotkey, have it "slide in"
|
||||
from the top. Similarly, slide out on deactivate.
|
||||
* **Story D** <kbd>Ctrl+1</kbd> to activate the terminal on monitor 1,
|
||||
<kbd>Ctrl+2</kbd> to activate the terminal on monitor 2.
|
||||
* **Story E** Variable dropdown speed
|
||||
* **Story F** Minimize to tray, press a hotkey to activate the terminal window
|
||||
(#5727)
|
||||
* **Story G** Terminal doesn't appear in alt+tab view, press a hotkey to
|
||||
activate the single terminal window / the nearest terminal window (I'm not
|
||||
sure this is distinct from the above)
|
||||
|
||||
## Solution Design
|
||||
|
||||
To implement this feature, we'll add the following settings:
|
||||
* a new action, named `globalSummon`.
|
||||
* a new global, app setting named `minimizeToTray`
|
||||
* a new global, app setting named `alwaysShowTrayIcon`
|
||||
* a new action, named `quakeMode`, and a specially named `_quake` window.
|
||||
|
||||
### `globalSummon` Action
|
||||
|
||||
The `globalSummon` action will be a keybinding the user can use to summon a
|
||||
Terminal window from anywhere in the OS. Various arguments to the action will
|
||||
specify which window is summoned, to where, and how the window should behave on
|
||||
summon.
|
||||
|
||||
From a technical perspective, the action will work by using the
|
||||
[`RegisterHotKey`] function. This API allows us to bind a particular hotkey with
|
||||
the OS. Whenever that hotkey is pressed, our window message loop will receive a
|
||||
`WM_HOTKEY`. We'll use the payload of that window message to lookup the action
|
||||
arguments for that hotkey. Then we'll use those arguments to control which
|
||||
window is invoked, where, and how the window behaves.
|
||||
|
||||
Since `RegisterHotKey` can only be used to register a hotkey _once_ with the OS,
|
||||
we'll need to make sure it's only ever set up by the Monarch process. We know
|
||||
that there will only ever be one Monarch for the Terminal at a time, so it's the
|
||||
perfect process to have the responsibility of managing the global hotkey.
|
||||
|
||||
The Monarch will be responsible for calling `RegisterHotKey`, and processing the
|
||||
`WM_HOTKEY` messages. It will then dispatch method calls to the appropriate
|
||||
window to summon it. When a Monarch dies and a new process becomes the Monarch,
|
||||
the new Monarch will re-register for the hotkeys.
|
||||
|
||||
#### Where in the settings?
|
||||
|
||||
Since users may want to bind multiple keys to summon different windows, we'll
|
||||
need to allow the user to specify multiple keybindings simultaneously, each with
|
||||
their own set of args.
|
||||
|
||||
We stick all the `globalSummon`s in the actions array, like they're any other
|
||||
keybinding.
|
||||
|
||||
However, these are not keys that are handled by the TerminalApp layer itself.
|
||||
These are keys that need to be registered with the OS. So while they will be in
|
||||
the normal `KeyMap`, they will need to be retrieved from that object and
|
||||
manually passed to the window layer.
|
||||
|
||||
> A previous iteration of this spec considered placing the `globalSummon`
|
||||
> actions in their own top-level array of the settings file, separate from the
|
||||
> keybindings. This is no longer being considered, because it would not work for
|
||||
> the case where the user has something like:
|
||||
> ```json
|
||||
> { "keys": "ctrl+c", "command": { "action": "globalSummon", "monitor": 1 } },
|
||||
> { "keys": "ctrl+v", "command": { "action": "copy" } },
|
||||
> ```
|
||||
|
||||
#### Which window, and where?
|
||||
|
||||
When looking at the list of requested scenarios, there are lots of different
|
||||
ways people would like to use the global summon action. Some want the most
|
||||
recent window activated, always. Others want to have one window _per monitor_.
|
||||
Some would like to move the window to where the user is currently interacting
|
||||
with the PC, and others want to activate the window where it already exists.
|
||||
Trying to properly express all these possible configurations is complex. The
|
||||
settings should be unambiguous as to what will happen when you press the
|
||||
keybinding.
|
||||
|
||||
I believe that in order to accurately support all the variations that people
|
||||
might want, we'll need two properties in the `globalSummon` action. These
|
||||
properties will specify _which_ window we're summoning, and _where_ to summon
|
||||
the window. To try and satisfy all these scenarios, I'm proposing the following
|
||||
two arguments to the `globalSummon` action:
|
||||
|
||||
```json
|
||||
"monitor": "any"|"toCurrent"|"toMouse"|"onCurrent"|int,
|
||||
"desktop": "any"|"toCurrent"|"onCurrent"
|
||||
```
|
||||
|
||||
The way these settings can be combined is in a table below. As an overview:
|
||||
|
||||
* `monitor`: This controls the monitor that the window will be summoned from/to
|
||||
- `"any"`: Summon the MRU window, regardless of which monitor it's currently
|
||||
on.
|
||||
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor
|
||||
with the current **foreground** window.
|
||||
- `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse**
|
||||
cursor is.
|
||||
- `"onCurrent"`: Summon the MRU window **ALREADY ON** the current monitor.
|
||||
- `int`: Summon the MRU window for the given monitor (as identified by the
|
||||
"Identify" displays feature in the OS settings)
|
||||
|
||||
* `desktop`: This controls how the terminal should interact with virtual desktops.
|
||||
- `"any"`: Leave the window on whatever desktop it's already on - we'll switch
|
||||
to that desktop as we activate the window.
|
||||
- > NOTE: A previous version of this spec had this enum value as `null`.
|
||||
This was changed to `"any"` for parity with the `monitor` property.
|
||||
- `"toCurrent"`/omitted: (_default_): Move the window **to** the current
|
||||
virtual desktop
|
||||
- `"onCurrent"`: Only summon the window if it's **already on** the current
|
||||
virtual desktop
|
||||
|
||||
Neither `desktop` nor `monitor` is a required parameter - if either is omitted,
|
||||
the omitted property will default to `toCurrent`.
|
||||
|
||||
Together, these settings interact in the following ways:
|
||||
|
||||
<!-- This table is formatted for viewing as rendered HTML. It's too complicated
|
||||
for pure markdown, sorry. -->
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
<th colspan=3><code>"desktop"</code></th>
|
||||
</tr>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
<tr>
|
||||
<th><code>"monitor"</code></th>
|
||||
<td><code>any</code><br><strong>Leave where it is</strong></td>
|
||||
<td><code>"toCurrent"</code><br><strong>Move to current desktop</strong></td>
|
||||
<td><code>"onCurrent"</code><br><strong>On current desktop only</strong></td>
|
||||
</tr>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
<tr>
|
||||
<td><code>"any"</code><br> Summon the MRU window</td>
|
||||
|
||||
<td>Go to the desktop the window is on (leave position alone)</td>
|
||||
<td>Move the window to this desktop (leave position alone)</td>
|
||||
<td>
|
||||
|
||||
If there isn't one on this desktop:
|
||||
* create a new one (default position)
|
||||
|
||||
Else:
|
||||
* activate the one on this desktop (don't move it)
|
||||
</td>
|
||||
</tr>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
<tr>
|
||||
<td><code>"toCurrent"</code><br> Summon the MRU window TO the monitor with the foreground window</td>
|
||||
<td>Go to the desktop the window is on, move to the monitor with the foreground window</td>
|
||||
<td>Move the window to this desktop, move to the monitor with the foreground window</td>
|
||||
<td>
|
||||
|
||||
If there isn't one on this desktop:
|
||||
* create a new one (on the monitor with the foreground window)
|
||||
|
||||
Else:
|
||||
* activate the one on this desktop, move to the monitor with the foreground window
|
||||
</td>
|
||||
</tr>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
<tr>
|
||||
<td>
|
||||
<code>"toMouse"</code>
|
||||
<sup><a href="#footnote-2">[2]</a></sup> <br>
|
||||
Summon the MRU window TO the monitor with the mouse</td>
|
||||
<td>Go to the desktop the window is on, move to the monitor with the mouse</td>
|
||||
<td>Move the window to this desktop, move to the monitor with the mouse</td>
|
||||
<td>
|
||||
|
||||
If there isn't one on this desktop:
|
||||
* create a new one (on the monitor with the mouse)
|
||||
|
||||
Else:
|
||||
* activate the one on this desktop, move to the monitor with the mouse
|
||||
</td>
|
||||
</tr>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
<tr>
|
||||
<td><code>"onCurrent"</code><br> Summon the MRU window for the current monitor</td>
|
||||
<td>
|
||||
|
||||
If there is a window on this monitor on any desktop,
|
||||
* Go to the desktop the window is on (leave position alone)
|
||||
|
||||
else
|
||||
* Create a new window on this monitor & desktop
|
||||
</td>
|
||||
<td>
|
||||
|
||||
If there is a window on this monitor on any desktop,
|
||||
* Move the window to this desktop (leave position alone)
|
||||
|
||||
else
|
||||
* Create a new window on this monitor & desktop
|
||||
</td>
|
||||
<td>
|
||||
|
||||
If there isn't one on this desktop, (even if there is one on this monitor on
|
||||
another desktop),
|
||||
* create a new one on this monitor
|
||||
|
||||
Else if ( there is one on this desktop, not this monitor)
|
||||
* create a new one on this monitor
|
||||
|
||||
Else (one on this desktop & monitor)
|
||||
* Activate the one on this desktop (don't move)
|
||||
</td>
|
||||
</tr>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
<tr>
|
||||
<td><code>int</code><br> Summon the MRU window for monitor N</td>
|
||||
<td>
|
||||
|
||||
If there is a window on monitor N on any desktop,
|
||||
* Go to the desktop the window is on (leave position alone)
|
||||
|
||||
else
|
||||
* Create a new window on this monitor & desktop
|
||||
</td>
|
||||
<td>
|
||||
|
||||
If there is a window on monitor N on any desktop,
|
||||
* Move the window to this desktop (leave position alone)
|
||||
|
||||
else
|
||||
* Create a new window on this monitor & desktop
|
||||
</td>
|
||||
<td>
|
||||
|
||||
If there isn't one on this desktop, (even if there is one on monitor N on
|
||||
another desktop),
|
||||
* create a new one on monitor N
|
||||
|
||||
Else if ( there is one on this desktop, not monitor N)
|
||||
* create a new one on monitor N
|
||||
|
||||
Else (one on this desktop & monitor N)
|
||||
* Activate the one on this desktop (don't move)
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
##### Stories, revisited
|
||||
|
||||
With the above settings, let's re-examine the original user stories, and see how
|
||||
they fit into the above settings. (_Stories that are omitted aren't relevant to
|
||||
the discussion of these settings_)
|
||||
|
||||
> When the `desktop` param is omitted below, that can be interpreted as "any
|
||||
> `desktop` value will make sense here"
|
||||
|
||||
* **Story A** Press a hotkey anywhere to activate the single Terminal window
|
||||
wherever it was
|
||||
- This is `{ "monitor": "any", "desktop": "any" }`
|
||||
* **Story B** Press a hotkey anywhere to activate the single Terminal window _on
|
||||
the current monitor_. If it wasn't previously on that monitor, move it there.
|
||||
- This is `{ "monitor": "toCurrent" }`
|
||||
* **Story D** <kbd>Ctrl+1</kbd> to activate the terminal on monitor 1,
|
||||
<kbd>Ctrl+2</kbd> to activate the terminal on monitor 2.
|
||||
- This is `[ { "keys": "ctrl+1", monitor": 1 }, { "keys": "ctrl+2", monitor": 2 } ]`
|
||||
|
||||
As some additional examples:
|
||||
|
||||
```json
|
||||
// Go to the MRU window, wherever it is
|
||||
{ "keys": "win+1", "command":{ "action":"globalSummon", "monitor":"any", "desktop": "any" } },
|
||||
|
||||
// activate the MRU window, and move it to this desktop & this monitor
|
||||
{ "keys": "win+2", "command":{ "action":"globalSummon", "monitor":"toCurrent", "desktop": "toCurrent" } },
|
||||
// Since "toCurrent" & "toCurrent" are the default values, just placing a single
|
||||
// entry here will bind the same behavior:
|
||||
{ "keys": "win+2", "command": "globalSummon" },
|
||||
|
||||
// activate the MRU window on this desktop
|
||||
{ "keys": "win+3", "command":{ "action":"globalSummon", "monitor":"any", "desktop": "onCurrent" } },
|
||||
|
||||
// Activate the MRU window on monitor 2 (from any desktop), and place it on the
|
||||
// current desktop. If there isn't one on monitor 2, make a new one.
|
||||
{ "keys": "win+4", "command":{ "action":"globalSummon", "monitor": 2, "desktop": "toCurrent" } },
|
||||
|
||||
// Activate the MRU window on monitor 3 (ONLY THIS desktop), or make a new one.
|
||||
{ "keys": "win+5", "command":{ "action":"globalSummon", "monitor": 3, "desktop": "onCurrent" } },
|
||||
|
||||
// Activate the MRU window on this monitor (from any desktop), and place it on
|
||||
// the current desktop. If there isn't one on this monitor, make a new one.
|
||||
{ "keys": "win+6", "command":{ "action":"globalSummon", "monitor": "onCurrent", "desktop": "toCurrent" } },
|
||||
```
|
||||
|
||||
#### Summoning a specific window
|
||||
|
||||
What if you want to press a keybinding to always summon a specific, named
|
||||
window? This window might not be the most recent terminal window, nor one that
|
||||
would be selected by the `monitor` and `desktop` selectors. You could name a
|
||||
window "Epona", and press `win+e` to always summon the "Epona" window.
|
||||
|
||||
We'll add the following property to address this scenario
|
||||
|
||||
* `"window": string|int`
|
||||
- When omitted (_default_): Use monitor and desktop to find the appropriate
|
||||
MRU window to summon.
|
||||
- When provided: Always summon the window who's name or ID matches the given
|
||||
`window` value. If no such window exists, then create a new window with that
|
||||
name/id.
|
||||
|
||||
When provided _with_ `monitor` and `desktop`, `window` behaves in the following
|
||||
ways:
|
||||
* `desktop`
|
||||
- `"any"`: Go to the desktop the given window is already on.
|
||||
- `"toCurrent"`: If the window is on another virtual desktop, then move it to
|
||||
the currently active one.
|
||||
- `"onCurrent"`: If the window is on another virtual desktop, then move it to
|
||||
the currently active one.
|
||||
* `monitor`
|
||||
- `"any"`: Leave the window on the monitor it is already on.
|
||||
- `"toCurrent"`: If the window is on another monitor, then move it to the
|
||||
currently active one.
|
||||
- `"onCurrent"`: If the window is on another monitor, then move it to the
|
||||
currently active one.
|
||||
- `<int>`: If the window is on another monitor, then move it to the specified
|
||||
monitor.
|
||||
|
||||
> NOTE: You read that right, `onCurrent` and `toCurrent` both do the same thing
|
||||
> when `window` is provided. They both already know which window to select, the
|
||||
> context of moving to the "current" monitor is all that those parameters add.
|
||||
|
||||
#### Other properties
|
||||
|
||||
Some users would like the terminal to just appear when the global hotkey is
|
||||
pressed. Others would like the true quake-like experience, where the terminal
|
||||
window "slides-in" from the top of the monitor. Furthermore, some users would
|
||||
like to configure the speed at which that dropdown happens. To support this
|
||||
functionality, the `globalSummon` action will support the following property:
|
||||
|
||||
* `"dropdownDuration": float`
|
||||
- When omitted, `0`, or a negative number: No animation is used
|
||||
when summoning the window. The summoned window is focused immediately where
|
||||
it is.
|
||||
- When a positive number is provided, the terminal will use that value as a
|
||||
duration (in seconds) to slide the terminal into position when activated.
|
||||
- The default would be some sensible value. The pane animation is .2s, so
|
||||
`0.2` might be a reasonable default here.
|
||||
|
||||
We could have alternatively provided a `"dropdownSpeed"` setting, that provided
|
||||
a number of pixels per second. In my opinion, that would be harder for users to
|
||||
use correctly. I believe that it's easier for users to mentally picture "I'd
|
||||
like the dropdown to last 100ms" vs "My monitor is 1504px tall, so I need to set
|
||||
this to 15040 to make the window traverse the entire display in .1s"
|
||||
|
||||
> NOTE: `dropdownDuration` will be ignored when the user has animations disabled
|
||||
> in the OS. In that case, the terminal will just appear, as if it was set to 0.
|
||||
|
||||
Some users might want to be able to use the global hotkey to hide the window
|
||||
when the window is already visible. This would let the hotkey act as a sort of
|
||||
global toggle for the Terminal window. Others might not like that behavior, and
|
||||
just want the action to always bring the Terminal into focus, and do nothing if
|
||||
the terminal is already focused. To facilitate both these use cases, we'll add
|
||||
the following property:
|
||||
|
||||
* `"toggleVisibility": bool`
|
||||
- When `true`: (_default_) When this hotkey is pressed, and the terminal
|
||||
window is currently active, minimize the window.
|
||||
- When `dropdownDuration` is not `0`, then the window will slide back off
|
||||
the top at the same speed as it would come down.
|
||||
- When `false`: When this hotkey is pressed, and the terminal window is
|
||||
currently active, do nothing.
|
||||
|
||||
### Quake Mode
|
||||
|
||||
In addition to just summoning the window from anywhere, some terminals also
|
||||
support a special "quake mode" buffer or window. This window is one that closely
|
||||
emulates the console from quake:
|
||||
* It's docked to the top of the screen
|
||||
* It takes the full width of the monitor, and only the bottom can be resized
|
||||
* It often doesn't have any other UI elements, like tabs
|
||||
|
||||
For fun, we'll also be adding a special `"_quake"` window with the same
|
||||
behavior. If the user names a window `_quake`, then it will behave in the
|
||||
following special ways:
|
||||
|
||||
* On launch, it will ignore the `initialPosition` and
|
||||
`initialRows`/`initialCols` setting, and instead resize to the top half of the
|
||||
monitor.
|
||||
* On launch, it will ignore the `launchMode` setting, and always launch in focus
|
||||
mode.
|
||||
- Users can disable focus mode on the `_quake` window if they do want tabs.
|
||||
* It will not be resizable from any side except the bottom of the window, nor
|
||||
will it be drag-able.
|
||||
* It will not be a valid target for the "most recent window" for window
|
||||
glomming. If it's the only open window, with `"windowingBehavior":
|
||||
"useExisting*"`, then a new window will be created instead.
|
||||
- It _is_ still a valid target for something like `wt -w _quake new-tab`
|
||||
|
||||
A window at runtime can be renamed to become the `_quake` window (if no other
|
||||
`_quake` window exists). When it does, it will resize to the position of the
|
||||
quake window, and enter focus mode.
|
||||
|
||||
We'll also be adding a special action `quakeMode`. This action is a special case
|
||||
of the `globalSummon` action, to specifically invoke the quake window in the
|
||||
current place. It is basically the same thing as the more elaborate:
|
||||
|
||||
```json
|
||||
{
|
||||
"monitor": "toCurrent",
|
||||
"desktop": "toCurrent",
|
||||
"window": "_quake",
|
||||
"toggleVisibility": true,
|
||||
"dropdownDuration": 0.5
|
||||
},
|
||||
```
|
||||
|
||||
### Minimize to Tray
|
||||
|
||||
Many users have requested that the terminal additionally supports minimizing the
|
||||
window "to the tray icon". This is a bit like when you close the Teams window,
|
||||
but Teams is actually still running in the system tray, or the "notification
|
||||
area".
|
||||
|
||||
![The Teams tray icon](tray-icon-000.png)
|
||||
|
||||
_fig 1: an example of the Teams tray icon in the notification area_.
|
||||
|
||||
When users want to be able to "minimize to the tray", they want:
|
||||
* The window to no longer appear on the taskbar
|
||||
* The window to no longer appear in the alt-tab order
|
||||
|
||||
When minimized to the tray, it's almost as if there's no window for the Terminal
|
||||
at all. This can be combined with the global hotkey (or the tray icon's context
|
||||
menu) to quickly restore the window.
|
||||
|
||||
The tray icon could be used for a variety of purposes. As a simple start, we
|
||||
could include the following three options:
|
||||
|
||||
```
|
||||
Focus Terminal
|
||||
---
|
||||
Windows > Window 1 - <un-named window>
|
||||
Window 2 - "This-window-does-have-a-name"
|
||||
---
|
||||
Quit
|
||||
```
|
||||
|
||||
Just clicking on the icon would summon the recent terminal window. Right
|
||||
clicking would show the menu with "Focus Terminal", "Windows" and "Quit" in it, and
|
||||
"Windows" would have nested entries for each Terminal window.
|
||||
|
||||
* "Focus Terminal" would do just that - summon the most recent terminal window,
|
||||
wherever it is.
|
||||
* "Windows" would have nested popups for each open Terminal window. Each of
|
||||
these nested entries would display the name and ID of the window. Clicking
|
||||
them would summon that window (wherever it may be)
|
||||
* "Quit" would be akin to quit in browsers - close all open windows
|
||||
<sup>[[1]](#footnote-1)</sup>.
|
||||
|
||||
The tray notification would be visible always when the user has
|
||||
`"minimizeToTray": true` set in their settings. If the user has that set to
|
||||
false, but would still like the tray, they can specify `"alwaysShowTrayIcon":
|
||||
true`. That will cause the tray icon to always be added to the system tray.
|
||||
|
||||
There's not a combination of settings where the Terminal is "minimized to the
|
||||
tray", and there's _no tray icon visible_. We don't want to let users get into a
|
||||
state where the Terminal is running, but is totally hidden from their control.
|
||||
|
||||
From a technical standpoint, the tray icon is managed similar to the global
|
||||
hotkey. The Monarch process is responsible for setting it up, and processing the
|
||||
messages. When a Monarch dies and a new process becomes the Monarch, then it
|
||||
will re-create the tray icon.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
To summarize, we're proposing the following set of settings:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"minimizeToTray": bool,
|
||||
"alwaysShowTrayIcon": bool,
|
||||
"actions": [
|
||||
{
|
||||
"keys": KeyChord,
|
||||
"command": {
|
||||
"action": "globalSummon",
|
||||
"dropdownDuration": float,
|
||||
"toggleVisibility": bool,
|
||||
"monitor": "any"|"toCurrent"|"onCurrent"|int,
|
||||
"desktop": "any"|"toCurrent"|"onCurrent"
|
||||
}
|
||||
},
|
||||
{
|
||||
"keys": KeyChord,
|
||||
"command": {
|
||||
"action": "quakeMode"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Potential Issues
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td><strong>Compatibility</strong></td>
|
||||
<td>
|
||||
|
||||
As part of this set of changes, we'll also be allowing the <kbd>Win</kbd> key in
|
||||
keybindings. Generally, the OS reserves the Windows key for its own shortcuts.
|
||||
For example, <kbd>Win+R</kbd> for the run dialog, <kbd>Win+A</kbd> for the
|
||||
Action Center, <kbd>Win+V</kbd> for the cloud clipboard, etc. Users will now be
|
||||
able to use the win key themselves, but they should be aware that the OS has
|
||||
"first dibs" on any hotkeys involving the Windows key.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Mixed elevation</strong></td>
|
||||
<td>
|
||||
|
||||
Only one app at a time gets to register for global hotkeys. However, from the
|
||||
Terminal's perspective, unelevated and elevated windows will act like different
|
||||
apps. Each privilege level has its own Monarch. The two are unable to
|
||||
communicate across the elevation boundary.
|
||||
|
||||
This means that if the user often runs terminals in both contexts, then only one
|
||||
will have the global hotkeys bound. The naive implementation would have the
|
||||
first elevation level "win" the keybindings.
|
||||
|
||||
A different option would be to have elevated windows not register global hotkeys
|
||||
_at all_. I don't believe that there's any sort of security implication for
|
||||
having a global hotkey for an elevated window.
|
||||
|
||||
A third option would be to have some sort of `"whenElevated": bool?` property
|
||||
for global hotkeys. This would explicitly enable a given hotkey for unelevated
|
||||
vs elevated windows.
|
||||
* `"whenElevated": null`: behave as normal - the first context level to run wins
|
||||
* `"whenElevated": true`: only register the hotkey when running elevated
|
||||
* `"whenElevated": false`: only register the hotkey when running unelevated
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>OneCore / Windows 10X</strong></td>
|
||||
<td>
|
||||
|
||||
I'm fairly certain that none of these APIs would work on Windows 10X at all.
|
||||
These features would have to initially be disabled in a pure UWP version of the
|
||||
Terminal, until we could find workarounds. Since the window layer is the one
|
||||
responsible for the management of the hotkeys and the tray icon, we're not too
|
||||
worried about this.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
* If there are any other applications running that have already registered
|
||||
hotkeys with `RegisterHotKey`, then it's possible that the Terminal's attempt
|
||||
to register that hotkey will fail. If that should happen, then we should
|
||||
display a warning dialog to the user indicating which hotkey will not work
|
||||
(because it's already used for something else).
|
||||
|
||||
* Which is the "current" monitor? The one with the mouse or the one with the
|
||||
active window? This isn't something that has an obvious answer. Guake
|
||||
implements this feature where the "current monitor" is the one with the mouse
|
||||
on it. At least for the first iterations of this action, that's what we'll
|
||||
use.
|
||||
`monitor: onCurrent|onCurrentWindow|toCurrent|<int>`
|
||||
|
||||
* Currently, running both the Release and Preview versions of the Terminal at
|
||||
the same time side-by-side is not generally supported. (For example, `wt.exe`
|
||||
can only ever point at one of two.) If a user binds the same key to a
|
||||
`globalSummon` or `quakeMode` action, then only one of the apps will actually
|
||||
be able to successfully claim the global hotkey.
|
||||
|
||||
## Implementation plan
|
||||
|
||||
Currently, in [`dev/migrie/f/653-QUAKE-MODE`], I have some sample rudimentary
|
||||
code to implement quake mode support. It allows for only a single global hotkey
|
||||
that summons the MRU window, without dropdown. That would be a good place for
|
||||
anyone starting to work on this feature. From there, I imagine the following
|
||||
work would be needed:
|
||||
|
||||
* [ ] Add a `globalSummon` action. `AppHost` would need to be able to get _all_
|
||||
of these actions, and register all of them. Each one would need to be assigned
|
||||
a unique ID, so `WM_HOTKEY` can identify which hotkey was pressed.
|
||||
- This could be committed without any other args to the `globalHotkeys`. In
|
||||
this initial version, the behavior would be summoning the MRU window,
|
||||
where it is, no dropdown, to start with. From there, we'd add the
|
||||
remaining properties:
|
||||
* [ ] Add support for the `toggleVisibility` property
|
||||
* [ ] Add support for the `desktop` property to control how window summoning
|
||||
interacts with virtual desktops
|
||||
* [ ] Add support for the `monitor` which monitor the window appears on.
|
||||
* [ ] Add support for the `dropdownDuration` property
|
||||
* [ ] Add the `minimizeToTray` setting, and implement it without any sort of flyout
|
||||
* [ ] Add a list of windows to the right-click flyout on the tray icon
|
||||
* [ ] Add support for the `alwaysShowTrayIcon` setting
|
||||
* [ ] When the user creates a window named `_quake`, ignore the initial size,
|
||||
position, and launch mode, and create the window in quake mode instead.
|
||||
* [ ] Exempt the `_quake` window from window glomming
|
||||
* [ ] Add the `quakeMode` action, which `globalSummon`'s the `_quake` window.
|
||||
* [ ] Prevent the `_quake` window from being dragged or resized on the
|
||||
top/left/right.
|
||||
|
||||
|
||||
### Future Considerations
|
||||
|
||||
I don't believe there are any other tracked requests that are planned that
|
||||
aren't already included in this spec.
|
||||
|
||||
* Should the tray icon's list of windows include window titles? Both the name
|
||||
and title? Maybe something like `({name}|{id}): {title}`? I'd bet that most
|
||||
people don't end up naming their windows.
|
||||
* Dropdown duration could be a `float|bool`, with `true`->(whatever the default
|
||||
is), `false`->0.
|
||||
- We could have the setting appear as a pair of radio buttons, with the first
|
||||
disabling dropdown, and the second enabling a text box for inputting an
|
||||
animation duration.
|
||||
* It might be an interesting idea to have the ability to dock the quake window
|
||||
to a specific side of the monitor, not just the top. We could probably do that
|
||||
with a global setting `"quakeModeDockSide": "top"|"left"|"bottom"|"right"` or
|
||||
something like that.
|
||||
* We might want to pre-load the quake window into the tray icon as an entry for
|
||||
"Quake Mode", and otherwise exclude it from the list of windows in that menu.
|
||||
* We might think of other things for the Quake Mode window in the future - this
|
||||
spec is by no means comprehensive. For example, it might make sense for the
|
||||
quake mode window to automatically open in "always on top" mode.
|
||||
* It was suggested that the quake mode window could auto-hide when it loses
|
||||
focus. That's a really neat idea, but we're a little worried about the
|
||||
implementation. What happens when the IME window gets focus? Or the Start
|
||||
Menu? Would those end up causing the quake window to prematurely minimize
|
||||
itself? For that reason, we're leaving this as a future consideration.
|
||||
* Perhaps there could be a top-level object in the settings like
|
||||
```json
|
||||
{
|
||||
"quakeMode": {
|
||||
"hideOnFocusLost": true,
|
||||
"useFocusMode": false,
|
||||
"profile": "my quake mode profile" ,
|
||||
"quakeModeDockSide": "bottom"
|
||||
}
|
||||
}
|
||||
```
|
||||
That would allow the user some further customizations on the quake mode
|
||||
behaviors.
|
||||
- This was later converted to the idea in [#9992] - Add per-window-name global
|
||||
settings
|
||||
* Another proposed idea was a simplification of some of the summoning modes. `{
|
||||
"monitor": "any", "desktop": "any" }` is a little long, and maybe not the most
|
||||
apparent naming. Perhaps we could add another property like `summonMode` that
|
||||
would act like an alias for a `monitor`, `desktop` combo.
|
||||
- `"summonMode": "activateInMyFace"`: `{ "monitor": "toCurrent", "desktop": "toCurrent" }`
|
||||
- `"summonMode": "activateWherever"`: `{ "monitor": "any", "desktop": "any" }`
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
Docs on adding a system tray item:
|
||||
* https://docs.microsoft.com/en-us/windows/win32/shell/notification-area
|
||||
* https://www.codeproject.com/Articles/18783/Example-of-a-SysTray-App-in-Win32
|
||||
|
||||
Docs regarding hiding a window from the taskbar:
|
||||
* https://docs.microsoft.com/en-us/previous-versions//bb776822(v=vs.85)#managing-taskbar-buttons
|
||||
|
||||
### Footnotes
|
||||
|
||||
<a name="footnote-1"><a>[1]: Quitting the terminal is different than closing the
|
||||
windows one-by-one. Quiting implies an atomic action, for closing all the
|
||||
windows. Once [#766] lands, this will give us a chance to persist the state of
|
||||
_all_ open windows. This will allow us to re-open with all the user's windows,
|
||||
not just the one that happened to be closed last.
|
||||
|
||||
<a name="footnote-2"><a>[2]: **Addenda, May 2021**: In the course of
|
||||
implementation, it became apparent that there's an important UX difference
|
||||
between summoning _to the monitor with the cursor_ vs _to the monitor with the
|
||||
foreground window_. `"monitor": "toMouse"` was added as an option, to allow the
|
||||
user to differentiate between the two behaviors.
|
||||
|
||||
[#653]: https://github.com/microsoft/terminal/issues/653
|
||||
[#766]: https://github.com/microsoft/terminal/issues/766
|
||||
[#5727]: https://github.com/microsoft/terminal/issues/5727
|
||||
[#9992]: https://github.com/microsoft/terminal/issues/9992
|
||||
|
||||
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md
|
||||
[Quake 3 sample]: https://youtu.be/ZmR6HQbuHPA?t=27
|
||||
[`RegisterHotKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey
|
||||
[`dev/migrie/f/653-QUAKE-MODE`]: https://github.com/microsoft/terminal/tree/dev/migrie/f/653-QUAKE-MODE
|
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 142 KiB |
Before Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 142 KiB |
Before Width: | Height: | Size: 142 KiB |
|
@ -1,130 +0,0 @@
|
|||
---
|
||||
author: Kayla Cinnamon - cinnamon-msft
|
||||
created on: 2021-03-04
|
||||
last updated: 2021-03-09
|
||||
issue id: 6900
|
||||
---
|
||||
|
||||
# Actions Page
|
||||
|
||||
## Abstract
|
||||
|
||||
We need to represent actions inside the settings UI. This spec goes through the possible use cases and reasoning for including specific features for actions inside the settings UI.
|
||||
|
||||
## Background
|
||||
|
||||
### Inspiration
|
||||
|
||||
It would be ideal if we could get the settings UI to have parity with the JSON file. This will take some design work if we want every feature possible in relation to actions. There is also the option of not having parity with the JSON file in order to present a simpler UX.
|
||||
|
||||
### User Stories
|
||||
|
||||
All of these features are possible with the JSON file. This spec will go into discussion of which (possibly all) of these user stories need to be handled by the settings UI.
|
||||
|
||||
- Add key bindings to an action that does not already have keys assigned
|
||||
- Edit key bindings for an action
|
||||
- Remove key bindings from an action
|
||||
- Add multiple key bindings for the same action
|
||||
- Create an iterable action
|
||||
- Create a nested action
|
||||
- Choose which actions appear inside the command palette
|
||||
- See all possible actions, regardless of keys
|
||||
|
||||
Commands with properties:
|
||||
- sendInput has "input"
|
||||
- closeOtherTabs has "index"
|
||||
- closeTabsAfter has "index"
|
||||
- renameTab has "title"*
|
||||
- setTabColor has "color"*
|
||||
- newWindow has "commandline", "startingDirectory", "tabTitle", "index", "profile"
|
||||
- splitPane has "split", "commandline", "startingDirectory", "tabTitle", "index", "profile", "splitMode", "size"
|
||||
- copy has "singleLine", "copyFormatting"
|
||||
- scrollUp has "rowsToScroll"
|
||||
- scrollDown has "rowsToScroll"
|
||||
- setColorScheme has "colorScheme"
|
||||
|
||||
Majority of these commands listed above are intended for the command palette, so they wouldn't make much sense with keys assigned to them anyway.
|
||||
|
||||
### Future Considerations
|
||||
|
||||
One day we'll have actions that can be invoked by items in the dropdown menu. This setting will have to live somewhere. Also, once we get a status bar, people may want to invoke actions from there.
|
||||
|
||||
## Solution Design
|
||||
|
||||
### Proposal 1: Keyboard and Command Palette pages
|
||||
|
||||
Implement a Keyboard page in place of the Actions page. Also plan for a Command Palette page in the future if it's something that's heavily requested. The Command Palette page would cover the missing use cases listed below.
|
||||
|
||||
When users want to add a new key binding, the dropdown will list every action, regardless if it already has keys assigned. This page should show every key binding assigned to an action, even if there are multiple bindings to the same action.
|
||||
|
||||
Users will be able to view every possible action from the command palette if they'd like.
|
||||
|
||||
Use cases covered:
|
||||
- Add key bindings to an action that does not already have keys assigned
|
||||
- Edit key bindings for an action
|
||||
- Remove key bindings from an action
|
||||
- Add multiple key bindings for the same action
|
||||
- See all actions that have keys assigned
|
||||
|
||||
Use cases missing:
|
||||
- Create an iterable action
|
||||
- Create a nested action
|
||||
- Choose which actions appear inside the command palette
|
||||
- See all possible actions, regardless of keys
|
||||
|
||||
* **Pros**:
|
||||
- This allows people to edit their actions in most of their scenarios.
|
||||
- This gives us some wiggle room to cover majority of the use cases we need and seeing if people want the other use cases that are missing.
|
||||
|
||||
* **Cons**:
|
||||
- Unfortunately we couldn't cover every single use case with this design.
|
||||
- You can't edit the properties that are on some commands, however the default commands from the command palette include options with properties anyway. For example "decrease font size" has the `delta` property already included.
|
||||
|
||||
### Proposal 2: Have everything on one Actions page
|
||||
|
||||
Implement an Actions page that allows you to create actions designed for the command palette as well as actions with keys.
|
||||
|
||||
Use cases covered:
|
||||
- Add key bindings to an action that does not already have keys assigned
|
||||
- Edit key bindings for an action
|
||||
- Remove key bindings from an action
|
||||
- Add multiple key bindings for the same action
|
||||
- See all actions that have keys assigned
|
||||
- Create an iterable action
|
||||
- Create a nested action
|
||||
- Choose which actions appear inside the command palette
|
||||
- See all possible actions, regardless of keys
|
||||
|
||||
I could not come up with a UX design that wasn't too complicated or confusing for this scenario.
|
||||
|
||||
**Pros**:
|
||||
- There is full parity with the JSON file.
|
||||
|
||||
**Cons**:
|
||||
- Could not come up with a simplistic design to represent all of the use cases (which makes the settings UI not as enticing since it promotes ease of use).
|
||||
|
||||
## Conclusion
|
||||
|
||||
We considered Proposal 2, however the design became cluttered very quickly and we agreed to create two pages and start off with Proposal 1.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
![Click edit on key binding](./edit-click.png)
|
||||
|
||||
The Add new button is using the secondary color, to align with the button on the Color schemes page.
|
||||
|
||||
![Edit key binding](./edit-keys.png)
|
||||
|
||||
![Click add new](./add-click.png)
|
||||
|
||||
![Add key binding](./add-keys.png)
|
||||
|
||||
## Potential Issues
|
||||
|
||||
This design is not 1:1 with the JSON file, so actions that don't have keys will not appear on this page. Additionally, you can't add a new action without keys with this current design.
|
||||
|
||||
You also cannot specify properties on commands (like the `newTab` command) and these will have to be added through the JSON file. Considering there are only a few of these and we're planning to iterate on this and add a Command Palette page, we were okay with this decision.
|
||||
|
||||
## Resources
|
||||
|
||||
### Footnotes
|
|
@ -268,7 +268,7 @@ Today, if the deserialization of `CascadiaSettings` encounters any errors, an ex
|
|||
To get around this issue, when `CascadiaSettings` encounters a serialization error, it must internally record
|
||||
any pertinent information for that error, and return the simple `CascadiaSettings` as if nothing happened.
|
||||
The consumer must then call `CascadiaSettings::GetErrors()` and `CascadiaSettings::GetWarnings()` to properly
|
||||
understand whether an error occurred and how to present that to the user.
|
||||
understand whether an error ocurred and how to present that to the user.
|
||||
|
||||
|
||||
#### TerminalApp: Loading and Reloading Changes
|
||||
|
|
|
@ -1,344 +0,0 @@
|
|||
---
|
||||
author: Carlos Zamora @carlos-zamora
|
||||
created on: 2021-03-12
|
||||
last updated: 2021-03-17
|
||||
issue id: [#885]
|
||||
---
|
||||
|
||||
# Actions in the Settings Model
|
||||
|
||||
## Abstract
|
||||
|
||||
This spec proposes a refactor of how Windows Terminal actions are stored in the settings model.
|
||||
The new representation would mainly allow the serialization and deserialization of commands and keybindings.
|
||||
|
||||
## Inspiration
|
||||
|
||||
A major component that is missing from the Settings UI is the representation of keybindings and commands.
|
||||
The JSON represents both of these as a combined entry as follows:
|
||||
```js
|
||||
{ "icon": "path/to/icon.png", "name": "Copy the selected text", "command": "copy", "keys": "ctrl+c" },
|
||||
```
|
||||
In the example above, the copy action is...
|
||||
- bound to <kbd>ctrl+c</kbd>
|
||||
- presented as "Copy the selected text" with the "path/to/icon.png" icon
|
||||
|
||||
However, at the time of writing this spec, the settings model represents it as...
|
||||
- (key binding) a `KeyChord` to `ActionAndArgs` entry in a `KeyMapping`
|
||||
- (command) a `Command` with an associated icon, name, and action (`ActionAndArgs`)
|
||||
|
||||
This introduces the following issues:
|
||||
1. Serialization
|
||||
- We have no way of knowing when a command and a key binding point to the same action. Thus, we don't
|
||||
know when to write a "name" to the json.
|
||||
- We also don't know if the name was auto-generated or set by the user. This can make the JSON much more bloated by
|
||||
actions with names that would normally be autogenerated.
|
||||
2. Handling Duplicates
|
||||
- The same action can be bound to multiple key chords. The command palette combines all of these actions into one entry
|
||||
because they have the same name. In reality, this same action is just being referenced in different ways.
|
||||
|
||||
## Solution Design
|
||||
|
||||
I propose that the issues stated above be handled via the following approach.
|
||||
|
||||
### Step 1: Consolidating actions
|
||||
|
||||
`Command` will be updated to look like the following:
|
||||
|
||||
```c++
|
||||
runtimeclass Command
|
||||
{
|
||||
// The path to the icon (or icon itself, if it's an emoji)
|
||||
String IconPath;
|
||||
|
||||
// The associated name. If none is defined, one is auto-generated.
|
||||
String Name;
|
||||
|
||||
// The key binding that can be used to invoke this action.
|
||||
// NOTE: We're actually holding the KeyChord instead of just the text.
|
||||
// KeyChordText just serializes the relevant keychord
|
||||
Microsoft.Terminal.Control.KeyChord Keys;
|
||||
String KeyChordText;
|
||||
|
||||
// The action itself.
|
||||
ActionAndArgs ActionAndArgs;
|
||||
|
||||
// NOTE: nested and iterable command logic will still be here,
|
||||
// But they are omitted to make this section seem cleaner.
|
||||
|
||||
// Future Considerations:
|
||||
// - [#6899]: Action IDs --> add an identifier here
|
||||
}
|
||||
```
|
||||
|
||||
The goal here is to consolidate key binding actions and command palette actions into a single class.
|
||||
This will also require the following supplemental changes:
|
||||
- `Command::LayerJson`
|
||||
- This must combine the logic of `KeyMapping::LayerJson` and `Command::LayerJson`.
|
||||
- Key Chord data
|
||||
- Internally, store a `vector<KeyChord> _keyMappings` to keep track of all the key chords associated with this action.
|
||||
- `RegisterKey` and `EraseKey` update `_keyMappings`, and ensure that the latest key registered is at the end of the list.
|
||||
- `Keys()` simply returns the last entry of `_keyMappings`, which is the latest key chord this action is bound to.
|
||||
- `KeyChordText())` is exposed to pass the text directly to the command palette.
|
||||
This depends on `Keys` and, thus, propagate changes automatically.
|
||||
- Observable properties
|
||||
- `Command` has observable properties today, but does not need them because `Command` will never change while the app is running.
|
||||
- Nested and iterable commands
|
||||
- `HasNestedCommands`, `NestedCommands{ get; }`, `IterateOn` will continue to be exposed.
|
||||
- A setter for these customizations will not be exposed until we find it necessary (i.e. adding support for customizing it in the Settings UI)
|
||||
- Command expansion can continue to be exposed here to reduce implementation cost.
|
||||
- An additional `IsNestedCommand` is necessary to record a case where a nested command is being unbound `{ "commands": null, "name": "foo" }`.
|
||||
|
||||
Overall, the `Command` class is simply being promoted to include the `KeyChord` it has.
|
||||
This allows the implementation cost of this step to be relatively small.
|
||||
|
||||
Completion of this step should only cause relatively minor changes to anything that depends on `Command`, because
|
||||
it is largely the same class. However, key bindings will largely be impacted because we represent key bindings as
|
||||
a map of `KeyChord`s to `ActionAndArgs`. This leads us to step 2 of this process.
|
||||
|
||||
|
||||
### Step 2: Querying actions
|
||||
|
||||
Key bindings and commands are deserialized by basically storing individual actions to a map.
|
||||
- `KeyMapping` is basically an `IMap<KeyChord, ActionAndArgs>` with a few extra functions. In fact, it actually
|
||||
stores key binding data to a `std::map<KeyChord, ActionAndArgs>` and directly interacts with it.
|
||||
- `Command::LayerJson` populates an `IMap<String, Command>` during deserialization as it iterates over every action.
|
||||
Note that `Command` can be interpreted as a wrapper for `ActionAndArgs` with more stuff here.
|
||||
|
||||
It makes sense to store these actions as maps. So, following step 1 above, we can also store and expose actions
|
||||
something like the following:
|
||||
|
||||
```c++
|
||||
runtimeclass ActionMap
|
||||
{
|
||||
ActionAndArgs GetActionByKeyChord(KeyChord keys);
|
||||
|
||||
KeyChord GetKeyBindingForAction(ShortcutAction action);
|
||||
KeyChord GetKeyBindingForAction(ShortcutAction action, IActionArgs actionArgs);
|
||||
|
||||
IMapView<String, Command> NameMap { get; };
|
||||
|
||||
// Future Considerations:
|
||||
// - [#6899]: Action IDs --> GetActionByID()
|
||||
}
|
||||
```
|
||||
|
||||
The getters will return null if a matching action or key chord is not found. Since iterable commands need to be expanded at in TerminalApp, we'll just expose `NameMap`, then let TerminalApp perform the expansion as they do now. Internally, we can store the actions as follows:
|
||||
|
||||
```c++
|
||||
std::map<KeyChord, InternalActionID> _KeyMap;
|
||||
std::map<InternalActionID, Command> _ActionMap;
|
||||
```
|
||||
|
||||
`InternalActionID` will be a hash of `ActionAndArgs` such that two `ActionAndArgs` with the same `ShortcutAction` and `IActionArgs` output the same hash value.
|
||||
|
||||
`GetActionByKeyChord` will use `_KeyMap` to find the `InternalActionID`, then use the `_ActionMap` to find the bound `Command`.
|
||||
`GetKeyBindingForAction` will hash the provided `ActionAndArgs` (constructed by the given parameters) and check `_ActionMap` for the given `InternalActionID`.
|
||||
|
||||
`NameMap` will need to ensure every action in `_ActionMap` is added to the output name map if it has an associated name. This is done by simply iterating over `_ActionMap`. Nested commands must be added separately because they cannot be hashed.
|
||||
|
||||
`ActionMap` will have an `AddAction(Command cmd)` that will update the internal state whenever a command is registered. If the given command is valid, we will check for collisions and resolve them. Otherwise, we will consider this an "unbound" action and update the internal state normally. It is important that we don't handle "unbound" actions differently because this ensures that we are explicitly unbinding a key chord.
|
||||
|
||||
### Step 3: Settings UI needs
|
||||
|
||||
After the former two steps are completed, the new representation of actions in the settings model is now on-par with
|
||||
what we have today. In order to bind these new actions to the Settings UI, we need the following:
|
||||
|
||||
1. Exposing the maps
|
||||
- `ActionMap::KeyBindings` and `ActionMap::Commands` may need to be added to pass the full list of actions to the Settings UI.
|
||||
- In doing this, we can already update the Settings UI to include a better view of our actions.
|
||||
2. Creating a copy of the settings model
|
||||
- The Settings UI operates by binding the XAML controls to a copy of the settings model.
|
||||
- Copying the `ActionMap` is fairly simple. Just copy the internal state and ensure that `Command::Copy` is called such that no reference to the original WinRT objects persist. Since we are using `InternalActionID`, we will not have to worry about multiple `Command` references existing within the same `ActionMap`.
|
||||
3. Modifying the `Command`s
|
||||
- `ActionMap` must be responsible for changing `Command`s so that we can ensure `ActionMap` always has a correct internal state:
|
||||
- It is important that `Command` only exposes getters (not setters) to ensure `ActionMap` is up to date.
|
||||
- If a key chord is being changed, update the `_KeyMap` and the `Command` itself.
|
||||
- If a key binding is being deleted, add an unbound action to the given key chord.
|
||||
- This is similar to how color schemes are maintained today.
|
||||
- In the event that name/key-chord is set to something that's already taken, we need to propagate those changes to
|
||||
the rest of `ActionMap`. As we do with the JSON, we respect the last name/key-chord set by the user. See [Modifying Actions](#modifying-actions)
|
||||
in potential issues.
|
||||
- For the purposes of the key bindings page, we will introduce a `KeyBindingViewModel` to serve as an intermediator between the settings UI and the settings model. The view model will be responsible for things like...
|
||||
- exposing relevant information to the UI controls
|
||||
- converting UI control interactions into proper API calls to the settings model
|
||||
4. Serialization
|
||||
- `Command::ToJson()` and `ActionMap::ToJson()` should perform most of the work for us. Simply iterate over the `_ActionMap` and call `Command::ToJson` on each action.
|
||||
- See [Unbinding actions](#unbinding-actions) in potential issues.
|
||||
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
N/A
|
||||
|
||||
## Capabilities
|
||||
|
||||
N/A
|
||||
|
||||
### Accessibility
|
||||
|
||||
N/A
|
||||
|
||||
### Security
|
||||
|
||||
N/A
|
||||
|
||||
### Reliability
|
||||
|
||||
N/A
|
||||
|
||||
### Compatibility
|
||||
|
||||
N/A
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
## Potential Issues
|
||||
|
||||
### Layering Actions
|
||||
|
||||
We need a way to determine where an action came from to minimize how many actions we serialize when we
|
||||
write to disk. This is a two part approach that happens as we're loading the settings
|
||||
1. Load defaults.json
|
||||
- For each of the actions in the JSON...
|
||||
- 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 pre-existing one,
|
||||
redirect `_KeyMap` to the newly added `Command` instead,
|
||||
and update the conflicting one.
|
||||
2. Load settings.json
|
||||
- Create a child for the `ActionMap`
|
||||
- The purpose of a parent is to continue a search when the current `ActionMap` can't find a `Command` for a query. The parent is intended to be immutable.
|
||||
- Load the actions array like normal into the child (see step 1)
|
||||
|
||||
Introducing a parent mechanism to `ActionMap` allows it to understand where a `Command` came from. This allows us to minimize the number of actions we serialize when we write to disk, as opposed to serializing the entire list of actions.
|
||||
|
||||
`ActionMap` queries will need to check their parent when they cannot find a matching `InternalActionID` in their `_ActionMap`.
|
||||
|
||||
Since `NameMap` is generated upon request, we will need to use a `std::set<InternalActionID>` as we generate the `NameMap`. This will ensure that each `Command` is only added to the `NameMap` once. The name map will be generated as follows:
|
||||
1. Get an accumulated list of `Command`s from our parents
|
||||
2. Iterate over the list...
|
||||
- Update `NameMap` with any new `Command`s (tracked by the `std::set<InternalActionID>`)
|
||||
|
||||
Nested commands will be saved to their own map since they do not have an `InternalActionID`.
|
||||
- During `ActionMap`'s population, we must ensure to resolve any conflicts immediately. This means that any new `Command`s that generate a name conflicting with a nested command will take priority (and we'll remove the nested command from its own map). Conversely, if a new nested command conflicts with an existing standard `Command`, we can ignore it because our generation of `NameMap` will handle it.
|
||||
- When populating `NameMap`, we must first add all of the standard `Command`s. To ensure layering is accomplished correctly, we will need to start from the top-most parent and update `NameMap`. As we go down the inheritance tree, any conflicts are resolved by prioritizing the current layer (the child). This ensures that the current layer takes priority.
|
||||
- After adding all of the standard `Command`s to the `NameMap`, we can then register all of the nested commands. Since nested commands have no identifier other than a name, we cannot use the `InternalActionID` heuristic. However, as mentioned earlier, we are updating our internal nested command map as we add new actions. So when we are generating the name map, we can assume that all of these nested commands now have priority. Thus, we simply add all of these nested commands to the name map. Any conflicts are resolved in favor of th nested command.
|
||||
|
||||
### Modifying Actions
|
||||
|
||||
There are several ways a command can be modified:
|
||||
- change/remove the key chord
|
||||
- change the name
|
||||
- change the icon
|
||||
- change the action
|
||||
|
||||
It is important that these modifications are done through `ActionMap` instead of `Command`.
|
||||
This is to ensure that the `ActionMap` is always aligned with `Command`'s values. `Command` should only expose getters in the projected type to enforce this. Thus, we can add the following functions to `ActionMap`:
|
||||
|
||||
```c++
|
||||
runtimeclass ActionMap
|
||||
{
|
||||
void SetKeyChord(Command cmd, KeyChord keys);
|
||||
void SetName(Command cmd, String name);
|
||||
void SetIcon(Command cmd, String iconPath);
|
||||
void SetAction(Command cmd, ShortcutAction action, IActionArgs actionArgs);
|
||||
}
|
||||
```
|
||||
|
||||
`SetKeyChord` will need to make sure to modify the `_KeyMap` and the provided `Command`.
|
||||
If the new key chord was already taken, we also need to update the conflicting `Command`
|
||||
and remove its key chord.
|
||||
|
||||
`SetName` will need to make sure to modify the `Command` in `_ActionMap` and regenerate `NameMap`.
|
||||
|
||||
`SetIcon` will only need to modify the provided `Command`. We can choose to not expose this in the `ActionMap`, but doing so makes the API consistent.
|
||||
|
||||
`SetAction` will need to begin by updating the provided `Command`'s `ActionAndArgs`.
|
||||
If the generated name is being used, the name will need to be updated. `_ActionMap` will need to be updated with a new `InternalActionID` for the new action. This is a major operation and so all views exposed will need to be regenerated.
|
||||
|
||||
Regarding [Layering Actions](#layering-actions), if the `Command` does not exist in the current layer,
|
||||
but exists in a parent layer, we need to...
|
||||
0. check if it exists
|
||||
- use the hash `InternalActionID` to see if it exists in the current layer
|
||||
- if it doesn't (which is the case we're trying to solve here), call `_GetActionByID(InternalActionID)` to retrieve the `Command` wherever it may be. This helper function simply checks the current layer, if none is found, it recursively checks its parents until a match is found.
|
||||
1. duplicate it with `Command::Copy`
|
||||
2. store the duplicate in the current layer
|
||||
- `ActionMap::AddAction(duplicate)`
|
||||
3. make the modification to the duplicate
|
||||
|
||||
This ensures that the change persists post-serialization.
|
||||
|
||||
TerminalApp has no reason to ever call these setters. To ensure that relationship, we will introduce an `IActionMapView` interface that will only expose `ActionMap` query functions. Conversely, `ActionMap` will be exposed to the TerminalSettingsEditor to allow for modifications.
|
||||
|
||||
### Unbinding actions
|
||||
|
||||
Removing a name is currently omitted from this spec because there
|
||||
is no Settings UI use case for it at the moment. This scenario is
|
||||
designed for Command Palette customization.
|
||||
|
||||
The only kind of unbinding currently in scope is freeing a key chord such that
|
||||
no action is executed on that key stroke. To do this, simply `ActionMap::AddAction` a `Command` with...
|
||||
- `ActionAndArgs`: `ShortcutAction = Invalid` and `IActionArgs = nullptr`
|
||||
- `Keys` being the provided key chord
|
||||
|
||||
In explicitly storing an "unbound" action, we are explicitly saying that this key chord
|
||||
must be passed through and this string must be removed from the command palette. `AddAction` automatically handles updating the internal state of `ActionMap` and any conflicting `Commands`.
|
||||
|
||||
This allows us to output something like this in the JSON:
|
||||
|
||||
```js
|
||||
{ "command": "unbound", "keys": "ctrl+c" }
|
||||
```
|
||||
|
||||
### Consolidated Actions
|
||||
|
||||
`AddAction` must be a bit smarter when it comes to the following scenario:
|
||||
- Given a command that unbinds a key chord: `{ "command": "unbound", "keys": "ctrl+c" }`
|
||||
- And... that key chord was set in a parent layer `{ "command": "copy", "keys": "ctrl+c" }`
|
||||
- But... the action has another key chord from a parent layer `{ "command": "copy", "keys": "ctrl+shift+c" }`
|
||||
|
||||
`_ActionMap` does not contain any information about a parent layer; it only contains actions introduced in the current layer. Thus, in the scenario above, unbinding `ctrl+c` is what is relevant to `_ActionMap`. However, this may cause some complications for `GetKeyChordForAction`. We cannot simply check our internal `_ActionMap`, because the primary key chord in the entry may be incorrect. Again, this is because `_ActionMap` is only aware of what was bound in the current layer.
|
||||
|
||||
To get around this issue, we've introduced `_ConsolidatedActions`. In a way, `_ConsolidatedActions` is similar to `_ActionMap`, except that it consolidates the `Command` data into one entry constructed across the current layer and the parent layers. Specifically, in the scenario above, `_ActionMap` will say that `copy` has no key chords. In fact, `_ActionMap` has no reason to have `copy` at all, because it was not introduced in this layer. Conversely, `_ConsolidatedActions` holds `copy` with a `ctrl+shift+c` binding, which is then returned to `GetKeyChordForAction`.
|
||||
|
||||
To maintain `_ConsolidatedActions`, any new action added to the Action Map must also update `_ConsolidatedActions`. It is especially important to handle and propagate collisions to `_ConsolidatedActions`.
|
||||
|
||||
When querying Action Map for an ID, we should always check in the following order:
|
||||
- `_ConsolidatedActions`
|
||||
- `_ActionMap`
|
||||
- repeat this process for each parent
|
||||
|
||||
This is to ensure that we are returning the correct and wholistic view of a `Command` on a query. Rather than acquiring a `Command` constructed in this layer, we receive one that contains all of the data acquired across the entire Action Map and its parents.
|
||||
|
||||
## Future considerations
|
||||
|
||||
There are a number of ideas regarding actions that would be fairly trivial to implement given this refactor:
|
||||
- [#6899]: Action IDs
|
||||
- As actions grow to become more widespread within Windows Terminal (i.e. dropdown and jumplist integration),
|
||||
a formal ID system would help users reference the same action throughout the app. With the internal
|
||||
ID system introduced earlier, we would simply introduce a new
|
||||
`std:map<string, InternalActionID> _ExternalIDMap` that is updated like the others, and add a `String ID`
|
||||
property to `Action`.
|
||||
- [#8100] Source Tracking
|
||||
- Identifying where a setting came from can be very beneficial in the settings model and UI. For example,
|
||||
profile settings now have an `OverrideSource` getter that describes what `Profile` object the setting
|
||||
came from (i.e. base layer, profile generator, etc...). A similar system can be used for `Action` in
|
||||
that we record if the action was last modified in defaults.json or settings.json.
|
||||
- There seems to be no desire for action inheritance (i.e. inheriting the name/key-chord from the parent).
|
||||
So this should be sufficient.
|
||||
|
||||
## Resources
|
||||
|
||||
[#885]: https://github.com/microsoft/terminal/issues/885
|
||||
[#6899]: https://github.com/microsoft/terminal/issues/6899
|
||||
[#8100]: https://github.com/microsoft/terminal/issues/8100
|
||||
[#8767]: https://github.com/microsoft/terminal/issues/8767
|
||||
|
||||
Other references:
|
||||
[Settings UI: Actions Page]: https://github.com/microsoft/terminal/issues/6900
|
||||
|
||||
[Settings UI: Actions Page Design]: https://github.com/microsoft/terminal/pulls/9427
|
||||
|
||||
[Action ID Spec]: https://github.com/microsoft/terminal/issues/7175
|
|
@ -1,171 +0,0 @@
|
|||
---
|
||||
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/
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Overview
|
||||
|
||||
This document outlines the roadmap towards delivering Windows Terminal 2.0.
|
||||
This document outlines the roadmap towards delivering Windows Terminal 2.0 by Winter 2021.
|
||||
|
||||
## Milestones
|
||||
|
||||
|
@ -27,13 +27,13 @@ Below is the schedule for when milestones will be included in release builds of
|
|||
| 2020-11-30 | [1.5] in Windows Terminal Preview<br>[1.4] in Windows Terminal | [Windows Terminal Preview 1.5 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-5-release/) |
|
||||
| 2021-01-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | [Windows Terminal Preview 1.6 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-6-release/) |
|
||||
| 2021-03-01 | [1.7] in Windows Terminal Preview<br>[1.6] in Windows Terminal | [Windows Terminal Preview 1.7 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-7-release/) |
|
||||
| 2021-04-14 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | [Windows Terminal Preview 1.8 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-8-release/) |
|
||||
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | [Windows Terminal Preview 1.9 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-9-release/) |
|
||||
| 2021-07-14 | [1.10] in Windows Terminal Preview<br>[1.9] in Windows Terminal | [Windows Terminal Preview 1.10 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-10-release/) |
|
||||
| 2021-08-31 | [1.11] in Windows Terminal Preview<br>[1.10] in Windows Terminal | [Windows Terminal Preview 1.11 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-11-release/) |
|
||||
| 2021-10-20 | [1.12] in Windows Terminal Preview<br>[1.11] in Windows Terminal | [Windows Terminal Preview 1.12 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-12-release/) |
|
||||
| | 2.0 RC in Windows Terminal Preview<br>2.0 RC in Windows Terminal | |
|
||||
| | [2.0] in Windows Terminal Preview<br>[2.0] in Windows Terminal | |
|
||||
| 2021-04-30 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | |
|
||||
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | |
|
||||
| 2021-07-31 | 1.10 in Windows Terminal Preview<br>[1.9] in Windows Terminal | |
|
||||
| 2021-08-30 | 1.11 in Windows Terminal Preview<br>1.10 in Windows Terminal | |
|
||||
| 2021-10-31 | 1.12 in Windows Terminal Preview<br>1.11 in Windows Terminal | |
|
||||
| 2021-11-30 | 2.0 RC in Windows Terminal Preview<br>2.0 RC in Windows Terminal | |
|
||||
| 2021-12-31 | [2.0] in Windows Terminal Preview<br>[2.0] in Windows Terminal | |
|
||||
|
||||
## Issue Triage & Prioritization
|
||||
|
||||
|
@ -49,32 +49,28 @@ The following are a list of the key scenarios we're aiming to deliver for Termin
|
|||
|
||||
> 👉 Note: There are many other features that don't fit within 2.0, but will be re-assessed and prioritized for 3.0, the plan for which will be published in 2021.
|
||||
|
||||
| Priority\* | Scenario | Description/Notes | State |
|
||||
| ---------- | -------- | ----------------- | ----- |
|
||||
| 0 | Settings UI | A user interface that connects to settings.json. This provides a way for people to edit their settings without having to edit a JSON file.<br><br>Issue: [#1564]<br>Specs: [#6720], [#6904]<br>Implementation: [#7283], [#7370], [#8048] | ✔️ |
|
||||
| 0 | Command palette | A popup menu to list possible actions and commands.<br><br>Issues: [#5400], [#2046]<br>Spec: [#2193]<br>Implementation: [#6635] | ✔️ |
|
||||
| 1 | Tab tear-off | The ability to tear a tab out of the current window and spawn a new window or attach it to a separate window.<br><br>Issue: [#1256], [#5000]<br>Spec: [#2080], [#7240] | 📝 |
|
||||
| 1 | Clickable links | Hyperlinking any links that appear in the text buffer. When clicking on the link, the link will open in your default browser.<br><br>Issue: [#574]<br>Implementation: [#7251] | ✔️ |
|
||||
| 1 | Default terminal | If a command-line application is spawned, it should open in Windows Terminal (if installed) or your preferred terminal<br><br>Issue: [#492]<br>Spec: [#2080], [#7414] | ✔️ |
|
||||
| 1 | Overall theme support | Tab coloring, title bar coloring, pane border coloring, pane border width, definition of what makes a theme<br><br>Issue: [#3327]<br>Spec: [#5772] | 🦶 |
|
||||
| 1 | Open profile elevated | Configure profiles to always open elevated (if Terminal was run unelevated)<br><br>Issue: [#5000], [#632]<br>Spec: [#8455] | 📝 |
|
||||
| 1 | Open tab in existing window | Open new tabs in existing Terminal windows<br><br>Issue: [#5000], [#4472]<br>Spec: [#8135] | ✔️ |
|
||||
| 1 | Traditional opacity | Have a transparent background without the acrylic blur.<br><br>Issue: [#603] | ✔️ |
|
||||
| 2 | SnapOnOutput, scroll lock | Pause output or scrolling on click.<br><br>Issue: [#980]<br>Spec: [#2529]<br>Implementation: [#6062] | ✔️ |
|
||||
| 2 | Infinite scrollback | Have an infinite history for the text buffer.<br><br>Issue: [#1410] | 🦶 |
|
||||
| 2 | Pane management | All issues listed out in the original issue. Some features include pane resizing with mouse, pane zooming, and opening a pane by prompting which profile to use.<br><br>Issue: [#1000] | 📝 |
|
||||
| 2 | Theme marketplace | Marketplace for creation and distribution of themes.<br>Dependent on overall theming | 🦶 |
|
||||
| 2 | Jump list | Show profiles from task bar (on right click)/start menu.<br><br>Issue: [#576]<br>Implementation: [#7515] | ✔️ |
|
||||
| 2 | Open with multiple tabs | A setting that allows Windows Terminal to launch with a specific tab configuration (not using only command line arguments).<br><br>Issue: [#756] | ✔️ |
|
||||
| 3 | Open in Windows Terminal | Functionality to right click on a file or folder and select Open in Windows Terminal.<br><br>Issue: [#1060]<br>Implementation: [#6100] | ✔️ |
|
||||
| 3 | Session restoration | Launch Windows Terminal and the previous session is restored with the proper tab and pane configuration and starting directories.<br><br>Issues: [#961], [#960], [#766] | ✔️ |
|
||||
| 3 | Quake mode | Provide a quick launch terminal that appears and disappears when a hotkey is pressed.<br><br>Issue: [#653] | ✔️ |
|
||||
| 3 | Settings migration infrastructure | Migrate people's settings without breaking them. Hand-in-hand with settings UI. | 🦶 |
|
||||
| 3 | Pointer bindings | Provide settings that can be bound to the mouse.<br><br>Issue: [#1553] | 🦶 |
|
||||
|
||||
* 📝: The feature is currently in progress
|
||||
* ✔️: The feature is complete and shipped in a Preview build
|
||||
* 🦶: The feature is at risk of being punted to a future release cycle (beyond 2.0)
|
||||
| Priority\* | Scenario | Description/Notes |
|
||||
| ---------- | -------- | ----------------- |
|
||||
| 0 | Settings UI | A user interface that connects to settings.json. This provides a way for people to edit their settings without having to edit a JSON file.<br><br>Issue: [#1564]<br>Specs: [#6720], [#6904]<br>Implementation: [#7283], [#7370], [#8048] |
|
||||
| 0 | Command palette | A popup menu to list possible actions and commands.<br><br>Issues: [#5400], [#2046]<br>Spec: [#2193]<br>Implementation: [#6635] |
|
||||
| 1 | Tab tear-off | The ability to tear a tab out of the current window and spawn a new window or attach it to a separate window.<br><br>Issue: [#1256], [#5000]<br>Spec: [#2080], [#7240] |
|
||||
| 1 | Clickable links | Hyperlinking any links that appear in the text buffer. When clicking on the link, the link will open in your default browser.<br><br>Issue: [#574]<br>Implementation: [#7251] |
|
||||
| 1 | Default terminal | If a command-line application is spawned, it should open in Windows Terminal (if installed) or your preferred terminal<br><br>Issue: [#492]<br>Spec: [#2080], [#7414] |
|
||||
| 1 | Overall theme support | Tab coloring, title bar coloring, pane border coloring, pane border width, definition of what makes a theme<br><br>Issue: [#3327]<br>Spec: [#5772] |
|
||||
| 1 | Open profile elevated | Configure profiles to always open elevated (if Terminal was run unelevated)<br><br>Issue: [#5000], [#632]<br>Spec: [#8455] |
|
||||
| 1 | Open tab in existing window | Open new tabs in existing Terminal windows<br><br>Issue: [#5000], [#4472]<br>Spec: [#8135] |
|
||||
| 1 | Traditional opacity | Have a transparent background without the acrylic blur.<br><br>Issue: [#603] <br>**Current State**: Blocked on WinUI 3.0 |
|
||||
| 2 | SnapOnOutput, scroll lock | Pause output or scrolling on click.<br><br>Issue: [#980]<br>Spec: [#2529]<br>Implementation: [#6062] |
|
||||
| 2 | Infinite scrollback | Have an infinite history for the text buffer.<br><br>Issue: [#1410] |
|
||||
| 2 | Pane management | All issues listed out in the original issue. Some features include pane resizing with mouse, pane zooming, and opening a pane by prompting which profile to use.<br><br>Issue: [#1000] |
|
||||
| 2 | Theme marketplace | Marketplace for creation and distribution of themes.<br>Dependent on overall theming |
|
||||
| 2 | Jump list | Show profiles from task bar (on right click)/start menu.<br><br>Issue: [#576]<br>Implementation: [#7515] |
|
||||
| 2 | Open with multiple tabs | A setting that allows Windows Terminal to launch with a specific tab configuration (not using only command line arguments).<br><br>Issue: [#756] |
|
||||
| 3 | Open in Windows Terminal | Functionality to right click on a file or folder and select Open in Windows Terminal.<br><br>Issue: [#1060]<br>Implementation: [#6100] |
|
||||
| 3 | Session restoration | Launch Windows Terminal and the previous session is restored with the proper tab and pane configuration and starting directories.<br><br>Issues: [#961], [#960], [#766] |
|
||||
| 3 | Quake mode | Provide a quick launch terminal that appears and disappears when a hotkey is pressed.<br><br>Issue: [#653] |
|
||||
| 3 | Settings migration infrastructure | Migrate people's settings without breaking them. Hand-in-hand with settings UI. |
|
||||
| 3 | Pointer bindings | Provide settings that can be bound to the mouse.<br><br>Issue: [#1553] |
|
||||
|
||||
Feature Notes:
|
||||
|
||||
|
@ -93,10 +89,6 @@ Feature Notes:
|
|||
[1.7]: https://github.com/microsoft/terminal/milestone/32
|
||||
[1.8]: https://github.com/microsoft/terminal/milestone/33
|
||||
[1.9]: https://github.com/microsoft/terminal/milestone/34
|
||||
[1.10]: https://github.com/microsoft/terminal/milestone/35
|
||||
[1.11]: https://github.com/microsoft/terminal/milestone/36
|
||||
[1.12]: https://github.com/microsoft/terminal/milestone/38
|
||||
[1.13]: https://github.com/microsoft/terminal/milestone/39
|
||||
[2.0]: https://github.com/microsoft/terminal/milestone/22
|
||||
[#1564]: https://github.com/microsoft/terminal/issues/1564
|
||||
[#6720]: https://github.com/microsoft/terminal/pull/6720
|
||||
|
|
|
@ -4,7 +4,7 @@ This was originally imported by @Austin-Lamb in December 2020.
|
|||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropriate governance standards.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
|
@ -12,4 +12,4 @@ That provenance file is automatically read and inventoried by Microsoft systems
|
|||
2. Take the parts you want, but leave most of it behind since it's HUGE and will bloat the repo to take it all. At the time of this writing, we only use small_vector.hpp and its dependencies as a header-only library.
|
||||
3. Validate that the license in the root of the repository didn't change and update it if so. It is sitting in a version-specific subdirectory below this readme.
|
||||
If it changed dramatically, ensure that it is still compatible with our license scheme. Also update the NOTICE file in the root of our repository to declare the third-party usage.
|
||||
4. Submit the pull.
|
||||
4. Submit the pull.
|
|
@ -4,7 +4,7 @@ This was originally imported by @miniksa in January 2020.
|
|||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropriate governance standards.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ This was originally imported by @miniksa in March 2020.
|
|||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropriate governance standards.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ This was originally imported by @DHowett-MSFT in April 2020.
|
|||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropriate governance standards.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ This was originally imported by @PankajBhojwani in September 2020.
|
|||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropriate governance standards.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ This was originally imported by @miniksa in March 2020.
|
|||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropriate governance standards.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -1,19 +0,0 @@
|
|||
Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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 OR COPYRIGHT HOLDERS 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.
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/imneme/pcg-cpp",
|
||||
"commitHash": "ffd522e7188bef30a00c74dc7eb9de5faff90092"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
// PCG Random Number Generation for C++
|
||||
//
|
||||
// Copyright 2014-2019 Melissa O'Neill <oneill@pcg-random.org>,
|
||||
// and the PCG Project contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (provided in
|
||||
// LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0)
|
||||
// or under the MIT license (provided in LICENSE-MIT.txt and at
|
||||
// http://opensource.org/licenses/MIT), at your option. This file may not
|
||||
// be copied, modified, or distributed except according to those terms.
|
||||
//
|
||||
// Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either
|
||||
// express or implied. See your chosen license for details.
|
||||
//
|
||||
// For additional information about the PCG random number generation scheme,
|
||||
// visit http://www.pcg-random.org/.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Leonard Hecker <lhecker@microsoft.com>:
|
||||
// The following contents are an extract of pcg_engines::oneseq_dxsm_64_32
|
||||
// reduced down to the bare essentials, while retaining base functionality.
|
||||
|
||||
namespace pcg_engines {
|
||||
class oneseq_dxsm_64_32 {
|
||||
using xtype = uint32_t;
|
||||
using itype = uint64_t;
|
||||
|
||||
itype state_;
|
||||
|
||||
static constexpr uint64_t multiplier() {
|
||||
return 6364136223846793005ULL;
|
||||
}
|
||||
|
||||
static constexpr uint64_t increment() {
|
||||
return 1442695040888963407ULL;
|
||||
}
|
||||
|
||||
static itype bump(itype state) {
|
||||
return state * multiplier() + increment();
|
||||
}
|
||||
|
||||
itype base_generate0() {
|
||||
itype old_state = state_;
|
||||
state_ = bump(state_);
|
||||
return old_state;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit oneseq_dxsm_64_32(itype state = 0xcafef00dd15ea5e5ULL) : state_(bump(state + increment())) {
|
||||
}
|
||||
|
||||
// Returns a value in the interval [0, UINT32_MAX].
|
||||
xtype operator()() {
|
||||
constexpr auto xtypebits = uint8_t(sizeof(xtype) * 8);
|
||||
constexpr auto itypebits = uint8_t(sizeof(itype) * 8);
|
||||
|
||||
auto internal = base_generate0();
|
||||
auto hi = xtype(internal >> (itypebits - xtypebits));
|
||||
auto lo = xtype(internal);
|
||||
|
||||
lo |= 1;
|
||||
hi ^= hi >> (xtypebits / 2);
|
||||
hi *= xtype(multiplier());
|
||||
hi ^= hi >> (3 * (xtypebits / 4));
|
||||
hi *= lo;
|
||||
return hi;
|
||||
}
|
||||
|
||||
// Returns a value in the interval [0, upper_bound).
|
||||
xtype operator()(xtype upper_bound) {
|
||||
uint32_t threshold = (UINT64_MAX + uint32_t(1) - upper_bound) % upper_bound;
|
||||
for (;;) {
|
||||
auto r = operator()();
|
||||
if (r >= threshold)
|
||||
return r % upper_bound;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -4,4 +4,4 @@ This manifest anchors our usage of rgb.txt from the X11 distribution.
|
|||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropriate governance standards.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
|
BIN
res/Cascadia.ttf
Normal file
BIN
res/CascadiaMono.ttf
Normal file
|
@ -6,3 +6,16 @@ The images in this directory do not fall under the same [license](https://raw.gi
|
|||
of the Windows Terminal code.
|
||||
|
||||
Please consult the [license](./LICENSE) in this directory for terms applicable to the image assets in this directory.
|
||||
|
||||
## Fonts
|
||||
|
||||
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
|
||||
of the Windows Terminal code.
|
||||
|
||||
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
|
||||
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
|
||||
|
||||
### Fonts Included
|
||||
|
||||
* Cascadia Code, Cascadia Mono (2102.25)
|
||||
* from microsoft/cascadia-code@911dc421f333e3b72b97381d16fee5b71eb48f04
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
# Windows Terminal and Console Assets (Fonts)
|
||||
|
||||
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
|
||||
of the Windows Terminal code.
|
||||
|
||||
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
|
||||
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
|
||||
|
||||
### Fonts Included
|
||||
|
||||
* Cascadia Code, Cascadia Mono (2108.26)
|
||||
* from microsoft/cascadia-code@f91d08f703ee61cf4ae936b9700ca974de2748fe
|
BIN
res/terminal/images-Dev/SplashScreen.scale-100.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.6 KiB |
BIN
res/terminal/images-Dev/SplashScreen.scale-125.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2 KiB |