Compare commits
103 commits
dev/cazamo
...
main
Author | SHA1 | Date | |
---|---|---|---|
f2386de422 | |||
80f8383860 | |||
bb71179a24 | |||
df06c54e70 | |||
a98d18c030 | |||
dc01926e3e | |||
6ad848e158 | |||
ea456cf121 | |||
442432ea15 | |||
fc85bdf314 | |||
a68b0d4f08 | |||
6742965bb8 | |||
131f5d2b32 | |||
7bfaad4592 | |||
c455418659 | |||
c79334ffbb | |||
2353349fe5 | |||
f6965aeb53 | |||
d5974f4c91 | |||
3fc82c2d4b | |||
305255c658 | |||
7db7ba1ac9 | |||
89c2b6d580 | |||
92643c1d34 | |||
e591d29000 | |||
88d58d313a | |||
87182554c8 | |||
5ff412fe6e | |||
30f7f2082b | |||
e6b871da47 | |||
f9c0f86705 | |||
86da0e041f | |||
a89b66f770 | |||
f9b97c4880 | |||
a74c37bbcd | |||
55dbda02a5 | |||
7aae2e9100 | |||
74d21afacf | |||
52b4bb760f | |||
b604117421 | |||
761203d95e | |||
4241d1c19e | |||
ab6ba9bdbb | |||
8826cc028b | |||
d3ca0e7878 | |||
726b428184 | |||
27e042b784 | |||
3667678df1 | |||
a7ce93a357 | |||
b90f3605a2 | |||
95cc7d9625 | |||
1cedac6a33 | |||
756fd444b1 | |||
5bc094e12a | |||
8560b4adfb | |||
fe26a6efc0 | |||
6d091f37b3 | |||
9aa4a115aa | |||
7b7dea009c | |||
a916a5d9de | |||
def1bdd693 | |||
9662bc6910 | |||
f63159db59 | |||
e10e1d8ef1 | |||
a2f26850c6 | |||
670ae2bd1c | |||
5cd9663269 | |||
8b8ad75024 | |||
6bf1507a6c | |||
5a23029dac | |||
284257a383 | |||
0d5af3fedc | |||
fd93c54ae3 | |||
c1d326693c | |||
2cf31ac72d | |||
02dd463b35 | |||
51c3011950 | |||
1c8b71b6e7 | |||
b3cc618af8 | |||
02ac246807 | |||
a89c3e2f85 | |||
462d8003a7 | |||
275cdcf63f | |||
08e36123b3 | |||
b036cab850 | |||
4a3e50cb16 | |||
0ab1529487 | |||
8dd317313b | |||
479ef264b2 | |||
dd5dbb2a40 | |||
bc4f410788 | |||
2b1468eaa2 | |||
e1c830dde0 | |||
84e7ec4f96 | |||
694c6b263f | |||
bd8bfa13bb | |||
dc865529b5 | |||
d26353bb32 | |||
431d51de4c | |||
184919fb24 | |||
01b5195275 | |||
dfda41074d | |||
26f4b0eacb |
19
.github/ISSUE_TEMPLATE/Bug_Report.yml
vendored
19
.github/ISSUE_TEMPLATE/Bug_Report.yml
vendored
|
@ -10,14 +10,21 @@ body:
|
|||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Windows Terminal version (or Windows build number)
|
||||
placeholder: "10.0.19042.0, 1.7.3651.0"
|
||||
label: Windows Terminal version
|
||||
placeholder: "1.7.3651.0"
|
||||
description: |
|
||||
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`.
|
||||
You can find the version in the about dialog, or by running `wt -v` at the commandline.
|
||||
validations:
|
||||
required: true
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Windows build number
|
||||
placeholder: "10.0.19042.0"
|
||||
description: |
|
||||
Please run `ver` or `[Environment]::OSVersion`.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
|
14
.github/actions/spelling/allow/allow.txt
vendored
14
.github/actions/spelling/allow/allow.txt
vendored
|
@ -1,12 +1,14 @@
|
|||
admins
|
||||
apc
|
||||
Apc
|
||||
bsd
|
||||
calt
|
||||
ccmp
|
||||
changelog
|
||||
cybersecurity
|
||||
Apc
|
||||
clickable
|
||||
clig
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
dcs
|
||||
Dcs
|
||||
|
@ -30,20 +32,22 @@ hyperlink
|
|||
hyperlinking
|
||||
hyperlinks
|
||||
img
|
||||
inlined
|
||||
It'd
|
||||
kje
|
||||
liga
|
||||
lje
|
||||
locl
|
||||
lorem
|
||||
Llast
|
||||
Lmid
|
||||
locl
|
||||
lorem
|
||||
Lorigin
|
||||
maxed
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
noreply
|
||||
nje
|
||||
noreply
|
||||
ogonek
|
||||
ok'd
|
||||
overlined
|
||||
|
|
12
.github/actions/spelling/allow/apis.txt
vendored
12
.github/actions/spelling/allow/apis.txt
vendored
|
@ -1,5 +1,7 @@
|
|||
ACCEPTFILES
|
||||
ACCESSDENIED
|
||||
acl
|
||||
aclapi
|
||||
alignas
|
||||
alignof
|
||||
APPLYTOSUBMENUS
|
||||
|
@ -9,6 +11,7 @@ BUILDBRANCH
|
|||
BUILDMSG
|
||||
BUILDNUMBER
|
||||
BYPOSITION
|
||||
BYCOMMAND
|
||||
charconv
|
||||
CLASSNOTAVAILABLE
|
||||
cmdletbinding
|
||||
|
@ -16,9 +19,11 @@ COLORPROPERTY
|
|||
colspan
|
||||
COMDLG
|
||||
comparand
|
||||
commandlinetoargv
|
||||
cstdint
|
||||
CXICON
|
||||
CYICON
|
||||
Dacl
|
||||
dataobject
|
||||
dcomp
|
||||
DERR
|
||||
|
@ -85,6 +90,7 @@ LSHIFT
|
|||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
memicmp
|
||||
mptt
|
||||
mov
|
||||
|
@ -114,15 +120,19 @@ OSVERSIONINFOEXW
|
|||
otms
|
||||
OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
ptstr
|
||||
rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
schandle
|
||||
semver
|
||||
serializer
|
||||
|
@ -159,6 +169,8 @@ toupper
|
|||
TTask
|
||||
TVal
|
||||
UChar
|
||||
UFIELD
|
||||
ULARGE
|
||||
UPDATEINIFILE
|
||||
userenv
|
||||
wcsstr
|
||||
|
|
8
.github/actions/spelling/allow/math.txt
vendored
8
.github/actions/spelling/allow/math.txt
vendored
|
@ -1,3 +1,11 @@
|
|||
atan
|
||||
CPrime
|
||||
HBar
|
||||
HPrime
|
||||
isnan
|
||||
LPrime
|
||||
LStep
|
||||
powf
|
||||
RSub
|
||||
sqrtf
|
||||
ULP
|
||||
|
|
3
.github/actions/spelling/allow/microsoft.txt
vendored
3
.github/actions/spelling/allow/microsoft.txt
vendored
|
@ -1,5 +1,6 @@
|
|||
ACLs
|
||||
ADMINS
|
||||
advapi
|
||||
altform
|
||||
altforms
|
||||
appendwttlogging
|
||||
|
@ -15,6 +16,7 @@ CPLs
|
|||
cpptools
|
||||
cppvsdbg
|
||||
CPRs
|
||||
cryptbase
|
||||
DACL
|
||||
DACLs
|
||||
diffs
|
||||
|
@ -46,6 +48,7 @@ powershell
|
|||
propkey
|
||||
pscustomobject
|
||||
QWORD
|
||||
regedit
|
||||
robocopy
|
||||
SACLs
|
||||
sdkddkver
|
||||
|
|
1
.github/actions/spelling/allow/names.txt
vendored
1
.github/actions/spelling/allow/names.txt
vendored
|
@ -9,6 +9,7 @@ Diviness
|
|||
dsafa
|
||||
duhowett
|
||||
ekg
|
||||
eryksun
|
||||
ethanschoonover
|
||||
Firefox
|
||||
Gatta
|
||||
|
|
2
.github/actions/spelling/excludes.txt
vendored
2
.github/actions/spelling/excludes.txt
vendored
|
@ -61,12 +61,14 @@ 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$
|
||||
|
|
10
.github/actions/spelling/expect/expect.txt
vendored
10
.github/actions/spelling/expect/expect.txt
vendored
|
@ -508,6 +508,7 @@ dealloc
|
|||
Debian
|
||||
debolden
|
||||
debugtype
|
||||
DECAC
|
||||
DECALN
|
||||
DECANM
|
||||
DECAUPSS
|
||||
|
@ -668,6 +669,7 @@ dwriteglyphrundescriptionclustermap
|
|||
dxgi
|
||||
dxgidwm
|
||||
dxinterop
|
||||
dxsm
|
||||
dxttbmp
|
||||
eachother
|
||||
eae
|
||||
|
@ -937,6 +939,7 @@ GTP
|
|||
guc
|
||||
gui
|
||||
guidatom
|
||||
guiddef
|
||||
GValue
|
||||
GWL
|
||||
GWLP
|
||||
|
@ -1231,6 +1234,7 @@ KLF
|
|||
KLMNO
|
||||
KLMNOPQRST
|
||||
KLMNOPQRSTQQQQQ
|
||||
KPRIORITY
|
||||
KVM
|
||||
langid
|
||||
LANGUAGELIST
|
||||
|
@ -1533,6 +1537,7 @@ NOCOLOR
|
|||
NOCOMM
|
||||
NOCONTEXTHELP
|
||||
NOCOPYBITS
|
||||
nodefaultlib
|
||||
nodiscard
|
||||
NODUP
|
||||
noexcept
|
||||
|
@ -1641,6 +1646,7 @@ onecoreuapuuid
|
|||
onecoreuuid
|
||||
ONECOREWINDOWS
|
||||
onehalf
|
||||
oneseq
|
||||
ONLCR
|
||||
openbash
|
||||
opencode
|
||||
|
@ -1707,6 +1713,7 @@ pcch
|
|||
PCCHAR
|
||||
PCCONSOLE
|
||||
PCD
|
||||
pcg
|
||||
pch
|
||||
PCHAR
|
||||
PCIDLIST
|
||||
|
@ -1802,6 +1809,7 @@ POSX
|
|||
POSXSCROLL
|
||||
POSYSCROLL
|
||||
ppci
|
||||
PPEB
|
||||
ppf
|
||||
ppguid
|
||||
ppidl
|
||||
|
@ -2021,6 +2029,7 @@ Rike
|
|||
RIPMSG
|
||||
RIS
|
||||
RMENU
|
||||
rng
|
||||
roadmap
|
||||
robomac
|
||||
roundtrip
|
||||
|
@ -2226,6 +2235,7 @@ STARTWPARMSW
|
|||
Statusline
|
||||
stdafx
|
||||
STDAPI
|
||||
stdc
|
||||
stdcall
|
||||
stdcpp
|
||||
stderr
|
||||
|
|
2
.github/actions/spelling/expect/web.txt
vendored
2
.github/actions/spelling/expect/web.txt
vendored
|
@ -1,5 +1,7 @@
|
|||
http
|
||||
www
|
||||
easyrgb
|
||||
php
|
||||
ecma
|
||||
rapidtables
|
||||
WCAG
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"Microsoft.Net.Component.4.5.TargetingPack",
|
||||
"Microsoft.VisualStudio.Component.DiagnosticTools",
|
||||
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.22000",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
|
||||
"Microsoft.VisualStudio.Component.VC.CoreIde",
|
||||
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
|
||||
|
|
|
@ -99,15 +99,29 @@ If you don't have any additional info/context to add but would like to indicate
|
|||
|
||||
## Contributing fixes / features
|
||||
|
||||
For those able & willing to help fix issues and/or implement 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.
|
||||
|
||||
### 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.
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
|
@ -125,7 +139,7 @@ Team members will be happy to help review specs and guide them to completion.
|
|||
|
||||
### Help Wanted
|
||||
|
||||
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).
|
||||
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).
|
||||
|
||||
---
|
||||
|
||||
|
|
67
NOTICE.md
67
NOTICE.md
|
@ -117,7 +117,6 @@ 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
|
||||
|
@ -148,7 +147,6 @@ 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\}
|
||||
|
@ -215,7 +213,6 @@ 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.
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
@ -249,7 +246,71 @@ 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
|
||||
|
|
|
@ -400,6 +400,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests",
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererAtlas", "src\renderer\atlas\atlas.vcxproj", "{8222900C-8B6C-452A-91AC-BE95DB04B95F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
AuditMode|Any CPU = AuditMode|Any CPU
|
||||
|
@ -3339,6 +3341,46 @@ Global
|
|||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.Build.0 = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.ActiveCfg = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.Build.0 = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -3438,6 +3480,7 @@ Global
|
|||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
|
||||
|
|
|
@ -214,7 +214,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](http://www.runasradio.com/Shows/Show/645)
|
||||
Turner](https://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)
|
||||
|
|
|
@ -63,8 +63,14 @@
|
|||
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)"
|
||||
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" />
|
||||
|
|
|
@ -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.19041.0\x86\MakeAppx.exe"
|
||||
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86\MakeAppx.exe"
|
||||
)
|
||||
|
||||
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {
|
||||
|
|
|
@ -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.19041.0"
|
||||
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2021</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>12</VersionMinor>
|
||||
<VersionMinor>13</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -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 introduce unexpected failures. However, the STL and other libraries like it are so useful that
|
||||
our code for fear that it might 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 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.
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
|
|
|
@ -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.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
</Dependencies>
|
||||
|
@ -517,7 +517,7 @@ This is because of a few key lines we already put in the appxmanifest:
|
|||
|
||||
```xml
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
</Dependencies>
|
||||
|
|
|
@ -188,6 +188,10 @@
|
|||
],
|
||||
"type": "string"
|
||||
},
|
||||
"adjustIndistinguishableColors": {
|
||||
"description": "When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.retroTerminalEffect": {
|
||||
"description": "When set to true, enable retro terminal effects when unfocused. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"type": "boolean"
|
||||
|
@ -455,7 +459,7 @@
|
|||
},
|
||||
"suppressApplicationTitle": {
|
||||
"type": "boolean",
|
||||
"default": "false",
|
||||
"default": false,
|
||||
"description": "When set to true, tabTitle overrides the default title of the tab and any title change messages from the application will be suppressed. When set to false, tabTitle behaves as normal"
|
||||
},
|
||||
"colorScheme": {
|
||||
|
@ -502,7 +506,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "adjustFontSize"
|
||||
"const": "adjustFontSize"
|
||||
},
|
||||
"delta": {
|
||||
"type": "integer",
|
||||
|
@ -526,7 +530,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "copy"
|
||||
"const": "copy"
|
||||
},
|
||||
"singleLine": {
|
||||
"type": "boolean",
|
||||
|
@ -562,7 +566,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "newTab"
|
||||
"const": "newTab"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -578,7 +582,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "switchToTab"
|
||||
"const": "switchToTab"
|
||||
},
|
||||
"index": {
|
||||
"type": "integer",
|
||||
|
@ -602,7 +606,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "movePane"
|
||||
"const": "movePane"
|
||||
},
|
||||
"index": {
|
||||
"type": "integer",
|
||||
|
@ -626,7 +630,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "moveFocus"
|
||||
"const": "moveFocus"
|
||||
},
|
||||
"direction": {
|
||||
"$ref": "#/$defs/FocusDirection",
|
||||
|
@ -650,7 +654,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "swapPane"
|
||||
"const": "swapPane"
|
||||
},
|
||||
"direction": {
|
||||
"$ref": "#/$defs/FocusDirection",
|
||||
|
@ -674,7 +678,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "resizePane"
|
||||
"const": "resizePane"
|
||||
},
|
||||
"direction": {
|
||||
"$ref": "#/$defs/ResizeDirection",
|
||||
|
@ -698,7 +702,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "sendInput"
|
||||
"const": "sendInput"
|
||||
},
|
||||
"input": {
|
||||
"type": "string",
|
||||
|
@ -725,7 +729,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "splitPane"
|
||||
"const": "splitPane"
|
||||
},
|
||||
"split": {
|
||||
"$ref": "#/$defs/SplitDirection",
|
||||
|
@ -757,7 +761,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "openSettings"
|
||||
"const": "openSettings"
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
|
@ -784,7 +788,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "setTabColor"
|
||||
"const": "setTabColor"
|
||||
},
|
||||
"color": {
|
||||
"$ref": "#/$defs/Color",
|
||||
|
@ -805,7 +809,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "setColorScheme"
|
||||
"const": "setColorScheme"
|
||||
},
|
||||
"colorScheme": {
|
||||
"type": "string",
|
||||
|
@ -829,7 +833,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "wt"
|
||||
"const": "wt"
|
||||
},
|
||||
"commandline": {
|
||||
"type": "string",
|
||||
|
@ -853,7 +857,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "closeOtherTabs"
|
||||
"const": "closeOtherTabs"
|
||||
},
|
||||
"index": {
|
||||
"oneOf": [
|
||||
|
@ -881,7 +885,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "closeTabsAfter"
|
||||
"const": "closeTabsAfter"
|
||||
},
|
||||
"index": {
|
||||
"oneOf": [
|
||||
|
@ -909,7 +913,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "closeTab"
|
||||
"const": "closeTab"
|
||||
},
|
||||
"index": {
|
||||
"oneOf": [
|
||||
|
@ -937,7 +941,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "scrollUp"
|
||||
"const": "scrollUp"
|
||||
},
|
||||
"rowsToScroll": {
|
||||
"type": [
|
||||
|
@ -961,7 +965,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "scrollDown"
|
||||
"const": "scrollDown"
|
||||
},
|
||||
"rowsToScroll": {
|
||||
"type": [
|
||||
|
@ -985,7 +989,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "moveTab"
|
||||
"const": "moveTab"
|
||||
},
|
||||
"direction": {
|
||||
"$ref": "#/$defs/MoveTabDirection",
|
||||
|
@ -1008,7 +1012,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "multipleActions"
|
||||
"const": "multipleActions"
|
||||
},
|
||||
"actions": {
|
||||
"$ref": "#/$defs/ShortcutAction",
|
||||
|
@ -1033,7 +1037,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "commandPalette"
|
||||
"const": "commandPalette"
|
||||
},
|
||||
"launchMode": {
|
||||
"$ref": "#/$defs/CommandPaletteLaunchMode",
|
||||
|
@ -1054,7 +1058,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "findMatch"
|
||||
"const": "findMatch"
|
||||
},
|
||||
"direction": {
|
||||
"$ref": "#/$defs/FindMatchDirection",
|
||||
|
@ -1081,7 +1085,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "newWindow"
|
||||
"const": "newWindow"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1097,7 +1101,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "prevTab"
|
||||
"const": "prevTab"
|
||||
},
|
||||
"tabSwitcherMode": {
|
||||
"$ref": "#/$defs/SwitchToAdjacentTabArgs",
|
||||
|
@ -1118,7 +1122,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "nextTab"
|
||||
"const": "nextTab"
|
||||
},
|
||||
"tabSwitcherMode": {
|
||||
"$ref": "#/$defs/SwitchToAdjacentTabArgs",
|
||||
|
@ -1139,7 +1143,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "renameTab"
|
||||
"const": "renameTab"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
|
@ -1160,7 +1164,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "renameWindow"
|
||||
"const": "renameWindow"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
|
@ -1181,7 +1185,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "focusPane"
|
||||
"const": "focusPane"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
|
@ -1203,7 +1207,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "globalSummon"
|
||||
"const": "globalSummon"
|
||||
},
|
||||
"desktop": {
|
||||
"type": "string",
|
||||
|
@ -1254,7 +1258,7 @@
|
|||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "quakeMode"
|
||||
"const": "quakeMode"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1329,6 +1333,12 @@
|
|||
{
|
||||
"$ref": "#/$defs/MoveTabAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/MultipleActionsAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/CommandPaletteAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/FindMatchAction"
|
||||
},
|
||||
|
@ -1468,6 +1478,11 @@
|
|||
"description": "When set to true, trailing white-spaces will be removed from text in rectangular (block) selection while copied to your clipboard. When set to false, the white-spaces will be preserved.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"trimPaste": {
|
||||
"default": true,
|
||||
"description": "When enabled, the Terminal will automatically trim trailing whitespace characters when pasting text",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.detectURLs": {
|
||||
"default": true,
|
||||
"description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.",
|
||||
|
@ -1571,22 +1586,22 @@
|
|||
"deprecated": true
|
||||
},
|
||||
"minimizeToNotificationArea": {
|
||||
"default": "false",
|
||||
"default": false,
|
||||
"description": "When set to true, minimizing a Terminal window will no longer appear in the taskbar. Instead, a Terminal icon will appear in the notification area through which the user can access their windows.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"alwaysShowNotificationIcon": {
|
||||
"default": "false",
|
||||
"default": false,
|
||||
"description": "When set to true, the Terminal's notification icon will always be shown in the notification area.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"showAdminShield": {
|
||||
"default": "true",
|
||||
"default": true,
|
||||
"description": "When set to true, the Terminal's tab row will display a shield icon when the Terminal is running with administrator privileges",
|
||||
"type": "boolean"
|
||||
},
|
||||
"useAcrylicInTabRow": {
|
||||
"default": "false",
|
||||
"default": false,
|
||||
"description": "When set to true, the tab row will have an acrylic background with 50% opacity.",
|
||||
"type": "boolean"
|
||||
},
|
||||
|
@ -1973,6 +1988,10 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"adjustIndistinguishableColors": {
|
||||
"description": "When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"scrollbarState": {
|
||||
"default": "visible",
|
||||
"description": "Defines the visibility of the scrollbar.",
|
||||
|
|
|
@ -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 ocurred and how to present that to the user.
|
||||
understand whether an error occurred and how to present that to the user.
|
||||
|
||||
|
||||
#### TerminalApp: Loading and Reloading Changes
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Overview
|
||||
|
||||
This document outlines the roadmap towards delivering Windows Terminal 2.0 by Winter 2021.
|
||||
This document outlines the roadmap towards delivering Windows Terminal 2.0.
|
||||
|
||||
## Milestones
|
||||
|
||||
|
@ -31,9 +31,9 @@ Below is the schedule for when milestones will be included in release builds of
|
|||
| 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-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 | |
|
||||
| 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 | |
|
||||
|
||||
## Issue Triage & Prioritization
|
||||
|
||||
|
@ -49,28 +49,32 @@ 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 |
|
||||
| ---------- | -------- | ----------------- |
|
||||
| 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] |
|
||||
| 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)
|
||||
|
||||
Feature Notes:
|
||||
|
||||
|
@ -91,6 +95,8 @@ Feature Notes:
|
|||
[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
|
||||
|
|
201
oss/pcg/LICENSE-APACHE.txt
Normal file
201
oss/pcg/LICENSE-APACHE.txt
Normal file
|
@ -0,0 +1,201 @@
|
|||
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.
|
19
oss/pcg/LICENSE-MIT.txt
Normal file
19
oss/pcg/LICENSE-MIT.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
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.
|
14
oss/pcg/cgmanifest.json
Normal file
14
oss/pcg/cgmanifest.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/imneme/pcg-cpp",
|
||||
"commitHash": "ffd522e7188bef30a00c74dc7eb9de5faff90092"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
82
oss/pcg/include/pcg_random.hpp
Normal file
82
oss/pcg/include/pcg_random.hpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
// 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>EchoCon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.22000.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
|
@ -163,4 +163,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
|
|
|
@ -118,6 +118,23 @@
|
|||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
BODGY
|
||||
|
||||
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
|
||||
executable we put in the package. But we DON'T produce a winmd. This makes the
|
||||
FastUpToDate check fail every time, and leads to the whole wapproj build
|
||||
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
|
||||
|
||||
Setting GenerateWindowsMetadata=false is enough to tell the build system that
|
||||
we don't produce one, and get it off our backs.
|
||||
-->
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
|
|
|
@ -13,6 +13,15 @@
|
|||
<EventProvider Id="EventProvider_TerminalRemoting" Name="d6f04aad-629f-539a-77c1-73f5c3e4aa7b" />
|
||||
<EventProvider Id="EventProvider_TerminalDirectX" Name="c93e739e-ae50-5a14-78e7-f171e947535d" />
|
||||
<EventProvider Id="EventProvider_TerminalUIA" Name="e7ebce59-2161-572d-b263-2f16a6afb9e5"/>
|
||||
<!-- Console providers here -->
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Launcher" Name="770aa552-671a-5e97-579b-151709ec0dbd"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Host" Name="fe1ff234-1f09-50a8-d38d-c44fab43e818"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Server" Name="1A541C01-589A-496E-85A7-A9E02170166D"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.VirtualTerminal.Parser" Name="c9ba2a84-d3ca-5e19-2bd6-776a0910cb9d"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Render.VtEngine" Name="c9ba2a95-d3ca-5e19-2bd6-776a0910cb9d"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.UIA" Name="e7ebce59-2161-572d-b263-2f16a6afb9e5"/>
|
||||
|
||||
<!-- Profile for General Terminal logging -->
|
||||
<Profile Id="Terminal.Verbose.File" Name="Terminal" Description="Terminal" LoggingMode="File" DetailLevel="Verbose">
|
||||
<Collectors>
|
||||
<EventCollectorId Value="EventCollector_Terminal">
|
||||
|
@ -32,5 +41,27 @@
|
|||
<Profile Id="Terminal.Light.File" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="File" DetailLevel="Light" />
|
||||
<Profile Id="Terminal.Verbose.Memory" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="Memory" DetailLevel="Verbose" />
|
||||
<Profile Id="Terminal.Light.Memory" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="Memory" DetailLevel="Light" />
|
||||
|
||||
<!-- Profile for DefTerm logging. Includes some conhost logging. -->
|
||||
<Profile Id="DefTerm.Verbose.File" Name="DefTerm" Description="DefTerm" LoggingMode="File" DetailLevel="Verbose">
|
||||
<Collectors>
|
||||
<EventCollectorId Value="EventCollector_Terminal">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EventProvider_TerminalControl" />
|
||||
<EventProviderId Value="EventProvider_TerminalConnection" />
|
||||
<EventProviderId Value="EventProvider_TerminalSettingsModel" />
|
||||
<EventProviderId Value="EventProvider_TerminalApp" />
|
||||
<EventProviderId Value="EventProvider_TerminalWin32Host" />
|
||||
<EventProviderId Value="EventProvider_TerminalRemoting" />
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.Launcher" />
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.Host" />
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.Server" />
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
</Profile>
|
||||
<Profile Id="DefTerm.Light.File" Name="DefTerm" Description="DefTerm" Base="DefTerm.Verbose.File" LoggingMode="File" DetailLevel="Light" />
|
||||
<Profile Id="DefTerm.Verbose.Memory" Name="DefTerm" Description="DefTerm" Base="DefTerm.Verbose.File" LoggingMode="Memory" DetailLevel="Verbose" />
|
||||
<Profile Id="DefTerm.Light.Memory" Name="DefTerm" Description="DefTerm" Base="DefTerm.Verbose.File" LoggingMode="Memory" DetailLevel="Light" />
|
||||
</Profiles>
|
||||
</WindowsPerformanceRecorder>
|
||||
</WindowsPerformanceRecorder>
|
||||
|
|
|
@ -12,8 +12,30 @@ static_assert(alignof(TextAttribute) == 2);
|
|||
// Ensure that we can memcpy() and memmove() the struct for performance.
|
||||
static_assert(std::is_trivially_copyable_v<TextAttribute>);
|
||||
|
||||
BYTE TextAttribute::s_legacyDefaultForeground = 7;
|
||||
BYTE TextAttribute::s_legacyDefaultBackground = 0;
|
||||
namespace
|
||||
{
|
||||
constexpr std::array<TextColor, 16> s_initLegacyColorMap(const BYTE defaultIndex)
|
||||
{
|
||||
std::array<TextColor, 16> legacyColorMap;
|
||||
for (auto i = 0u; i < legacyColorMap.size(); i++)
|
||||
{
|
||||
const auto legacyIndex = TextColor::TransposeLegacyIndex(i);
|
||||
gsl::at(legacyColorMap, i) = i == defaultIndex ? TextColor{} : TextColor{ legacyIndex, true };
|
||||
}
|
||||
return legacyColorMap;
|
||||
}
|
||||
|
||||
BYTE s_legacyDefaultForeground = 7;
|
||||
BYTE s_legacyDefaultBackground = 0;
|
||||
BYTE s_ansiDefaultForeground = 7;
|
||||
BYTE s_ansiDefaultBackground = 0;
|
||||
}
|
||||
|
||||
// These maps allow for an efficient conversion from a legacy attribute index
|
||||
// to a TextColor with the corresponding ANSI index, also taking into account
|
||||
// the legacy index values that need to be converted to a default TextColor.
|
||||
std::array<TextColor, 16> TextAttribute::s_legacyForegroundColorMap = s_initLegacyColorMap(7);
|
||||
std::array<TextColor, 16> TextAttribute::s_legacyBackgroundColorMap = s_initLegacyColorMap(0);
|
||||
|
||||
// Routine Description:
|
||||
// - Sets the legacy attributes which map to and from the default colors.
|
||||
|
@ -23,8 +45,22 @@ BYTE TextAttribute::s_legacyDefaultBackground = 0;
|
|||
// - None
|
||||
void TextAttribute::SetLegacyDefaultAttributes(const WORD defaultAttributes) noexcept
|
||||
{
|
||||
// First we reset the current default color map entries to what they should
|
||||
// be for a regular translation from a legacy index to an ANSI TextColor.
|
||||
gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{ s_ansiDefaultForeground, true };
|
||||
gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{ s_ansiDefaultBackground, true };
|
||||
|
||||
// Then we save the new default attribute values and their corresponding
|
||||
// ANSI translations. We use the latter values to more efficiently handle
|
||||
// the "VT Quirk" conversion below.
|
||||
s_legacyDefaultForeground = defaultAttributes & FG_ATTRS;
|
||||
s_legacyDefaultBackground = (defaultAttributes & BG_ATTRS) >> 4;
|
||||
s_ansiDefaultForeground = TextColor::TransposeLegacyIndex(s_legacyDefaultForeground);
|
||||
s_ansiDefaultBackground = TextColor::TransposeLegacyIndex(s_legacyDefaultBackground);
|
||||
|
||||
// Finally we set the new default color map entries.
|
||||
gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{};
|
||||
gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{};
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -55,13 +91,13 @@ TextAttribute TextAttribute::StripErroneousVT16VersionsOfLegacyDefaults(const Te
|
|||
const auto bg{ attribute.GetBackground() };
|
||||
auto copy{ attribute };
|
||||
if (fg.IsIndex16() &&
|
||||
attribute.IsBold() == WI_IsFlagSet(s_legacyDefaultForeground, FOREGROUND_INTENSITY) &&
|
||||
fg.GetIndex() == (s_legacyDefaultForeground & ~FOREGROUND_INTENSITY))
|
||||
attribute.IsBold() == WI_IsFlagSet(s_ansiDefaultForeground, FOREGROUND_INTENSITY) &&
|
||||
fg.GetIndex() == (s_ansiDefaultForeground & ~FOREGROUND_INTENSITY))
|
||||
{
|
||||
// We don't want to turn 1;37m into 39m (or even 1;39m), as this was meant to mimic a legacy color.
|
||||
copy.SetDefaultForeground();
|
||||
}
|
||||
if (bg.IsIndex16() && bg.GetIndex() == s_legacyDefaultBackground)
|
||||
if (bg.IsIndex16() && bg.GetIndex() == s_ansiDefaultBackground)
|
||||
{
|
||||
copy.SetDefaultBackground();
|
||||
}
|
||||
|
@ -92,22 +128,22 @@ bool TextAttribute::IsLegacy() const noexcept
|
|||
// - Calculates rgb colors based off of current color table and active modification attributes.
|
||||
// Arguments:
|
||||
// - colorTable: the current color table rgb values.
|
||||
// - defaultFgColor: the default foreground color rgb value.
|
||||
// - defaultBgColor: the default background color rgb value.
|
||||
// - defaultFgIndex: the color table index of the default foreground color.
|
||||
// - defaultBgIndex: the color table index of the default background color.
|
||||
// - reverseScreenMode: true if the screen mode is reversed.
|
||||
// - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false)
|
||||
// - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true)
|
||||
// Return Value:
|
||||
// - the foreground and background colors that should be displayed.
|
||||
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
|
||||
const COLORREF defaultFgColor,
|
||||
const COLORREF defaultBgColor,
|
||||
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
|
||||
const size_t defaultFgIndex,
|
||||
const size_t defaultBgIndex,
|
||||
const bool reverseScreenMode,
|
||||
const bool blinkingIsFaint,
|
||||
const bool boldIsBright) const noexcept
|
||||
{
|
||||
auto fg = _foreground.GetColor(colorTable, defaultFgColor, boldIsBright && IsBold());
|
||||
auto bg = _background.GetColor(colorTable, defaultBgColor);
|
||||
auto fg = _foreground.GetColor(colorTable, defaultFgIndex, boldIsBright && IsBold());
|
||||
auto bg = _background.GetColor(colorTable, defaultBgIndex);
|
||||
if (IsFaint() || (IsBlinking() && blinkingIsFaint))
|
||||
{
|
||||
fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two.
|
||||
|
|
|
@ -41,8 +41,8 @@ public:
|
|||
|
||||
explicit constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
|
||||
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
|
||||
_foreground{ s_LegacyIndexOrDefault(wLegacyAttr & FG_ATTRS, s_legacyDefaultForeground) },
|
||||
_background{ s_LegacyIndexOrDefault((wLegacyAttr & BG_ATTRS) >> 4, s_legacyDefaultBackground) },
|
||||
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
|
||||
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
|
||||
_extendedAttrs{ ExtendedAttributes::Normal },
|
||||
_hyperlinkId{ 0 }
|
||||
{
|
||||
|
@ -64,9 +64,9 @@ public:
|
|||
static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept;
|
||||
WORD GetLegacyAttributes() const noexcept;
|
||||
|
||||
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
|
||||
const COLORREF defaultFgColor,
|
||||
const COLORREF defaultBgColor,
|
||||
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
|
||||
const size_t defaultFgIndex,
|
||||
const size_t defaultBgIndex,
|
||||
const bool reverseScreenMode = false,
|
||||
const bool blinkingIsFaint = false,
|
||||
const bool boldIsBright = true) const noexcept;
|
||||
|
@ -167,13 +167,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
static constexpr TextColor s_LegacyIndexOrDefault(const BYTE requestedIndex, const BYTE defaultIndex)
|
||||
{
|
||||
return requestedIndex == defaultIndex ? TextColor{} : TextColor{ requestedIndex, true };
|
||||
}
|
||||
|
||||
static BYTE s_legacyDefaultForeground;
|
||||
static BYTE s_legacyDefaultBackground;
|
||||
static std::array<TextColor, 16> s_legacyForegroundColorMap;
|
||||
static std::array<TextColor, 16> s_legacyBackgroundColorMap;
|
||||
|
||||
uint16_t _wAttrLegacy; // sizeof: 2, alignof: 2
|
||||
uint16_t _hyperlinkId; // sizeof: 2, alignof: 2
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "precomp.h"
|
||||
#include "TextColor.h"
|
||||
|
||||
#include <til/bit.h>
|
||||
|
||||
// clang-format off
|
||||
|
||||
// A table mapping 8-bit RGB colors, in the form RRRGGGBB,
|
||||
|
@ -30,7 +32,7 @@ constexpr std::array<BYTE, 256> CompressedRgbToIndex16 = {
|
|||
// A table mapping indexed colors from the 256-color palette,
|
||||
// down to one of the 16 colors in the legacy palette.
|
||||
constexpr std::array<BYTE, 256> Index256ToIndex16 = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15,
|
||||
0, 1, 1, 1, 9, 9, 2, 1, 1, 1, 1, 1, 2, 2, 3, 3,
|
||||
3, 3, 2, 2, 11, 11, 3, 3, 10, 10, 11, 11, 11, 11, 10, 10,
|
||||
10, 10, 11, 11, 5, 5, 5, 5, 1, 1, 8, 8, 1, 1, 9, 9,
|
||||
|
@ -137,14 +139,16 @@ void TextColor::SetDefault() noexcept
|
|||
// Arguments:
|
||||
// - colorTable: The table of colors we should use to look up the value of
|
||||
// an indexed attribute from.
|
||||
// - defaultColor: The color value to use if we're a default attribute.
|
||||
// - defaultIndex: The color table index to use if we're a default attribute.
|
||||
// - brighten: if true, we'll brighten a dark color table index.
|
||||
// Return Value:
|
||||
// - a COLORREF containing the real value of this TextColor.
|
||||
COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten) const noexcept
|
||||
COLORREF TextColor::GetColor(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten) const noexcept
|
||||
{
|
||||
if (IsDefault())
|
||||
{
|
||||
const auto defaultColor = til::at(colorTable, defaultIndex);
|
||||
|
||||
if (brighten)
|
||||
{
|
||||
// See MSFT:20266024 for context on this fix.
|
||||
|
@ -186,7 +190,7 @@ COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const
|
|||
// the result will be something like 0b00100000.
|
||||
// 5. Use BitScanForward (bsf) to find the index of the most significant 1 bit.
|
||||
const auto haystack = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(colorTable.data())); // 1.
|
||||
const auto needle = _mm256_set1_epi32(__builtin_bit_cast(int, defaultColor)); // 2.
|
||||
const auto needle = _mm256_set1_epi32(til::bit_cast<int>(defaultColor)); // 2.
|
||||
const auto result = _mm256_cmpeq_epi32(haystack, needle); // 3.
|
||||
const auto mask = _mm256_movemask_ps(_mm256_castsi256_ps(result)); // 4.
|
||||
unsigned long index;
|
||||
|
@ -203,7 +207,7 @@ COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const
|
|||
// --> the index returned by _BitScanForward must be divided by 2.
|
||||
const auto haystack1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 0));
|
||||
const auto haystack2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 4));
|
||||
const auto needle = _mm_set1_epi32(__builtin_bit_cast(int, defaultColor));
|
||||
const auto needle = _mm_set1_epi32(til::bit_cast<int>(defaultColor));
|
||||
const auto result1 = _mm_cmpeq_epi32(haystack1, needle);
|
||||
const auto result2 = _mm_cmpeq_epi32(haystack2, needle);
|
||||
const auto result = _mm_packs_epi32(result1, result2); // 3.5
|
||||
|
@ -250,11 +254,7 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept
|
|||
{
|
||||
return defaultIndex;
|
||||
}
|
||||
else if (IsIndex16())
|
||||
{
|
||||
return GetIndex();
|
||||
}
|
||||
else if (IsIndex256())
|
||||
else if (IsIndex16() || IsIndex256())
|
||||
{
|
||||
return til::at(Index256ToIndex16, GetIndex());
|
||||
}
|
||||
|
|
|
@ -48,6 +48,28 @@ enum class ColorType : BYTE
|
|||
struct TextColor
|
||||
{
|
||||
public:
|
||||
static constexpr BYTE DARK_BLACK = 0;
|
||||
static constexpr BYTE DARK_RED = 1;
|
||||
static constexpr BYTE DARK_GREEN = 2;
|
||||
static constexpr BYTE DARK_YELLOW = 3;
|
||||
static constexpr BYTE DARK_BLUE = 4;
|
||||
static constexpr BYTE DARK_MAGENTA = 5;
|
||||
static constexpr BYTE DARK_CYAN = 6;
|
||||
static constexpr BYTE DARK_WHITE = 7;
|
||||
static constexpr BYTE BRIGHT_BLACK = 8;
|
||||
static constexpr BYTE BRIGHT_RED = 9;
|
||||
static constexpr BYTE BRIGHT_GREEN = 10;
|
||||
static constexpr BYTE BRIGHT_YELLOW = 11;
|
||||
static constexpr BYTE BRIGHT_BLUE = 12;
|
||||
static constexpr BYTE BRIGHT_MAGENTA = 13;
|
||||
static constexpr BYTE BRIGHT_CYAN = 14;
|
||||
static constexpr BYTE BRIGHT_WHITE = 15;
|
||||
|
||||
static constexpr size_t DEFAULT_FOREGROUND = 256;
|
||||
static constexpr size_t DEFAULT_BACKGROUND = 257;
|
||||
static constexpr size_t CURSOR_COLOR = 258;
|
||||
static constexpr size_t TABLE_SIZE = 259;
|
||||
|
||||
constexpr TextColor() noexcept :
|
||||
_meta{ ColorType::IsDefault },
|
||||
_red{ 0 },
|
||||
|
@ -86,7 +108,7 @@ public:
|
|||
void SetIndex(const BYTE index, const bool isIndex256) noexcept;
|
||||
void SetDefault() noexcept;
|
||||
|
||||
COLORREF GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten = false) const noexcept;
|
||||
COLORREF GetColor(const std::array<COLORREF, TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten = false) const noexcept;
|
||||
BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept;
|
||||
|
||||
constexpr BYTE GetIndex() const noexcept
|
||||
|
@ -96,6 +118,16 @@ public:
|
|||
|
||||
COLORREF GetRGB() const noexcept;
|
||||
|
||||
static constexpr BYTE TransposeLegacyIndex(const size_t index)
|
||||
{
|
||||
// When converting a 16-color index in the legacy Windows order to or
|
||||
// from an ANSI-compatible order, we need to swap the bits in positions
|
||||
// 0 and 2. We do this by XORing the index with 00000101, but only if
|
||||
// one (but not both) of those bit positions is set.
|
||||
const auto oneBitSet = (index ^ (index >> 2)) & 1;
|
||||
return gsl::narrow_cast<BYTE>(index ^ oneBitSet ^ (oneBitSet << 2));
|
||||
}
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
|
|
|
@ -27,9 +27,7 @@ Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
|
|||
_fDeferCursorRedraw(false),
|
||||
_fHaveDeferredCursorRedraw(false),
|
||||
_ulSize(ulSize),
|
||||
_cursorType(CursorType::Legacy),
|
||||
_fUseColor(false),
|
||||
_color(s_InvertCursorColor)
|
||||
_cursorType(CursorType::Legacy)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -143,10 +141,9 @@ void Cursor::SetSize(const ULONG ulSize) noexcept
|
|||
_RedrawCursor();
|
||||
}
|
||||
|
||||
void Cursor::SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept
|
||||
void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept
|
||||
{
|
||||
_ulSize = ulSize;
|
||||
_color = color;
|
||||
_cursorType = type;
|
||||
|
||||
_RedrawCursor();
|
||||
|
@ -285,7 +282,6 @@ void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
|
|||
// Size will be handled separately in the resize operation.
|
||||
//_ulSize = OtherCursor._ulSize;
|
||||
_cursorType = OtherCursor._cursorType;
|
||||
_color = OtherCursor._color;
|
||||
}
|
||||
|
||||
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
|
||||
|
@ -335,21 +331,6 @@ const CursorType Cursor::GetType() const noexcept
|
|||
return _cursorType;
|
||||
}
|
||||
|
||||
const bool Cursor::IsUsingColor() const noexcept
|
||||
{
|
||||
return GetColor() != INVALID_COLOR;
|
||||
}
|
||||
|
||||
const COLORREF Cursor::GetColor() const noexcept
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
void Cursor::SetColor(const unsigned int color) noexcept
|
||||
{
|
||||
_color = gsl::narrow_cast<COLORREF>(color);
|
||||
}
|
||||
|
||||
void Cursor::SetType(const CursorType type) noexcept
|
||||
{
|
||||
_cursorType = type;
|
||||
|
|
|
@ -24,7 +24,6 @@ class TextBuffer;
|
|||
class Cursor final
|
||||
{
|
||||
public:
|
||||
static const unsigned int s_InvertCursorColor = INVALID_COLOR;
|
||||
// the following values are used to create the textmode cursor.
|
||||
static constexpr unsigned int CURSOR_SMALL_SIZE = 25; // large enough to be one pixel on a six pixel font
|
||||
|
||||
|
@ -51,8 +50,6 @@ public:
|
|||
COORD GetPosition() const noexcept;
|
||||
|
||||
const CursorType GetType() const noexcept;
|
||||
const bool IsUsingColor() const noexcept;
|
||||
const COLORREF GetColor() const noexcept;
|
||||
|
||||
void StartDeferDrawing() noexcept;
|
||||
bool IsDeferDrawing() noexcept;
|
||||
|
@ -67,7 +64,7 @@ public:
|
|||
void SetIsPopupShown(const bool fIsPopupShown) noexcept;
|
||||
void SetDelay(const bool fDelay) noexcept;
|
||||
void SetSize(const ULONG ulSize) noexcept;
|
||||
void SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept;
|
||||
void SetStyle(const ULONG ulSize, const CursorType type) noexcept;
|
||||
|
||||
void SetPosition(const COORD cPosition) noexcept;
|
||||
void SetXPosition(const int NewX) noexcept;
|
||||
|
@ -84,7 +81,6 @@ public:
|
|||
COORD GetDelayedAtPosition() const noexcept;
|
||||
bool IsDelayedEOLWrap() const noexcept;
|
||||
|
||||
void SetColor(const unsigned int color) noexcept;
|
||||
void SetType(const CursorType type) noexcept;
|
||||
|
||||
private:
|
||||
|
@ -117,6 +113,4 @@ private:
|
|||
void _RedrawCursorAlways() noexcept;
|
||||
|
||||
CursorType _cursorType;
|
||||
bool _fUseColor;
|
||||
COLORREF _color;
|
||||
};
|
||||
|
|
|
@ -24,9 +24,11 @@ class TextAttributeTests
|
|||
TEST_METHOD(TestRoundtripDefaultColors);
|
||||
TEST_METHOD(TestBoldAsBright);
|
||||
|
||||
std::array<COLORREF, 256> _colorTable;
|
||||
COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||
const COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
const COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
|
||||
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
|
||||
};
|
||||
|
||||
bool TextAttributeTests::ClassSetup()
|
||||
|
@ -47,6 +49,8 @@ bool TextAttributeTests::ClassSetup()
|
|||
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
|
||||
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
|
||||
_colorTable[15] = RGB(242, 242, 242); // White
|
||||
_colorTable[_defaultFgIndex] = _defaultFg;
|
||||
_colorTable[_defaultBgIndex] = _defaultBg;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -132,17 +136,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
|||
// values when reverse video is not set
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// reset the reverse video
|
||||
attr.SetReverseVideo(false);
|
||||
|
@ -151,17 +155,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
|||
// while the background and getters stay the same
|
||||
attr.SetFaint(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched, and the background fainter, while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// reset the reverse video and faint attributes
|
||||
attr.SetReverseVideo(false);
|
||||
|
@ -171,17 +175,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
|||
// background, while getters stay the same
|
||||
attr.SetInvisible(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// with reverse video set, the calculated background value should match
|
||||
// the foreground, while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
}
|
||||
|
||||
void TextAttributeTests::TestReverseDefaultColors()
|
||||
|
@ -194,34 +198,34 @@ void TextAttributeTests::TestReverseDefaultColors()
|
|||
// values when reverse video is not set
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
attr.SetForeground(red);
|
||||
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
attr.Invert();
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
attr.SetDefaultForeground();
|
||||
attr.SetBackground(green);
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
}
|
||||
|
||||
void TextAttributeTests::TestRoundtripDefaultColors()
|
||||
|
@ -237,7 +241,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
|
|||
Log::Comment(L"Foreground legacy default index should map to default text color.");
|
||||
legacyAttribute = fgLegacyDefault | BACKGROUND_GREEN;
|
||||
textAttribute.SetDefaultForeground();
|
||||
textAttribute.SetIndexedBackground256(BACKGROUND_GREEN >> 4);
|
||||
textAttribute.SetIndexedBackground256(TextColor::DARK_GREEN);
|
||||
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
|
||||
|
||||
Log::Comment(L"Default foreground text color should map back to legacy default index.");
|
||||
|
@ -245,7 +249,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
|
|||
|
||||
Log::Comment(L"Background legacy default index should map to default text color.");
|
||||
legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault;
|
||||
textAttribute.SetIndexedForeground256(FOREGROUND_GREEN);
|
||||
textAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
|
||||
textAttribute.SetDefaultBackground();
|
||||
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
|
||||
|
||||
|
@ -277,43 +281,43 @@ void TextAttributeTests::TestBoldAsBright()
|
|||
// values when not bold
|
||||
VERIFY_IS_FALSE(attr.IsBold());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
// with bold set, calculated foreground/background values shouldn't change for the default colors.
|
||||
attr.SetBold(true);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
attr.SetIndexedForeground(0);
|
||||
attr.SetIndexedForeground(TextColor::DARK_BLACK);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
|
||||
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
|
||||
Log::Comment(L"Foreground should be dark black when bold is bright is disabled");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
attr.SetIndexedBackground(2);
|
||||
attr.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
|
||||
Log::Comment(L"background should be unaffected by 'bold is bright'");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
attr.SetBold(false);
|
||||
VERIFY_IS_FALSE(attr.IsBold());
|
||||
Log::Comment(L"when not bold, 'bold is bright' changes nothing");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
|
||||
attr.SetBold(true);
|
||||
attr.SetIndexedForeground(8);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
}
|
||||
|
|
|
@ -23,9 +23,11 @@ class TextColorTests
|
|||
TEST_METHOD(TestRgbColor);
|
||||
TEST_METHOD(TestChangeColor);
|
||||
|
||||
std::array<COLORREF, 256> _colorTable;
|
||||
COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||
const COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
const COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
|
||||
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
|
||||
};
|
||||
|
||||
bool TextColorTests::ClassSetup()
|
||||
|
@ -46,6 +48,8 @@ bool TextColorTests::ClassSetup()
|
|||
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
|
||||
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
|
||||
_colorTable[15] = RGB(242, 242, 242); // White
|
||||
_colorTable[_defaultFgIndex] = _defaultFg;
|
||||
_colorTable[_defaultBgIndex] = _defaultBg;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -57,16 +61,16 @@ void TextColorTests::TestDefaultColor()
|
|||
VERIFY_IS_FALSE(defaultColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(defaultColor.IsRgb());
|
||||
|
||||
auto color = defaultColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = defaultColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = defaultColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
}
|
||||
|
||||
|
@ -78,16 +82,16 @@ void TextColorTests::TestDarkIndexColor()
|
|||
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(indexColor.IsRgb());
|
||||
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
||||
|
@ -99,16 +103,16 @@ void TextColorTests::TestBrightIndexColor()
|
|||
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(indexColor.IsRgb());
|
||||
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
||||
|
@ -121,16 +125,16 @@ void TextColorTests::TestRgbColor()
|
|||
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
||||
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
||||
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
}
|
||||
|
||||
|
@ -143,55 +147,55 @@ void TextColorTests::TestChangeColor()
|
|||
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
||||
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
||||
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
rgbColor.SetDefault();
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
rgbColor.SetIndex(7, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
rgbColor.SetIndex(15, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
|
|
@ -61,13 +61,26 @@
|
|||
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
|
||||
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WindowsTerminal\WindowsTerminal.vcxproj" />
|
||||
<ProjectReference Include="..\..\host\exe\Host.EXE.vcxproj" />
|
||||
<ProjectReference Include="..\..\host\proxy\Host.Proxy.vcxproj" />
|
||||
<ProjectReference Include="..\TerminalAzBridge\TerminalAzBridge.vcxproj" />
|
||||
<ProjectReference Include="..\ShellExtension\WindowsTerminalShellExt.vcxproj" />
|
||||
<ProjectReference Include="..\wt\wt.vcxproj" />
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj">
|
||||
<Project>{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj">
|
||||
<Project>{067F0A06-FCB7-472C-96E9-B03B54E8E18D}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj">
|
||||
<Project>{f2ed628a-db22-446f-a081-4cc845b51a2b}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\wt\wt.vcxproj">
|
||||
<Project>{506fd703-baa7-4f6e-9361-64f550ec8fca}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\host\exe\Host.EXE.vcxproj">
|
||||
<Project>{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\host\proxy\Host.Proxy.vcxproj">
|
||||
<Project>{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace SettingsModelLocalTests
|
|||
|
||||
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
|
||||
const auto campbellSpan = gsl::make_span(expectedCampbellTable);
|
||||
Utils::InitializeCampbellColorTable(campbellSpan);
|
||||
Utils::InitializeColorTable(campbellSpan);
|
||||
Utils::SetColorTableAlpha(campbellSpan, 0);
|
||||
|
||||
for (size_t i = 0; i < expectedCampbellTable.size(); i++)
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
||||
#include "JsonTestClass.h"
|
||||
#include "TestUtils.h"
|
||||
|
||||
#include <defaults.h>
|
||||
#include <userDefaults.h>
|
||||
|
||||
using namespace Microsoft::Console;
|
||||
using namespace WEX::Logging;
|
||||
|
@ -70,6 +72,7 @@ namespace SettingsModelLocalTests
|
|||
TEST_METHOD(TestCloneInheritanceTree);
|
||||
TEST_METHOD(TestValidDefaults);
|
||||
TEST_METHOD(TestInheritedCommand);
|
||||
TEST_METHOD(LoadFragmentsWithMultipleUpdates);
|
||||
|
||||
private:
|
||||
static winrt::com_ptr<implementation::CascadiaSettings> createSettings(const std::string_view& userJSON)
|
||||
|
@ -1979,4 +1982,34 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_NULL(actualKeyChord);
|
||||
}
|
||||
}
|
||||
|
||||
// This test ensures GH#11597 doesn't regress.
|
||||
void DeserializationTests::LoadFragmentsWithMultipleUpdates()
|
||||
{
|
||||
static constexpr std::wstring_view fragmentSource{ L"fragment" };
|
||||
static constexpr std::string_view fragmentJson{ R"({
|
||||
"profiles": [
|
||||
{
|
||||
"updates": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
||||
"cursorShape": "filledBox"
|
||||
},
|
||||
{
|
||||
"updates": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
|
||||
"cursorShape": "filledBox"
|
||||
},
|
||||
{
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"commandline": "cmd.exe"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
implementation::SettingsLoader loader{ std::string_view{}, DefaultJson };
|
||||
loader.MergeInboxIntoUserSettings();
|
||||
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
|
||||
loader.FinalizeLayering();
|
||||
|
||||
VERIFY_IS_FALSE(loader.duplicateProfile);
|
||||
VERIFY_ARE_EQUAL(3u, loader.userSettings.profiles.size());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,20 +272,30 @@ namespace SettingsModelLocalTests
|
|||
void ProfileTests::DuplicateProfileTest()
|
||||
{
|
||||
static constexpr std::string_view userProfiles{ R"({
|
||||
"profiles": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"backgroundImage": "file:///some/path",
|
||||
"hidden": false,
|
||||
}
|
||||
]
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"font": {
|
||||
"size": 123
|
||||
}
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"backgroundImage": "file:///some/path",
|
||||
"hidden": false,
|
||||
}
|
||||
]
|
||||
}
|
||||
})" };
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userProfiles);
|
||||
const auto profile = settings->AllProfiles().GetAt(0);
|
||||
const auto duplicatedProfile = settings->DuplicateProfile(profile);
|
||||
|
||||
// GH#11392: Ensure duplicated profiles properly inherit the base layer, even for nested objects.
|
||||
VERIFY_ARE_EQUAL(123, duplicatedProfile.FontInfo().FontSize());
|
||||
|
||||
duplicatedProfile.Guid(profile.Guid());
|
||||
duplicatedProfile.Name(profile.Name());
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ namespace SettingsModelLocalTests
|
|||
"confirmCloseAllTabs": true,
|
||||
"largePasteWarning": true,
|
||||
"multiLinePasteWarning": true,
|
||||
"trimPaste": true,
|
||||
|
||||
"experimental.input.forceVT": false,
|
||||
"experimental.rendering.forceFullRepaint": false,
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "pch.h"
|
||||
|
||||
#include <til/rand.h>
|
||||
|
||||
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
||||
#include "../TerminalSettingsModel/TerminalSettings.h"
|
||||
#include "TestUtils.h"
|
||||
|
@ -34,14 +36,12 @@ namespace SettingsModelLocalTests
|
|||
END_TEST_CLASS()
|
||||
|
||||
TEST_METHOD(TryCreateWinRTType);
|
||||
|
||||
TEST_METHOD(TestTerminalArgsForBinding);
|
||||
|
||||
TEST_METHOD(CommandLineToArgvW);
|
||||
TEST_METHOD(GetProfileForArgsWithCommandline);
|
||||
TEST_METHOD(MakeSettingsForProfile);
|
||||
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
|
||||
|
||||
TEST_METHOD(TestLayerProfileOnColorScheme);
|
||||
|
||||
TEST_METHOD(TestCommandlineToTitlePromotion);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
|
@ -60,6 +60,139 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
|
||||
}
|
||||
|
||||
// CascadiaSettings::_normalizeCommandLine abuses some aspects from CommandLineToArgvW
|
||||
// to simplify the implementation. It assumes that all arguments returned by
|
||||
// CommandLineToArgvW are returned back to back in memory as "arg1\0arg2\0arg3\0...".
|
||||
// This test ensures CommandLineToArgvW doesn't change just to be sure.
|
||||
void TerminalSettingsTests::CommandLineToArgvW()
|
||||
{
|
||||
pcg_engines::oneseq_dxsm_64_32 rng{ til::gen_random<uint64_t>() };
|
||||
|
||||
const auto expectedArgc = static_cast<int>(rng(16) + 1);
|
||||
std::wstring expectedArgv;
|
||||
std::wstring input;
|
||||
|
||||
// We generate up to 16 arguments. Each argument is up to 64 chars long, is quoted
|
||||
// (2 chars, only applies to the input) and separated by a whitespace (1 char).
|
||||
expectedArgv.reserve(expectedArgc * 65);
|
||||
input.reserve(expectedArgc * 67);
|
||||
|
||||
for (int i = 0; i < expectedArgc; ++i)
|
||||
{
|
||||
const bool useQuotes = static_cast<bool>(rng(2));
|
||||
const auto count = static_cast<size_t>(rng(64));
|
||||
const auto ch = static_cast<wchar_t>(rng('z' - 'a' + 1) + 'a');
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
expectedArgv.push_back(L'\0');
|
||||
input.push_back(L' ');
|
||||
}
|
||||
|
||||
if (useQuotes)
|
||||
{
|
||||
input.push_back(L'"');
|
||||
}
|
||||
|
||||
expectedArgv.append(count, ch);
|
||||
input.append(count, ch);
|
||||
|
||||
if (useQuotes)
|
||||
{
|
||||
input.push_back(L'"');
|
||||
}
|
||||
}
|
||||
|
||||
int argc;
|
||||
wil::unique_hlocal_ptr<PWSTR[]> argv{ ::CommandLineToArgvW(input.c_str(), &argc) };
|
||||
VERIFY_ARE_EQUAL(expectedArgc, argc);
|
||||
VERIFY_IS_NOT_NULL(argv);
|
||||
|
||||
const auto lastArg = argv[argc - 1];
|
||||
const auto beg = argv[0];
|
||||
const auto end = lastArg + wcslen(lastArg);
|
||||
VERIFY_IS_GREATER_THAN(end, beg);
|
||||
VERIFY_ARE_EQUAL(expectedArgv.size(), static_cast<size_t>(end - beg));
|
||||
VERIFY_ARE_EQUAL(0, memcmp(beg, expectedArgv.data(), expectedArgv.size()));
|
||||
}
|
||||
|
||||
void TerminalSettingsTests::GetProfileForArgsWithCommandline()
|
||||
{
|
||||
// I'm exclusively using cmd.exe as I know exactly where it resides at.
|
||||
static constexpr std::string_view settingsJson{ R"({
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"historySize": 123
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"commandline": "%SystemRoot%\\System32\\cmd.exe"
|
||||
},
|
||||
{
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"commandline": "cmd.exe /A"
|
||||
},
|
||||
{
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"commandline": "cmd.exe /A /B"
|
||||
},
|
||||
{
|
||||
"guid": "{6239a42c-3333-49a3-80bd-e8fdd045185c}",
|
||||
"commandline": "cmd.exe /A /C",
|
||||
"connectionType": "{9a9977a7-1fe0-49c0-b6c0-13a0cd1c98a1}"
|
||||
}
|
||||
]
|
||||
}
|
||||
})" };
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settingsJson);
|
||||
|
||||
struct TestCase
|
||||
{
|
||||
std::wstring_view input;
|
||||
int expected;
|
||||
};
|
||||
|
||||
static constexpr std::array testCases{
|
||||
// Base test.
|
||||
TestCase{ L"cmd.exe", 0 },
|
||||
// SearchPathW() normalization + case insensitive matching.
|
||||
TestCase{ L"cmd.exe /a", 1 },
|
||||
TestCase{ L"C:\\Windows\\System32\\cmd.exe /A", 1 },
|
||||
// Test that we don't pick the equally long but different "/A /B" variant.
|
||||
TestCase{ L"C:\\Windows\\System32\\cmd.exe /A /C", 1 },
|
||||
// Test that we don't pick the shorter "/A" variant,
|
||||
// but do pick the shorter "/A /B" variant for longer inputs.
|
||||
TestCase{ L"cmd.exe /A /B", 2 },
|
||||
TestCase{ L"cmd.exe /A /B /C", 2 },
|
||||
// Ignore profiles with a connection type, like the Azure cloud shell.
|
||||
// Instead it should pick any other prefix.
|
||||
TestCase{ L"C:\\Windows\\System32\\cmd.exe /A /C", 1 },
|
||||
// Return base layer profile for missing profiles.
|
||||
TestCase{ L"C:\\Windows\\regedit.exe", -1 },
|
||||
};
|
||||
|
||||
for (const auto& testCase : testCases)
|
||||
{
|
||||
NewTerminalArgs args;
|
||||
args.Commandline(testCase.input);
|
||||
|
||||
const auto profile = settings->GetProfileForArgs(args);
|
||||
VERIFY_IS_NOT_NULL(profile);
|
||||
|
||||
if (testCase.expected < 0)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(123, profile.HistorySize());
|
||||
}
|
||||
else
|
||||
{
|
||||
GUID expectedGUID{ 0x6239a42c, static_cast<uint16_t>(0x1111 * testCase.expected), 0x49a3, { 0x80, 0xbd, 0xe8, 0xfd, 0xd0, 0x45, 0x18, 0x5c } };
|
||||
VERIFY_ARE_EQUAL(expectedGUID, static_cast<const GUID&>(profile.Guid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalSettingsTests::TestTerminalArgsForBinding()
|
||||
{
|
||||
static constexpr std::string_view settingsJson{ R"(
|
||||
|
|
|
@ -508,7 +508,7 @@ namespace TerminalAppLocalTests
|
|||
|
||||
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
|
@ -526,7 +526,7 @@ namespace TerminalAppLocalTests
|
|||
|
||||
Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
|
@ -844,7 +844,7 @@ namespace TerminalAppLocalTests
|
|||
// | 1 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Right, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
secondId = tab->_activePane->Id().value();
|
||||
});
|
||||
Sleep(250);
|
||||
|
@ -862,7 +862,7 @@ namespace TerminalAppLocalTests
|
|||
// | 3 | |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
// Split again to make the 3rd tab
|
||||
thirdId = tab->_activePane->Id().value();
|
||||
|
@ -882,7 +882,7 @@ namespace TerminalAppLocalTests
|
|||
// | 3 | 4 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
fourthId = tab->_activePane->Id().value();
|
||||
});
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
</Dependencies>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<uap:SupportedUsers>multiple</uap:SupportedUsers>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
|
|
|
@ -239,8 +239,8 @@ HRESULT HwndTerminal::Initialize()
|
|||
_terminal->SetBackgroundCallback([](auto) {});
|
||||
|
||||
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
|
||||
_terminal->SetDefaultBackground(RGB(12, 12, 12));
|
||||
_terminal->SetDefaultForeground(RGB(204, 204, 204));
|
||||
_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12));
|
||||
_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204));
|
||||
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
|
||||
localPointerToThread->EnablePainting();
|
||||
|
||||
|
@ -781,8 +781,8 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
|
|||
{
|
||||
auto lock = publicTerminal->_terminal->LockForWriting();
|
||||
|
||||
publicTerminal->_terminal->SetDefaultForeground(theme.DefaultForeground);
|
||||
publicTerminal->_terminal->SetDefaultBackground(theme.DefaultBackground);
|
||||
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground);
|
||||
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground);
|
||||
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha);
|
||||
|
||||
// Set the font colors
|
||||
|
@ -977,7 +977,7 @@ void HwndTerminal::_StringPaste(const wchar_t* const pData) noexcept
|
|||
CATCH_LOG();
|
||||
}
|
||||
|
||||
COORD HwndTerminal::GetFontSize() const
|
||||
COORD HwndTerminal::GetFontSize() const noexcept
|
||||
{
|
||||
return _actualFont.GetSize();
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ private:
|
|||
void _SendCharEvent(wchar_t ch, WORD scanCode, WORD flags) noexcept;
|
||||
|
||||
// Inherited via IControlAccessibilityInfo
|
||||
COORD GetFontSize() const override;
|
||||
COORD GetFontSize() const noexcept override;
|
||||
RECT GetBounds() const noexcept override;
|
||||
double GetScaleFactor() const noexcept override;
|
||||
void ChangeViewport(const SMALL_RECT NewWindow) override;
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
<ProjectReference Include="$(SolutionDir)src\types\lib\types.vcxproj">
|
||||
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)src\renderer\atlas\atlas.vcxproj">
|
||||
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)src\renderer\base\lib\base.vcxproj">
|
||||
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
||||
</ProjectReference>
|
||||
|
|
|
@ -174,10 +174,9 @@ namespace winrt::TerminalApp::implementation
|
|||
else if (const auto& realArgs = args.ActionArgs().try_as<SplitPaneArgs>())
|
||||
{
|
||||
_SplitPane(realArgs.SplitDirection(),
|
||||
realArgs.SplitMode(),
|
||||
// This is safe, we're already filtering so the value is (0, 1)
|
||||
::base::saturated_cast<float>(realArgs.SplitSize()),
|
||||
realArgs.TerminalArgs());
|
||||
_MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +555,7 @@ namespace winrt::TerminalApp::implementation
|
|||
auto actions = winrt::single_threaded_vector<ActionAndArgs>(std::move(
|
||||
TerminalPage::ConvertExecuteCommandlineToActions(realArgs)));
|
||||
|
||||
if (_startupActions.Size() != 0)
|
||||
if (actions.Size() != 0)
|
||||
{
|
||||
actionArgs.Handled(true);
|
||||
ProcessStartupActions(actions, false);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <WtExeUtils.h>
|
||||
#include <wil/token_helpers.h >
|
||||
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
using namespace winrt::Windows::ApplicationModel;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
@ -131,38 +133,6 @@ static Documents::Run _BuildErrorRun(const winrt::hstring& text, const ResourceD
|
|||
return textRun;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns whether the user is either a member of the Administrators group or
|
||||
// is currently elevated.
|
||||
// - This will return **FALSE** if the user has UAC disabled entirely, because
|
||||
// there's no separation of power between the user and an admin in that case.
|
||||
// Return Value:
|
||||
// - true if the user is an administrator
|
||||
static bool _isUserAdmin() noexcept
|
||||
try
|
||||
{
|
||||
wil::unique_handle processToken{ GetCurrentProcessToken() };
|
||||
const auto elevationType = wil::get_token_information<TOKEN_ELEVATION_TYPE>(processToken.get());
|
||||
const auto elevationState = wil::get_token_information<TOKEN_ELEVATION>(processToken.get());
|
||||
if (elevationType == TokenElevationTypeDefault && elevationState.TokenIsElevated)
|
||||
{
|
||||
// In this case, the user has UAC entirely disabled. This is sort of
|
||||
// weird, we treat this like the user isn't an admin at all. There's no
|
||||
// separation of powers, so the things we normally want to gate on
|
||||
// "having special powers" doesn't apply.
|
||||
//
|
||||
// See GH#7754, GH#11096
|
||||
return false;
|
||||
}
|
||||
|
||||
return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Function Description:
|
||||
|
@ -214,7 +184,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// The TerminalPage has to be constructed during our construction, to
|
||||
// make sure that there's a terminal page for callers of
|
||||
// SetTitleBarContent
|
||||
_isElevated = _isUserAdmin();
|
||||
_isElevated = ::Microsoft::Console::Utils::IsElevated();
|
||||
_root = winrt::make_self<TerminalPage>();
|
||||
|
||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||
|
@ -334,6 +304,9 @@ namespace winrt::TerminalApp::implementation
|
|||
_RefreshThemeRoutine();
|
||||
_ApplyStartupTaskStateChange();
|
||||
|
||||
auto args = winrt::make_self<SystemMenuChangeArgs>(RS_(L"SettingsMenuItem"), SystemMenuChangeAction::Add, SystemMenuItemHandler(this, &AppLogic::_OpenSettingsUI));
|
||||
_SystemMenuChangeRequestedHandlers(*this, *args);
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"AppCreated",
|
||||
|
@ -375,6 +348,8 @@ namespace winrt::TerminalApp::implementation
|
|||
co_return ContentDialogResult::None;
|
||||
}
|
||||
|
||||
_dialog = dialog;
|
||||
|
||||
// IMPORTANT: This is necessary as documented in the ContentDialog MSDN docs.
|
||||
// Since we're hosting the dialog in a Xaml island, we need to connect it to the
|
||||
// xaml tree somehow.
|
||||
|
@ -412,6 +387,16 @@ namespace winrt::TerminalApp::implementation
|
|||
// be released so another can be shown
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Dismiss the (only) visible ContentDialog
|
||||
void AppLogic::DismissDialog()
|
||||
{
|
||||
if (auto localDialog = std::exchange(_dialog, nullptr))
|
||||
{
|
||||
localDialog.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Displays a dialog for errors found while loading or validating the
|
||||
// settings. Uses the resources under the provided title and content keys
|
||||
|
@ -895,8 +880,6 @@ namespace winrt::TerminalApp::implementation
|
|||
void AppLogic::_RegisterSettingsChange()
|
||||
{
|
||||
const std::filesystem::path settingsPath{ std::wstring_view{ CascadiaSettings::SettingsPath() } };
|
||||
const std::filesystem::path statePath{ std::wstring_view{ ApplicationState::SharedInstance().FilePath() } };
|
||||
|
||||
_reader.create(
|
||||
settingsPath.parent_path().c_str(),
|
||||
false,
|
||||
|
@ -905,14 +888,29 @@ namespace winrt::TerminalApp::implementation
|
|||
// editors, who will write a temp file, then rename it to be the
|
||||
// actual file you wrote. So listen for that too.
|
||||
wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime,
|
||||
[this, settingsBasename = settingsPath.filename(), stateBasename = statePath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
|
||||
const auto modifiedBasename = std::filesystem::path{ fileModified }.filename();
|
||||
[this, settingsBasename = settingsPath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
|
||||
// DO NOT create a static reference to ApplicationState::SharedInstance here.
|
||||
//
|
||||
// ApplicationState::SharedInstance already caches its own
|
||||
// static ref. If _we_ keep a static ref to the member in
|
||||
// AppState, then our reference will keep ApplicationState alive
|
||||
// after the `ActionToStringMap` gets cleaned up. Then, when we
|
||||
// try to persist the actions in the window state, we won't be
|
||||
// able to. We'll try to look up the action and the map just
|
||||
// won't exist. We'll explode, even though the Terminal is
|
||||
// tearing down anyways. So we'll just die, but still invoke
|
||||
// WinDBG's post-mortem debugger, who won't be able to attach to
|
||||
// the process that's already exiting.
|
||||
//
|
||||
// So DON'T ~give a mouse a cookie~ take a static ref here.
|
||||
|
||||
const winrt::hstring modifiedBasename{ std::filesystem::path{ fileModified }.filename().c_str() };
|
||||
|
||||
if (modifiedBasename == settingsBasename)
|
||||
{
|
||||
_reloadSettings->Run();
|
||||
}
|
||||
else if (modifiedBasename == stateBasename)
|
||||
else if (ApplicationState::SharedInstance().IsStatePath(modifiedBasename))
|
||||
{
|
||||
_reloadState();
|
||||
}
|
||||
|
@ -1039,6 +1037,11 @@ namespace winrt::TerminalApp::implementation
|
|||
_SettingsChangedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
void AppLogic::_OpenSettingsUI()
|
||||
{
|
||||
_root->OpenSettingsUI();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns a pointer to the global shared settings.
|
||||
[[nodiscard]] CascadiaSettings AppLogic::GetSettings() const noexcept
|
||||
|
@ -1545,6 +1548,11 @@ namespace winrt::TerminalApp::implementation
|
|||
return _root->IsQuakeWindow();
|
||||
}
|
||||
|
||||
void AppLogic::RequestExitFullscreen()
|
||||
{
|
||||
_root->SetFullscreen(false);
|
||||
}
|
||||
|
||||
bool AppLogic::GetMinimizeToNotificationArea()
|
||||
{
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "AppLogic.g.h"
|
||||
#include "FindTargetWindowResult.g.h"
|
||||
#include "SystemMenuChangeArgs.g.h"
|
||||
#include "Jumplist.h"
|
||||
#include "LanguageProfileNotifier.h"
|
||||
#include "TerminalPage.h"
|
||||
|
@ -35,6 +36,17 @@ namespace winrt::TerminalApp::implementation
|
|||
FindTargetWindowResult(id, L""){};
|
||||
};
|
||||
|
||||
struct SystemMenuChangeArgs : SystemMenuChangeArgsT<SystemMenuChangeArgs>
|
||||
{
|
||||
WINRT_PROPERTY(winrt::hstring, Name, L"");
|
||||
WINRT_PROPERTY(SystemMenuChangeAction, Action, SystemMenuChangeAction::Add);
|
||||
WINRT_PROPERTY(SystemMenuItemHandler, Handler, nullptr);
|
||||
|
||||
public:
|
||||
SystemMenuChangeArgs(const winrt::hstring& name, SystemMenuChangeAction action, SystemMenuItemHandler handler = nullptr) :
|
||||
_Name{ name }, _Action{ action }, _Handler{ handler } {};
|
||||
};
|
||||
|
||||
struct AppLogic : AppLogicT<AppLogic, IInitializeWithWindow>
|
||||
{
|
||||
public:
|
||||
|
@ -79,6 +91,7 @@ namespace winrt::TerminalApp::implementation
|
|||
void SetPersistedLayoutIdx(const uint32_t idx);
|
||||
void SetNumberOfOpenWindows(const uint64_t num);
|
||||
bool IsQuakeWindow() const noexcept;
|
||||
void RequestExitFullscreen();
|
||||
|
||||
Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
|
||||
bool CenterOnLaunch();
|
||||
|
@ -106,12 +119,14 @@ namespace winrt::TerminalApp::implementation
|
|||
bool GetShowTitleInTitlebar();
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||
void DismissDialog();
|
||||
|
||||
Windows::Foundation::Collections::IMapView<Microsoft::Terminal::Control::KeyChord, Microsoft::Terminal::Settings::Model::Command> GlobalHotkeys();
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
|
||||
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs);
|
||||
|
||||
private:
|
||||
bool _isUwp{ false };
|
||||
|
@ -132,6 +147,7 @@ namespace winrt::TerminalApp::implementation
|
|||
uint64_t _numOpenWindows{ 0 };
|
||||
|
||||
std::shared_mutex _dialogLock;
|
||||
winrt::Windows::UI::Xaml::Controls::ContentDialog _dialog;
|
||||
|
||||
::TerminalApp::AppCommandlineArgs _appArgs;
|
||||
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
||||
|
@ -161,6 +177,7 @@ namespace winrt::TerminalApp::implementation
|
|||
void _RegisterSettingsChange();
|
||||
fire_and_forget _DispatchReloadSettings();
|
||||
void _ReloadSettings();
|
||||
void _OpenSettingsUI();
|
||||
|
||||
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);
|
||||
|
||||
|
|
|
@ -19,6 +19,20 @@ namespace TerminalApp
|
|||
String WindowName { get; };
|
||||
};
|
||||
|
||||
delegate void SystemMenuItemHandler();
|
||||
|
||||
enum SystemMenuChangeAction
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SystemMenuChangeArgs {
|
||||
String Name { get; };
|
||||
SystemMenuChangeAction Action { get; };
|
||||
SystemMenuItemHandler Handler { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter
|
||||
{
|
||||
AppLogic();
|
||||
|
@ -60,6 +74,7 @@ namespace TerminalApp
|
|||
void SetPersistedLayoutIdx(UInt32 idx);
|
||||
void SetNumberOfOpenWindows(UInt64 num);
|
||||
void RenameFailed();
|
||||
void RequestExitFullscreen();
|
||||
Boolean IsQuakeWindow();
|
||||
|
||||
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
|
||||
|
@ -91,6 +106,7 @@ namespace TerminalApp
|
|||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||
// information.
|
||||
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
|
||||
void DismissDialog();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
|
@ -109,5 +125,6 @@ namespace TerminalApp
|
|||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,22 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
|||
}
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {}
|
||||
~DebugInputTapConnection() = default;
|
||||
void Start()
|
||||
winrt::fire_and_forget Start()
|
||||
{
|
||||
// GH#11282: It's possible that we're about to be started, _before_
|
||||
// our paired connection is started. Both will get Start()'ed when
|
||||
// their owning TermControl is finally laid out. However, if we're
|
||||
// started first, then we'll immediately start printing to the other
|
||||
// control as well, which might not have initialized yet. If we do
|
||||
// that, we'll explode.
|
||||
//
|
||||
// Instead, wait here until the other connection is started too,
|
||||
// before actually starting the connection to the client app. This
|
||||
// will ensure both controls are initialized before the client app
|
||||
// is.
|
||||
co_await winrt::resume_background();
|
||||
_pairedTap->_start.wait();
|
||||
|
||||
_wrappedConnection.Start();
|
||||
}
|
||||
void WriteInput(hstring const& data)
|
||||
|
@ -59,6 +73,9 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
|||
void DebugTapConnection::Start()
|
||||
{
|
||||
// presume the wrapped connection is started.
|
||||
|
||||
// This is explained in the comment for GH#11282 above.
|
||||
_start.count_down();
|
||||
}
|
||||
|
||||
void DebugTapConnection::WriteInput(hstring const& data)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
|
||||
#include "../../inc/cppwinrt_utils.h"
|
||||
#include <til/latch.h>
|
||||
|
||||
namespace winrt::Microsoft::TerminalApp::implementation
|
||||
{
|
||||
|
@ -36,6 +37,8 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
|||
winrt::weak_ref<Microsoft::Terminal::TerminalConnection::ITerminalConnection> _wrappedConnection;
|
||||
winrt::weak_ref<Microsoft::Terminal::TerminalConnection::ITerminalConnection> _inputSide;
|
||||
|
||||
til::latch _start{ 1 };
|
||||
|
||||
friend class DebugInputTapConnection;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2351,35 +2351,32 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Split the focused pane in our tree of panes, and place the given
|
||||
// TermControl into the newly created pane. If we're the focused pane, then
|
||||
// we'll create two new children, and place them side-by-side in our Grid.
|
||||
// - The same as above, except this takes in the pane directly instead of a
|
||||
// profile and control to make a pane with
|
||||
// Arguments:
|
||||
// - splitType: what type of split we want to create.
|
||||
// - profile: The profile to associate with the newly created pane.
|
||||
// - control: A TermControl to use in the new pane.
|
||||
// - splitSize: the desired size of the split
|
||||
// - newPane: the new pane
|
||||
// Return Value:
|
||||
// - The two newly created Panes, with the original pane first
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const Profile& profile,
|
||||
const TermControl& control)
|
||||
std::shared_ptr<Pane> newPane)
|
||||
{
|
||||
if (!_lastActive)
|
||||
{
|
||||
if (_firstChild && _firstChild->_HasFocusedChild())
|
||||
{
|
||||
return _firstChild->Split(splitType, splitSize, profile, control);
|
||||
return _firstChild->Split(splitType, splitSize, newPane);
|
||||
}
|
||||
else if (_secondChild && _secondChild->_HasFocusedChild())
|
||||
{
|
||||
return _secondChild->Split(splitType, splitSize, profile, control);
|
||||
return _secondChild->Split(splitType, splitSize, newPane);
|
||||
}
|
||||
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
auto newPane = std::make_shared<Pane>(profile, control);
|
||||
return _Split(splitType, splitSize, newPane);
|
||||
}
|
||||
|
||||
|
|
|
@ -110,8 +110,7 @@ public:
|
|||
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
std::shared_ptr<Pane> pane);
|
||||
bool ToggleSplitOrientation();
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
|
|
|
@ -718,10 +718,17 @@
|
|||
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
|
||||
<value>Termination behavior can be configured in advanced profile settings.</value>
|
||||
</data>
|
||||
<data name="SetAsDefaultInfoBar.Message" xml:space="preserve">
|
||||
<value>Windows Terminal can be set as the default terminal application in your settings.</value>
|
||||
</data>
|
||||
<data name="InfoBarDismissButton.Content" xml:space="preserve">
|
||||
<value>Don't show again</value>
|
||||
</data>
|
||||
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>This Terminal window is running as Admin</value>
|
||||
</data>
|
||||
<data name="SetAsDefaultTip_OpenSettingsLink.Content" xml:space="preserve">
|
||||
<value>Open Settings</value>
|
||||
<comment>This is a call-to-action hyperlink; it will open the settings.</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace winrt::TerminalApp::implementation
|
|||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
|
||||
|
||||
_CreateNewTabWithProfileAndSettings(profile, settings, existingConnection);
|
||||
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection));
|
||||
|
||||
const uint32_t tabCount = _tabs.Size();
|
||||
const bool usedManualProfile = (newTerminalArgs != nullptr) &&
|
||||
|
@ -244,58 +244,6 @@ namespace winrt::TerminalApp::implementation
|
|||
_InitializeTab(newTabImpl);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates a new tab with the given settings. If the tab bar is not being
|
||||
// currently displayed, it will be shown.
|
||||
// Arguments:
|
||||
// - profile: profile settings for this connection
|
||||
// - settings: the TerminalSettings object to use to create the TerminalControl with.
|
||||
// - existingConnection: optionally receives a connection from the outside world instead of attempting to create one
|
||||
void TerminalPage::_CreateNewTabWithProfileAndSettings(const Profile& profile, const TerminalSettingsCreateResult& settings, TerminalConnection::ITerminalConnection existingConnection)
|
||||
{
|
||||
// Initialize the new tab
|
||||
// Create a connection based on the values in our settings object if we weren't given one.
|
||||
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, settings.DefaultSettings());
|
||||
|
||||
// If we had an `existingConnection`, then this is an inbound handoff from somewhere else.
|
||||
// We need to tell it about our size information so it can match the dimensions of what
|
||||
// we are about to present.
|
||||
if (existingConnection)
|
||||
{
|
||||
connection.Resize(settings.DefaultSettings().InitialRows(), settings.DefaultSettings().InitialCols());
|
||||
}
|
||||
|
||||
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
|
||||
if (_settings.GlobalSettings().DebugFeaturesEnabled())
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
||||
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
||||
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
if (bothAltsPressed)
|
||||
{
|
||||
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
// Give term control a child of the settings so that any overrides go in the child
|
||||
// This way, when we do a settings reload we just update the parent and the overrides remain
|
||||
auto term = _InitControl(settings, connection);
|
||||
|
||||
auto newTabImpl = winrt::make_self<TerminalTab>(profile, term);
|
||||
_RegisterTerminalEvents(term);
|
||||
_InitializeTab(newTabImpl);
|
||||
|
||||
if (debugConnection) // this will only be set if global debugging is on and tap is active
|
||||
{
|
||||
auto newControl = _InitControl(settings, debugConnection);
|
||||
_RegisterTerminalEvents(newControl);
|
||||
// Split (auto) with the debug tap.
|
||||
newTabImpl->SplitPane(SplitDirection::Automatic, 0.5f, profile, newControl);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the icon of the currently focused terminal control, and set its
|
||||
// tab's icon to that icon.
|
||||
|
@ -365,28 +313,14 @@ namespace winrt::TerminalApp::implementation
|
|||
// In the future, it may be preferable to just duplicate the
|
||||
// current control's live settings (which will include changes
|
||||
// made through VT).
|
||||
_CreateNewTabFromPane(_MakePane(nullptr, true, nullptr));
|
||||
|
||||
if (auto profile = tab.GetFocusedProfile())
|
||||
const auto runtimeTabText{ tab.GetTabText() };
|
||||
if (!runtimeTabText.empty())
|
||||
{
|
||||
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
||||
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
||||
const auto settingsCreateResult{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
|
||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
||||
if (validWorkingDirectory)
|
||||
if (auto newTab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
settingsCreateResult.DefaultSettings().StartingDirectory(workingDirectory);
|
||||
}
|
||||
|
||||
_CreateNewTabWithProfileAndSettings(profile, settingsCreateResult);
|
||||
|
||||
const auto runtimeTabText{ tab.GetTabText() };
|
||||
if (!runtimeTabText.empty())
|
||||
{
|
||||
if (auto newTab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
newTab->SetTabText(runtimeTabText);
|
||||
}
|
||||
newTab->SetTabText(runtimeTabText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +336,7 @@ namespace winrt::TerminalApp::implementation
|
|||
try
|
||||
{
|
||||
_SetFocusedTab(tab);
|
||||
_SplitPane(tab, SplitDirection::Automatic, SplitType::Duplicate);
|
||||
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
|
|
@ -318,7 +318,29 @@
|
|||
</ProjectReference>
|
||||
<!-- For whatever reason, we can't include the TerminalControl and
|
||||
TerminalSettings projects' winmds via project references. So we'll have to
|
||||
manually include the winmds as References below -->
|
||||
manually include the winmds as References below
|
||||
|
||||
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
|
||||
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
|
||||
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
|
||||
Up-to-date Check will look for the .xaml files from that project in our
|
||||
output, which won't actually be there.
|
||||
|
||||
We do still need to separately reference the winmds manually below, which is annoying.
|
||||
-->
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
|
||||
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
|
||||
the manual reference to TerminalControl.winmd below make sure that this
|
||||
project will compile correct, and that we won't roll up the TermControl
|
||||
xbf's into the packaging project twice. -->
|
||||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj">
|
||||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- This is a hack to get the ARM64 CI build working. See
|
||||
|
|
|
@ -3,38 +3,38 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "TerminalPage.h"
|
||||
#include "Utils.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "TerminalPage.g.cpp"
|
||||
#include "RenameWindowRequestedArgs.g.cpp"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <inc/WindowingBehavior.h>
|
||||
#include <LibraryResources.h>
|
||||
#include <TerminalCore/ControlKeyStates.hpp>
|
||||
#include <til/latch.h>
|
||||
|
||||
#include "TerminalPage.g.cpp"
|
||||
#include <winrt/Windows.Storage.h>
|
||||
|
||||
#include "TabRowControl.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "ColorHelper.h"
|
||||
#include "DebugTapConnection.h"
|
||||
#include "SettingsTab.h"
|
||||
#include "RenameWindowRequestedArgs.g.cpp"
|
||||
#include "../inc/WindowingBehavior.h"
|
||||
|
||||
#include <til/latch.h>
|
||||
#include "TabRowControl.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace ::TerminalApp;
|
||||
using namespace ::Microsoft::Console;
|
||||
using namespace ::Microsoft::Terminal::Core;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });
|
||||
|
@ -218,7 +218,7 @@ namespace winrt::TerminalApp::implementation
|
|||
_RegisterActionCallbacks();
|
||||
|
||||
// Hook up inbound connection event handler
|
||||
TerminalConnection::ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection });
|
||||
ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection });
|
||||
|
||||
//Event Bindings (Early)
|
||||
_newTabButton.Click([weakThis{ get_weak() }](auto&&, auto&&) {
|
||||
|
@ -287,6 +287,8 @@ namespace winrt::TerminalApp::implementation
|
|||
_defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
ShowSetAsDefaultInfoBar();
|
||||
}
|
||||
|
||||
// Method Description;
|
||||
|
@ -298,10 +300,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - true if the ApplicationState should be used.
|
||||
bool TerminalPage::ShouldUsePersistedLayout(CascadiaSettings& settings) const
|
||||
{
|
||||
// GH#5000 Until there is a separate state file for elevated sessions we should just not
|
||||
// save at all while in an elevated window.
|
||||
return Feature_PersistedWindowLayout::IsEnabled() &&
|
||||
!IsElevated() &&
|
||||
settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout;
|
||||
}
|
||||
|
||||
|
@ -848,14 +847,7 @@ namespace winrt::TerminalApp::implementation
|
|||
WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
|
||||
if (altPressed && !debugTap)
|
||||
{
|
||||
this->_SplitPane(SplitDirection::Automatic,
|
||||
SplitType::Manual,
|
||||
0.5f,
|
||||
newTerminalArgs);
|
||||
}
|
||||
else if (shiftPressed && !debugTap)
|
||||
if (shiftPressed && !debugTap)
|
||||
{
|
||||
// Manually fill in the evaluated profile.
|
||||
if (newTerminalArgs.ProfileIndex() != nullptr)
|
||||
|
@ -871,7 +863,17 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_IF_FAILED(this->_OpenNewTab(newTerminalArgs));
|
||||
const auto newPane = _MakePane(newTerminalArgs);
|
||||
if (altPressed && !debugTap)
|
||||
{
|
||||
this->_SplitPane(SplitDirection::Automatic,
|
||||
0.5f,
|
||||
newPane);
|
||||
}
|
||||
else
|
||||
{
|
||||
_CreateNewTabFromPane(newPane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1036,29 +1038,153 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// Called when the users pressed keyBindings while CommandPalette is open.
|
||||
// - Called when the users pressed keyBindings while CommandPalette is open.
|
||||
// - This method is effectively an extract of TermControl::_KeyHandler and TermControl::_TryHandleKeyBinding.
|
||||
// Arguments:
|
||||
// - e: the KeyRoutedEventArgs containing info about the keystroke.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
|
||||
{
|
||||
const auto key = e.OriginalKey();
|
||||
const auto scanCode = e.KeyStatus().ScanCode;
|
||||
const auto coreWindow = CoreWindow::GetForCurrentThread();
|
||||
const auto ctrlDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
|
||||
const auto altDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
|
||||
const auto shiftDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
|
||||
const auto keyStatus = e.KeyStatus();
|
||||
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey());
|
||||
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||
const auto modifiers = _GetPressedModifierKeys();
|
||||
|
||||
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, false, static_cast<int32_t>(key), static_cast<int32_t>(scanCode) };
|
||||
if (const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) })
|
||||
// GH#11076:
|
||||
// For some weird reason we sometimes receive a WM_KEYDOWN
|
||||
// message without vkey or scanCode if a user drags a tab.
|
||||
// The KeyChord constructor has a debug assertion ensuring that all KeyChord
|
||||
// either have a valid vkey/scanCode. This is important, because this prevents
|
||||
// accidential insertion of invalid KeyChords into classes like ActionMap.
|
||||
if (!vkey && !scanCode)
|
||||
{
|
||||
if (CommandPalette().Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
return;
|
||||
}
|
||||
|
||||
// Alt-Numpad# input will send us a character once the user releases
|
||||
// Alt, so we should be ignoring the individual keydowns. The character
|
||||
// will be sent through the TSFInputControl. See GH#1401 for more
|
||||
// details
|
||||
if (modifiers.IsAltPressed() && (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// GH#2235: Terminal::Settings hasn't been modified to differentiate
|
||||
// between AltGr and Ctrl+Alt yet.
|
||||
// -> Don't check for key bindings if this is an AltGr key combination.
|
||||
if (modifiers.IsAltGrPressed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto actionMap = _settings.ActionMap();
|
||||
if (!actionMap)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto cmd = actionMap.GetActionByKeyChord({
|
||||
modifiers.IsCtrlPressed(),
|
||||
modifiers.IsAltPressed(),
|
||||
modifiers.IsShiftPressed(),
|
||||
modifiers.IsWinPressed(),
|
||||
vkey,
|
||||
scanCode,
|
||||
});
|
||||
if (!cmd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_actionDispatch->DoAction(cmd.ActionAndArgs()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
{
|
||||
p.Visibility(Visibility::Collapsed);
|
||||
}
|
||||
|
||||
// Let's assume the user has bound the dead key "^" to a sendInput command that sends "b".
|
||||
// If the user presses the two keys "^a" it'll produce "bâ", despite us marking the key event as handled.
|
||||
// The following is used to manually "consume" such dead keys and clear them from the keyboard state.
|
||||
_ClearKeyboardState(vkey, scanCode);
|
||||
e.Handled(true);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the modifier keys that are currently pressed. This can be used to
|
||||
// find out which modifiers (ctrl, alt, shift) are pressed in events that
|
||||
// don't necessarily include that state.
|
||||
// - This is a copy of TermControl::_GetPressedModifierKeys.
|
||||
// Return Value:
|
||||
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
|
||||
ControlKeyStates TerminalPage::_GetPressedModifierKeys() noexcept
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
// DONT USE
|
||||
// != CoreVirtualKeyStates::None
|
||||
// OR
|
||||
// == CoreVirtualKeyStates::Down
|
||||
// Sometimes with the key down, the state is Down | Locked.
|
||||
// Sometimes with the key up, the state is Locked.
|
||||
// IsFlagSet(Down) is the only correct solution.
|
||||
|
||||
struct KeyModifier
|
||||
{
|
||||
VirtualKey vkey;
|
||||
ControlKeyStates flags;
|
||||
};
|
||||
|
||||
constexpr std::array<KeyModifier, 7> modifiers{ {
|
||||
{ VirtualKey::RightMenu, ControlKeyStates::RightAltPressed },
|
||||
{ VirtualKey::LeftMenu, ControlKeyStates::LeftAltPressed },
|
||||
{ VirtualKey::RightControl, ControlKeyStates::RightCtrlPressed },
|
||||
{ VirtualKey::LeftControl, ControlKeyStates::LeftCtrlPressed },
|
||||
{ VirtualKey::Shift, ControlKeyStates::ShiftPressed },
|
||||
{ VirtualKey::RightWindows, ControlKeyStates::RightWinPressed },
|
||||
{ VirtualKey::LeftWindows, ControlKeyStates::LeftWinPressed },
|
||||
} };
|
||||
|
||||
ControlKeyStates flags;
|
||||
|
||||
for (const auto& mod : modifiers)
|
||||
{
|
||||
const auto state = window.GetKeyState(mod.vkey);
|
||||
const auto isDown = WI_IsFlagSet(state, CoreVirtualKeyStates::Down);
|
||||
|
||||
if (isDown)
|
||||
{
|
||||
CommandPalette().Visibility(Visibility::Collapsed);
|
||||
flags |= mod.flags;
|
||||
}
|
||||
_actionDispatch->DoAction(cmd.ActionAndArgs());
|
||||
e.Handled(true);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Discards currently pressed dead keys.
|
||||
// - This is a copy of TermControl::_ClearKeyboardState.
|
||||
// Arguments:
|
||||
// - vkey: The vkey of the key pressed.
|
||||
// - scanCode: The scan code of the key pressed.
|
||||
void TerminalPage::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
|
||||
{
|
||||
std::array<BYTE, 256> keyState;
|
||||
if (!GetKeyboardState(keyState.data()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// As described in "Sometimes you *want* to interfere with the keyboard's state buffer":
|
||||
// http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
|
||||
// > "The key here is to keep trying to pass stuff to ToUnicode until -1 is not returned."
|
||||
std::array<wchar_t, 16> buffer;
|
||||
while (ToUnicodeEx(vkey, scanCode, keyState.data(), buffer.data(), gsl::narrow_cast<int>(buffer.size()), 0b1, nullptr) < 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1483,18 +1609,15 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
// Method Description:
|
||||
// - Split the focused pane either horizontally or vertically, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// given pane accordingly in the tree
|
||||
// Arguments:
|
||||
// - newPane: the pane to add to our tree of panes
|
||||
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
||||
// new pane should be split from its parent.
|
||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
||||
// - newTerminalArgs: An object that may contain a blob of parameters to
|
||||
// control which profile is created and with possible other
|
||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||
// - splitSize: the size of the split
|
||||
void TerminalPage::_SplitPane(const SplitDirection splitDirection,
|
||||
const SplitType splitMode,
|
||||
const float splitSize,
|
||||
const NewTerminalArgs& newTerminalArgs)
|
||||
std::shared_ptr<Pane> newPane)
|
||||
{
|
||||
const auto focusedTab{ _GetFocusedTabImpl() };
|
||||
|
||||
|
@ -1504,101 +1627,52 @@ namespace winrt::TerminalApp::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
_SplitPane(*focusedTab, splitDirection, splitMode, splitSize, newTerminalArgs);
|
||||
_SplitPane(*focusedTab, splitDirection, splitSize, newPane);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Split the focused pane of the given tab, either horizontally or vertically, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// given pane accordingly
|
||||
// Arguments:
|
||||
// - tab: The tab that is going to be split.
|
||||
// - newPane: the pane to add to our tree of panes
|
||||
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
||||
// new pane should be split from its parent.
|
||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
||||
// - newTerminalArgs: An object that may contain a blob of parameters to
|
||||
// control which profile is created and with possible other
|
||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||
// - splitSize: the size of the split
|
||||
void TerminalPage::_SplitPane(TerminalTab& tab,
|
||||
const SplitDirection splitDirection,
|
||||
const SplitType splitMode,
|
||||
const float splitSize,
|
||||
const NewTerminalArgs& newTerminalArgs)
|
||||
std::shared_ptr<Pane> newPane)
|
||||
{
|
||||
try
|
||||
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
|
||||
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
|
||||
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
|
||||
|
||||
auto realSplitType = splitDirection;
|
||||
if (realSplitType == SplitDirection::Automatic)
|
||||
{
|
||||
TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||
Profile profile{ nullptr };
|
||||
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
|
||||
}
|
||||
|
||||
if (splitMode == SplitType::Duplicate)
|
||||
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
|
||||
if (!canSplit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_UnZoomIfNeeded();
|
||||
tab.SplitPane(realSplitType, splitSize, newPane);
|
||||
|
||||
// After GH#6586, the control will no longer focus itself
|
||||
// automatically when it's finished being laid out. Manually focus
|
||||
// the control here instead.
|
||||
if (_startupState == StartupState::Initialized)
|
||||
{
|
||||
if (const auto control = _GetActiveControl())
|
||||
{
|
||||
profile = tab.GetFocusedProfile();
|
||||
if (profile)
|
||||
{
|
||||
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
||||
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
||||
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
|
||||
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
|
||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
||||
if (validWorkingDirectory)
|
||||
{
|
||||
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
|
||||
}
|
||||
}
|
||||
// TODO: GH#5047 - In the future, we should get the Profile of
|
||||
// the focused pane, and use that to build a new instance of the
|
||||
// settings so we can duplicate this tab/pane.
|
||||
//
|
||||
// Currently, if the profile doesn't exist anymore in our
|
||||
// settings, we'll silently do nothing.
|
||||
//
|
||||
// In the future, it will be preferable to just duplicate the
|
||||
// current control's settings, but we can't do that currently,
|
||||
// because we won't be able to create a new instance of the
|
||||
// connection without keeping an instance of the original Profile
|
||||
// object around.
|
||||
}
|
||||
if (!profile)
|
||||
{
|
||||
profile = _settings.GetProfileForArgs(newTerminalArgs);
|
||||
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
|
||||
}
|
||||
|
||||
const auto controlConnection = _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
|
||||
|
||||
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
|
||||
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
|
||||
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
|
||||
|
||||
auto realSplitType = splitDirection;
|
||||
if (realSplitType == SplitDirection::Automatic)
|
||||
{
|
||||
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
|
||||
}
|
||||
|
||||
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
|
||||
if (!canSplit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto newControl = _InitControl(controlSettings, controlConnection);
|
||||
|
||||
// Hookup our event handlers to the new terminal
|
||||
_RegisterTerminalEvents(newControl);
|
||||
|
||||
_UnZoomIfNeeded();
|
||||
|
||||
tab.SplitPane(realSplitType, splitSize, profile, newControl);
|
||||
|
||||
// After GH#6586, the control will no longer focus itself
|
||||
// automatically when it's finished being laid out. Manually focus
|
||||
// the control here instead.
|
||||
if (_startupState == StartupState::Initialized)
|
||||
{
|
||||
_GetActiveControl().Focus(FocusState::Programmatic);
|
||||
control.Focus(FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1867,6 +1941,22 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
if (_settings.GlobalSettings().TrimPaste())
|
||||
{
|
||||
std::wstring_view textView{ text };
|
||||
const auto pos = textView.find_last_not_of(L"\t\n\v\f\r ");
|
||||
if (pos == textView.npos)
|
||||
{
|
||||
// Text is all white space, nothing to paste
|
||||
co_return;
|
||||
}
|
||||
else if (const auto toRemove = textView.size() - 1 - pos; toRemove > 0)
|
||||
{
|
||||
textView.remove_suffix(toRemove);
|
||||
text = { textView };
|
||||
}
|
||||
}
|
||||
|
||||
bool warnMultiLine = _settings.GlobalSettings().WarnAboutMultiLinePaste();
|
||||
if (warnMultiLine)
|
||||
{
|
||||
|
@ -2090,7 +2180,7 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
if (target == SettingsTarget::SettingsUI)
|
||||
{
|
||||
_OpenSettingsUI();
|
||||
OpenSettingsUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2167,6 +2257,96 @@ namespace winrt::TerminalApp::implementation
|
|||
return term;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates a pane and returns a shared_ptr to it
|
||||
// - The caller should handle where the pane goes after creation,
|
||||
// either to split an already existing pane or to create a new tab with it
|
||||
// Arguments:
|
||||
// - newTerminalArgs: an object that may contain a blob of parameters to
|
||||
// control which profile is created and with possible other
|
||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||
// - duplicate: a boolean to indicate whether the pane we create should be
|
||||
// a duplicate of the currently focused pane
|
||||
// - existingConnection: optionally receives a connection from the outside
|
||||
// world instead of attempting to create one
|
||||
std::shared_ptr<Pane> TerminalPage::_MakePane(const NewTerminalArgs& newTerminalArgs, const bool duplicate, TerminalConnection::ITerminalConnection existingConnection)
|
||||
{
|
||||
TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||
Profile profile{ nullptr };
|
||||
|
||||
if (duplicate)
|
||||
{
|
||||
const auto focusedTab{ _GetFocusedTabImpl() };
|
||||
if (focusedTab)
|
||||
{
|
||||
profile = focusedTab->GetFocusedProfile();
|
||||
if (profile)
|
||||
{
|
||||
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
||||
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
||||
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
|
||||
const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
|
||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
||||
if (validWorkingDirectory)
|
||||
{
|
||||
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!profile)
|
||||
{
|
||||
profile = _settings.GetProfileForArgs(newTerminalArgs);
|
||||
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
|
||||
}
|
||||
|
||||
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
|
||||
if (existingConnection)
|
||||
{
|
||||
connection.Resize(controlSettings.DefaultSettings().InitialRows(), controlSettings.DefaultSettings().InitialCols());
|
||||
}
|
||||
|
||||
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
|
||||
if (_settings.GlobalSettings().DebugFeaturesEnabled())
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
||||
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
||||
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
if (bothAltsPressed)
|
||||
{
|
||||
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
const auto control = _InitControl(controlSettings, connection);
|
||||
_RegisterTerminalEvents(control);
|
||||
|
||||
auto resultPane = std::make_shared<Pane>(profile, control);
|
||||
|
||||
if (debugConnection) // this will only be set if global debugging is on and tap is active
|
||||
{
|
||||
auto newControl = _InitControl(controlSettings, debugConnection);
|
||||
_RegisterTerminalEvents(newControl);
|
||||
// Split (auto) with the debug tap.
|
||||
auto debugPane = std::make_shared<Pane>(profile, newControl);
|
||||
|
||||
// Since we're doing this split directly on the pane (instead of going through TerminalTab,
|
||||
// we need to handle the panes 'active' states
|
||||
|
||||
// Set the pane we're splitting to active (otherwise Split will not do anything)
|
||||
resultPane->SetActive();
|
||||
auto [original, _] = resultPane->Split(SplitDirection::Automatic, 0.5f, debugPane);
|
||||
|
||||
// Set the non-debug pane as active
|
||||
resultPane->ClearActive();
|
||||
original->SetActive();
|
||||
}
|
||||
|
||||
return resultPane;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Hook up keybindings, and refresh the UI of the terminal.
|
||||
// This includes update the settings of all the tabs according
|
||||
|
@ -2476,9 +2656,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
void TerminalPage::ToggleFullscreen()
|
||||
{
|
||||
_isFullscreen = !_isFullscreen;
|
||||
_UpdateTabView();
|
||||
_FullscreenChangedHandlers(*this, nullptr);
|
||||
SetFullscreen(!_isFullscreen);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -2695,52 +2873,51 @@ namespace winrt::TerminalApp::implementation
|
|||
return _isAlwaysOnTop;
|
||||
}
|
||||
|
||||
HRESULT TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection)
|
||||
void TerminalPage::SetFullscreen(bool newFullscreen)
|
||||
{
|
||||
if (_isFullscreen == newFullscreen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isFullscreen = newFullscreen;
|
||||
_UpdateTabView();
|
||||
_FullscreenChangedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
HRESULT TerminalPage::_OnNewConnection(const ConptyConnection& connection)
|
||||
{
|
||||
// We need to be on the UI thread in order for _OpenNewTab to run successfully.
|
||||
// HasThreadAccess will return true if we're currently on a UI thread and false otherwise.
|
||||
// When we're on a COM thread, we'll need to dispatch the calls to the UI thread
|
||||
// and wait on it hence the locking mechanism.
|
||||
if (Dispatcher().HasThreadAccess())
|
||||
{
|
||||
try
|
||||
{
|
||||
NewTerminalArgs newTerminalArgs{};
|
||||
// TODO GH#10952: When we pass the actual commandline (or originating application), the
|
||||
// settings model can choose the right settings based on command matching, or synthesize
|
||||
// a profile from the registry/link settings (TODO GH#9458).
|
||||
// TODO GH#9458: Get and pass the LNK/EXE filenames.
|
||||
// Passing in a commandline forces GetProfileForArgs to use Base Layer instead of Default Profile;
|
||||
// in the future, it can make a better decision based on the value we pull out of the process handle.
|
||||
// TODO GH#5047: When we hang on to the N.T.A., try not to spawn "default... .exe" :)
|
||||
newTerminalArgs.Commandline(L"default-terminal-invocation-placeholder");
|
||||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||
|
||||
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
|
||||
|
||||
// Request a summon of this window to the foreground
|
||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
if (!Dispatcher().HasThreadAccess())
|
||||
{
|
||||
til::latch latch{ 1 };
|
||||
HRESULT finalVal = S_OK;
|
||||
|
||||
Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [&]() {
|
||||
// Re-running ourselves under the dispatcher will cause us to take the first branch above.
|
||||
finalVal = _OnNewConnection(connection);
|
||||
|
||||
latch.count_down();
|
||||
});
|
||||
|
||||
latch.wait();
|
||||
return finalVal;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NewTerminalArgs newTerminalArgs;
|
||||
newTerminalArgs.Commandline(connection.Commandline());
|
||||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||
|
||||
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, connection));
|
||||
|
||||
// Request a summon of this window to the foreground
|
||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN()
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -2750,7 +2927,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_OpenSettingsUI()
|
||||
void TerminalPage::OpenSettingsUI()
|
||||
{
|
||||
// If we're holding the settings tab's switch command, don't create a new one, switch to the existing one.
|
||||
if (!_settingsTab)
|
||||
|
@ -2893,6 +3070,30 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Displays a info popup guiding the user into setting their default terminal.
|
||||
void TerminalPage::ShowSetAsDefaultInfoBar() const
|
||||
{
|
||||
if (!CascadiaSettings::IsDefaultTerminalAvailable() || _IsMessageDismissed(InfoBarMessage::SetAsDefault))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user has already configured any terminal for hand-off we
|
||||
// shouldn't inform them again about the possibility to do so.
|
||||
if (CascadiaSettings::IsDefaultTerminalSet())
|
||||
{
|
||||
_DismissMessage(InfoBarMessage::SetAsDefault);
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipPresented", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
infoBar.IsOpen(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Helper function to get the OS-localized name for the "Touch Keyboard
|
||||
// and Handwriting Panel Service". If we can't open up the service for any
|
||||
|
@ -3313,6 +3514,40 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Persists the user's choice not to show the information bar warning about "Windows Terminal can be set as your default terminal application"
|
||||
// Then hides this information buffer.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_SetAsDefaultDismissHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||
{
|
||||
_DismissMessage(InfoBarMessage::SetAsDefault);
|
||||
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
infoBar.IsOpen(false);
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipDismissed", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
_FocusCurrentTab(true);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Dismisses the Default Terminal tip and opens the settings.
|
||||
void TerminalPage::_SetAsDefaultOpenSettingsHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||
{
|
||||
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
infoBar.IsOpen(false);
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
OpenSettingsUI();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks whether information bar message was dismissed earlier (in the application state)
|
||||
// Arguments:
|
||||
|
@ -3342,13 +3577,20 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
void TerminalPage::_DismissMessage(const InfoBarMessage& message)
|
||||
{
|
||||
auto dismissedMessages = ApplicationState::SharedInstance().DismissedMessages();
|
||||
if (!dismissedMessages)
|
||||
const auto applicationState = ApplicationState::SharedInstance();
|
||||
std::vector<InfoBarMessage> messages;
|
||||
|
||||
if (const auto values = applicationState.DismissedMessages())
|
||||
{
|
||||
dismissedMessages = winrt::single_threaded_vector<InfoBarMessage>();
|
||||
messages.resize(values.Size());
|
||||
values.GetMany(0, messages);
|
||||
}
|
||||
|
||||
dismissedMessages.Append(message);
|
||||
ApplicationState::SharedInstance().DismissedMessages(dismissedMessages);
|
||||
if (std::none_of(messages.begin(), messages.end(), [&](const auto& m) { return m == message; }))
|
||||
{
|
||||
messages.emplace_back(message);
|
||||
}
|
||||
|
||||
applicationState.DismissedMessages(std::move(messages));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,17 @@
|
|||
|
||||
static constexpr uint32_t DefaultRowsToScroll{ 3 };
|
||||
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
|
||||
// fwdecl unittest classes
|
||||
|
||||
namespace TerminalAppLocalTests
|
||||
{
|
||||
class TabTests;
|
||||
class SettingsTests;
|
||||
};
|
||||
}
|
||||
|
||||
namespace Microsoft::Terminal::Core
|
||||
{
|
||||
class ControlKeyStates;
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
|
@ -83,6 +88,7 @@ namespace winrt::TerminalApp::implementation
|
|||
bool FocusMode() const;
|
||||
bool Fullscreen() const;
|
||||
bool AlwaysOnTop() const;
|
||||
void SetFullscreen(bool);
|
||||
|
||||
void SetStartupActions(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>& actions);
|
||||
|
||||
|
@ -95,6 +101,7 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::TerminalApp::TaskbarState TaskbarState() const;
|
||||
|
||||
void ShowKeyboardServiceWarning() const;
|
||||
void ShowSetAsDefaultInfoBar() const;
|
||||
winrt::hstring KeyboardServiceDisabledText();
|
||||
|
||||
winrt::fire_and_forget IdentifyWindow();
|
||||
|
@ -120,6 +127,8 @@ namespace winrt::TerminalApp::implementation
|
|||
bool IsQuakeWindow() const noexcept;
|
||||
bool IsElevated() const noexcept;
|
||||
|
||||
void OpenSettingsUI();
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
|
@ -208,7 +217,6 @@ namespace winrt::TerminalApp::implementation
|
|||
void _OpenNewTabDropdown();
|
||||
HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
void _CreateNewTabFromPane(std::shared_ptr<Pane> pane);
|
||||
void _CreateNewTabWithProfileAndSettings(const Microsoft::Terminal::Settings::Model::Profile& profile, const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettings settings);
|
||||
|
||||
winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);
|
||||
|
@ -222,6 +230,8 @@ namespace winrt::TerminalApp::implementation
|
|||
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||
|
||||
void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
|
||||
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
|
||||
void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) noexcept;
|
||||
void _RegisterActionCallbacks();
|
||||
|
||||
|
@ -296,14 +306,12 @@ namespace winrt::TerminalApp::implementation
|
|||
void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference<uint32_t>& rowsToScroll);
|
||||
|
||||
void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
||||
const float splitSize = 0.5f,
|
||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
||||
const float splitSize,
|
||||
std::shared_ptr<Pane> newPane);
|
||||
void _SplitPane(TerminalTab& tab,
|
||||
const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
||||
const float splitSize = 0.5f,
|
||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
||||
const float splitSize,
|
||||
std::shared_ptr<Pane> newPane);
|
||||
void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||
void _ToggleSplitOrientation();
|
||||
|
||||
|
@ -350,6 +358,10 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::Microsoft::Terminal::Control::TermControl _InitControl(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
|
||||
const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection);
|
||||
|
||||
std::shared_ptr<Pane> _MakePane(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr,
|
||||
const bool duplicate = false,
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
|
||||
void _RefreshUIForSettingsReload();
|
||||
|
||||
void _SetNonClientAreaColors(const Windows::UI::Color& selectedTabColor);
|
||||
|
@ -365,8 +377,6 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void _UnZoomIfNeeded();
|
||||
|
||||
void _OpenSettingsUI();
|
||||
|
||||
static int _ComputeScrollDelta(ScrollDirection scrollDirection, const uint32_t rowsToScroll);
|
||||
static uint32_t _ReadSystemRowsToScroll();
|
||||
|
||||
|
@ -387,7 +397,7 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::Microsoft::Terminal::Settings::Model::Command _lastPreviewedCommand{ nullptr };
|
||||
std::vector<std::function<void()>> _restorePreviewFuncs{};
|
||||
|
||||
HRESULT _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection);
|
||||
HRESULT _OnNewConnection(const winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection& connection);
|
||||
void _HandleToggleInboundPty(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args);
|
||||
|
||||
void _WindowRenamerActionClick(const IInspectable& sender, const IInspectable& eventArgs);
|
||||
|
@ -403,6 +413,8 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::fire_and_forget _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
void _SetAsDefaultDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
void _SetAsDefaultOpenSettingsHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<Grid x:Name="Root"
|
||||
Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
@ -22,8 +23,50 @@
|
|||
<local:TabRowControl x:Name="TabRow"
|
||||
Grid.Row="0" />
|
||||
|
||||
<StackPanel Grid.Row="1">
|
||||
<mux:InfoBar x:Name="KeyboardServiceWarningInfoBar"
|
||||
x:Load="False"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Message="{x:Bind KeyboardServiceDisabledText, Mode=OneWay}"
|
||||
Severity="Warning">
|
||||
<mux:InfoBar.ActionButton>
|
||||
<Button x:Uid="InfoBarDismissButton"
|
||||
Click="_KeyboardServiceWarningInfoDismissHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
|
||||
<mux:InfoBar x:Name="CloseOnExitInfoBar"
|
||||
x:Uid="CloseOnExitInfoBar"
|
||||
x:Load="False"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Severity="Informational">
|
||||
<mux:InfoBar.ActionButton>
|
||||
<Button x:Uid="InfoBarDismissButton"
|
||||
Click="_CloseOnExitInfoDismissHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
|
||||
<mux:InfoBar x:Name="SetAsDefaultInfoBar"
|
||||
x:Uid="SetAsDefaultInfoBar"
|
||||
x:Load="False"
|
||||
CloseButtonClick="_SetAsDefaultDismissHandler"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Severity="Informational">
|
||||
<mux:InfoBar.ActionButton>
|
||||
<HyperlinkButton x:Uid="SetAsDefaultTip_OpenSettingsLink"
|
||||
Click="_SetAsDefaultOpenSettingsHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
</StackPanel>
|
||||
|
||||
<Grid x:Name="TabContent"
|
||||
Grid.Row="1"
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch" />
|
||||
|
||||
|
@ -110,39 +153,11 @@
|
|||
</ContentDialog>
|
||||
|
||||
<local:CommandPalette x:Name="CommandPalette"
|
||||
Grid.Row="1"
|
||||
Grid.Row="2"
|
||||
VerticalAlignment="Stretch"
|
||||
PreviewKeyDown="_KeyDownHandler"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
<StackPanel>
|
||||
<mux:InfoBar x:Name="KeyboardServiceWarningInfoBar"
|
||||
x:Load="False"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Message="{x:Bind KeyboardServiceDisabledText, Mode=OneWay}"
|
||||
Severity="Warning">
|
||||
<mux:InfoBar.ActionButton>
|
||||
<Button x:Uid="InfoBarDismissButton"
|
||||
Click="_KeyboardServiceWarningInfoDismissHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
|
||||
<mux:InfoBar x:Name="CloseOnExitInfoBar"
|
||||
x:Uid="CloseOnExitInfoBar"
|
||||
x:Load="False"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Severity="Informational">
|
||||
<mux:InfoBar.ActionButton>
|
||||
<Button x:Uid="InfoBarDismissButton"
|
||||
Click="_CloseOnExitInfoDismissHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
</StackPanel>
|
||||
|
||||
<!--
|
||||
A TeachingTip with IsLightDismissEnabled="True" will immediately
|
||||
dismiss itself if the window is unfocused (In Xaml Islands). This is
|
||||
|
|
|
@ -25,18 +25,6 @@ namespace winrt
|
|||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TerminalTab::TerminalTab(const Profile& profile, const TermControl& control)
|
||||
{
|
||||
_rootPane = std::make_shared<Pane>(profile, control, true);
|
||||
|
||||
_rootPane->Id(_nextPaneId);
|
||||
_activePane = _rootPane;
|
||||
_mruPanes.insert(_mruPanes.begin(), _nextPaneId);
|
||||
++_nextPaneId;
|
||||
|
||||
_Setup();
|
||||
}
|
||||
|
||||
TerminalTab::TerminalTab(std::shared_ptr<Pane> rootPane)
|
||||
{
|
||||
_rootPane = rootPane;
|
||||
|
@ -64,8 +52,9 @@ namespace winrt::TerminalApp::implementation
|
|||
// focus the first one.
|
||||
if (_activePane == nullptr)
|
||||
{
|
||||
_rootPane->FocusPane(firstId);
|
||||
_activePane = _rootPane->GetActivePane();
|
||||
const auto firstPane = _rootPane->FindPane(firstId);
|
||||
firstPane->SetActive();
|
||||
_activePane = firstPane;
|
||||
}
|
||||
// If the focused pane is a leaf, add it to the MRU panes
|
||||
if (const auto id = _activePane->Id())
|
||||
|
@ -503,39 +492,48 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
// Method Description:
|
||||
// - Split the focused pane in our tree of panes, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// given pane into the tree of panes according to the split
|
||||
// Arguments:
|
||||
// - splitType: The type of split we want to create.
|
||||
// - profile: The profile GUID to associate with the newly created pane.
|
||||
// - control: A TermControl to use in the new pane.
|
||||
// - splitType: The type of split we want to create
|
||||
// - splitSize: The size of the split we want to create
|
||||
// - pane: The new pane to add to the tree of panes; note that this pane
|
||||
// could itself be a parent pane/the root node of a tree of panes
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::SplitPane(SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const Profile& profile,
|
||||
TermControl& control)
|
||||
std::shared_ptr<Pane> pane)
|
||||
{
|
||||
// Add the new event handlers to the new pane(s)
|
||||
// and update their ids.
|
||||
pane->WalkTree([&](auto p) {
|
||||
_AttachEventHandlersToPane(p);
|
||||
if (p->_IsLeaf())
|
||||
{
|
||||
p->Id(_nextPaneId);
|
||||
_AttachEventHandlersToControl(p->Id().value(), p->_control);
|
||||
_nextPaneId++;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
|
||||
const auto activePaneId = _activePane->Id();
|
||||
// Depending on which direction will be split, the new pane can be
|
||||
// either the first or second child, but this will always return the
|
||||
// original pane first.
|
||||
auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control);
|
||||
auto [original, newPane] = _activePane->Split(splitType, splitSize, pane);
|
||||
|
||||
// The active pane has an id if it is a leaf
|
||||
if (activePaneId)
|
||||
{
|
||||
original->Id(activePaneId.value());
|
||||
}
|
||||
newPane->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
|
||||
_activePane = original;
|
||||
|
||||
// Add a event handlers to the new panes' GotFocus event. When the pane
|
||||
// gains focus, we'll mark it as the new active pane.
|
||||
_AttachEventHandlersToControl(newPane->Id().value(), control);
|
||||
_AttachEventHandlersToPane(original);
|
||||
_AttachEventHandlersToPane(newPane);
|
||||
|
||||
// Immediately update our tracker of the focused pane now. If we're
|
||||
// splitting panes during startup (from a commandline), then it's
|
||||
|
|
|
@ -21,7 +21,6 @@ namespace winrt::TerminalApp::implementation
|
|||
struct TerminalTab : TerminalTabT<TerminalTab, TabBase>
|
||||
{
|
||||
public:
|
||||
TerminalTab(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile, const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
TerminalTab(std::shared_ptr<Pane> rootPane);
|
||||
|
||||
// Called after construction to perform the necessary setup, which relies on weak_ptr
|
||||
|
@ -40,8 +39,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
std::shared_ptr<Pane> newPane);
|
||||
|
||||
void ToggleSplitOrientation();
|
||||
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
|
||||
|
|
|
@ -68,5 +68,22 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!--
|
||||
BODGY
|
||||
|
||||
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
|
||||
executable we put in the package. But we DON'T produce a winmd. This makes the
|
||||
FastUpToDate check fail every time, and leads to the whole wapproj build
|
||||
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
|
||||
|
||||
Setting GenerateWindowsMetadata=false is enough to tell the build system that
|
||||
we don't produce one, and get it off our backs.
|
||||
-->
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
|
||||
</Project>
|
||||
|
|
|
@ -99,29 +99,57 @@ static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept
|
|||
// from the registered handler event function.
|
||||
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client)
|
||||
{
|
||||
// Stash a local copy of _pfnHandoff before we stop listening.
|
||||
auto localPfnHandoff = _pfnHandoff;
|
||||
try
|
||||
{
|
||||
// Stash a local copy of _pfnHandoff before we stop listening.
|
||||
auto localPfnHandoff = _pfnHandoff;
|
||||
|
||||
// Because we are REGCLS_SINGLEUSE... we need to `CoRevokeClassObject` after we handle this ONE call.
|
||||
// COM does not automatically clean that up for us. We must do it.
|
||||
s_StopListening();
|
||||
// Because we are REGCLS_SINGLEUSE... we need to `CoRevokeClassObject` after we handle this ONE call.
|
||||
// COM does not automatically clean that up for us. We must do it.
|
||||
s_StopListening();
|
||||
|
||||
std::unique_lock lock{ _mtx };
|
||||
std::unique_lock lock{ _mtx };
|
||||
|
||||
// Report an error if no one registered a handoff function before calling this.
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
||||
// Report an error if no one registered a handoff function before calling this.
|
||||
THROW_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
||||
|
||||
// Duplicate the handles from what we received.
|
||||
// The contract with COM specifies that any HANDLEs we receive from the caller belong
|
||||
// to the caller and will be freed when we leave the scope of this method.
|
||||
// Making our own duplicate copy ensures they hang around in our lifetime.
|
||||
RETURN_IF_FAILED(_duplicateHandle(in, in));
|
||||
RETURN_IF_FAILED(_duplicateHandle(out, out));
|
||||
RETURN_IF_FAILED(_duplicateHandle(signal, signal));
|
||||
RETURN_IF_FAILED(_duplicateHandle(ref, ref));
|
||||
RETURN_IF_FAILED(_duplicateHandle(server, server));
|
||||
RETURN_IF_FAILED(_duplicateHandle(client, client));
|
||||
// Duplicate the handles from what we received.
|
||||
// The contract with COM specifies that any HANDLEs we receive from the caller belong
|
||||
// to the caller and will be freed when we leave the scope of this method.
|
||||
// Making our own duplicate copy ensures they hang around in our lifetime.
|
||||
THROW_IF_FAILED(_duplicateHandle(in, in));
|
||||
THROW_IF_FAILED(_duplicateHandle(out, out));
|
||||
THROW_IF_FAILED(_duplicateHandle(signal, signal));
|
||||
THROW_IF_FAILED(_duplicateHandle(ref, ref));
|
||||
THROW_IF_FAILED(_duplicateHandle(server, server));
|
||||
THROW_IF_FAILED(_duplicateHandle(client, client));
|
||||
|
||||
// Call registered handler from when we started listening.
|
||||
return localPfnHandoff(in, out, signal, ref, server, client);
|
||||
// Call registered handler from when we started listening.
|
||||
THROW_IF_FAILED(localPfnHandoff(in, out, signal, ref, server, client));
|
||||
|
||||
#pragma warning(suppress : 26477)
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalConnectionProvider,
|
||||
"ReceiveTerminalHandoff_Success",
|
||||
TraceLoggingDescription("successfully received a terminal handoff"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
const auto hr = wil::ResultFromCaughtException();
|
||||
|
||||
#pragma warning(suppress : 26477)
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalConnectionProvider,
|
||||
"ReceiveTerminalHandoff_Failed",
|
||||
TraceLoggingDescription("failed while receiving a terminal handoff"),
|
||||
TraceLoggingHResult(hr),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "ConptyConnection.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <userenv.h>
|
||||
#include <UserEnv.h>
|
||||
#include <winternl.h>
|
||||
|
||||
#include "ConptyConnection.g.cpp"
|
||||
#include "CTerminalHandoff.h"
|
||||
|
@ -276,24 +276,18 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
const HANDLE hClientProcess) :
|
||||
_initialRows{ 25 },
|
||||
_initialCols{ 80 },
|
||||
_commandline{ L"" },
|
||||
_startingDirectory{ L"" },
|
||||
_startingTitle{ L"" },
|
||||
_environment{ nullptr },
|
||||
_guid{},
|
||||
_u8State{},
|
||||
_u16Str{},
|
||||
_buffer{},
|
||||
_guid{ Utils::CreateGuid() },
|
||||
_inPipe{ hIn },
|
||||
_outPipe{ hOut }
|
||||
{
|
||||
THROW_IF_FAILED(ConptyPackPseudoConsole(hServerProcess, hRef, hSig, &_hPC));
|
||||
if (_guid == guid{})
|
||||
{
|
||||
_guid = Utils::CreateGuid();
|
||||
}
|
||||
|
||||
_piClient.hProcess = hClientProcess;
|
||||
|
||||
try
|
||||
{
|
||||
_commandline = _commandlineFromProcess(hClientProcess);
|
||||
}
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
@ -355,6 +349,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
return _guid;
|
||||
}
|
||||
|
||||
winrt::hstring ConptyConnection::Commandline() const
|
||||
{
|
||||
return _commandline;
|
||||
}
|
||||
|
||||
void ConptyConnection::Start()
|
||||
try
|
||||
{
|
||||
|
@ -373,6 +372,16 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
// window is expecting it to be on the first layout.
|
||||
else
|
||||
{
|
||||
#pragma warning(suppress : 26477 26485 26494 26482 26446) // We don't control TraceLoggingWrite
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalConnectionProvider,
|
||||
"ConPtyConnectedToDefterm",
|
||||
TraceLoggingDescription("Event emitted when ConPTY connection is started, for a defterm session"),
|
||||
TraceLoggingGuid(_guid, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingWideString(_clientName.c_str(), "Client", "The attached client process"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
||||
THROW_IF_FAILED(ConptyResizePseudoConsole(_hPC.get(), dimensions));
|
||||
}
|
||||
|
||||
|
@ -420,8 +429,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
// EXIT POINT
|
||||
const auto hr = wil::ResultFromCaughtException();
|
||||
|
||||
// GH#11556 - make sure to format the error code to this string as an UNSIGNED int
|
||||
winrt::hstring failureText{ fmt::format(std::wstring_view{ RS_(L"ProcessFailedToLaunch") },
|
||||
fmt::format(_errorFormat, hr),
|
||||
fmt::format(_errorFormat, static_cast<unsigned int>(hr)),
|
||||
_commandline) };
|
||||
_TerminalOutputHandlers(failureText);
|
||||
|
||||
|
@ -448,6 +458,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
{
|
||||
try
|
||||
{
|
||||
// GH#11556 - make sure to format the error code to this string as an UNSIGNED int
|
||||
winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, fmt::format(_errorFormat, status)) };
|
||||
_TerminalOutputHandlers(L"\r\n");
|
||||
_TerminalOutputHandlers(exitText);
|
||||
|
@ -560,6 +571,38 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
}
|
||||
CATCH_LOG()
|
||||
|
||||
// Returns the command line of the given process.
|
||||
// Requires PROCESS_BASIC_INFORMATION | PROCESS_VM_READ privileges.
|
||||
winrt::hstring ConptyConnection::_commandlineFromProcess(HANDLE process)
|
||||
{
|
||||
struct PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
NTSTATUS ExitStatus;
|
||||
PPEB PebBaseAddress;
|
||||
ULONG_PTR AffinityMask;
|
||||
KPRIORITY BasePriority;
|
||||
ULONG_PTR UniqueProcessId;
|
||||
ULONG_PTR InheritedFromUniqueProcessId;
|
||||
} info;
|
||||
THROW_IF_NTSTATUS_FAILED(NtQueryInformationProcess(process, ProcessBasicInformation, &info, sizeof(info), nullptr));
|
||||
|
||||
// PEB: Process Environment Block
|
||||
// This is a funny structure allocated by the kernel which contains all sorts of useful
|
||||
// information, only a tiny fraction of which are documented publicly unfortunately.
|
||||
// Fortunately however it contains a copy of the command line the process launched with.
|
||||
PEB peb;
|
||||
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, info.PebBaseAddress, &peb, sizeof(peb), nullptr));
|
||||
|
||||
RTL_USER_PROCESS_PARAMETERS params;
|
||||
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, peb.ProcessParameters, ¶ms, sizeof(params), nullptr));
|
||||
|
||||
// Yeah I know... Don't use "impl" stuff... But why do you make something _that_ useful private? :(
|
||||
// The hstring_builder allows us to create a hstring without intermediate copies. Neat!
|
||||
winrt::impl::hstring_builder commandline{ params.CommandLine.Length / 2u };
|
||||
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, params.CommandLine.Buffer, commandline.data(), params.CommandLine.Length, nullptr));
|
||||
return commandline.to_hstring();
|
||||
}
|
||||
|
||||
DWORD ConptyConnection::_OutputThread()
|
||||
{
|
||||
// Keep us alive until the output thread terminates; the destructor
|
||||
|
@ -636,8 +679,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept
|
||||
try
|
||||
{
|
||||
auto conn = winrt::make<implementation::ConptyConnection>(signal, in, out, ref, server, client);
|
||||
_newConnectionHandlers(conn);
|
||||
_newConnectionHandlers(winrt::make<ConptyConnection>(signal, in, out, ref, server, client));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
void ClearBuffer();
|
||||
|
||||
winrt::guid Guid() const noexcept;
|
||||
winrt::hstring Commandline() const;
|
||||
|
||||
static void StartInboundListener();
|
||||
static void StopInboundListener();
|
||||
|
@ -56,12 +57,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);
|
||||
|
||||
private:
|
||||
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept;
|
||||
static winrt::hstring _commandlineFromProcess(HANDLE process);
|
||||
|
||||
HRESULT _LaunchAttachedClient() noexcept;
|
||||
void _indicateExitWithStatus(unsigned int status) noexcept;
|
||||
void _ClientTerminated() noexcept;
|
||||
|
||||
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept;
|
||||
|
||||
uint32_t _initialRows{};
|
||||
uint32_t _initialCols{};
|
||||
hstring _commandline{};
|
||||
|
|
|
@ -5,10 +5,13 @@ import "ITerminalConnection.idl";
|
|||
|
||||
namespace Microsoft.Terminal.TerminalConnection
|
||||
{
|
||||
delegate void NewConnectionHandler(ConptyConnection connection);
|
||||
|
||||
[default_interface] runtimeclass ConptyConnection : ITerminalConnection
|
||||
{
|
||||
ConptyConnection();
|
||||
Guid Guid { get; };
|
||||
String Commandline { get; };
|
||||
void ClearBuffer();
|
||||
|
||||
static event NewConnectionHandler NewConnection;
|
||||
|
|
|
@ -29,6 +29,4 @@ namespace Microsoft.Terminal.TerminalConnection
|
|||
event Windows.Foundation.TypedEventHandler<ITerminalConnection, Object> StateChanged;
|
||||
ConnectionState State { get; };
|
||||
};
|
||||
|
||||
delegate void NewConnectionHandler(ITerminalConnection connection);
|
||||
}
|
||||
|
|
|
@ -97,4 +97,39 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
|
||||
<!--
|
||||
BODGY:
|
||||
|
||||
We depend on `cpprest142*.dll`, which comes from our vcpkg dependency. As a
|
||||
part of the vcpkg dependency restore, msbuild will call the `deployBinary()`
|
||||
function in
|
||||
`packages\vcpkg-cpprestsdk.2.10.14\scripts\BuildSystems\msbuild\AppLocal.ps1`.
|
||||
That function does the actual job of copying the file. It copies it outside of
|
||||
MsBuild. MsBuild then, in the `_CopyFilesMarkedCopyLocal` target, determines
|
||||
that it needs to copy `cpprest142*.dll`, because that dll is a member of
|
||||
`@(ReferencesCopiedInThisBuild)`. However, the file's already been copied, so
|
||||
MsBuild never copies it. But that also prevents MsBuild from setting
|
||||
`WroteAtLeastOneFile`, which then means that MsBuild will never create the
|
||||
.CopyComplete file for this project.
|
||||
|
||||
Because that file is missing, MsBuild will never think the project is up to
|
||||
date, and the FastUpToDate check in VS will always force MsBuild to run a pass
|
||||
on this project.
|
||||
|
||||
To mitigate this, we're adding this other target here, which runs after
|
||||
_CopyFilesMarkedCopyLocal, and always creates the CopyUpToDateMarker. This
|
||||
makes the FastUpToDate check succeed.
|
||||
-->
|
||||
|
||||
<Target
|
||||
Name="_Post_CopyFilesMarkedCopyLocal"
|
||||
AfterTargets="_CopyFilesMarkedCopyLocal"
|
||||
Condition="'@(ReferenceCopyLocalPaths)' != ''">
|
||||
|
||||
<Touch Files="@(CopyUpToDateMarker)"
|
||||
AlwaysCreate="true" />
|
||||
</Target>
|
||||
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -3,16 +3,18 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "ControlCore.h"
|
||||
#include <argb.h>
|
||||
|
||||
#include <DefaultSettings.h>
|
||||
#include <unicode.hpp>
|
||||
#include <Utf16Parser.hpp>
|
||||
#include <Utils.h>
|
||||
#include <WinUser.h>
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "EventArgs.h"
|
||||
#include "../../types/inc/GlyphWidth.hpp"
|
||||
#include "../../types/inc/Utils.hpp"
|
||||
#include "../../buffer/out/search.h"
|
||||
#include "../../renderer/atlas/AtlasEngine.h"
|
||||
#include "../../renderer/dx/DxRenderer.hpp"
|
||||
|
||||
#include "ControlCore.g.cpp"
|
||||
|
||||
|
@ -202,6 +204,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const double actualHeight,
|
||||
const double compositionScale)
|
||||
{
|
||||
assert(_settings);
|
||||
|
||||
_panelWidth = actualWidth;
|
||||
_panelHeight = actualHeight;
|
||||
_compositionScale = compositionScale;
|
||||
|
@ -222,10 +226,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return false;
|
||||
}
|
||||
|
||||
// Set up the DX Engine
|
||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
_renderer->AddRenderEngine(dxEngine.get());
|
||||
_renderEngine = std::move(dxEngine);
|
||||
if (Feature_AtlasEngine::IsEnabled() && _settings.UseAtlasEngine())
|
||||
{
|
||||
_renderEngine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
|
||||
}
|
||||
else
|
||||
{
|
||||
_renderEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
}
|
||||
|
||||
_renderer->AddRenderEngine(_renderEngine.get());
|
||||
|
||||
// Initialize our font with the renderer
|
||||
// We don't have to care about DPI. We'll get a change message immediately if it's not 96
|
||||
|
@ -271,11 +281,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
|
||||
|
||||
_updateAntiAliasingMode(_renderEngine.get());
|
||||
_updateAntiAliasingMode();
|
||||
|
||||
// GH#5098: Inform the engine of the opacity of the default text background.
|
||||
// GH#11315: Always do this, even if they don't have acrylic on.
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.Opacity()));
|
||||
const auto backgroundIsOpaque = _settings.Opacity() == 1.0 && _settings.BackgroundImage().empty();
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
|
||||
|
||||
THROW_IF_FAILED(_renderEngine->Enable());
|
||||
|
||||
|
@ -442,6 +453,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
_settings.Opacity(newOpacity);
|
||||
|
||||
// GH#11285 - If the user is on Windows 10, and they changed the
|
||||
// transparency of the control s.t. it should be partially opaque, then
|
||||
// opt them in to acrylic. It's the only way to have transparency on
|
||||
// Windows 10.
|
||||
// We'll also turn the acrylic back off when they're fully opaque, which
|
||||
// is what the Terminal did prior to 1.12.
|
||||
if (!IsVintageOpacityAvailable())
|
||||
{
|
||||
_settings.UseAcrylic(newOpacity < 1.0);
|
||||
}
|
||||
|
||||
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
|
||||
_TransparencyChangedHandlers(*this, *eventArgs);
|
||||
}
|
||||
|
@ -570,6 +592,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
_settings = settings;
|
||||
|
||||
// GH#11285 - If the user is on Windows 10, and they wanted opacity, but
|
||||
// didn't explicitly request acrylic, then opt them in to acrylic.
|
||||
// On Windows 11+, this isn't needed, because we can have vintage opacity.
|
||||
if (!IsVintageOpacityAvailable() && _settings.Opacity() < 1.0 && !_settings.UseAcrylic())
|
||||
{
|
||||
_settings.UseAcrylic(true);
|
||||
}
|
||||
|
||||
// Initialize our font information.
|
||||
const auto fontFace = _settings.FontFace();
|
||||
const short fontHeight = ::base::saturated_cast<short>(_settings.FontSize());
|
||||
|
@ -581,6 +611,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// not, but DX doesn't use that info at all.
|
||||
// The Codepage is additionally not actually used by the DX engine at all.
|
||||
_actualFont = { fontFace, 0, fontWeight.Weight, { 0, fontHeight }, CP_UTF8, false };
|
||||
_actualFontFaceName = { fontFace };
|
||||
_desiredFont = { _actualFont };
|
||||
|
||||
// Update the terminal core with its new Core settings
|
||||
|
@ -596,7 +627,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
|
||||
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||
|
||||
_updateAntiAliasingMode(_renderEngine.get());
|
||||
_updateAntiAliasingMode();
|
||||
|
||||
// Refresh our font with the renderer
|
||||
const auto actualFontOldSize = _actualFont.GetSize();
|
||||
|
@ -630,22 +661,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
}
|
||||
|
||||
void ControlCore::_updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine)
|
||||
void ControlCore::_updateAntiAliasingMode()
|
||||
{
|
||||
// Update DxEngine's AntialiasingMode
|
||||
D2D1_TEXT_ANTIALIAS_MODE mode;
|
||||
|
||||
switch (_settings.AntialiasingMode())
|
||||
{
|
||||
case TextAntialiasingMode::Cleartype:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
|
||||
mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
break;
|
||||
case TextAntialiasingMode::Aliased:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||
break;
|
||||
case TextAntialiasingMode::Grayscale:
|
||||
default:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
break;
|
||||
}
|
||||
|
||||
_renderEngine->SetAntialiasingMode(mode);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -723,6 +756,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const auto fontFace = _settings.FontFace();
|
||||
const auto fontWeight = _settings.FontWeight();
|
||||
_actualFont = { fontFace, 0, fontWeight.Weight, { 0, newSize }, CP_UTF8, false };
|
||||
_actualFontFaceName = { fontFace };
|
||||
_desiredFont = { _actualFont };
|
||||
|
||||
auto lock = _terminal->LockForWriting();
|
||||
|
@ -1001,7 +1035,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
winrt::Windows::Foundation::Size ControlCore::FontSize() const noexcept
|
||||
{
|
||||
const auto fontSize = GetFont().GetSize();
|
||||
const auto fontSize = _actualFont.GetSize();
|
||||
return {
|
||||
::base::saturated_cast<float>(fontSize.X),
|
||||
::base::saturated_cast<float>(fontSize.Y)
|
||||
|
@ -1009,23 +1043,26 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
winrt::hstring ControlCore::FontFaceName() const noexcept
|
||||
{
|
||||
return winrt::hstring{ GetFont().GetFaceName() };
|
||||
// This getter used to return _actualFont.GetFaceName(), however GetFaceName() returns a STL
|
||||
// string and we need to return a WinRT string. This would require an additional allocation.
|
||||
// This method is called 10/s by TSFInputControl at the time of writing.
|
||||
return _actualFontFaceName;
|
||||
}
|
||||
|
||||
uint16_t ControlCore::FontWeight() const noexcept
|
||||
{
|
||||
return static_cast<uint16_t>(GetFont().GetWeight());
|
||||
return static_cast<uint16_t>(_actualFont.GetWeight());
|
||||
}
|
||||
|
||||
til::size ControlCore::FontSizeInDips() const
|
||||
{
|
||||
const til::size fontSize{ GetFont().GetSize() };
|
||||
const til::size fontSize{ _actualFont.GetSize() };
|
||||
return fontSize.scale(til::math::rounding, 1.0f / ::base::saturated_cast<float>(_compositionScale));
|
||||
}
|
||||
|
||||
TerminalConnection::ConnectionState ControlCore::ConnectionState() const
|
||||
{
|
||||
return _connection.State();
|
||||
return _connection ? _connection.State() : TerminalConnection::ConnectionState::Closed;
|
||||
}
|
||||
|
||||
hstring ControlCore::Title()
|
||||
|
@ -1052,7 +1089,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
til::color ControlCore::BackgroundColor() const
|
||||
{
|
||||
return _terminal->GetDefaultBackground();
|
||||
return _terminal->GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1272,7 +1309,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
if (_renderEngine)
|
||||
{
|
||||
auto lock = _terminal->LockForWriting();
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(opacity));
|
||||
const auto backgroundIsOpaque = opacity == 1.0 && _settings.BackgroundImage().empty();
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1545,4 +1583,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
return hstring(ss.str());
|
||||
}
|
||||
|
||||
// Helper to check if we're on Windows 11 or not. This is used to check if
|
||||
// we need to use acrylic to achieve transparency, because vintage opacity
|
||||
// doesn't work in islands on win10.
|
||||
// Remove when we can remove the rest of GH#11285
|
||||
bool ControlCore::IsVintageOpacityAvailable() noexcept
|
||||
{
|
||||
OSVERSIONINFOEXW osver{};
|
||||
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
osver.dwBuildNumber = 22000;
|
||||
|
||||
DWORDLONG dwlConditionMask = 0;
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||
|
||||
return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "EventArgs.h"
|
||||
#include "ControlCore.g.h"
|
||||
#include "../../renderer/base/Renderer.hpp"
|
||||
#include "../../renderer/dx/DxRenderer.hpp"
|
||||
#include "../../renderer/uia/UiaRenderer.hpp"
|
||||
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
||||
#include "../buffer/out/search.h"
|
||||
#include "cppwinrt_utils.h"
|
||||
|
@ -149,6 +146,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
hstring ReadEntireBuffer() const;
|
||||
|
||||
static bool IsVintageOpacityAvailable() noexcept;
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
// clang-format off
|
||||
WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs);
|
||||
|
@ -186,13 +185,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// As _renderer has a dependency on _renderEngine (through a raw pointer)
|
||||
// we must ensure the _renderer is deallocated first.
|
||||
// (C++ class members are destroyed in reverse order.)
|
||||
std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr };
|
||||
std::unique_ptr<::Microsoft::Console::Render::IRenderEngine> _renderEngine{ nullptr };
|
||||
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr };
|
||||
|
||||
IControlSettings _settings{ nullptr };
|
||||
|
||||
FontInfoDesired _desiredFont;
|
||||
FontInfo _actualFont;
|
||||
winrt::hstring _actualFontFaceName;
|
||||
|
||||
// storage location for the leading surrogate of a utf-16 surrogate pair
|
||||
std::optional<wchar_t> _leadingSurrogate{ std::nullopt };
|
||||
|
@ -245,7 +245,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
#pragma endregion
|
||||
|
||||
void _raiseReadOnlyWarning();
|
||||
void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine);
|
||||
void _updateAntiAliasingMode();
|
||||
void _connectionOutputHandler(const hstring& hstr);
|
||||
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "cppwinrt_utils.h"
|
||||
|
||||
#include "ControlCore.h"
|
||||
#include "../../renderer/uia/UiaRenderer.hpp"
|
||||
|
||||
namespace ControlUnitTests
|
||||
{
|
||||
|
|
|
@ -27,10 +27,11 @@ namespace Microsoft.Terminal.Control
|
|||
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings, Microsoft.Terminal.Control.IControlAppearance
|
||||
{
|
||||
String ProfileName;
|
||||
String ProfileSource;
|
||||
|
||||
Boolean UseAcrylic;
|
||||
ScrollbarState ScrollState;
|
||||
|
||||
Boolean UseAtlasEngine;
|
||||
String FontFace;
|
||||
Int32 FontSize;
|
||||
Windows.UI.Text.FontWeight FontWeight;
|
||||
|
|
|
@ -43,6 +43,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
_controlPadding = padding;
|
||||
}
|
||||
void InteractivityAutomationPeer::ParentProvider(AutomationPeer parentProvider)
|
||||
{
|
||||
_parentProvider = parentProvider;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Signals the ui automation client that the terminal's selection has
|
||||
|
@ -110,30 +114,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// ScreenInfoUiaProvider doesn't actually use parameter, so just pass in nullptr
|
||||
THROW_IF_FAILED(_uiaProvider->RangeFromChild(/* IRawElementProviderSimple */ nullptr,
|
||||
&returnVal));
|
||||
|
||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||
return _CreateXamlUiaTextRange(returnVal);
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::RangeFromPoint(Windows::Foundation::Point screenLocation)
|
||||
{
|
||||
UIA::ITextRangeProvider* returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->RangeFromPoint({ screenLocation.X, screenLocation.Y }, &returnVal));
|
||||
|
||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||
return _CreateXamlUiaTextRange(returnVal);
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::DocumentRange()
|
||||
{
|
||||
UIA::ITextRangeProvider* returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->get_DocumentRange(&returnVal));
|
||||
|
||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||
return _CreateXamlUiaTextRange(returnVal);
|
||||
}
|
||||
|
||||
XamlAutomation::SupportedTextSelection InteractivityAutomationPeer::SupportedTextSelection()
|
||||
|
@ -146,12 +141,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
#pragma endregion
|
||||
|
||||
#pragma region IControlAccessibilityInfo
|
||||
COORD InteractivityAutomationPeer::GetFontSize() const
|
||||
COORD InteractivityAutomationPeer::GetFontSize() const noexcept
|
||||
{
|
||||
return til::size{ til::math::rounding, _interactivity->Core().FontSize() };
|
||||
}
|
||||
|
||||
RECT InteractivityAutomationPeer::GetBounds() const
|
||||
RECT InteractivityAutomationPeer::GetBounds() const noexcept
|
||||
{
|
||||
return _controlBounds;
|
||||
}
|
||||
|
@ -164,12 +159,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
RECT InteractivityAutomationPeer::GetPadding() const
|
||||
RECT InteractivityAutomationPeer::GetPadding() const noexcept
|
||||
{
|
||||
return _controlPadding;
|
||||
}
|
||||
|
||||
double InteractivityAutomationPeer::GetScaleFactor() const
|
||||
double InteractivityAutomationPeer::GetScaleFactor() const noexcept
|
||||
{
|
||||
return DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
||||
}
|
||||
|
@ -180,6 +175,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
#pragma endregion
|
||||
|
||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::_CreateXamlUiaTextRange(UIA::ITextRangeProvider* returnVal) const
|
||||
{
|
||||
// LOAD-BEARING: use _parentProvider->ProviderFromPeer(_parentProvider) instead of this->ProviderFromPeer(*this).
|
||||
// Since we split the automation peer into TermControlAutomationPeer and InteractivityAutomationPeer,
|
||||
// using "this" returns null. This can cause issues with some UIA Client scenarios like any navigation in Narrator.
|
||||
const auto parent{ _parentProvider.get() };
|
||||
if (!parent)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parent.ProviderFromPeer(parent));
|
||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||
};
|
||||
|
||||
// Method Description:
|
||||
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
|
||||
// Arguments:
|
||||
|
@ -194,11 +203,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
std::vector<XamlAutomation::ITextRangeProvider> vec;
|
||||
vec.reserve(count);
|
||||
auto parentProvider = this->ProviderFromPeer(*this);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
auto xutr = make_self<XamlUiaTextRange>(providers[i].detach(), parentProvider);
|
||||
vec.emplace_back(xutr.as<XamlAutomation::ITextRangeProvider>());
|
||||
if (auto xutr = _CreateXamlUiaTextRange(providers[i].detach()))
|
||||
{
|
||||
vec.emplace_back(std::move(xutr));
|
||||
}
|
||||
}
|
||||
|
||||
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
void SetControlBounds(const Windows::Foundation::Rect bounds);
|
||||
void SetControlPadding(const Core::Padding padding);
|
||||
void ParentProvider(Windows::UI::Xaml::Automation::Peers::AutomationPeer parentProvider);
|
||||
|
||||
#pragma region IUiaEventDispatcher
|
||||
void SignalSelectionChanged() override;
|
||||
|
@ -61,10 +62,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
#pragma region IControlAccessibilityInfo Pattern
|
||||
// Inherited via IControlAccessibilityInfo
|
||||
virtual COORD GetFontSize() const override;
|
||||
virtual RECT GetBounds() const override;
|
||||
virtual RECT GetPadding() const override;
|
||||
virtual double GetScaleFactor() const override;
|
||||
virtual COORD GetFontSize() const noexcept override;
|
||||
virtual RECT GetBounds() const noexcept override;
|
||||
virtual RECT GetPadding() const noexcept override;
|
||||
virtual double GetScaleFactor() const noexcept override;
|
||||
virtual void ChangeViewport(SMALL_RECT NewWindow) override;
|
||||
virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override;
|
||||
#pragma endregion
|
||||
|
@ -74,8 +75,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
TYPED_EVENT(CursorChanged, IInspectable, IInspectable);
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider _CreateXamlUiaTextRange(::ITextRangeProvider* returnVal) const;
|
||||
|
||||
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
|
||||
winrt::Microsoft::Terminal::Control::implementation::ControlInteractivity* _interactivity;
|
||||
weak_ref<Windows::UI::Xaml::Automation::Peers::AutomationPeer> _parentProvider;
|
||||
|
||||
til::rectangle _controlBounds{};
|
||||
til::rectangle _controlPadding{};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Microsoft.Terminal.Control
|
||||
{
|
||||
[default_interface] runtimeclass InteractivityAutomationPeer :
|
||||
|
@ -10,6 +9,7 @@ namespace Microsoft.Terminal.Control
|
|||
|
||||
void SetControlBounds(Windows.Foundation.Rect bounds);
|
||||
void SetControlPadding(Microsoft.Terminal.Core.Padding padding);
|
||||
void ParentProvider(Windows.UI.Xaml.Automation.Peers.AutomationPeer parentProvider);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SelectionChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TextChanged;
|
||||
|
|
|
@ -3,17 +3,16 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "TermControl.h"
|
||||
#include <argb.h>
|
||||
#include <DefaultSettings.h>
|
||||
|
||||
#include <unicode.hpp>
|
||||
#include <Utf16Parser.hpp>
|
||||
#include <Utils.h>
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "TermControlAutomationPeer.h"
|
||||
#include "../../types/inc/GlyphWidth.hpp"
|
||||
#include "../../types/inc/Utils.hpp"
|
||||
#include "../../renderer/atlas/AtlasEngine.h"
|
||||
|
||||
#include "TermControl.g.cpp"
|
||||
#include "TermControlAutomationPeer.h"
|
||||
|
||||
using namespace ::Microsoft::Console::Types;
|
||||
using namespace ::Microsoft::Console::VirtualTerminal;
|
||||
|
@ -297,37 +296,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
if (!newAppearance.BackgroundImage().empty())
|
||||
{
|
||||
Windows::Foundation::Uri imageUri{ newAppearance.BackgroundImage() };
|
||||
|
||||
// Check if the image brush is already pointing to the image
|
||||
// in the modified settings; if it isn't (or isn't there),
|
||||
// set a new image source for the brush
|
||||
auto imageSource = BackgroundImage().Source().try_as<Media::Imaging::BitmapImage>();
|
||||
|
||||
if (imageSource == nullptr ||
|
||||
imageSource.UriSource() == nullptr ||
|
||||
imageSource.UriSource().RawUri() != imageUri.RawUri())
|
||||
{
|
||||
// Note that BitmapImage handles the image load asynchronously,
|
||||
// which is especially important since the image
|
||||
// may well be both large and somewhere out on the
|
||||
// internet.
|
||||
Media::Imaging::BitmapImage image(imageUri);
|
||||
BackgroundImage().Source(image);
|
||||
}
|
||||
|
||||
// Apply stretch, opacity and alignment settings
|
||||
BackgroundImage().Stretch(newAppearance.BackgroundImageStretchMode());
|
||||
BackgroundImage().Opacity(newAppearance.BackgroundImageOpacity());
|
||||
BackgroundImage().HorizontalAlignment(newAppearance.BackgroundImageHorizontalAlignment());
|
||||
BackgroundImage().VerticalAlignment(newAppearance.BackgroundImageVerticalAlignment());
|
||||
}
|
||||
else
|
||||
{
|
||||
BackgroundImage().Source(nullptr);
|
||||
}
|
||||
_SetBackgroundImage(newAppearance);
|
||||
|
||||
// Update our control settings
|
||||
const auto bg = newAppearance.DefaultBackground();
|
||||
|
@ -412,6 +381,57 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets background image and applies its settings (stretch, opacity and alignment)
|
||||
// - Checks path validity
|
||||
// Arguments:
|
||||
// - newAppearance
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TermControl::_SetBackgroundImage(const IControlAppearance& newAppearance)
|
||||
{
|
||||
if (newAppearance.BackgroundImage().empty())
|
||||
{
|
||||
BackgroundImage().Source(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
Windows::Foundation::Uri imageUri{ nullptr };
|
||||
try
|
||||
{
|
||||
imageUri = Windows::Foundation::Uri{ newAppearance.BackgroundImage() };
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
BackgroundImage().Source(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the image brush is already pointing to the image
|
||||
// in the modified settings; if it isn't (or isn't there),
|
||||
// set a new image source for the brush
|
||||
auto imageSource = BackgroundImage().Source().try_as<Media::Imaging::BitmapImage>();
|
||||
|
||||
if (imageSource == nullptr ||
|
||||
imageSource.UriSource() == nullptr ||
|
||||
imageSource.UriSource().RawUri() != imageUri.RawUri())
|
||||
{
|
||||
// Note that BitmapImage handles the image load asynchronously,
|
||||
// which is especially important since the image
|
||||
// may well be both large and somewhere out on the
|
||||
// internet.
|
||||
Media::Imaging::BitmapImage image(imageUri);
|
||||
BackgroundImage().Source(image);
|
||||
}
|
||||
|
||||
// Apply stretch, opacity and alignment settings
|
||||
BackgroundImage().Stretch(newAppearance.BackgroundImageStretchMode());
|
||||
BackgroundImage().Opacity(newAppearance.BackgroundImageOpacity());
|
||||
BackgroundImage().HorizontalAlignment(newAppearance.BackgroundImageHorizontalAlignment());
|
||||
BackgroundImage().VerticalAlignment(newAppearance.BackgroundImageVerticalAlignment());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Set up each layer's brush used to display the control's background.
|
||||
// - Respects the settings for acrylic, background image and opacity from
|
||||
|
@ -753,12 +773,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_HidePointerCursorHandlers(*this, nullptr);
|
||||
|
||||
const auto ch = e.Character();
|
||||
const auto scanCode = gsl::narrow_cast<WORD>(e.KeyStatus().ScanCode);
|
||||
const auto keyStatus = e.KeyStatus();
|
||||
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||
auto modifiers = _GetPressedModifierKeys();
|
||||
if (e.KeyStatus().IsExtendedKey)
|
||||
|
||||
if (keyStatus.IsExtendedKey)
|
||||
{
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
|
||||
const bool handled = _core.SendCharEvent(ch, scanCode, modifiers);
|
||||
e.Handled(handled);
|
||||
}
|
||||
|
@ -853,6 +876,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||
auto modifiers = _GetPressedModifierKeys();
|
||||
|
||||
if (keyStatus.IsExtendedKey)
|
||||
{
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
|
||||
// GH#11076:
|
||||
// For some weird reason we sometimes receive a WM_KEYDOWN
|
||||
// message without vkey or scanCode if a user drags a tab.
|
||||
|
@ -886,11 +914,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
if (keyStatus.IsExtendedKey)
|
||||
{
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
|
||||
// Alt-Numpad# input will send us a character once the user releases
|
||||
// Alt, so we should be ignoring the individual keydowns. The character
|
||||
// will be sent through the TSFInputControl. See GH#1401 for more
|
||||
|
@ -968,7 +991,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// Arguments:
|
||||
// - vkey: The vkey of the key pressed.
|
||||
// - scanCode: The scan code of the key pressed.
|
||||
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept
|
||||
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
|
||||
{
|
||||
std::array<BYTE, 256> keyState;
|
||||
if (!GetKeyboardState(keyState.data()))
|
||||
|
@ -1807,13 +1830,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
const winrt::Windows::Foundation::Size initialSize{ cols, rows };
|
||||
|
||||
return GetProposedDimensions(initialSize,
|
||||
settings.FontSize(),
|
||||
settings.FontWeight(),
|
||||
settings.FontFace(),
|
||||
settings.ScrollState(),
|
||||
settings.Padding(),
|
||||
dpi);
|
||||
return GetProposedDimensions(settings, dpi, initialSize);
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
@ -1834,16 +1851,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// caller knows what monitor the control is about to appear on.
|
||||
// Return Value:
|
||||
// - a size containing the requested dimensions in pixels.
|
||||
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
|
||||
const int32_t& fontHeight,
|
||||
const winrt::Windows::UI::Text::FontWeight& fontWeight,
|
||||
const winrt::hstring& fontFace,
|
||||
const ScrollbarState& scrollState,
|
||||
const winrt::hstring& padding,
|
||||
const uint32_t dpi)
|
||||
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars)
|
||||
{
|
||||
const auto cols = ::base::saturated_cast<int>(initialSizeInChars.Width);
|
||||
const auto rows = ::base::saturated_cast<int>(initialSizeInChars.Height);
|
||||
const auto fontSize = settings.FontSize();
|
||||
const auto fontWeight = settings.FontWeight();
|
||||
const auto fontFace = settings.FontFace();
|
||||
const auto scrollState = settings.ScrollState();
|
||||
const auto padding = settings.Padding();
|
||||
|
||||
// Initialize our font information.
|
||||
// The font width doesn't terribly matter, we'll only be using the
|
||||
|
@ -1852,28 +1868,39 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// The family is only used to determine if the font is truetype or
|
||||
// not, but DX doesn't use that info at all.
|
||||
// The Codepage is additionally not actually used by the DX engine at all.
|
||||
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast<short>(fontHeight) }, CP_UTF8, false };
|
||||
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast<short>(fontSize) }, CP_UTF8, false };
|
||||
FontInfoDesired desiredFont = { actualFont };
|
||||
|
||||
// Create a DX engine and initialize it with our font and DPI. We'll
|
||||
// then use it to measure how much space the requested rows and columns
|
||||
// will take up.
|
||||
// TODO: MSFT:21254947 - use a static function to do this instead of
|
||||
// instantiating a DxEngine
|
||||
// instantiating a DxEngine/AtlasEngine.
|
||||
// GH#10211 - UNDER NO CIRCUMSTANCE should this fail. If it does, the
|
||||
// whole app will crash instantaneously on launch, which is no good.
|
||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
LOG_IF_FAILED(dxEngine->UpdateDpi(dpi));
|
||||
LOG_IF_FAILED(dxEngine->UpdateFont(desiredFont, actualFont));
|
||||
double scale;
|
||||
if (Feature_AtlasEngine::IsEnabled() && settings.UseAtlasEngine())
|
||||
{
|
||||
auto engine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
|
||||
LOG_IF_FAILED(engine->UpdateDpi(dpi));
|
||||
LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont));
|
||||
scale = engine->GetScaling();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto engine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
LOG_IF_FAILED(engine->UpdateDpi(dpi));
|
||||
LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont));
|
||||
scale = engine->GetScaling();
|
||||
}
|
||||
|
||||
const auto scale = dxEngine->GetScaling();
|
||||
const auto fontSize = actualFont.GetSize();
|
||||
const auto actualFontSize = actualFont.GetSize();
|
||||
|
||||
// UWP XAML scrollbars aren't guaranteed to be the same size as the
|
||||
// ComCtl scrollbars, but it's certainly close enough.
|
||||
const auto scrollbarSize = GetSystemMetricsForDpi(SM_CXVSCROLL, dpi);
|
||||
|
||||
double width = cols * fontSize.X;
|
||||
double width = cols * actualFontSize.X;
|
||||
|
||||
// Reserve additional space if scrollbar is intended to be visible
|
||||
if (scrollState == ScrollbarState::Visible)
|
||||
|
@ -1881,7 +1908,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
width += scrollbarSize;
|
||||
}
|
||||
|
||||
double height = rows * fontSize.Y;
|
||||
double height = rows * actualFontSize.Y;
|
||||
const auto thickness = ParseThicknessFromPadding(padding);
|
||||
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
|
||||
width += scale * (thickness.Left + thickness.Right);
|
||||
|
@ -1941,13 +1968,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
|
||||
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
||||
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
|
||||
return GetProposedDimensions(minSize,
|
||||
_settings.FontSize(),
|
||||
_settings.FontWeight(),
|
||||
_settings.FontFace(),
|
||||
_settings.ScrollState(),
|
||||
_settings.Padding(),
|
||||
dpi);
|
||||
return GetProposedDimensions(_settings, dpi, minSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2042,7 +2063,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// don't necessarily include that state.
|
||||
// Return Value:
|
||||
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
|
||||
ControlKeyStates TermControl::_GetPressedModifierKeys() const
|
||||
ControlKeyStates TermControl::_GetPressedModifierKeys() noexcept
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
// DONT USE
|
||||
|
@ -2250,6 +2271,42 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
|
||||
std::wstring fullPath{ item.Path() };
|
||||
|
||||
// Fix path for WSL
|
||||
if (_settings.ProfileSource() == L"Windows.Terminal.Wsl")
|
||||
{
|
||||
std::replace(fullPath.begin(), fullPath.end(), L'\\', L'/');
|
||||
|
||||
if (fullPath.size() >= 2 && fullPath.at(1) == L':')
|
||||
{
|
||||
// C:/foo/bar -> Cc/foo/bar
|
||||
fullPath.at(1) = til::tolower_ascii(fullPath.at(0));
|
||||
// Cc/foo/bar -> /mnt/c/foo/bar
|
||||
fullPath.replace(0, 1, L"/mnt/");
|
||||
}
|
||||
else
|
||||
{
|
||||
static constexpr std::wstring_view wslPathPrefixes[] = { L"//wsl.localhost/", L"//wsl$/" };
|
||||
for (auto prefix : wslPathPrefixes)
|
||||
{
|
||||
if (til::starts_with(fullPath, prefix))
|
||||
{
|
||||
if (const auto idx = fullPath.find(L'/', prefix.size()); idx != std::wstring::npos)
|
||||
{
|
||||
// //wsl.localhost/Ubuntu-18.04/foo/bar -> /foo/bar
|
||||
fullPath.erase(0, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
// //wsl.localhost/Ubuntu-18.04 -> /
|
||||
fullPath = L"/";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto containsSpaces = std::find(fullPath.begin(),
|
||||
fullPath.end(),
|
||||
L' ') != fullPath.end();
|
||||
|
@ -2262,6 +2319,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
allPaths += fullPath;
|
||||
}
|
||||
|
||||
_core.PasteText(winrt::hstring{ allPaths });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,13 +92,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void Settings(IControlSettings newSettings);
|
||||
|
||||
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi);
|
||||
static Windows::Foundation::Size GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
|
||||
const int32_t& fontSize,
|
||||
const winrt::Windows::UI::Text::FontWeight& fontWeight,
|
||||
const winrt::hstring& fontFace,
|
||||
const ScrollbarState& scrollState,
|
||||
const winrt::hstring& padding,
|
||||
const uint32_t dpi);
|
||||
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars);
|
||||
|
||||
void BellLightOn();
|
||||
|
||||
|
@ -202,6 +196,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void _UpdateSettingsFromUIThread(IControlSettings newSettings);
|
||||
void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance);
|
||||
void _ApplyUISettings(const IControlSettings&);
|
||||
void _SetBackgroundImage(const IControlAppearance& newAppearance);
|
||||
|
||||
void _InitializeBackgroundBrush();
|
||||
void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args);
|
||||
|
@ -250,9 +245,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
|
||||
|
||||
void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown);
|
||||
::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
|
||||
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
|
||||
bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const;
|
||||
void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept;
|
||||
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
|
||||
bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
|
||||
|
||||
const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition);
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_contentAutomationPeer.SelectionChanged([this](auto&&, auto&&) { SignalSelectionChanged(); });
|
||||
_contentAutomationPeer.TextChanged([this](auto&&, auto&&) { SignalTextChanged(); });
|
||||
_contentAutomationPeer.CursorChanged([this](auto&&, auto&&) { SignalCursorChanged(); });
|
||||
_contentAutomationPeer.ParentProvider(*this);
|
||||
};
|
||||
|
||||
// Method Description:
|
||||
|
@ -226,30 +227,4 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// Method Description:
|
||||
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
|
||||
// Arguments:
|
||||
// - SAFEARRAY of UIA::UiaTextRange (ITextRangeProviders)
|
||||
// Return Value:
|
||||
// - com_array of Xaml Wrapped UiaTextRange (ITextRangeProviders)
|
||||
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges)
|
||||
{
|
||||
// transfer ownership of UiaTextRanges to this new vector
|
||||
auto providers = SafeArrayToOwningVector<::Microsoft::Terminal::TermControlUiaTextRange>(textRanges);
|
||||
int count = gsl::narrow<int>(providers.size());
|
||||
|
||||
std::vector<XamlAutomation::ITextRangeProvider> vec;
|
||||
vec.reserve(count);
|
||||
auto parentProvider = this->ProviderFromPeer(*this);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
auto xutr = make_self<XamlUiaTextRange>(providers[i].detach(), parentProvider);
|
||||
vec.emplace_back(xutr.as<XamlAutomation::ITextRangeProvider>());
|
||||
}
|
||||
|
||||
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,5 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
private:
|
||||
winrt::Microsoft::Terminal::Control::implementation::TermControl* _termControl;
|
||||
Control::InteractivityAutomationPeer _contentAutomationPeer;
|
||||
|
||||
winrt::com_array<Windows::UI::Xaml::Automation::Provider::ITextRangeProvider> WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
<ProjectReference Include="..\..\types\lib\types.vcxproj" />
|
||||
<ProjectReference Include="..\..\buffer\out\lib\bufferout.vcxproj" />
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\renderer\base\lib\base.vcxproj" />
|
||||
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj" />
|
||||
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj" />
|
||||
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj" />
|
||||
<ProjectReference Include="..\..\terminal\parser\lib\parser.vcxproj" />
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../types/TermControlUiaTextRange.hpp"
|
||||
#include <UIAutomationClient.h>
|
||||
#include <UIAutomationCoreApi.h>
|
||||
#include "../types/UiaTracing.h"
|
||||
|
||||
// the same as COR_E_NOTSUPPORTED
|
||||
// we don't want to import the CLR headers to get it
|
||||
|
@ -182,6 +183,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
XamlAutomation::IRawElementProviderSimple XamlUiaTextRange::GetEnclosingElement()
|
||||
{
|
||||
::Microsoft::Console::Types::UiaTracing::TextRange::GetEnclosingElement(*static_cast<::Microsoft::Console::Types::UiaTextRangeBase*>(_uiaProvider.get()));
|
||||
return _parentProvider;
|
||||
}
|
||||
|
||||
|
|
228
src/cascadia/TerminalCore/ColorFix.cpp
Normal file
228
src/cascadia/TerminalCore/ColorFix.cpp
Normal file
|
@ -0,0 +1,228 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
// A lot of code was taken from
|
||||
// https://github.com/Maximus5/ConEmu/blob/master/src/ConEmu/ColorFix.cpp
|
||||
// and then adjusted to fit our style guidelines
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include "ColorFix.hpp"
|
||||
|
||||
static constexpr double gMinThreshold = 12.0;
|
||||
static constexpr double gExpThreshold = 20.0;
|
||||
static constexpr double gLStep = 5.0;
|
||||
|
||||
static constexpr double rad006 = 0.104719755119659774;
|
||||
static constexpr double rad025 = 0.436332312998582394;
|
||||
static constexpr double rad030 = 0.523598775598298873;
|
||||
static constexpr double rad060 = 1.047197551196597746;
|
||||
static constexpr double rad063 = 1.099557428756427633;
|
||||
static constexpr double rad180 = 3.141592653589793238;
|
||||
static constexpr double rad275 = 4.799655442984406336;
|
||||
static constexpr double rad360 = 6.283185307179586476;
|
||||
|
||||
ColorFix::ColorFix(COLORREF color)
|
||||
{
|
||||
rgb = color;
|
||||
_ToLab();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper function to calculate HPrime
|
||||
double ColorFix::_GetHPrimeFn(double x, double y)
|
||||
{
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto hueAngle = atan2(x, y);
|
||||
return hueAngle >= 0 ? hueAngle : hueAngle + rad360;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Given 2 colors, computes the DeltaE value between them
|
||||
// Arguments:
|
||||
// - x1: the first color
|
||||
// - x2: the second color
|
||||
// Return Value:
|
||||
// - The DeltaE value between x1 and x2
|
||||
double ColorFix::_GetDeltaE(ColorFix x1, ColorFix x2)
|
||||
{
|
||||
constexpr double kSubL = 1;
|
||||
constexpr double kSubC = 1;
|
||||
constexpr double kSubH = 1;
|
||||
|
||||
// Delta L Prime
|
||||
const double deltaLPrime = x2.L - x1.L;
|
||||
|
||||
// L Bar
|
||||
const double lBar = (x1.L + x2.L) / 2;
|
||||
|
||||
// C1 & C2
|
||||
const double c1 = sqrt(pow(x1.A, 2) + pow(x1.B, 2));
|
||||
const double c2 = sqrt(pow(x2.A, 2) + pow(x2.B, 2));
|
||||
|
||||
// C Bar
|
||||
const double cBar = (c1 + c2) / 2;
|
||||
|
||||
// A Prime 1
|
||||
const double aPrime1 = x1.A + (x1.A / 2) * (1 - sqrt(pow(cBar, 7) / (pow(cBar, 7) + pow(25.0, 7))));
|
||||
|
||||
// A Prime 2
|
||||
const double aPrime2 = x2.A + (x2.A / 2) * (1 - sqrt(pow(cBar, 7) / (pow(cBar, 7) + pow(25.0, 7))));
|
||||
|
||||
// C Prime 1
|
||||
const double cPrime1 = sqrt(pow(aPrime1, 2) + pow(x1.B, 2));
|
||||
|
||||
// C Prime 2
|
||||
const double cPrime2 = sqrt(pow(aPrime2, 2) + pow(x2.B, 2));
|
||||
|
||||
// C Bar Prime
|
||||
const double cBarPrime = (cPrime1 + cPrime2) / 2;
|
||||
|
||||
// Delta C Prime
|
||||
const double deltaCPrime = cPrime2 - cPrime1;
|
||||
|
||||
// S sub L
|
||||
const double sSubL = 1 + ((0.015 * pow(lBar - 50, 2)) / sqrt(20 + pow(lBar - 50, 2)));
|
||||
|
||||
// S sub C
|
||||
const double sSubC = 1 + 0.045 * cBarPrime;
|
||||
|
||||
// h Prime 1
|
||||
const double hPrime1 = _GetHPrimeFn(x1.B, aPrime1);
|
||||
|
||||
// h Prime 2
|
||||
const double hPrime2 = _GetHPrimeFn(x2.B, aPrime2);
|
||||
|
||||
// Delta H Prime
|
||||
const double deltaHPrime = 0 == c1 || 0 == c2 ? 0 : 2 * sqrt(cPrime1 * cPrime2) * sin(abs(hPrime1 - hPrime2) <= rad180 ? hPrime2 - hPrime1 : (hPrime2 <= hPrime1 ? hPrime2 - hPrime1 + rad360 : hPrime2 - hPrime1 - rad360) / 2);
|
||||
|
||||
// H Bar Prime
|
||||
const double hBarPrime = (abs(hPrime1 - hPrime2) > rad180) ? (hPrime1 + hPrime2 + rad360) / 2 : (hPrime1 + hPrime2) / 2;
|
||||
|
||||
// T
|
||||
const double t = 1 - 0.17 * cos(hBarPrime - rad030) + 0.24 * cos(2 * hBarPrime) + 0.32 * cos(3 * hBarPrime + rad006) - 0.20 * cos(4 * hBarPrime - rad063);
|
||||
|
||||
// S sub H
|
||||
const double sSubH = 1 + 0.015 * cBarPrime * t;
|
||||
|
||||
// R sub T
|
||||
const double rSubT = -2 * sqrt(pow(cBarPrime, 7) / (pow(cBarPrime, 7) + pow(25.0, 7))) * sin(rad060 * exp(-pow((hBarPrime - rad275) / rad025, 2)));
|
||||
|
||||
// Put it all together!
|
||||
const double lightness = deltaLPrime / (kSubL * sSubL);
|
||||
const double chroma = deltaCPrime / (kSubC * sSubC);
|
||||
const double hue = deltaHPrime / (kSubH * sSubH);
|
||||
|
||||
return sqrt(pow(lightness, 2) + pow(chroma, 2) + pow(hue, 2) + rSubT * chroma * hue);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Populates our L, A, B values, based on our r, g, b values
|
||||
// - Converts a color in rgb format to a color in lab format
|
||||
// - Reference: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
|
||||
void ColorFix::_ToLab()
|
||||
{
|
||||
double var_R = r / 255.0;
|
||||
double var_G = g / 255.0;
|
||||
double var_B = b / 255.0;
|
||||
|
||||
var_R = var_R > 0.04045 ? pow(((var_R + 0.055) / 1.055), 2.4) : var_R / 12.92;
|
||||
var_G = var_G > 0.04045 ? pow(((var_G + 0.055) / 1.055), 2.4) : var_G / 12.92;
|
||||
var_B = var_B > 0.04045 ? pow(((var_B + 0.055) / 1.055), 2.4) : var_B / 12.92;
|
||||
|
||||
var_R = var_R * 100.;
|
||||
var_G = var_G * 100.;
|
||||
var_B = var_B * 100.;
|
||||
|
||||
//Observer. = 2 degrees, Illuminant = D65
|
||||
const double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
|
||||
const double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
|
||||
const double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
|
||||
|
||||
double var_X = X / 95.047; //ref_X = 95.047 (Observer= 2 degrees, Illuminant= D65)
|
||||
double var_Y = Y / 100.000; //ref_Y = 100.000
|
||||
double var_Z = Z / 108.883; //ref_Z = 108.883
|
||||
|
||||
var_X = var_X > 0.008856 ? pow(var_X, (1. / 3.)) : (7.787 * var_X) + (16. / 116.);
|
||||
var_Y = var_Y > 0.008856 ? pow(var_Y, (1. / 3.)) : (7.787 * var_Y) + (16. / 116.);
|
||||
var_Z = var_Z > 0.008856 ? pow(var_Z, (1. / 3.)) : (7.787 * var_Z) + (16. / 116.);
|
||||
|
||||
L = (116. * var_Y) - 16.;
|
||||
A = 500. * (var_X - var_Y);
|
||||
B = 200. * (var_Y - var_Z);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Populates our r, g, b values, based on our L, A, B values
|
||||
// - Converts a color in lab format to a color in rgb format
|
||||
// - Reference: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
|
||||
void ColorFix::_ToRGB()
|
||||
{
|
||||
double var_Y = (L + 16.) / 116.;
|
||||
double var_X = A / 500. + var_Y;
|
||||
double var_Z = var_Y - B / 200.;
|
||||
|
||||
var_Y = (pow(var_Y, 3) > 0.008856) ? pow(var_Y, 3) : (var_Y - 16. / 116.) / 7.787;
|
||||
var_X = (pow(var_X, 3) > 0.008856) ? pow(var_X, 3) : (var_X - 16. / 116.) / 7.787;
|
||||
var_Z = (pow(var_Z, 3) > 0.008856) ? pow(var_Z, 3) : (var_Z - 16. / 116.) / 7.787;
|
||||
|
||||
double X = 95.047 * var_X; //ref_X = 95.047 (Observer= 2 degrees, Illuminant= D65)
|
||||
double Y = 100.000 * var_Y; //ref_Y = 100.000
|
||||
double Z = 108.883 * var_Z; //ref_Z = 108.883
|
||||
|
||||
var_X = X / 100.; //X from 0 to 95.047 (Observer = 2 degrees, Illuminant = D65)
|
||||
var_Y = Y / 100.; //Y from 0 to 100.000
|
||||
var_Z = Z / 100.; //Z from 0 to 108.883
|
||||
|
||||
double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
|
||||
double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
|
||||
double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
|
||||
|
||||
var_R = var_R > 0.0031308 ? 1.055 * pow(var_R, (1 / 2.4)) - 0.055 : var_R = 12.92 * var_R;
|
||||
var_G = var_G > 0.0031308 ? 1.055 * pow(var_G, (1 / 2.4)) - 0.055 : var_G = 12.92 * var_G;
|
||||
var_B = var_B > 0.0031308 ? 1.055 * pow(var_B, (1 / 2.4)) - 0.055 : var_B = 12.92 * var_B;
|
||||
|
||||
r = (BYTE)std::clamp(var_R * 255., 0., 255.);
|
||||
g = (BYTE)std::clamp(var_G * 255., 0., 255.);
|
||||
b = (BYTE)std::clamp(var_B * 255., 0., 255.);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Given foreground and background colors, change the foreground color to
|
||||
// make it more perceivable if necessary
|
||||
// - Arguments:
|
||||
// - fg: the foreground color
|
||||
// - bg: the background color
|
||||
// - Return Value:
|
||||
// - The foreground color after performing any necessary changes to make it more perceivable
|
||||
COLORREF ColorFix::GetPerceivableColor(COLORREF fg, COLORREF bg)
|
||||
{
|
||||
ColorFix backLab(bg);
|
||||
ColorFix frontLab(fg);
|
||||
const double de1 = _GetDeltaE(frontLab, backLab);
|
||||
if (de1 < gMinThreshold)
|
||||
{
|
||||
for (int i = 0; i <= 1; i++)
|
||||
{
|
||||
const double step = (i == 0) ? gLStep : -gLStep;
|
||||
frontLab.L += step;
|
||||
|
||||
while (((i == 0) && (frontLab.L <= 100)) || ((i == 1) && (frontLab.L >= 0)))
|
||||
{
|
||||
const double de2 = _GetDeltaE(frontLab, backLab);
|
||||
if (de2 >= gExpThreshold)
|
||||
{
|
||||
frontLab._ToRGB();
|
||||
return frontLab.rgb;
|
||||
}
|
||||
frontLab.L += step;
|
||||
}
|
||||
}
|
||||
}
|
||||
return frontLab.rgb;
|
||||
}
|
49
src/cascadia/TerminalCore/ColorFix.hpp
Normal file
49
src/cascadia/TerminalCore/ColorFix.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- ColorFix
|
||||
|
||||
Abstract:
|
||||
- Implementation of perceptual color nudging, which allows the Terminal
|
||||
to slightly shift the foreground color to make it more perceivable on
|
||||
the current background (for cases where the foreground is very close
|
||||
to being imperceivable on the background).
|
||||
|
||||
Author(s):
|
||||
- Pankaj Bhojwani - Sep 2021
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct ColorFix
|
||||
{
|
||||
public:
|
||||
ColorFix(COLORREF color);
|
||||
|
||||
static COLORREF GetPerceivableColor(COLORREF fg, COLORREF bg);
|
||||
|
||||
// RGB
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE r, g, b, dummy;
|
||||
};
|
||||
COLORREF rgb;
|
||||
};
|
||||
|
||||
// Lab
|
||||
struct
|
||||
{
|
||||
double L, A, B;
|
||||
};
|
||||
|
||||
private:
|
||||
static double _GetHPrimeFn(double x, double y);
|
||||
static double _GetDeltaE(ColorFix x1, ColorFix x2);
|
||||
void _ToLab();
|
||||
void _ToRGB();
|
||||
};
|
|
@ -67,5 +67,6 @@ namespace Microsoft.Terminal.Core
|
|||
CursorStyle CursorShape;
|
||||
UInt32 CursorHeight;
|
||||
Boolean IntenseIsBright;
|
||||
Boolean AdjustIndistinguishableColors;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../terminal/adapter/DispatchTypes.hpp"
|
||||
#include "../../terminal/input/terminalInput.hpp"
|
||||
#include "../../buffer/out/TextAttribute.hpp"
|
||||
#include "../../types/inc/Viewport.hpp"
|
||||
|
||||
|
@ -39,24 +40,14 @@ namespace Microsoft::Terminal::Core
|
|||
virtual bool WarningBell() noexcept = 0;
|
||||
virtual bool SetWindowTitle(std::wstring_view title) noexcept = 0;
|
||||
|
||||
virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept = 0;
|
||||
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept = 0;
|
||||
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept = 0;
|
||||
|
||||
virtual bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept = 0;
|
||||
virtual bool SetCursorColor(const DWORD color) noexcept = 0;
|
||||
|
||||
virtual bool SetDefaultForeground(const DWORD color) noexcept = 0;
|
||||
virtual bool SetDefaultBackground(const DWORD color) noexcept = 0;
|
||||
virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;
|
||||
|
||||
virtual bool EnableWin32InputMode(const bool win32InputMode) noexcept = 0;
|
||||
virtual bool SetCursorKeysMode(const bool applicationMode) noexcept = 0;
|
||||
virtual bool SetKeypadMode(const bool applicationMode) noexcept = 0;
|
||||
virtual bool SetScreenMode(const bool reverseMode) noexcept = 0;
|
||||
virtual bool EnableVT200MouseMode(const bool enabled) noexcept = 0;
|
||||
virtual bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept = 0;
|
||||
virtual bool EnableSGRExtendedMouseMode(const bool enabled) noexcept = 0;
|
||||
virtual bool EnableButtonEventMouseMode(const bool enabled) noexcept = 0;
|
||||
virtual bool EnableAnyEventMouseMode(const bool enabled) noexcept = 0;
|
||||
virtual bool EnableAlternateScrollMode(const bool enabled) noexcept = 0;
|
||||
virtual bool EnableXtermBracketedPasteMode(const bool enabled) noexcept = 0;
|
||||
virtual bool IsXtermBracketedPasteModeEnabled() const = 0;
|
||||
|
||||
|
|
|
@ -41,8 +41,6 @@ Terminal::Terminal() :
|
|||
_mutableViewport{ Viewport::Empty() },
|
||||
_title{},
|
||||
_colorTable{},
|
||||
_defaultFg{ RGB(255, 255, 255) },
|
||||
_defaultBg{ ARGB(0, 0, 0, 0) },
|
||||
_screenReversed{ false },
|
||||
_pfnWriteInput{ nullptr },
|
||||
_scrollOffset{ 0 },
|
||||
|
@ -53,13 +51,22 @@ Terminal::Terminal() :
|
|||
_taskbarState{ 0 },
|
||||
_taskbarProgress{ 0 },
|
||||
_trimBlockSelection{ false },
|
||||
_intenseIsBright{ true }
|
||||
_intenseIsBright{ true },
|
||||
_adjustIndistinguishableColors{ true }
|
||||
{
|
||||
auto dispatch = std::make_unique<TerminalDispatch>(*this);
|
||||
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||
|
||||
_stateMachine = std::make_unique<StateMachine>(std::move(engine));
|
||||
|
||||
// Until we have a true pass-through mode (GH#1173), the decision as to
|
||||
// whether C1 controls are interpreted or not is made at the conhost level.
|
||||
// If they are being filtered out, then we will simply never receive them.
|
||||
// But if they are being accepted by conhost, there's a chance they may get
|
||||
// passed through in some situations, so it's important that our state
|
||||
// machine is always prepared to accept them.
|
||||
_stateMachine->SetParserMode(StateMachine::Mode::AcceptC1, true);
|
||||
|
||||
auto passAlongInput = [&](std::deque<std::unique_ptr<IInputEvent>>& inEventsToWrite) {
|
||||
if (!_pfnWriteInput)
|
||||
{
|
||||
|
@ -72,6 +79,10 @@ Terminal::Terminal() :
|
|||
_terminalInput = std::make_unique<TerminalInput>(passAlongInput);
|
||||
|
||||
_InitializeColorTable();
|
||||
|
||||
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = RGB(255, 255, 255);
|
||||
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = ARGB(0, 0, 0, 0);
|
||||
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
|
||||
}
|
||||
|
||||
void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, IRenderTarget& renderTarget)
|
||||
|
@ -171,15 +182,24 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
|||
{
|
||||
// Set the default background as transparent to prevent the
|
||||
// DX layer from overwriting the background image or acrylic effect
|
||||
til::color newBackgroundColor{ appearance.DefaultBackground() };
|
||||
_defaultBg = newBackgroundColor.with_alpha(0);
|
||||
_defaultFg = appearance.DefaultForeground();
|
||||
const til::color newBackgroundColor{ appearance.DefaultBackground() };
|
||||
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = newBackgroundColor.with_alpha(0);
|
||||
const til::color newForegroundColor{ appearance.DefaultForeground() };
|
||||
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = newForegroundColor;
|
||||
const til::color newCursorColor{ appearance.CursorColor() };
|
||||
_colorTable.at(TextColor::CURSOR_COLOR) = newCursorColor;
|
||||
|
||||
_intenseIsBright = appearance.IntenseIsBright();
|
||||
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
_colorTable.at(i) = til::color{ appearance.GetColorTableEntry(i) };
|
||||
}
|
||||
if (_adjustIndistinguishableColors)
|
||||
{
|
||||
_MakeAdjustedColorArray();
|
||||
}
|
||||
|
||||
CursorType cursorShape = CursorType::VerticalBar;
|
||||
switch (appearance.CursorShape())
|
||||
|
@ -207,9 +227,7 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
|||
|
||||
if (_buffer)
|
||||
{
|
||||
_buffer->GetCursor().SetStyle(appearance.CursorHeight(),
|
||||
til::color{ appearance.CursorColor() },
|
||||
cursorShape);
|
||||
_buffer->GetCursor().SetStyle(appearance.CursorHeight(), cursorShape);
|
||||
}
|
||||
|
||||
_defaultCursorShape = cursorShape;
|
||||
|
@ -1204,9 +1222,7 @@ try
|
|||
{
|
||||
const gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
|
||||
// First set up the basic 256 colors
|
||||
Utils::Initialize256ColorTable(tableView);
|
||||
// Then use fill the first 16 values with the Campbell scheme
|
||||
Utils::InitializeCampbellColorTable(tableView);
|
||||
Utils::InitializeColorTable(tableView);
|
||||
// Then make sure all the values have an alpha of 255
|
||||
Utils::SetColorTableAlpha(tableView, 0xff);
|
||||
}
|
||||
|
|
|
@ -106,22 +106,13 @@ public:
|
|||
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
|
||||
bool WarningBell() noexcept override;
|
||||
bool SetWindowTitle(std::wstring_view title) noexcept override;
|
||||
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
|
||||
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
|
||||
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
|
||||
bool SetCursorColor(const COLORREF color) noexcept override;
|
||||
bool SetDefaultForeground(const COLORREF color) noexcept override;
|
||||
bool SetDefaultBackground(const COLORREF color) noexcept override;
|
||||
|
||||
bool EnableWin32InputMode(const bool win32InputMode) noexcept override;
|
||||
bool SetCursorKeysMode(const bool applicationMode) noexcept override;
|
||||
bool SetKeypadMode(const bool applicationMode) noexcept override;
|
||||
bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
|
||||
|
||||
bool SetScreenMode(const bool reverseMode) noexcept override;
|
||||
bool EnableVT200MouseMode(const bool enabled) noexcept override;
|
||||
bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept override;
|
||||
bool EnableSGRExtendedMouseMode(const bool enabled) noexcept override;
|
||||
bool EnableButtonEventMouseMode(const bool enabled) noexcept override;
|
||||
bool EnableAnyEventMouseMode(const bool enabled) noexcept override;
|
||||
bool EnableAlternateScrollMode(const bool enabled) noexcept override;
|
||||
bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override;
|
||||
bool IsXtermBracketedPasteModeEnabled() const noexcept override;
|
||||
|
||||
|
@ -219,7 +210,6 @@ public:
|
|||
void ClearPatternTree() noexcept;
|
||||
|
||||
const std::optional<til::color> GetTabColor() const noexcept;
|
||||
til::color GetDefaultBackground() const noexcept;
|
||||
|
||||
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
|
||||
|
||||
|
@ -288,9 +278,7 @@ private:
|
|||
std::optional<til::color> _startingTabColor;
|
||||
|
||||
// This is still stored as a COLORREF because it interacts with some code in ConTypes
|
||||
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
|
||||
til::color _defaultFg;
|
||||
til::color _defaultBg;
|
||||
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||
CursorType _defaultCursorShape;
|
||||
bool _screenReversed;
|
||||
mutable Microsoft::Console::Render::BlinkingState _blinkingState;
|
||||
|
@ -301,6 +289,7 @@ private:
|
|||
bool _bracketedPasteMode;
|
||||
bool _trimBlockSelection;
|
||||
bool _intenseIsBright;
|
||||
bool _adjustIndistinguishableColors;
|
||||
|
||||
size_t _taskbarState;
|
||||
size_t _taskbarProgress;
|
||||
|
@ -401,6 +390,9 @@ private:
|
|||
|
||||
Microsoft::Console::VirtualTerminal::SgrStack _sgrStack;
|
||||
|
||||
void _MakeAdjustedColorArray();
|
||||
std::array<std::array<COLORREF, 18>, 18> _adjustedForegroundColors;
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class TerminalCoreUnitTests::TerminalBufferTests;
|
||||
friend class TerminalCoreUnitTests::TerminalApiTest;
|
||||
|
|
|
@ -69,14 +69,6 @@ COORD Terminal::GetCursorPosition() noexcept
|
|||
return newPos;
|
||||
}
|
||||
|
||||
bool Terminal::SetCursorColor(const COLORREF color) noexcept
|
||||
try
|
||||
{
|
||||
_buffer->GetCursor().SetColor(color);
|
||||
return true;
|
||||
}
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Moves the cursor down one line, and possibly also to the leftmost column.
|
||||
// Arguments:
|
||||
|
@ -370,6 +362,22 @@ try
|
|||
}
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the value in the colortable at the specified index.
|
||||
// Arguments:
|
||||
// - tableIndex: the index of the color table to retrieve.
|
||||
// Return Value:
|
||||
// - the COLORREF value for the color at that index in the table.
|
||||
COLORREF Terminal::GetColorTableEntry(const size_t tableIndex) const noexcept
|
||||
try
|
||||
{
|
||||
return _colorTable.at(tableIndex);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return INVALID_COLOR;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the value in the colortable at index tableIndex to the new color
|
||||
// color. color is a COLORREF, format 0x00BBGGRR.
|
||||
|
@ -383,6 +391,11 @@ try
|
|||
{
|
||||
_colorTable.at(tableIndex) = color;
|
||||
|
||||
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
|
||||
{
|
||||
_pfnBackgroundColorChanged(color);
|
||||
}
|
||||
|
||||
// Repaint everything - the colors might have changed
|
||||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
return true;
|
||||
|
@ -442,64 +455,14 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
|
|||
return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the default foreground color from a COLORREF, format 0x00BBGGRR.
|
||||
// Arguments:
|
||||
// - color: the new COLORREF to use as the default foreground color
|
||||
// Return Value:
|
||||
// - true
|
||||
bool Terminal::SetDefaultForeground(const COLORREF color) noexcept
|
||||
bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
|
||||
try
|
||||
{
|
||||
_defaultFg = color;
|
||||
|
||||
// Repaint everything - the colors might have changed
|
||||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
_terminalInput->SetInputMode(mode, enabled);
|
||||
return true;
|
||||
}
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Updates the default background color from a COLORREF, format 0x00BBGGRR.
|
||||
// Arguments:
|
||||
// - color: the new COLORREF to use as the default background color
|
||||
// Return Value:
|
||||
// - true
|
||||
bool Terminal::SetDefaultBackground(const COLORREF color) noexcept
|
||||
try
|
||||
{
|
||||
_defaultBg = color;
|
||||
_pfnBackgroundColorChanged(color);
|
||||
|
||||
// Repaint everything - the colors might have changed
|
||||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
return true;
|
||||
}
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
til::color Terminal::GetDefaultBackground() const noexcept
|
||||
{
|
||||
return _defaultBg;
|
||||
}
|
||||
|
||||
bool Terminal::EnableWin32InputMode(const bool win32InputMode) noexcept
|
||||
{
|
||||
_terminalInput->ChangeWin32InputMode(win32InputMode);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::SetCursorKeysMode(const bool applicationMode) noexcept
|
||||
{
|
||||
_terminalInput->ChangeCursorKeysMode(applicationMode);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::SetKeypadMode(const bool applicationMode) noexcept
|
||||
{
|
||||
_terminalInput->ChangeKeypadMode(applicationMode);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::SetScreenMode(const bool reverseMode) noexcept
|
||||
try
|
||||
{
|
||||
|
@ -511,42 +474,6 @@ try
|
|||
}
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
bool Terminal::EnableVT200MouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalInput->EnableDefaultTracking(enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalInput->SetUtf8ExtendedMode(enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::EnableSGRExtendedMouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalInput->SetSGRExtendedMode(enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::EnableButtonEventMouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalInput->EnableButtonEventTracking(enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::EnableAnyEventMouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalInput->EnableAnyEventTracking(enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::EnableAlternateScrollMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalInput->EnableAlternateScroll(enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::EnableXtermBracketedPasteMode(const bool enabled) noexcept
|
||||
{
|
||||
_bracketedPasteMode = enabled;
|
||||
|
|
|
@ -227,7 +227,7 @@ CATCH_LOG_RETURN_FALSE()
|
|||
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
|
||||
try
|
||||
{
|
||||
return _terminalApi.SetCursorColor(color);
|
||||
return _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color);
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
|
||||
|
@ -247,7 +247,7 @@ CATCH_LOG_RETURN_FALSE()
|
|||
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
|
||||
try
|
||||
{
|
||||
return _terminalApi.SetDefaultForeground(color);
|
||||
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color);
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
|
||||
|
@ -260,7 +260,7 @@ CATCH_LOG_RETURN_FALSE()
|
|||
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
|
||||
try
|
||||
{
|
||||
return _terminalApi.SetDefaultBackground(color);
|
||||
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color);
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
|
||||
|
@ -321,9 +321,9 @@ CATCH_LOG_RETURN_FALSE()
|
|||
// - applicationMode - set to true to enable Application Mode Input, false for Numeric Mode Input.
|
||||
// Return Value:
|
||||
// - True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::SetKeypadMode(const bool fApplicationMode) noexcept
|
||||
bool TerminalDispatch::SetKeypadMode(const bool applicationMode) noexcept
|
||||
{
|
||||
_terminalApi.SetKeypadMode(fApplicationMode);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::Keypad, applicationMode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -334,7 +334,7 @@ bool TerminalDispatch::SetKeypadMode(const bool fApplicationMode) noexcept
|
|||
// - True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode) noexcept
|
||||
{
|
||||
_terminalApi.SetCursorKeysMode(applicationMode);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::CursorKey, applicationMode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,7 @@ bool TerminalDispatch::SetScreenMode(const bool reverseMode) noexcept
|
|||
// - True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept
|
||||
{
|
||||
_terminalApi.EnableWin32InputMode(win32Mode);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::Win32, win32Mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -371,7 +371,7 @@ bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept
|
|||
// True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalApi.EnableVT200MouseMode(enabled);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::DefaultMouseTracking, enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) noexcept
|
|||
// True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalApi.EnableUTF8ExtendedMouseMode(enabled);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::Utf8MouseEncoding, enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -397,7 +397,7 @@ bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
|
|||
// True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalApi.EnableSGRExtendedMouseMode(enabled);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::SgrMouseEncoding, enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -409,7 +409,7 @@ bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) noexcept
|
|||
// True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalApi.EnableButtonEventMouseMode(enabled);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -422,7 +422,7 @@ bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) noexcept
|
|||
// True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalApi.EnableAnyEventMouseMode(enabled);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -435,7 +435,7 @@ bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) noexcept
|
|||
// True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::EnableAlternateScroll(const bool enabled) noexcept
|
||||
{
|
||||
_terminalApi.EnableAlternateScrollMode(enabled);
|
||||
_terminalApi.SetInputMode(TerminalInput::Mode::AlternateScroll, enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue