Compare commits
21 commits
dev/miniks
...
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 |
19
.github/ISSUE_TEMPLATE/Bug_Report.yml
vendored
19
.github/ISSUE_TEMPLATE/Bug_Report.yml
vendored
|
@ -10,14 +10,21 @@ body:
|
||||||
|
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Windows Terminal version (or Windows build number)
|
label: Windows Terminal version
|
||||||
placeholder: "10.0.19042.0, 1.7.3651.0"
|
placeholder: "1.7.3651.0"
|
||||||
description: |
|
description: |
|
||||||
If you are reporting an issue in Windows Terminal, you can find the version in the about dialog.
|
You can find the version in the about dialog, or by running `wt -v` at the commandline.
|
||||||
|
|
||||||
If you are reporting an issue with the Windows Console, please run `ver` or `[Environment]::OSVersion`.
|
|
||||||
validations:
|
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
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
|
|
14
.github/actions/spelling/allow/allow.txt
vendored
14
.github/actions/spelling/allow/allow.txt
vendored
|
@ -1,12 +1,14 @@
|
||||||
|
admins
|
||||||
apc
|
apc
|
||||||
|
Apc
|
||||||
|
bsd
|
||||||
calt
|
calt
|
||||||
ccmp
|
ccmp
|
||||||
changelog
|
changelog
|
||||||
cybersecurity
|
|
||||||
Apc
|
|
||||||
clickable
|
clickable
|
||||||
clig
|
clig
|
||||||
copyable
|
copyable
|
||||||
|
cybersecurity
|
||||||
dalet
|
dalet
|
||||||
dcs
|
dcs
|
||||||
Dcs
|
Dcs
|
||||||
|
@ -30,20 +32,22 @@ hyperlink
|
||||||
hyperlinking
|
hyperlinking
|
||||||
hyperlinks
|
hyperlinks
|
||||||
img
|
img
|
||||||
|
inlined
|
||||||
It'd
|
It'd
|
||||||
kje
|
kje
|
||||||
liga
|
liga
|
||||||
lje
|
lje
|
||||||
locl
|
|
||||||
lorem
|
|
||||||
Llast
|
Llast
|
||||||
Lmid
|
Lmid
|
||||||
|
locl
|
||||||
|
lorem
|
||||||
Lorigin
|
Lorigin
|
||||||
maxed
|
maxed
|
||||||
mkmk
|
mkmk
|
||||||
|
mnt
|
||||||
mru
|
mru
|
||||||
noreply
|
|
||||||
nje
|
nje
|
||||||
|
noreply
|
||||||
ogonek
|
ogonek
|
||||||
ok'd
|
ok'd
|
||||||
overlined
|
overlined
|
||||||
|
|
8
.github/actions/spelling/allow/apis.txt
vendored
8
.github/actions/spelling/allow/apis.txt
vendored
|
@ -1,5 +1,7 @@
|
||||||
ACCEPTFILES
|
ACCEPTFILES
|
||||||
ACCESSDENIED
|
ACCESSDENIED
|
||||||
|
acl
|
||||||
|
aclapi
|
||||||
alignas
|
alignas
|
||||||
alignof
|
alignof
|
||||||
APPLYTOSUBMENUS
|
APPLYTOSUBMENUS
|
||||||
|
@ -21,6 +23,7 @@ commandlinetoargv
|
||||||
cstdint
|
cstdint
|
||||||
CXICON
|
CXICON
|
||||||
CYICON
|
CYICON
|
||||||
|
Dacl
|
||||||
dataobject
|
dataobject
|
||||||
dcomp
|
dcomp
|
||||||
DERR
|
DERR
|
||||||
|
@ -117,15 +120,19 @@ OSVERSIONINFOEXW
|
||||||
otms
|
otms
|
||||||
OUTLINETEXTMETRICW
|
OUTLINETEXTMETRICW
|
||||||
overridable
|
overridable
|
||||||
|
PACL
|
||||||
PAGESCROLL
|
PAGESCROLL
|
||||||
|
PEXPLICIT
|
||||||
PICKFOLDERS
|
PICKFOLDERS
|
||||||
pmr
|
pmr
|
||||||
|
ptstr
|
||||||
rcx
|
rcx
|
||||||
REGCLS
|
REGCLS
|
||||||
RETURNCMD
|
RETURNCMD
|
||||||
rfind
|
rfind
|
||||||
roundf
|
roundf
|
||||||
RSHIFT
|
RSHIFT
|
||||||
|
SACL
|
||||||
schandle
|
schandle
|
||||||
semver
|
semver
|
||||||
serializer
|
serializer
|
||||||
|
@ -162,6 +169,7 @@ toupper
|
||||||
TTask
|
TTask
|
||||||
TVal
|
TVal
|
||||||
UChar
|
UChar
|
||||||
|
UFIELD
|
||||||
ULARGE
|
ULARGE
|
||||||
UPDATEINIFILE
|
UPDATEINIFILE
|
||||||
userenv
|
userenv
|
||||||
|
|
1
.github/actions/spelling/allow/names.txt
vendored
1
.github/actions/spelling/allow/names.txt
vendored
|
@ -9,6 +9,7 @@ Diviness
|
||||||
dsafa
|
dsafa
|
||||||
duhowett
|
duhowett
|
||||||
ekg
|
ekg
|
||||||
|
eryksun
|
||||||
ethanschoonover
|
ethanschoonover
|
||||||
Firefox
|
Firefox
|
||||||
Gatta
|
Gatta
|
||||||
|
|
1
.github/actions/spelling/excludes.txt
vendored
1
.github/actions/spelling/excludes.txt
vendored
|
@ -61,6 +61,7 @@ SUMS$
|
||||||
^src/host/runft\.bat$
|
^src/host/runft\.bat$
|
||||||
^src/host/runut\.bat$
|
^src/host/runut\.bat$
|
||||||
^src/interactivity/onecore/BgfxEngine\.
|
^src/interactivity/onecore/BgfxEngine\.
|
||||||
|
^src/renderer/atlas/
|
||||||
^src/renderer/wddmcon/WddmConRenderer\.
|
^src/renderer/wddmcon/WddmConRenderer\.
|
||||||
^src/terminal/adapter/ut_adapter/run\.bat$
|
^src/terminal/adapter/ut_adapter/run\.bat$
|
||||||
^src/terminal/parser/delfuzzpayload\.bat$
|
^src/terminal/parser/delfuzzpayload\.bat$
|
||||||
|
|
1
.github/actions/spelling/expect/expect.txt
vendored
1
.github/actions/spelling/expect/expect.txt
vendored
|
@ -508,6 +508,7 @@ dealloc
|
||||||
Debian
|
Debian
|
||||||
debolden
|
debolden
|
||||||
debugtype
|
debugtype
|
||||||
|
DECAC
|
||||||
DECALN
|
DECALN
|
||||||
DECANM
|
DECANM
|
||||||
DECAUPSS
|
DECAUPSS
|
||||||
|
|
|
@ -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\.vt100\.net/docs/[-a-zA-Z0-9#_\/.]*
|
||||||
https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
|
https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
|
||||||
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-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?&=\/_#]*
|
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
|
||||||
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
|
[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)
|
(?:[{"]|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.Net.Component.4.5.TargetingPack",
|
||||||
"Microsoft.VisualStudio.Component.DiagnosticTools",
|
"Microsoft.VisualStudio.Component.DiagnosticTools",
|
||||||
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
|
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
|
||||||
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
|
"Microsoft.VisualStudio.Component.Windows10SDK.22000",
|
||||||
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
|
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
|
||||||
"Microsoft.VisualStudio.Component.VC.CoreIde",
|
"Microsoft.VisualStudio.Component.VC.CoreIde",
|
||||||
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
|
"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
|
## 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
|
### 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.
|
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.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -400,6 +400,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests",
|
||||||
EndProject
|
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}"
|
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
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererAtlas", "src\renderer\atlas\atlas.vcxproj", "{8222900C-8B6C-452A-91AC-BE95DB04B95F}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
AuditMode|Any CPU = AuditMode|Any CPU
|
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|x64.Build.0 = Release|x64
|
||||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
|
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -3438,6 +3480,7 @@ Global
|
||||||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {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}
|
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
|
||||||
|
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
|
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
|
||||||
|
|
|
@ -63,8 +63,14 @@
|
||||||
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
|
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
|
||||||
DependsOnTargets="_GenerateBranchAndBrandingCache">
|
DependsOnTargets="_GenerateBranchAndBrandingCache">
|
||||||
<MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" />
|
<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
|
<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"
|
ConsoleToMsBuild="true"
|
||||||
StandardOutputImportance="low">
|
StandardOutputImportance="low">
|
||||||
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />
|
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />
|
||||||
|
|
|
@ -22,7 +22,7 @@ Param(
|
||||||
[Parameter(HelpMessage="Path to makeappx.exe")]
|
[Parameter(HelpMessage="Path to makeappx.exe")]
|
||||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||||
[string]
|
[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)) {
|
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ Param(
|
||||||
[Parameter(HelpMessage="Path to Windows Kit")]
|
[Parameter(HelpMessage="Path to Windows Kit")]
|
||||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||||
[string]
|
[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"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
|
@ -380,7 +380,7 @@ Here's the AppxManifest we're using:
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Dependencies>
|
<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" 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" />
|
<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>
|
</Dependencies>
|
||||||
|
@ -517,7 +517,7 @@ This is because of a few key lines we already put in the appxmanifest:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<Dependencies>
|
<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" 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" />
|
<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>
|
</Dependencies>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
|
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>EchoCon</RootNamespace>
|
<RootNamespace>EchoCon</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>10.0.22000.0</WindowsTargetPlatformVersion>
|
||||||
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
|
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
@ -163,4 +163,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Dependencies>
|
<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>
|
</Dependencies>
|
||||||
|
|
||||||
<Resources>
|
<Resources>
|
||||||
|
|
|
@ -118,6 +118,23 @@
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</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="$(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')" />
|
<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')" />
|
||||||
|
|
|
@ -128,22 +128,22 @@ bool TextAttribute::IsLegacy() const noexcept
|
||||||
// - Calculates rgb colors based off of current color table and active modification attributes.
|
// - Calculates rgb colors based off of current color table and active modification attributes.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - colorTable: the current color table rgb values.
|
// - colorTable: the current color table rgb values.
|
||||||
// - defaultFgColor: the default foreground color rgb value.
|
// - defaultFgIndex: the color table index of the default foreground color.
|
||||||
// - defaultBgColor: the default background color rgb value.
|
// - defaultBgIndex: the color table index of the default background color.
|
||||||
// - reverseScreenMode: true if the screen mode is reversed.
|
// - reverseScreenMode: true if the screen mode is reversed.
|
||||||
// - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false)
|
// - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false)
|
||||||
// - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true)
|
// - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true)
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - the foreground and background colors that should be displayed.
|
// - the foreground and background colors that should be displayed.
|
||||||
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
|
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
|
||||||
const COLORREF defaultFgColor,
|
const size_t defaultFgIndex,
|
||||||
const COLORREF defaultBgColor,
|
const size_t defaultBgIndex,
|
||||||
const bool reverseScreenMode,
|
const bool reverseScreenMode,
|
||||||
const bool blinkingIsFaint,
|
const bool blinkingIsFaint,
|
||||||
const bool boldIsBright) const noexcept
|
const bool boldIsBright) const noexcept
|
||||||
{
|
{
|
||||||
auto fg = _foreground.GetColor(colorTable, defaultFgColor, boldIsBright && IsBold());
|
auto fg = _foreground.GetColor(colorTable, defaultFgIndex, boldIsBright && IsBold());
|
||||||
auto bg = _background.GetColor(colorTable, defaultBgColor);
|
auto bg = _background.GetColor(colorTable, defaultBgIndex);
|
||||||
if (IsFaint() || (IsBlinking() && blinkingIsFaint))
|
if (IsFaint() || (IsBlinking() && blinkingIsFaint))
|
||||||
{
|
{
|
||||||
fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two.
|
fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two.
|
||||||
|
|
|
@ -64,9 +64,9 @@ public:
|
||||||
static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept;
|
static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept;
|
||||||
WORD GetLegacyAttributes() const noexcept;
|
WORD GetLegacyAttributes() const noexcept;
|
||||||
|
|
||||||
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
|
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
|
||||||
const COLORREF defaultFgColor,
|
const size_t defaultFgIndex,
|
||||||
const COLORREF defaultBgColor,
|
const size_t defaultBgIndex,
|
||||||
const bool reverseScreenMode = false,
|
const bool reverseScreenMode = false,
|
||||||
const bool blinkingIsFaint = false,
|
const bool blinkingIsFaint = false,
|
||||||
const bool boldIsBright = true) const noexcept;
|
const bool boldIsBright = true) const noexcept;
|
||||||
|
|
|
@ -139,14 +139,16 @@ void TextColor::SetDefault() noexcept
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - colorTable: The table of colors we should use to look up the value of
|
// - colorTable: The table of colors we should use to look up the value of
|
||||||
// an indexed attribute from.
|
// 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.
|
// - brighten: if true, we'll brighten a dark color table index.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - a COLORREF containing the real value of this TextColor.
|
// - 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())
|
if (IsDefault())
|
||||||
{
|
{
|
||||||
|
const auto defaultColor = til::at(colorTable, defaultIndex);
|
||||||
|
|
||||||
if (brighten)
|
if (brighten)
|
||||||
{
|
{
|
||||||
// See MSFT:20266024 for context on this fix.
|
// See MSFT:20266024 for context on this fix.
|
||||||
|
|
|
@ -65,6 +65,11 @@ public:
|
||||||
static constexpr BYTE BRIGHT_CYAN = 14;
|
static constexpr BYTE BRIGHT_CYAN = 14;
|
||||||
static constexpr BYTE BRIGHT_WHITE = 15;
|
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 :
|
constexpr TextColor() noexcept :
|
||||||
_meta{ ColorType::IsDefault },
|
_meta{ ColorType::IsDefault },
|
||||||
_red{ 0 },
|
_red{ 0 },
|
||||||
|
@ -103,7 +108,7 @@ public:
|
||||||
void SetIndex(const BYTE index, const bool isIndex256) noexcept;
|
void SetIndex(const BYTE index, const bool isIndex256) noexcept;
|
||||||
void SetDefault() 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;
|
BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept;
|
||||||
|
|
||||||
constexpr BYTE GetIndex() const noexcept
|
constexpr BYTE GetIndex() const noexcept
|
||||||
|
|
|
@ -27,9 +27,7 @@ Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
|
||||||
_fDeferCursorRedraw(false),
|
_fDeferCursorRedraw(false),
|
||||||
_fHaveDeferredCursorRedraw(false),
|
_fHaveDeferredCursorRedraw(false),
|
||||||
_ulSize(ulSize),
|
_ulSize(ulSize),
|
||||||
_cursorType(CursorType::Legacy),
|
_cursorType(CursorType::Legacy)
|
||||||
_fUseColor(false),
|
|
||||||
_color(s_InvertCursorColor)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,10 +141,9 @@ void Cursor::SetSize(const ULONG ulSize) noexcept
|
||||||
_RedrawCursor();
|
_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;
|
_ulSize = ulSize;
|
||||||
_color = color;
|
|
||||||
_cursorType = type;
|
_cursorType = type;
|
||||||
|
|
||||||
_RedrawCursor();
|
_RedrawCursor();
|
||||||
|
@ -285,7 +282,6 @@ void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
|
||||||
// Size will be handled separately in the resize operation.
|
// Size will be handled separately in the resize operation.
|
||||||
//_ulSize = OtherCursor._ulSize;
|
//_ulSize = OtherCursor._ulSize;
|
||||||
_cursorType = OtherCursor._cursorType;
|
_cursorType = OtherCursor._cursorType;
|
||||||
_color = OtherCursor._color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
|
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
|
||||||
|
@ -335,21 +331,6 @@ const CursorType Cursor::GetType() const noexcept
|
||||||
return _cursorType;
|
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
|
void Cursor::SetType(const CursorType type) noexcept
|
||||||
{
|
{
|
||||||
_cursorType = type;
|
_cursorType = type;
|
||||||
|
|
|
@ -24,7 +24,6 @@ class TextBuffer;
|
||||||
class Cursor final
|
class Cursor final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const unsigned int s_InvertCursorColor = INVALID_COLOR;
|
|
||||||
// the following values are used to create the textmode cursor.
|
// 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
|
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;
|
COORD GetPosition() const noexcept;
|
||||||
|
|
||||||
const CursorType GetType() const noexcept;
|
const CursorType GetType() const noexcept;
|
||||||
const bool IsUsingColor() const noexcept;
|
|
||||||
const COLORREF GetColor() const noexcept;
|
|
||||||
|
|
||||||
void StartDeferDrawing() noexcept;
|
void StartDeferDrawing() noexcept;
|
||||||
bool IsDeferDrawing() noexcept;
|
bool IsDeferDrawing() noexcept;
|
||||||
|
@ -67,7 +64,7 @@ public:
|
||||||
void SetIsPopupShown(const bool fIsPopupShown) noexcept;
|
void SetIsPopupShown(const bool fIsPopupShown) noexcept;
|
||||||
void SetDelay(const bool fDelay) noexcept;
|
void SetDelay(const bool fDelay) noexcept;
|
||||||
void SetSize(const ULONG ulSize) 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 SetPosition(const COORD cPosition) noexcept;
|
||||||
void SetXPosition(const int NewX) noexcept;
|
void SetXPosition(const int NewX) noexcept;
|
||||||
|
@ -84,7 +81,6 @@ public:
|
||||||
COORD GetDelayedAtPosition() const noexcept;
|
COORD GetDelayedAtPosition() const noexcept;
|
||||||
bool IsDelayedEOLWrap() const noexcept;
|
bool IsDelayedEOLWrap() const noexcept;
|
||||||
|
|
||||||
void SetColor(const unsigned int color) noexcept;
|
|
||||||
void SetType(const CursorType type) noexcept;
|
void SetType(const CursorType type) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -117,6 +113,4 @@ private:
|
||||||
void _RedrawCursorAlways() noexcept;
|
void _RedrawCursorAlways() noexcept;
|
||||||
|
|
||||||
CursorType _cursorType;
|
CursorType _cursorType;
|
||||||
bool _fUseColor;
|
|
||||||
COLORREF _color;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,9 +24,11 @@ class TextAttributeTests
|
||||||
TEST_METHOD(TestRoundtripDefaultColors);
|
TEST_METHOD(TestRoundtripDefaultColors);
|
||||||
TEST_METHOD(TestBoldAsBright);
|
TEST_METHOD(TestBoldAsBright);
|
||||||
|
|
||||||
std::array<COLORREF, 256> _colorTable;
|
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||||
COLORREF _defaultFg = RGB(1, 2, 3);
|
const COLORREF _defaultFg = RGB(1, 2, 3);
|
||||||
COLORREF _defaultBg = RGB(4, 5, 6);
|
const COLORREF _defaultBg = RGB(4, 5, 6);
|
||||||
|
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
|
||||||
|
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TextAttributeTests::ClassSetup()
|
bool TextAttributeTests::ClassSetup()
|
||||||
|
@ -47,6 +49,8 @@ bool TextAttributeTests::ClassSetup()
|
||||||
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
|
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
|
||||||
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
|
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
|
||||||
_colorTable[15] = RGB(242, 242, 242); // White
|
_colorTable[15] = RGB(242, 242, 242); // White
|
||||||
|
_colorTable[_defaultFgIndex] = _defaultFg;
|
||||||
|
_colorTable[_defaultBgIndex] = _defaultBg;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,17 +136,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
||||||
// values when reverse video is not set
|
// values when reverse video is not set
|
||||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
|
|
||||||
// with reverse video set, calculated foreground/background values should be
|
// with reverse video set, calculated foreground/background values should be
|
||||||
// switched while getters stay the same
|
// switched while getters stay the same
|
||||||
attr.SetReverseVideo(true);
|
attr.SetReverseVideo(true);
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
|
|
||||||
// reset the reverse video
|
// reset the reverse video
|
||||||
attr.SetReverseVideo(false);
|
attr.SetReverseVideo(false);
|
||||||
|
@ -151,17 +155,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
||||||
// while the background and getters stay the same
|
// while the background and getters stay the same
|
||||||
attr.SetFaint(true);
|
attr.SetFaint(true);
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
|
|
||||||
// with reverse video set, calculated foreground/background values should be
|
// with reverse video set, calculated foreground/background values should be
|
||||||
// switched, and the background fainter, while getters stay the same
|
// switched, and the background fainter, while getters stay the same
|
||||||
attr.SetReverseVideo(true);
|
attr.SetReverseVideo(true);
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
|
|
||||||
// reset the reverse video and faint attributes
|
// reset the reverse video and faint attributes
|
||||||
attr.SetReverseVideo(false);
|
attr.SetReverseVideo(false);
|
||||||
|
@ -171,17 +175,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
||||||
// background, while getters stay the same
|
// background, while getters stay the same
|
||||||
attr.SetInvisible(true);
|
attr.SetInvisible(true);
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
|
|
||||||
// with reverse video set, the calculated background value should match
|
// with reverse video set, the calculated background value should match
|
||||||
// the foreground, while getters stay the same
|
// the foreground, while getters stay the same
|
||||||
attr.SetReverseVideo(true);
|
attr.SetReverseVideo(true);
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextAttributeTests::TestReverseDefaultColors()
|
void TextAttributeTests::TestReverseDefaultColors()
|
||||||
|
@ -194,34 +198,34 @@ void TextAttributeTests::TestReverseDefaultColors()
|
||||||
// values when reverse video is not set
|
// values when reverse video is not set
|
||||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
|
|
||||||
// with reverse video set, calculated foreground/background values should be
|
// with reverse video set, calculated foreground/background values should be
|
||||||
// switched while getters stay the same
|
// switched while getters stay the same
|
||||||
attr.SetReverseVideo(true);
|
attr.SetReverseVideo(true);
|
||||||
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
|
|
||||||
attr.SetForeground(red);
|
attr.SetForeground(red);
|
||||||
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
|
|
||||||
attr.Invert();
|
attr.Invert();
|
||||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||||
attr.SetDefaultForeground();
|
attr.SetDefaultForeground();
|
||||||
attr.SetBackground(green);
|
attr.SetBackground(green);
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextAttributeTests::TestRoundtripDefaultColors()
|
void TextAttributeTests::TestRoundtripDefaultColors()
|
||||||
|
@ -277,43 +281,43 @@ void TextAttributeTests::TestBoldAsBright()
|
||||||
// values when not bold
|
// values when not bold
|
||||||
VERIFY_IS_FALSE(attr.IsBold());
|
VERIFY_IS_FALSE(attr.IsBold());
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||||
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, _defaultFgIndex, _defaultBgIndex, 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, false));
|
||||||
|
|
||||||
// with bold set, calculated foreground/background values shouldn't change for the default colors.
|
// with bold set, calculated foreground/background values shouldn't change for the default colors.
|
||||||
attr.SetBold(true);
|
attr.SetBold(true);
|
||||||
VERIFY_IS_TRUE(attr.IsBold());
|
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, _defaultFgIndex, _defaultBgIndex, 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, false));
|
||||||
|
|
||||||
attr.SetIndexedForeground(TextColor::DARK_BLACK);
|
attr.SetIndexedForeground(TextColor::DARK_BLACK);
|
||||||
VERIFY_IS_TRUE(attr.IsBold());
|
VERIFY_IS_TRUE(attr.IsBold());
|
||||||
|
|
||||||
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
|
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");
|
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(TextColor::DARK_GREEN);
|
attr.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||||
VERIFY_IS_TRUE(attr.IsBold());
|
VERIFY_IS_TRUE(attr.IsBold());
|
||||||
|
|
||||||
Log::Comment(L"background should be unaffected by 'bold is bright'");
|
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(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, 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, false));
|
||||||
|
|
||||||
attr.SetBold(false);
|
attr.SetBold(false);
|
||||||
VERIFY_IS_FALSE(attr.IsBold());
|
VERIFY_IS_FALSE(attr.IsBold());
|
||||||
Log::Comment(L"when not bold, 'bold is bright' changes nothing");
|
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, _defaultFgIndex, _defaultBgIndex, 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, false));
|
||||||
|
|
||||||
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
|
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
|
||||||
attr.SetBold(true);
|
attr.SetBold(true);
|
||||||
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
||||||
VERIFY_IS_TRUE(attr.IsBold());
|
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, _defaultFgIndex, _defaultBgIndex, 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, false));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,11 @@ class TextColorTests
|
||||||
TEST_METHOD(TestRgbColor);
|
TEST_METHOD(TestRgbColor);
|
||||||
TEST_METHOD(TestChangeColor);
|
TEST_METHOD(TestChangeColor);
|
||||||
|
|
||||||
std::array<COLORREF, 256> _colorTable;
|
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||||
COLORREF _defaultFg = RGB(1, 2, 3);
|
const COLORREF _defaultFg = RGB(1, 2, 3);
|
||||||
COLORREF _defaultBg = RGB(4, 5, 6);
|
const COLORREF _defaultBg = RGB(4, 5, 6);
|
||||||
|
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
|
||||||
|
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TextColorTests::ClassSetup()
|
bool TextColorTests::ClassSetup()
|
||||||
|
@ -46,6 +48,8 @@ bool TextColorTests::ClassSetup()
|
||||||
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
|
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
|
||||||
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
|
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
|
||||||
_colorTable[15] = RGB(242, 242, 242); // White
|
_colorTable[15] = RGB(242, 242, 242); // White
|
||||||
|
_colorTable[_defaultFgIndex] = _defaultFg;
|
||||||
|
_colorTable[_defaultBgIndex] = _defaultBg;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,16 +61,16 @@ void TextColorTests::TestDefaultColor()
|
||||||
VERIFY_IS_FALSE(defaultColor.IsLegacy());
|
VERIFY_IS_FALSE(defaultColor.IsLegacy());
|
||||||
VERIFY_IS_FALSE(defaultColor.IsRgb());
|
VERIFY_IS_FALSE(defaultColor.IsRgb());
|
||||||
|
|
||||||
auto color = defaultColor.GetColor(_colorTable, _defaultFg, false);
|
auto color = defaultColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||||
|
|
||||||
color = defaultColor.GetColor(_colorTable, _defaultFg, true);
|
color = defaultColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||||
|
|
||||||
color = defaultColor.GetColor(_colorTable, _defaultBg, false);
|
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||||
|
|
||||||
color = defaultColor.GetColor(_colorTable, _defaultBg, true);
|
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,16 +82,16 @@ void TextColorTests::TestDarkIndexColor()
|
||||||
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
||||||
VERIFY_IS_FALSE(indexColor.IsRgb());
|
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);
|
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||||
|
|
||||||
color = indexColor.GetColor(_colorTable, _defaultFg, true);
|
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
color = indexColor.GetColor(_colorTable, _defaultBg, false);
|
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||||
|
|
||||||
color = indexColor.GetColor(_colorTable, _defaultBg, true);
|
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,16 +103,16 @@ void TextColorTests::TestBrightIndexColor()
|
||||||
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
||||||
VERIFY_IS_FALSE(indexColor.IsRgb());
|
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);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
color = indexColor.GetColor(_colorTable, _defaultFg, true);
|
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
color = indexColor.GetColor(_colorTable, _defaultBg, false);
|
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
color = indexColor.GetColor(_colorTable, _defaultBg, true);
|
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,16 +125,16 @@ void TextColorTests::TestRgbColor()
|
||||||
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
||||||
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
||||||
|
|
||||||
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(myColor, color);
|
VERIFY_ARE_EQUAL(myColor, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(myColor, color);
|
VERIFY_ARE_EQUAL(myColor, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(myColor, color);
|
VERIFY_ARE_EQUAL(myColor, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(myColor, color);
|
VERIFY_ARE_EQUAL(myColor, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,55 +147,55 @@ void TextColorTests::TestChangeColor()
|
||||||
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
||||||
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
||||||
|
|
||||||
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(myColor, color);
|
VERIFY_ARE_EQUAL(myColor, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(myColor, color);
|
VERIFY_ARE_EQUAL(myColor, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(myColor, color);
|
VERIFY_ARE_EQUAL(myColor, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(myColor, color);
|
VERIFY_ARE_EQUAL(myColor, color);
|
||||||
|
|
||||||
rgbColor.SetDefault();
|
rgbColor.SetDefault();
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||||
|
|
||||||
rgbColor.SetIndex(7, false);
|
rgbColor.SetIndex(7, false);
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
rgbColor.SetIndex(15, false);
|
rgbColor.SetIndex(15, false);
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
|
|
||||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,13 +61,26 @@
|
||||||
|
|
||||||
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
|
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
|
||||||
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
|
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\WindowsTerminal\WindowsTerminal.vcxproj" />
|
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj">
|
||||||
<ProjectReference Include="..\..\host\exe\Host.EXE.vcxproj" />
|
<Project>{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}</Project>
|
||||||
<ProjectReference Include="..\..\host\proxy\Host.Proxy.vcxproj" />
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\TerminalAzBridge\TerminalAzBridge.vcxproj" />
|
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj">
|
||||||
<ProjectReference Include="..\ShellExtension\WindowsTerminalShellExt.vcxproj" />
|
<Project>{067F0A06-FCB7-472C-96E9-B03B54E8E18D}</Project>
|
||||||
<ProjectReference Include="..\wt\wt.vcxproj" />
|
</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>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">
|
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Dependencies>
|
<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>
|
</Dependencies>
|
||||||
|
|
||||||
<Resources>
|
<Resources>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Dependencies>
|
<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>
|
</Dependencies>
|
||||||
|
|
||||||
<Resources>
|
<Resources>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Dependencies>
|
<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>
|
</Dependencies>
|
||||||
|
|
||||||
<Resources>
|
<Resources>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Dependencies>
|
<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" 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" />
|
<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>
|
</Dependencies>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<uap:SupportedUsers>multiple</uap:SupportedUsers>
|
<uap:SupportedUsers>multiple</uap:SupportedUsers>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Dependencies>
|
<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>
|
</Dependencies>
|
||||||
<Resources>
|
<Resources>
|
||||||
<Resource Language="x-generate" />
|
<Resource Language="x-generate" />
|
||||||
|
|
|
@ -239,8 +239,8 @@ HRESULT HwndTerminal::Initialize()
|
||||||
_terminal->SetBackgroundCallback([](auto) {});
|
_terminal->SetBackgroundCallback([](auto) {});
|
||||||
|
|
||||||
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
|
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
|
||||||
_terminal->SetDefaultBackground(RGB(12, 12, 12));
|
_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12));
|
||||||
_terminal->SetDefaultForeground(RGB(204, 204, 204));
|
_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204));
|
||||||
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
|
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
|
||||||
localPointerToThread->EnablePainting();
|
localPointerToThread->EnablePainting();
|
||||||
|
|
||||||
|
@ -781,8 +781,8 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
|
||||||
{
|
{
|
||||||
auto lock = publicTerminal->_terminal->LockForWriting();
|
auto lock = publicTerminal->_terminal->LockForWriting();
|
||||||
|
|
||||||
publicTerminal->_terminal->SetDefaultForeground(theme.DefaultForeground);
|
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground);
|
||||||
publicTerminal->_terminal->SetDefaultBackground(theme.DefaultBackground);
|
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground);
|
||||||
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha);
|
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha);
|
||||||
|
|
||||||
// Set the font colors
|
// Set the font colors
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
<ProjectReference Include="$(SolutionDir)src\types\lib\types.vcxproj">
|
<ProjectReference Include="$(SolutionDir)src\types\lib\types.vcxproj">
|
||||||
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
|
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
|
||||||
</ProjectReference>
|
</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">
|
<ProjectReference Include="$(SolutionDir)src\renderer\base\lib\base.vcxproj">
|
||||||
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include <WtExeUtils.h>
|
#include <WtExeUtils.h>
|
||||||
#include <wil/token_helpers.h >
|
#include <wil/token_helpers.h >
|
||||||
|
|
||||||
|
#include "../../types/inc/utils.hpp"
|
||||||
|
|
||||||
using namespace winrt::Windows::ApplicationModel;
|
using namespace winrt::Windows::ApplicationModel;
|
||||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||||
using namespace winrt::Windows::UI::Xaml;
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
|
@ -131,38 +133,6 @@ static Documents::Run _BuildErrorRun(const winrt::hstring& text, const ResourceD
|
||||||
return textRun;
|
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
|
namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
// Function Description:
|
// Function Description:
|
||||||
|
@ -214,7 +184,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
// The TerminalPage has to be constructed during our construction, to
|
// The TerminalPage has to be constructed during our construction, to
|
||||||
// make sure that there's a terminal page for callers of
|
// make sure that there's a terminal page for callers of
|
||||||
// SetTitleBarContent
|
// SetTitleBarContent
|
||||||
_isElevated = _isUserAdmin();
|
_isElevated = ::Microsoft::Console::Utils::IsElevated();
|
||||||
_root = winrt::make_self<TerminalPage>();
|
_root = winrt::make_self<TerminalPage>();
|
||||||
|
|
||||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||||
|
@ -910,8 +880,6 @@ namespace winrt::TerminalApp::implementation
|
||||||
void AppLogic::_RegisterSettingsChange()
|
void AppLogic::_RegisterSettingsChange()
|
||||||
{
|
{
|
||||||
const std::filesystem::path settingsPath{ std::wstring_view{ CascadiaSettings::SettingsPath() } };
|
const std::filesystem::path settingsPath{ std::wstring_view{ CascadiaSettings::SettingsPath() } };
|
||||||
const std::filesystem::path statePath{ std::wstring_view{ ApplicationState::SharedInstance().FilePath() } };
|
|
||||||
|
|
||||||
_reader.create(
|
_reader.create(
|
||||||
settingsPath.parent_path().c_str(),
|
settingsPath.parent_path().c_str(),
|
||||||
false,
|
false,
|
||||||
|
@ -920,14 +888,29 @@ namespace winrt::TerminalApp::implementation
|
||||||
// editors, who will write a temp file, then rename it to be the
|
// editors, who will write a temp file, then rename it to be the
|
||||||
// actual file you wrote. So listen for that too.
|
// actual file you wrote. So listen for that too.
|
||||||
wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime,
|
wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime,
|
||||||
[this, settingsBasename = settingsPath.filename(), stateBasename = statePath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
|
[this, settingsBasename = settingsPath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
|
||||||
const auto modifiedBasename = std::filesystem::path{ fileModified }.filename();
|
// 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)
|
if (modifiedBasename == settingsBasename)
|
||||||
{
|
{
|
||||||
_reloadSettings->Run();
|
_reloadSettings->Run();
|
||||||
}
|
}
|
||||||
else if (modifiedBasename == stateBasename)
|
else if (ApplicationState::SharedInstance().IsStatePath(modifiedBasename))
|
||||||
{
|
{
|
||||||
_reloadState();
|
_reloadState();
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,7 +318,29 @@
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<!-- For whatever reason, we can't include the TerminalControl and
|
<!-- For whatever reason, we can't include the TerminalControl and
|
||||||
TerminalSettings projects' winmds via project references. So we'll have to
|
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>
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- This is a hack to get the ARM64 CI build working. See
|
<!-- This is a hack to get the ARM64 CI build working. See
|
||||||
|
|
|
@ -3,38 +3,38 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "TerminalPage.h"
|
#include "TerminalPage.h"
|
||||||
#include "Utils.h"
|
#include "TerminalPage.g.cpp"
|
||||||
#include "../../types/inc/utils.hpp"
|
#include "RenameWindowRequestedArgs.g.cpp"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include <inc/WindowingBehavior.h>
|
||||||
#include <LibraryResources.h>
|
#include <LibraryResources.h>
|
||||||
|
#include <TerminalCore/ControlKeyStates.hpp>
|
||||||
|
#include <til/latch.h>
|
||||||
|
|
||||||
#include "TerminalPage.g.cpp"
|
#include "../../types/inc/utils.hpp"
|
||||||
#include <winrt/Windows.Storage.h>
|
|
||||||
|
|
||||||
#include "TabRowControl.h"
|
|
||||||
#include "ColorHelper.h"
|
#include "ColorHelper.h"
|
||||||
#include "DebugTapConnection.h"
|
#include "DebugTapConnection.h"
|
||||||
#include "SettingsTab.h"
|
#include "SettingsTab.h"
|
||||||
#include "RenameWindowRequestedArgs.g.cpp"
|
#include "TabRowControl.h"
|
||||||
#include "../inc/WindowingBehavior.h"
|
|
||||||
|
|
||||||
#include <til/latch.h>
|
|
||||||
|
|
||||||
using namespace winrt;
|
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::Control;
|
||||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
|
||||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
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 ::TerminalApp;
|
||||||
using namespace ::Microsoft::Console;
|
using namespace ::Microsoft::Console;
|
||||||
|
using namespace ::Microsoft::Terminal::Core;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });
|
#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });
|
||||||
|
@ -300,10 +300,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - true if the ApplicationState should be used.
|
// - true if the ApplicationState should be used.
|
||||||
bool TerminalPage::ShouldUsePersistedLayout(CascadiaSettings& settings) const
|
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() &&
|
return Feature_PersistedWindowLayout::IsEnabled() &&
|
||||||
!IsElevated() &&
|
|
||||||
settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout;
|
settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1041,29 +1038,153 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// 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:
|
// Arguments:
|
||||||
// - e: the KeyRoutedEventArgs containing info about the keystroke.
|
// - e: the KeyRoutedEventArgs containing info about the keystroke.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
|
void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
|
||||||
{
|
{
|
||||||
const auto key = e.OriginalKey();
|
const auto keyStatus = e.KeyStatus();
|
||||||
const auto scanCode = e.KeyStatus().ScanCode;
|
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey());
|
||||||
const auto coreWindow = CoreWindow::GetForCurrentThread();
|
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||||
const auto ctrlDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
|
const auto modifiers = _GetPressedModifierKeys();
|
||||||
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);
|
|
||||||
|
|
||||||
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, false, static_cast<int32_t>(key), static_cast<int32_t>(scanCode) };
|
// GH#11076:
|
||||||
if (const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) })
|
// 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)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,17 @@
|
||||||
|
|
||||||
static constexpr uint32_t DefaultRowsToScroll{ 3 };
|
static constexpr uint32_t DefaultRowsToScroll{ 3 };
|
||||||
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
|
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
|
||||||
// fwdecl unittest classes
|
|
||||||
namespace TerminalAppLocalTests
|
namespace TerminalAppLocalTests
|
||||||
{
|
{
|
||||||
class TabTests;
|
class TabTests;
|
||||||
class SettingsTests;
|
class SettingsTests;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
namespace Microsoft::Terminal::Core
|
||||||
|
{
|
||||||
|
class ControlKeyStates;
|
||||||
|
}
|
||||||
|
|
||||||
namespace winrt::TerminalApp::implementation
|
namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
|
@ -225,6 +230,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
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);
|
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 _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) noexcept;
|
||||||
void _RegisterActionCallbacks();
|
void _RegisterActionCallbacks();
|
||||||
|
|
||||||
|
|
|
@ -68,5 +68,22 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</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" />
|
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -97,4 +97,39 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
<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 "pch.h"
|
||||||
#include "ControlCore.h"
|
#include "ControlCore.h"
|
||||||
#include <argb.h>
|
|
||||||
#include <DefaultSettings.h>
|
#include <DefaultSettings.h>
|
||||||
#include <unicode.hpp>
|
#include <unicode.hpp>
|
||||||
#include <Utf16Parser.hpp>
|
#include <Utf16Parser.hpp>
|
||||||
#include <Utils.h>
|
|
||||||
#include <WinUser.h>
|
#include <WinUser.h>
|
||||||
#include <LibraryResources.h>
|
#include <LibraryResources.h>
|
||||||
|
|
||||||
|
#include "EventArgs.h"
|
||||||
#include "../../types/inc/GlyphWidth.hpp"
|
#include "../../types/inc/GlyphWidth.hpp"
|
||||||
#include "../../types/inc/Utils.hpp"
|
|
||||||
#include "../../buffer/out/search.h"
|
#include "../../buffer/out/search.h"
|
||||||
|
#include "../../renderer/atlas/AtlasEngine.h"
|
||||||
|
#include "../../renderer/dx/DxRenderer.hpp"
|
||||||
|
|
||||||
#include "ControlCore.g.cpp"
|
#include "ControlCore.g.cpp"
|
||||||
|
|
||||||
|
@ -202,6 +204,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
const double actualHeight,
|
const double actualHeight,
|
||||||
const double compositionScale)
|
const double compositionScale)
|
||||||
{
|
{
|
||||||
|
assert(_settings);
|
||||||
|
|
||||||
_panelWidth = actualWidth;
|
_panelWidth = actualWidth;
|
||||||
_panelHeight = actualHeight;
|
_panelHeight = actualHeight;
|
||||||
_compositionScale = compositionScale;
|
_compositionScale = compositionScale;
|
||||||
|
@ -222,10 +226,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the DX Engine
|
if (Feature_AtlasEngine::IsEnabled() && _settings.UseAtlasEngine())
|
||||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
{
|
||||||
_renderer->AddRenderEngine(dxEngine.get());
|
_renderEngine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
|
||||||
_renderEngine = std::move(dxEngine);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_renderEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderer->AddRenderEngine(_renderEngine.get());
|
||||||
|
|
||||||
// Initialize our font with the renderer
|
// 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
|
// 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->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||||
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
|
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
|
||||||
|
|
||||||
_updateAntiAliasingMode(_renderEngine.get());
|
_updateAntiAliasingMode();
|
||||||
|
|
||||||
// GH#5098: Inform the engine of the opacity of the default text background.
|
// 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.
|
// 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());
|
THROW_IF_FAILED(_renderEngine->Enable());
|
||||||
|
|
||||||
|
@ -616,7 +627,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
|
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
|
||||||
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||||
|
|
||||||
_updateAntiAliasingMode(_renderEngine.get());
|
_updateAntiAliasingMode();
|
||||||
|
|
||||||
// Refresh our font with the renderer
|
// Refresh our font with the renderer
|
||||||
const auto actualFontOldSize = _actualFont.GetSize();
|
const auto actualFontOldSize = _actualFont.GetSize();
|
||||||
|
@ -650,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())
|
switch (_settings.AntialiasingMode())
|
||||||
{
|
{
|
||||||
case TextAntialiasingMode::Cleartype:
|
case TextAntialiasingMode::Cleartype:
|
||||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
|
mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||||
break;
|
break;
|
||||||
case TextAntialiasingMode::Aliased:
|
case TextAntialiasingMode::Aliased:
|
||||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||||
break;
|
break;
|
||||||
case TextAntialiasingMode::Grayscale:
|
|
||||||
default:
|
default:
|
||||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_renderEngine->SetAntialiasingMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -1076,7 +1089,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
til::color ControlCore::BackgroundColor() const
|
til::color ControlCore::BackgroundColor() const
|
||||||
{
|
{
|
||||||
return _terminal->GetDefaultBackground();
|
return _terminal->GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -1296,7 +1309,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
if (_renderEngine)
|
if (_renderEngine)
|
||||||
{
|
{
|
||||||
auto lock = _terminal->LockForWriting();
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "EventArgs.h"
|
|
||||||
#include "ControlCore.g.h"
|
#include "ControlCore.g.h"
|
||||||
#include "../../renderer/base/Renderer.hpp"
|
#include "../../renderer/base/Renderer.hpp"
|
||||||
#include "../../renderer/dx/DxRenderer.hpp"
|
|
||||||
#include "../../renderer/uia/UiaRenderer.hpp"
|
|
||||||
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
||||||
#include "../buffer/out/search.h"
|
#include "../buffer/out/search.h"
|
||||||
#include "cppwinrt_utils.h"
|
#include "cppwinrt_utils.h"
|
||||||
|
@ -188,7 +185,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// As _renderer has a dependency on _renderEngine (through a raw pointer)
|
// As _renderer has a dependency on _renderEngine (through a raw pointer)
|
||||||
// we must ensure the _renderer is deallocated first.
|
// we must ensure the _renderer is deallocated first.
|
||||||
// (C++ class members are destroyed in reverse order.)
|
// (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 };
|
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr };
|
||||||
|
|
||||||
IControlSettings _settings{ nullptr };
|
IControlSettings _settings{ nullptr };
|
||||||
|
@ -248,7 +245,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
void _raiseReadOnlyWarning();
|
void _raiseReadOnlyWarning();
|
||||||
void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine);
|
void _updateAntiAliasingMode();
|
||||||
void _connectionOutputHandler(const hstring& hstr);
|
void _connectionOutputHandler(const hstring& hstr);
|
||||||
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
|
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "cppwinrt_utils.h"
|
#include "cppwinrt_utils.h"
|
||||||
|
|
||||||
#include "ControlCore.h"
|
#include "ControlCore.h"
|
||||||
|
#include "../../renderer/uia/UiaRenderer.hpp"
|
||||||
|
|
||||||
namespace ControlUnitTests
|
namespace ControlUnitTests
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,10 +27,11 @@ namespace Microsoft.Terminal.Control
|
||||||
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings, Microsoft.Terminal.Control.IControlAppearance
|
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings, Microsoft.Terminal.Control.IControlAppearance
|
||||||
{
|
{
|
||||||
String ProfileName;
|
String ProfileName;
|
||||||
|
String ProfileSource;
|
||||||
|
|
||||||
Boolean UseAcrylic;
|
Boolean UseAcrylic;
|
||||||
ScrollbarState ScrollState;
|
ScrollbarState ScrollState;
|
||||||
|
Boolean UseAtlasEngine;
|
||||||
String FontFace;
|
String FontFace;
|
||||||
Int32 FontSize;
|
Int32 FontSize;
|
||||||
Windows.UI.Text.FontWeight FontWeight;
|
Windows.UI.Text.FontWeight FontWeight;
|
||||||
|
|
|
@ -3,17 +3,16 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "TermControl.h"
|
#include "TermControl.h"
|
||||||
#include <argb.h>
|
|
||||||
#include <DefaultSettings.h>
|
|
||||||
#include <unicode.hpp>
|
#include <unicode.hpp>
|
||||||
#include <Utf16Parser.hpp>
|
#include <Utf16Parser.hpp>
|
||||||
#include <Utils.h>
|
|
||||||
#include <LibraryResources.h>
|
#include <LibraryResources.h>
|
||||||
|
|
||||||
|
#include "TermControlAutomationPeer.h"
|
||||||
#include "../../types/inc/GlyphWidth.hpp"
|
#include "../../types/inc/GlyphWidth.hpp"
|
||||||
#include "../../types/inc/Utils.hpp"
|
#include "../../renderer/atlas/AtlasEngine.h"
|
||||||
|
|
||||||
#include "TermControl.g.cpp"
|
#include "TermControl.g.cpp"
|
||||||
#include "TermControlAutomationPeer.h"
|
|
||||||
|
|
||||||
using namespace ::Microsoft::Console::Types;
|
using namespace ::Microsoft::Console::Types;
|
||||||
using namespace ::Microsoft::Console::VirtualTerminal;
|
using namespace ::Microsoft::Console::VirtualTerminal;
|
||||||
|
@ -774,12 +773,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
_HidePointerCursorHandlers(*this, nullptr);
|
_HidePointerCursorHandlers(*this, nullptr);
|
||||||
|
|
||||||
const auto ch = e.Character();
|
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();
|
auto modifiers = _GetPressedModifierKeys();
|
||||||
if (e.KeyStatus().IsExtendedKey)
|
|
||||||
|
if (keyStatus.IsExtendedKey)
|
||||||
{
|
{
|
||||||
modifiers |= ControlKeyStates::EnhancedKey;
|
modifiers |= ControlKeyStates::EnhancedKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool handled = _core.SendCharEvent(ch, scanCode, modifiers);
|
const bool handled = _core.SendCharEvent(ch, scanCode, modifiers);
|
||||||
e.Handled(handled);
|
e.Handled(handled);
|
||||||
}
|
}
|
||||||
|
@ -874,6 +876,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||||
auto modifiers = _GetPressedModifierKeys();
|
auto modifiers = _GetPressedModifierKeys();
|
||||||
|
|
||||||
|
if (keyStatus.IsExtendedKey)
|
||||||
|
{
|
||||||
|
modifiers |= ControlKeyStates::EnhancedKey;
|
||||||
|
}
|
||||||
|
|
||||||
// GH#11076:
|
// GH#11076:
|
||||||
// For some weird reason we sometimes receive a WM_KEYDOWN
|
// For some weird reason we sometimes receive a WM_KEYDOWN
|
||||||
// message without vkey or scanCode if a user drags a tab.
|
// message without vkey or scanCode if a user drags a tab.
|
||||||
|
@ -907,11 +914,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyStatus.IsExtendedKey)
|
|
||||||
{
|
|
||||||
modifiers |= ControlKeyStates::EnhancedKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alt-Numpad# input will send us a character once the user releases
|
// Alt-Numpad# input will send us a character once the user releases
|
||||||
// Alt, so we should be ignoring the individual keydowns. The character
|
// Alt, so we should be ignoring the individual keydowns. The character
|
||||||
// will be sent through the TSFInputControl. See GH#1401 for more
|
// will be sent through the TSFInputControl. See GH#1401 for more
|
||||||
|
@ -989,7 +991,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - vkey: The vkey of the key pressed.
|
// - vkey: The vkey of the key pressed.
|
||||||
// - scanCode: The scan code 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;
|
std::array<BYTE, 256> keyState;
|
||||||
if (!GetKeyboardState(keyState.data()))
|
if (!GetKeyboardState(keyState.data()))
|
||||||
|
@ -1828,13 +1830,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
const winrt::Windows::Foundation::Size initialSize{ cols, rows };
|
const winrt::Windows::Foundation::Size initialSize{ cols, rows };
|
||||||
|
|
||||||
return GetProposedDimensions(initialSize,
|
return GetProposedDimensions(settings, dpi, initialSize);
|
||||||
settings.FontSize(),
|
|
||||||
settings.FontWeight(),
|
|
||||||
settings.FontFace(),
|
|
||||||
settings.ScrollState(),
|
|
||||||
settings.Padding(),
|
|
||||||
dpi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
|
@ -1855,16 +1851,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// caller knows what monitor the control is about to appear on.
|
// caller knows what monitor the control is about to appear on.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - a size containing the requested dimensions in pixels.
|
// - a size containing the requested dimensions in pixels.
|
||||||
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
|
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, 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)
|
|
||||||
{
|
{
|
||||||
const auto cols = ::base::saturated_cast<int>(initialSizeInChars.Width);
|
const auto cols = ::base::saturated_cast<int>(initialSizeInChars.Width);
|
||||||
const auto rows = ::base::saturated_cast<int>(initialSizeInChars.Height);
|
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.
|
// Initialize our font information.
|
||||||
// The font width doesn't terribly matter, we'll only be using the
|
// The font width doesn't terribly matter, we'll only be using the
|
||||||
|
@ -1873,28 +1868,39 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// The family is only used to determine if the font is truetype or
|
// The family is only used to determine if the font is truetype or
|
||||||
// not, but DX doesn't use that info at all.
|
// not, but DX doesn't use that info at all.
|
||||||
// The Codepage is additionally not actually used by the DX engine 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 };
|
FontInfoDesired desiredFont = { actualFont };
|
||||||
|
|
||||||
// Create a DX engine and initialize it with our font and DPI. We'll
|
// 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
|
// then use it to measure how much space the requested rows and columns
|
||||||
// will take up.
|
// will take up.
|
||||||
// TODO: MSFT:21254947 - use a static function to do this instead of
|
// 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
|
// GH#10211 - UNDER NO CIRCUMSTANCE should this fail. If it does, the
|
||||||
// whole app will crash instantaneously on launch, which is no good.
|
// whole app will crash instantaneously on launch, which is no good.
|
||||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
double scale;
|
||||||
LOG_IF_FAILED(dxEngine->UpdateDpi(dpi));
|
if (Feature_AtlasEngine::IsEnabled() && settings.UseAtlasEngine())
|
||||||
LOG_IF_FAILED(dxEngine->UpdateFont(desiredFont, actualFont));
|
{
|
||||||
|
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 actualFontSize = actualFont.GetSize();
|
||||||
const auto fontSize = actualFont.GetSize();
|
|
||||||
|
|
||||||
// UWP XAML scrollbars aren't guaranteed to be the same size as the
|
// UWP XAML scrollbars aren't guaranteed to be the same size as the
|
||||||
// ComCtl scrollbars, but it's certainly close enough.
|
// ComCtl scrollbars, but it's certainly close enough.
|
||||||
const auto scrollbarSize = GetSystemMetricsForDpi(SM_CXVSCROLL, dpi);
|
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
|
// Reserve additional space if scrollbar is intended to be visible
|
||||||
if (scrollState == ScrollbarState::Visible)
|
if (scrollState == ScrollbarState::Visible)
|
||||||
|
@ -1902,7 +1908,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
width += scrollbarSize;
|
width += scrollbarSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
double height = rows * fontSize.Y;
|
double height = rows * actualFontSize.Y;
|
||||||
const auto thickness = ParseThicknessFromPadding(padding);
|
const auto thickness = ParseThicknessFromPadding(padding);
|
||||||
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
|
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
|
||||||
width += scale * (thickness.Left + thickness.Right);
|
width += scale * (thickness.Left + thickness.Right);
|
||||||
|
@ -1962,13 +1968,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
|
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
|
||||||
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
||||||
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
|
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
|
||||||
return GetProposedDimensions(minSize,
|
return GetProposedDimensions(_settings, dpi, minSize);
|
||||||
_settings.FontSize(),
|
|
||||||
_settings.FontWeight(),
|
|
||||||
_settings.FontFace(),
|
|
||||||
_settings.ScrollState(),
|
|
||||||
_settings.Padding(),
|
|
||||||
dpi);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2063,7 +2063,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// don't necessarily include that state.
|
// don't necessarily include that state.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
|
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
|
||||||
ControlKeyStates TermControl::_GetPressedModifierKeys() const
|
ControlKeyStates TermControl::_GetPressedModifierKeys() noexcept
|
||||||
{
|
{
|
||||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||||
// DONT USE
|
// DONT USE
|
||||||
|
@ -2271,6 +2271,42 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring fullPath{ item.Path() };
|
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(),
|
const auto containsSpaces = std::find(fullPath.begin(),
|
||||||
fullPath.end(),
|
fullPath.end(),
|
||||||
L' ') != fullPath.end();
|
L' ') != fullPath.end();
|
||||||
|
@ -2283,6 +2319,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
allPaths += fullPath;
|
allPaths += fullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
_core.PasteText(winrt::hstring{ allPaths });
|
_core.PasteText(winrt::hstring{ allPaths });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,13 +92,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
void Settings(IControlSettings newSettings);
|
void Settings(IControlSettings newSettings);
|
||||||
|
|
||||||
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi);
|
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi);
|
||||||
static Windows::Foundation::Size GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
|
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, 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);
|
|
||||||
|
|
||||||
void BellLightOn();
|
void BellLightOn();
|
||||||
|
|
||||||
|
@ -251,9 +245,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
|
void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
|
||||||
|
|
||||||
void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown);
|
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;
|
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);
|
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);
|
const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition);
|
||||||
|
|
|
@ -147,6 +147,7 @@
|
||||||
<ProjectReference Include="..\..\types\lib\types.vcxproj" />
|
<ProjectReference Include="..\..\types\lib\types.vcxproj" />
|
||||||
<ProjectReference Include="..\..\buffer\out\lib\bufferout.vcxproj" />
|
<ProjectReference Include="..\..\buffer\out\lib\bufferout.vcxproj" />
|
||||||
<ProjectReference Include="$(OpenConsoleDir)src\renderer\base\lib\base.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\dx\lib\dx.vcxproj" />
|
||||||
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj" />
|
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj" />
|
||||||
<ProjectReference Include="..\..\terminal\parser\lib\parser.vcxproj" />
|
<ProjectReference Include="..\..\terminal\parser\lib\parser.vcxproj" />
|
||||||
|
|
|
@ -40,13 +40,10 @@ namespace Microsoft::Terminal::Core
|
||||||
virtual bool WarningBell() noexcept = 0;
|
virtual bool WarningBell() noexcept = 0;
|
||||||
virtual bool SetWindowTitle(std::wstring_view title) 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 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 SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,6 @@ Terminal::Terminal() :
|
||||||
_mutableViewport{ Viewport::Empty() },
|
_mutableViewport{ Viewport::Empty() },
|
||||||
_title{},
|
_title{},
|
||||||
_colorTable{},
|
_colorTable{},
|
||||||
_defaultFg{ RGB(255, 255, 255) },
|
|
||||||
_defaultBg{ ARGB(0, 0, 0, 0) },
|
|
||||||
_screenReversed{ false },
|
_screenReversed{ false },
|
||||||
_pfnWriteInput{ nullptr },
|
_pfnWriteInput{ nullptr },
|
||||||
_scrollOffset{ 0 },
|
_scrollOffset{ 0 },
|
||||||
|
@ -61,6 +59,14 @@ Terminal::Terminal() :
|
||||||
|
|
||||||
_stateMachine = std::make_unique<StateMachine>(std::move(engine));
|
_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) {
|
auto passAlongInput = [&](std::deque<std::unique_ptr<IInputEvent>>& inEventsToWrite) {
|
||||||
if (!_pfnWriteInput)
|
if (!_pfnWriteInput)
|
||||||
{
|
{
|
||||||
|
@ -73,6 +79,10 @@ Terminal::Terminal() :
|
||||||
_terminalInput = std::make_unique<TerminalInput>(passAlongInput);
|
_terminalInput = std::make_unique<TerminalInput>(passAlongInput);
|
||||||
|
|
||||||
_InitializeColorTable();
|
_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)
|
void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, IRenderTarget& renderTarget)
|
||||||
|
@ -172,9 +182,13 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||||
{
|
{
|
||||||
// Set the default background as transparent to prevent the
|
// Set the default background as transparent to prevent the
|
||||||
// DX layer from overwriting the background image or acrylic effect
|
// DX layer from overwriting the background image or acrylic effect
|
||||||
til::color newBackgroundColor{ appearance.DefaultBackground() };
|
const til::color newBackgroundColor{ appearance.DefaultBackground() };
|
||||||
_defaultBg = newBackgroundColor.with_alpha(0);
|
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = newBackgroundColor.with_alpha(0);
|
||||||
_defaultFg = appearance.DefaultForeground();
|
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();
|
_intenseIsBright = appearance.IntenseIsBright();
|
||||||
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
|
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
|
||||||
|
|
||||||
|
@ -213,9 +227,7 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||||
|
|
||||||
if (_buffer)
|
if (_buffer)
|
||||||
{
|
{
|
||||||
_buffer->GetCursor().SetStyle(appearance.CursorHeight(),
|
_buffer->GetCursor().SetStyle(appearance.CursorHeight(), cursorShape);
|
||||||
til::color{ appearance.CursorColor() },
|
|
||||||
cursorShape);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaultCursorShape = cursorShape;
|
_defaultCursorShape = cursorShape;
|
||||||
|
|
|
@ -106,11 +106,9 @@ public:
|
||||||
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
|
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
|
||||||
bool WarningBell() noexcept override;
|
bool WarningBell() noexcept override;
|
||||||
bool SetWindowTitle(std::wstring_view title) 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 SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
|
||||||
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) 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 SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
|
bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
|
||||||
|
|
||||||
|
@ -212,7 +210,6 @@ public:
|
||||||
void ClearPatternTree() noexcept;
|
void ClearPatternTree() noexcept;
|
||||||
|
|
||||||
const std::optional<til::color> GetTabColor() const noexcept;
|
const std::optional<til::color> GetTabColor() const noexcept;
|
||||||
til::color GetDefaultBackground() const noexcept;
|
|
||||||
|
|
||||||
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
|
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
|
||||||
|
|
||||||
|
@ -281,9 +278,7 @@ private:
|
||||||
std::optional<til::color> _startingTabColor;
|
std::optional<til::color> _startingTabColor;
|
||||||
|
|
||||||
// This is still stored as a COLORREF because it interacts with some code in ConTypes
|
// This is still stored as a COLORREF because it interacts with some code in ConTypes
|
||||||
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
|
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||||
til::color _defaultFg;
|
|
||||||
til::color _defaultBg;
|
|
||||||
CursorType _defaultCursorShape;
|
CursorType _defaultCursorShape;
|
||||||
bool _screenReversed;
|
bool _screenReversed;
|
||||||
mutable Microsoft::Console::Render::BlinkingState _blinkingState;
|
mutable Microsoft::Console::Render::BlinkingState _blinkingState;
|
||||||
|
|
|
@ -69,14 +69,6 @@ COORD Terminal::GetCursorPosition() noexcept
|
||||||
return newPos;
|
return newPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Terminal::SetCursorColor(const COLORREF color) noexcept
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_buffer->GetCursor().SetColor(color);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
CATCH_RETURN_FALSE()
|
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Moves the cursor down one line, and possibly also to the leftmost column.
|
// - Moves the cursor down one line, and possibly also to the leftmost column.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
@ -370,6 +362,22 @@ try
|
||||||
}
|
}
|
||||||
CATCH_RETURN_FALSE()
|
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:
|
// Method Description:
|
||||||
// - Updates the value in the colortable at index tableIndex to the new color
|
// - Updates the value in the colortable at index tableIndex to the new color
|
||||||
// color. color is a COLORREF, format 0x00BBGGRR.
|
// color. color is a COLORREF, format 0x00BBGGRR.
|
||||||
|
@ -383,6 +391,11 @@ try
|
||||||
{
|
{
|
||||||
_colorTable.at(tableIndex) = color;
|
_colorTable.at(tableIndex) = color;
|
||||||
|
|
||||||
|
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
|
||||||
|
{
|
||||||
|
_pfnBackgroundColorChanged(color);
|
||||||
|
}
|
||||||
|
|
||||||
// Repaint everything - the colors might have changed
|
// Repaint everything - the colors might have changed
|
||||||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||||
return true;
|
return true;
|
||||||
|
@ -442,46 +455,6 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
|
||||||
return true;
|
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
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_defaultFg = color;
|
|
||||||
|
|
||||||
// Repaint everything - the colors might have changed
|
|
||||||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
|
||||||
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::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
|
bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -227,7 +227,7 @@ CATCH_LOG_RETURN_FALSE()
|
||||||
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
|
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return _terminalApi.SetCursorColor(color);
|
return _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color);
|
||||||
}
|
}
|
||||||
CATCH_LOG_RETURN_FALSE()
|
CATCH_LOG_RETURN_FALSE()
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ CATCH_LOG_RETURN_FALSE()
|
||||||
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
|
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return _terminalApi.SetDefaultForeground(color);
|
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color);
|
||||||
}
|
}
|
||||||
CATCH_LOG_RETURN_FALSE()
|
CATCH_LOG_RETURN_FALSE()
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ CATCH_LOG_RETURN_FALSE()
|
||||||
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
|
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return _terminalApi.SetDefaultBackground(color);
|
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color);
|
||||||
}
|
}
|
||||||
CATCH_LOG_RETURN_FALSE()
|
CATCH_LOG_RETURN_FALSE()
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
<ProjectReference Include="$(OpenConsoleDir)src\terminal\parser\lib\parser.vcxproj">
|
<ProjectReference Include="$(OpenConsoleDir)src\terminal\parser\lib\parser.vcxproj">
|
||||||
<Project>{3ae13314-1939-4dfa-9c14-38ca0834050c}</Project>
|
<Project>{3ae13314-1939-4dfa-9c14-38ca0834050c}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="$(OpenConsoleDir)src\renderer\atlas\atlas.vcxproj">
|
||||||
|
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="$(OpenConsoleDir)src\renderer\dx\lib\dx.vcxproj">
|
<ProjectReference Include="$(OpenConsoleDir)src\renderer\dx\lib\dx.vcxproj">
|
||||||
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
|
|
@ -73,19 +73,19 @@ std::pair<COLORREF, COLORREF> Terminal::GetAttributeColors(const TextAttribute&
|
||||||
if (attr.IsReverseVideo() ^ _screenReversed)
|
if (attr.IsReverseVideo() ^ _screenReversed)
|
||||||
{
|
{
|
||||||
colors.first = _adjustedForegroundColors[fgIndex][bgIndex];
|
colors.first = _adjustedForegroundColors[fgIndex][bgIndex];
|
||||||
colors.second = fgTextColor.GetColor(_colorTable, _defaultFg);
|
colors.second = fgTextColor.GetColor(_colorTable, TextColor::DEFAULT_FOREGROUND);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
|
colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
|
||||||
colors.second = bgTextColor.GetColor(_colorTable, _defaultBg);
|
colors.second = bgTextColor.GetColor(_colorTable, TextColor::DEFAULT_BACKGROUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
colors = attr.CalculateRgbColors(_colorTable,
|
colors = attr.CalculateRgbColors(_colorTable,
|
||||||
_defaultFg,
|
TextColor::DEFAULT_FOREGROUND,
|
||||||
_defaultBg,
|
TextColor::DEFAULT_BACKGROUND,
|
||||||
_screenReversed,
|
_screenReversed,
|
||||||
_blinkingState.IsBlinkingFaint(),
|
_blinkingState.IsBlinkingFaint(),
|
||||||
_intenseIsBright);
|
_intenseIsBright);
|
||||||
|
@ -135,7 +135,7 @@ CursorType Terminal::GetCursorStyle() const noexcept
|
||||||
|
|
||||||
COLORREF Terminal::GetCursorColor() const noexcept
|
COLORREF Terminal::GetCursorColor() const noexcept
|
||||||
{
|
{
|
||||||
return _buffer->GetCursor().GetColor();
|
return _colorTable.at(TextColor::CURSOR_COLOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Terminal::IsCursorDoubleWidth() const
|
bool Terminal::IsCursorDoubleWidth() const
|
||||||
|
@ -312,8 +312,8 @@ void Terminal::_MakeAdjustedColorArray()
|
||||||
// to include the default background and default foreground colors
|
// to include the default background and default foreground colors
|
||||||
std::array<COLORREF, 18> colorTableWithDefaults;
|
std::array<COLORREF, 18> colorTableWithDefaults;
|
||||||
std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults));
|
std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults));
|
||||||
colorTableWithDefaults[DefaultBgIndex] = _defaultBg;
|
colorTableWithDefaults[DefaultBgIndex] = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
|
||||||
colorTableWithDefaults[DefaultFgIndex] = _defaultFg;
|
colorTableWithDefaults[DefaultFgIndex] = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
|
||||||
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
|
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
|
||||||
{
|
{
|
||||||
const auto fg = til::at(colorTableWithDefaults, fgIndex);
|
const auto fg = til::at(colorTableWithDefaults, fgIndex);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Profiles.h"
|
#include "Profiles.h"
|
||||||
|
|
||||||
#include "PreviewConnection.h"
|
#include "PreviewConnection.h"
|
||||||
#include "Profiles.g.cpp"
|
#include "Profiles.g.cpp"
|
||||||
#include "EnumEntry.h"
|
#include "EnumEntry.h"
|
||||||
|
@ -10,6 +11,54 @@
|
||||||
#include <LibraryResources.h>
|
#include <LibraryResources.h>
|
||||||
#include "..\WinRTUtils\inc\Utils.h"
|
#include "..\WinRTUtils\inc\Utils.h"
|
||||||
|
|
||||||
|
// This function is a copy of DxFontInfo::_NearbyCollection() with
|
||||||
|
// * the call to DxFontInfo::s_GetNearbyFonts() inlined
|
||||||
|
// * checkForUpdates for GetSystemFontCollection() set to true
|
||||||
|
static wil::com_ptr<IDWriteFontCollection1> NearbyCollection(IDWriteFactory* dwriteFactory)
|
||||||
|
{
|
||||||
|
// The convenience interfaces for loading fonts from files
|
||||||
|
// are only available on Windows 10+.
|
||||||
|
wil::com_ptr<IDWriteFactory6> factory6;
|
||||||
|
// wil's query() facilities don't work inside WinRT land at the moment.
|
||||||
|
// They produce a compilation error due to IUnknown and winrt::Windows::Foundation::IUnknown being ambiguous.
|
||||||
|
if (!SUCCEEDED(dwriteFactory->QueryInterface(__uuidof(IDWriteFactory6), factory6.put_void())))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr<IDWriteFontCollection1> systemFontCollection;
|
||||||
|
THROW_IF_FAILED(factory6->GetSystemFontCollection(false, systemFontCollection.addressof(), true));
|
||||||
|
|
||||||
|
wil::com_ptr<IDWriteFontSet> systemFontSet;
|
||||||
|
THROW_IF_FAILED(systemFontCollection->GetFontSet(systemFontSet.addressof()));
|
||||||
|
|
||||||
|
wil::com_ptr<IDWriteFontSetBuilder2> fontSetBuilder2;
|
||||||
|
THROW_IF_FAILED(factory6->CreateFontSetBuilder(fontSetBuilder2.addressof()));
|
||||||
|
|
||||||
|
THROW_IF_FAILED(fontSetBuilder2->AddFontSet(systemFontSet.get()));
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
|
||||||
|
const auto folder{ module.parent_path() };
|
||||||
|
|
||||||
|
for (const auto& p : std::filesystem::directory_iterator(folder))
|
||||||
|
{
|
||||||
|
if (til::ends_with(p.path().native(), L".ttf"))
|
||||||
|
{
|
||||||
|
fontSetBuilder2->AddFontFile(p.path().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::com_ptr<IDWriteFontSet> fontSet;
|
||||||
|
THROW_IF_FAILED(fontSetBuilder2->CreateFontSet(fontSet.addressof()));
|
||||||
|
|
||||||
|
wil::com_ptr<IDWriteFontCollection1> fontCollection;
|
||||||
|
THROW_IF_FAILED(factory6->CreateFontCollectionFromFontSet(fontSet.get(), &fontCollection));
|
||||||
|
|
||||||
|
return fontCollection;
|
||||||
|
}
|
||||||
|
|
||||||
using namespace winrt::Windows::UI::Text;
|
using namespace winrt::Windows::UI::Text;
|
||||||
using namespace winrt::Windows::UI::Xaml;
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||||
|
@ -107,8 +156,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
reinterpret_cast<::IUnknown**>(factory.put())));
|
reinterpret_cast<::IUnknown**>(factory.put())));
|
||||||
|
|
||||||
// get the font collection; subscribe to updates
|
// get the font collection; subscribe to updates
|
||||||
com_ptr<IDWriteFontCollection> fontCollection;
|
const auto fontCollection = NearbyCollection(factory.get());
|
||||||
THROW_IF_FAILED(factory->GetSystemFontCollection(fontCollection.put(), TRUE));
|
|
||||||
|
|
||||||
for (UINT32 i = 0; i < fontCollection->GetFontFamilyCount(); ++i)
|
for (UINT32 i = 0; i < fontCollection->GetFontFamilyCount(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -246,13 +294,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
return _profile.HasUnfocusedAppearance();
|
return _profile.HasUnfocusedAppearance();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProfileViewModel::EditableUnfocusedAppearance()
|
bool ProfileViewModel::EditableUnfocusedAppearance() const noexcept
|
||||||
{
|
{
|
||||||
if constexpr (Feature_EditableUnfocusedAppearance::IsEnabled())
|
return Feature_EditableUnfocusedAppearance::IsEnabled();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProfileViewModel::ShowUnfocusedAppearance()
|
bool ProfileViewModel::ShowUnfocusedAppearance()
|
||||||
|
@ -286,6 +330,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
return _unfocusedAppearanceViewModel;
|
return _unfocusedAppearanceViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProfileViewModel::AtlasEngineAvailable() const noexcept
|
||||||
|
{
|
||||||
|
return Feature_AtlasEngine::IsEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
bool ProfileViewModel::UseParentProcessDirectory()
|
bool ProfileViewModel::UseParentProcessDirectory()
|
||||||
{
|
{
|
||||||
return StartingDirectory().empty();
|
return StartingDirectory().empty();
|
||||||
|
|
|
@ -61,12 +61,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
Editor::AppearanceViewModel DefaultAppearance();
|
Editor::AppearanceViewModel DefaultAppearance();
|
||||||
Editor::AppearanceViewModel UnfocusedAppearance();
|
Editor::AppearanceViewModel UnfocusedAppearance();
|
||||||
bool HasUnfocusedAppearance();
|
bool HasUnfocusedAppearance();
|
||||||
bool EditableUnfocusedAppearance();
|
bool EditableUnfocusedAppearance() const noexcept;
|
||||||
bool ShowUnfocusedAppearance();
|
bool ShowUnfocusedAppearance();
|
||||||
|
|
||||||
void CreateUnfocusedAppearance(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
|
void CreateUnfocusedAppearance(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
|
||||||
const IHostedInWindow& windowRoot);
|
const IHostedInWindow& windowRoot);
|
||||||
void DeleteUnfocusedAppearance();
|
void DeleteUnfocusedAppearance();
|
||||||
|
bool AtlasEngineAvailable() const noexcept;
|
||||||
|
|
||||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
|
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);
|
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_profile, BellStyle);
|
OBSERVABLE_PROJECTED_SETTING(_profile, BellStyle);
|
||||||
|
OBSERVABLE_PROJECTED_SETTING(_profile, UseAtlasEngine);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model::Profile _profile;
|
Model::Profile _profile;
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||||
Boolean EditableUnfocusedAppearance { get; };
|
Boolean EditableUnfocusedAppearance { get; };
|
||||||
Boolean ShowUnfocusedAppearance { get; };
|
Boolean ShowUnfocusedAppearance { get; };
|
||||||
AppearanceViewModel UnfocusedAppearance { get; };
|
AppearanceViewModel UnfocusedAppearance { get; };
|
||||||
|
Boolean AtlasEngineAvailable { get; };
|
||||||
|
|
||||||
void CreateUnfocusedAppearance(Windows.Foundation.Collections.IMapView<String, Microsoft.Terminal.Settings.Model.ColorScheme> Schemes, IHostedInWindow WindowRoot);
|
void CreateUnfocusedAppearance(Windows.Foundation.Collections.IMapView<String, Microsoft.Terminal.Settings.Model.ColorScheme> Schemes, IHostedInWindow WindowRoot);
|
||||||
void DeleteUnfocusedAppearance();
|
void DeleteUnfocusedAppearance();
|
||||||
|
@ -61,6 +62,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput);
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing);
|
||||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.BellStyle, BellStyle);
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.BellStyle, BellStyle);
|
||||||
|
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAtlasEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeclass DeleteProfileEventArgs
|
runtimeclass DeleteProfileEventArgs
|
||||||
|
|
|
@ -319,7 +319,7 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<StackPanel Orientation="Horizontal"
|
<StackPanel Orientation="Horizontal"
|
||||||
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance, Mode=OneWay}">
|
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance}">
|
||||||
<TextBlock x:Uid="Profile_UnfocusedAppearanceTextBlock"
|
<TextBlock x:Uid="Profile_UnfocusedAppearanceTextBlock"
|
||||||
Style="{StaticResource TitleTextBlockStyle}" />
|
Style="{StaticResource TitleTextBlockStyle}" />
|
||||||
<Button x:Uid="Profile_CreateUnfocusedAppearanceButton"
|
<Button x:Uid="Profile_CreateUnfocusedAppearanceButton"
|
||||||
|
@ -477,6 +477,15 @@
|
||||||
IsChecked="{x:Bind IsBellStyleFlagSet(4), BindBack=SetBellStyleTaskbar, Mode=TwoWay}" />
|
IsChecked="{x:Bind IsBellStyleFlagSet(4), BindBack=SetBellStyleTaskbar, Mode=TwoWay}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
||||||
|
<!-- AtlasEngine -->
|
||||||
|
<local:SettingContainer x:Uid="Profile_UseAtlasEngine"
|
||||||
|
ClearSettingValue="{x:Bind State.Profile.ClearUseAtlasEngine}"
|
||||||
|
HasSettingValue="{x:Bind State.Profile.HasUseAtlasEngine, Mode=OneWay}"
|
||||||
|
SettingOverrideSource="{x:Bind State.Profile.UseAtlasEngineOverrideSource, Mode=OneWay}"
|
||||||
|
Visibility="{x:Bind State.Profile.AtlasEngineAvailable}">
|
||||||
|
<ToggleSwitch IsOn="{x:Bind State.Profile.UseAtlasEngine, Mode=TwoWay}" />
|
||||||
|
</local:SettingContainer>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
|
|
|
@ -927,6 +927,10 @@
|
||||||
<value>Controls what happens when the application emits a BEL character.</value>
|
<value>Controls what happens when the application emits a BEL character.</value>
|
||||||
<comment>A description for what the "bell style" setting does. Presented near "Profile_BellStyle".{Locked="BEL"}</comment>
|
<comment>A description for what the "bell style" setting does. Presented near "Profile_BellStyle".{Locked="BEL"}</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Profile_UseAtlasEngine.Header" xml:space="preserve">
|
||||||
|
<value>Enable experimental text rendering engine</value>
|
||||||
|
<comment>An option to enable an experimental text rendering engine</comment>
|
||||||
|
</data>
|
||||||
<data name="Profile_BellStyleAudible.Content" xml:space="preserve">
|
<data name="Profile_BellStyleAudible.Content" xml:space="preserve">
|
||||||
<value>Audible</value>
|
<value>Audible</value>
|
||||||
<comment>An option to choose from for the "bell style" setting. When selected, an audible cue is used to notify the user.</comment>
|
<comment>An option to choose from for the "bell style" setting. When selected, an audible cue is used to notify the user.</comment>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
//
|
//
|
||||||
// pch.h
|
// pch.h
|
||||||
|
@ -51,8 +51,7 @@
|
||||||
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <shobjidl_core.h>
|
#include <shobjidl_core.h>
|
||||||
#include <dwrite.h>
|
#include <dwrite_3.h>
|
||||||
#include <dwrite_1.h>
|
|
||||||
|
|
||||||
// Manually include til after we include Windows.Foundation to give it winrt superpowers
|
// Manually include til after we include Windows.Foundation to give it winrt superpowers
|
||||||
#include "til.h"
|
#include "til.h"
|
||||||
|
|
|
@ -9,8 +9,11 @@
|
||||||
#include "ActionAndArgs.h"
|
#include "ActionAndArgs.h"
|
||||||
#include "JsonUtils.h"
|
#include "JsonUtils.h"
|
||||||
#include "FileUtils.h"
|
#include "FileUtils.h"
|
||||||
|
#include "../../types/inc/utils.hpp"
|
||||||
|
|
||||||
static constexpr std::wstring_view stateFileName{ L"state.json" };
|
static constexpr std::wstring_view stateFileName{ L"state.json" };
|
||||||
|
static constexpr std::wstring_view elevatedStateFileName{ L"elevated-state.json" };
|
||||||
|
|
||||||
static constexpr std::string_view TabLayoutKey{ "tabLayout" };
|
static constexpr std::string_view TabLayoutKey{ "tabLayout" };
|
||||||
static constexpr std::string_view InitialPositionKey{ "initialPosition" };
|
static constexpr std::string_view InitialPositionKey{ "initialPosition" };
|
||||||
static constexpr std::string_view InitialSizeKey{ "initialSize" };
|
static constexpr std::string_view InitialSizeKey{ "initialSize" };
|
||||||
|
@ -85,15 +88,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
return trait.FromJson(root);
|
return trait.FromJson(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the application-global ApplicationState object.
|
ApplicationState::ApplicationState(const std::filesystem::path& stateRoot) noexcept :
|
||||||
Microsoft::Terminal::Settings::Model::ApplicationState ApplicationState::SharedInstance()
|
_sharedPath{ stateRoot / stateFileName },
|
||||||
{
|
_elevatedPath{ stateRoot / elevatedStateFileName },
|
||||||
static auto state = winrt::make_self<ApplicationState>(GetBaseSettingsPath() / stateFileName);
|
|
||||||
return *state;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplicationState::ApplicationState(std::filesystem::path path) noexcept :
|
|
||||||
_path{ std::move(path) },
|
|
||||||
_throttler{ std::chrono::seconds(1), [this]() { _write(); } }
|
_throttler{ std::chrono::seconds(1), [this]() { _write(); } }
|
||||||
{
|
{
|
||||||
_read();
|
_read();
|
||||||
|
@ -102,9 +99,21 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
// The destructor ensures that the last write is flushed to disk before returning.
|
// The destructor ensures that the last write is flushed to disk before returning.
|
||||||
ApplicationState::~ApplicationState()
|
ApplicationState::~ApplicationState()
|
||||||
{
|
{
|
||||||
|
TraceLoggingWrite(g_hSettingsModelProvider,
|
||||||
|
"ApplicationState_Dtor_Start",
|
||||||
|
TraceLoggingDescription("Event at the start of the ApplicationState destructor"),
|
||||||
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
|
|
||||||
// This will ensure that we not just cancel the last outstanding timer,
|
// This will ensure that we not just cancel the last outstanding timer,
|
||||||
// but instead force it to run as soon as possible and wait for it to complete.
|
// but instead force it to run as soon as possible and wait for it to complete.
|
||||||
_throttler.flush();
|
_throttler.flush();
|
||||||
|
|
||||||
|
TraceLoggingWrite(g_hSettingsModelProvider,
|
||||||
|
"ApplicationState_Dtor_End",
|
||||||
|
TraceLoggingDescription("Event at the end of the ApplicationState destructor"),
|
||||||
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-read the state.json from disk.
|
// Re-read the state.json from disk.
|
||||||
|
@ -113,34 +122,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
_read();
|
_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the state.json path on the disk.
|
bool ApplicationState::IsStatePath(const winrt::hstring& filename)
|
||||||
winrt::hstring ApplicationState::FilePath() const noexcept
|
|
||||||
{
|
{
|
||||||
return winrt::hstring{ _path.wstring() };
|
static const auto sharedPath{ _sharedPath.filename() };
|
||||||
|
static const auto elevatedPath{ _elevatedPath.filename() };
|
||||||
|
return filename == sharedPath || filename == elevatedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate all getter/setters
|
|
||||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
|
||||||
type ApplicationState::name() const noexcept \
|
|
||||||
{ \
|
|
||||||
const auto state = _state.lock_shared(); \
|
|
||||||
const auto& value = state->name; \
|
|
||||||
return value ? *value : type{ __VA_ARGS__ }; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void ApplicationState::name(const type& value) noexcept \
|
|
||||||
{ \
|
|
||||||
{ \
|
|
||||||
auto state = _state.lock(); \
|
|
||||||
state->name.emplace(value); \
|
|
||||||
state->name##Changed = true; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
_throttler(); \
|
|
||||||
}
|
|
||||||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
|
||||||
#undef MTSM_APPLICATION_STATE_GEN
|
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - See GH#11119. Removes all of the data in this ApplicationState object
|
// - See GH#11119. Removes all of the data in this ApplicationState object
|
||||||
// and resets it to the defaults. This will delete the state file! That's
|
// and resets it to the defaults. This will delete the state file! That's
|
||||||
|
@ -156,57 +144,58 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
void ApplicationState::Reset() noexcept
|
void ApplicationState::Reset() noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LOG_LAST_ERROR_IF(!DeleteFile(_path.c_str()));
|
LOG_LAST_ERROR_IF(!DeleteFile(_sharedPath.c_str()));
|
||||||
|
LOG_LAST_ERROR_IF(!DeleteFile(_elevatedPath.c_str()));
|
||||||
*_state.lock() = {};
|
*_state.lock() = {};
|
||||||
}
|
}
|
||||||
CATCH_LOG()
|
CATCH_LOG()
|
||||||
|
|
||||||
Json::Value ApplicationState::_getRoot(const locked_hfile& file) const noexcept
|
// Deserializes the state.json and user-state (or elevated-state if
|
||||||
{
|
// elevated) into this ApplicationState.
|
||||||
Json::Value root;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const auto data = ReadUTF8FileLocked(file);
|
|
||||||
if (data.empty())
|
|
||||||
{
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string errs;
|
|
||||||
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
|
|
||||||
|
|
||||||
if (!reader->parse(data.data(), data.data() + data.size(), &root, &errs))
|
|
||||||
{
|
|
||||||
throw winrt::hresult_error(WEB_E_INVALID_JSON_STRING, winrt::to_hstring(errs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CATCH_LOG()
|
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserializes the state.json at _path into this ApplicationState.
|
|
||||||
// * ANY errors during app state will result in the creation of a new empty state.
|
// * ANY errors during app state will result in the creation of a new empty state.
|
||||||
// * ANY errors during runtime will result in changes being partially ignored.
|
// * ANY errors during runtime will result in changes being partially ignored.
|
||||||
void ApplicationState::_read() const noexcept
|
void ApplicationState::_read() const noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto state = _state.lock();
|
std::string errs;
|
||||||
const auto file = OpenFileReadSharedLocked(_path);
|
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
|
||||||
|
|
||||||
auto root = _getRoot(file);
|
// First get shared state out of `state.json`.
|
||||||
// GetValueForKey() comes in two variants:
|
const auto sharedData = _readSharedContents().value_or(std::string{});
|
||||||
// * take a std::optional<T> reference
|
if (!sharedData.empty())
|
||||||
// * return std::optional<T> by value
|
{
|
||||||
// At the time of writing the former version skips missing fields in the json,
|
Json::Value root;
|
||||||
// but we want to explicitly clear state fields that were removed from state.json.
|
if (!reader->parse(sharedData.data(), sharedData.data() + sharedData.size(), &root, &errs))
|
||||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
{
|
||||||
if (!state->name##Changed) \
|
throw winrt::hresult_error(WEB_E_INVALID_JSON_STRING, winrt::to_hstring(errs));
|
||||||
{ \
|
}
|
||||||
state->name = JsonUtils::GetValueForKey<std::optional<type>>(root, key); \
|
|
||||||
}
|
// - If we're elevated, we want to only load the Shared properties
|
||||||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
// from state.json. We'll then load the Local props from
|
||||||
#undef MTSM_APPLICATION_STATE_GEN
|
// `elevated-state.json`
|
||||||
|
// - If we're unelevated, then load _everything_ from state.json.
|
||||||
|
if (::Microsoft::Console::Utils::IsElevated())
|
||||||
|
{
|
||||||
|
// Only load shared properties if we're elevated
|
||||||
|
FromJson(root, FileSource::Shared);
|
||||||
|
|
||||||
|
// Then, try and get anything in elevated-state
|
||||||
|
if (const auto localData{ _readLocalContents().value_or(std::string{}) }; !localData.empty())
|
||||||
|
{
|
||||||
|
Json::Value root;
|
||||||
|
if (!reader->parse(localData.data(), localData.data() + localData.size(), &root, &errs))
|
||||||
|
{
|
||||||
|
throw winrt::hresult_error(WEB_E_INVALID_JSON_STRING, winrt::to_hstring(errs));
|
||||||
|
}
|
||||||
|
FromJson(root, FileSource::Local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we're unelevated, then load everything.
|
||||||
|
FromJson(root, FileSource::Shared | FileSource::Local);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CATCH_LOG()
|
CATCH_LOG()
|
||||||
|
|
||||||
|
@ -214,29 +203,191 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
// * Errors are only logged.
|
// * Errors are only logged.
|
||||||
// * _state->_writeScheduled is set to false, signaling our
|
// * _state->_writeScheduled is set to false, signaling our
|
||||||
// setters that _synchronize() needs to be called again.
|
// setters that _synchronize() needs to be called again.
|
||||||
void ApplicationState::_write() noexcept
|
void ApplicationState::_write() const noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// re-read the state so that we can only update the properties that were changed.
|
Json::StreamWriterBuilder wbuilder;
|
||||||
Json::Value root{};
|
|
||||||
|
// When we're elevated, we've got to be tricky. We don't want to write
|
||||||
|
// our window state, allowed commandlines, and other Local properties
|
||||||
|
// into the shared `state.json`. But, if we only serialize the Shared
|
||||||
|
// properties to a json blob, then we'll omit windowState entirely,
|
||||||
|
// _removing_ the window state of the unelevated instance. Oh no!
|
||||||
|
//
|
||||||
|
// So, to be tricky, we'll first _load_ the shared state to a json blob.
|
||||||
|
// We'll then serialize our view of the shared properties on top of that
|
||||||
|
// blob. Then we'll write that blob back to the file. This will
|
||||||
|
// round-trip the Local properties for the unelevated instances
|
||||||
|
// untouched in state.json
|
||||||
|
//
|
||||||
|
// After that's done, we'll write our Local properties into
|
||||||
|
// elevated-state.json.
|
||||||
|
if (::Microsoft::Console::Utils::IsElevated())
|
||||||
{
|
{
|
||||||
auto state = _state.lock();
|
std::string errs;
|
||||||
const auto file = OpenFileRWExclusiveLocked(_path);
|
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
|
||||||
root = _getRoot(file);
|
Json::Value root;
|
||||||
|
|
||||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
// First load the contents of state.json into a json blob. This will
|
||||||
if (state->name##Changed) \
|
// contain the Shared properties and the unelevated instance's Local
|
||||||
{ \
|
// properties.
|
||||||
JsonUtils::SetValueForKey(root, key, state->name); \
|
const auto sharedData = _readSharedContents().value_or(std::string{});
|
||||||
state->name##Changed = false; \
|
if (!sharedData.empty())
|
||||||
}
|
{
|
||||||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
if (!reader->parse(sharedData.data(), sharedData.data() + sharedData.size(), &root, &errs))
|
||||||
#undef MTSM_APPLICATION_STATE_GEN
|
{
|
||||||
|
throw winrt::hresult_error(WEB_E_INVALID_JSON_STRING, winrt::to_hstring(errs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Layer our shared properties on top of the blob from state.json,
|
||||||
|
// and write it back out.
|
||||||
|
_writeSharedContents(Json::writeString(wbuilder, _toJsonWithBlob(root, FileSource::Shared)));
|
||||||
|
|
||||||
Json::StreamWriterBuilder wbuilder;
|
// Finally, write our Local properties back to elevated-state.json
|
||||||
const auto content = Json::writeString(wbuilder, root);
|
_writeLocalContents(Json::writeString(wbuilder, ToJson(FileSource::Local)));
|
||||||
WriteUTF8FileLocked(file, content);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We're unelevated, this is easy. Just write everything back out.
|
||||||
|
_writeLocalContents(Json::writeString(wbuilder, ToJson(FileSource::Local | FileSource::Shared)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CATCH_LOG()
|
CATCH_LOG()
|
||||||
|
|
||||||
|
// Returns the application-global ApplicationState object.
|
||||||
|
Microsoft::Terminal::Settings::Model::ApplicationState ApplicationState::SharedInstance()
|
||||||
|
{
|
||||||
|
std::filesystem::path root{ GetBaseSettingsPath() };
|
||||||
|
static auto state = winrt::make_self<ApplicationState>(root);
|
||||||
|
return *state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Loads data from the given json blob. Will only read the data that's in
|
||||||
|
// the specified parseSource - so if we're reading the Local state file,
|
||||||
|
// we won't destroy previously parsed Shared data.
|
||||||
|
// - READ: there's no layering for app state.
|
||||||
|
void ApplicationState::FromJson(const Json::Value& root, FileSource parseSource) const noexcept
|
||||||
|
{
|
||||||
|
auto state = _state.lock();
|
||||||
|
// GetValueForKey() comes in two variants:
|
||||||
|
// * take a std::optional<T> reference
|
||||||
|
// * return std::optional<T> by value
|
||||||
|
// At the time of writing the former version skips missing fields in the json,
|
||||||
|
// but we want to explicitly clear state fields that were removed from state.json.
|
||||||
|
//
|
||||||
|
// GH#11222: We only load properties that are of the same type (Local or
|
||||||
|
// Shared) which we requested. If we didn't want to load this type of
|
||||||
|
// property, just skip it.
|
||||||
|
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \
|
||||||
|
if (WI_IsFlagSet(parseSource, source)) \
|
||||||
|
state->name = JsonUtils::GetValueForKey<std::optional<type>>(root, key);
|
||||||
|
|
||||||
|
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||||
|
#undef MTSM_APPLICATION_STATE_GEN
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value ApplicationState::ToJson(FileSource parseSource) const noexcept
|
||||||
|
{
|
||||||
|
Json::Value root{ Json::objectValue };
|
||||||
|
return _toJsonWithBlob(root, parseSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value ApplicationState::_toJsonWithBlob(Json::Value& root, FileSource parseSource) const noexcept
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto state = _state.lock_shared();
|
||||||
|
|
||||||
|
// GH#11222: We only write properties that are of the same type (Local
|
||||||
|
// or Shared) which we requested. If we didn't want to serialize this
|
||||||
|
// type of property, just skip it.
|
||||||
|
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \
|
||||||
|
if (WI_IsFlagSet(parseSource, source)) \
|
||||||
|
JsonUtils::SetValueForKey(root, key, state->name);
|
||||||
|
|
||||||
|
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||||
|
#undef MTSM_APPLICATION_STATE_GEN
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate all getter/setters
|
||||||
|
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \
|
||||||
|
type ApplicationState::name() const noexcept \
|
||||||
|
{ \
|
||||||
|
const auto state = _state.lock_shared(); \
|
||||||
|
const auto& value = state->name; \
|
||||||
|
return value ? *value : type{ __VA_ARGS__ }; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void ApplicationState::name(const type& value) noexcept \
|
||||||
|
{ \
|
||||||
|
{ \
|
||||||
|
auto state = _state.lock(); \
|
||||||
|
state->name.emplace(value); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
_throttler(); \
|
||||||
|
}
|
||||||
|
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||||
|
#undef MTSM_APPLICATION_STATE_GEN
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Read the contents of our "shared" state - state that should be shared
|
||||||
|
// for elevated and unelevated instances. This is things like the list of
|
||||||
|
// generated profiles, the command palette commandlines.
|
||||||
|
std::optional<std::string> ApplicationState::_readSharedContents() const
|
||||||
|
{
|
||||||
|
return ReadUTF8FileIfExists(_sharedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Read the contents of our "local" state - state that should be kept in
|
||||||
|
// separate files for elevated and unelevated instances. This is things
|
||||||
|
// like the persisted window state, and the approved commandlines (though,
|
||||||
|
// those don't matter when unelevated).
|
||||||
|
// - When elevated, this will DELETE `elevated-state.json` if it has bad
|
||||||
|
// permissions, so we don't potentially read malicious data.
|
||||||
|
std::optional<std::string> ApplicationState::_readLocalContents() const
|
||||||
|
{
|
||||||
|
return ::Microsoft::Console::Utils::IsElevated() ?
|
||||||
|
ReadUTF8FileIfExists(_elevatedPath, true) :
|
||||||
|
ReadUTF8FileIfExists(_sharedPath, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Write the contents of our "shared" state - state that should be shared
|
||||||
|
// for elevated and unelevated instances. This will atomically write to
|
||||||
|
// `state.json`
|
||||||
|
void ApplicationState::_writeSharedContents(const std::string_view content) const
|
||||||
|
{
|
||||||
|
WriteUTF8FileAtomic(_sharedPath, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Write the contents of our "local" state - state that should be kept in
|
||||||
|
// separate files for elevated and unelevated instances. When elevated,
|
||||||
|
// this will write to `elevated-state.json`, and when unelevated, this
|
||||||
|
// will atomically write to `user-state.json`
|
||||||
|
void ApplicationState::_writeLocalContents(const std::string_view content) const
|
||||||
|
{
|
||||||
|
if (::Microsoft::Console::Utils::IsElevated())
|
||||||
|
{
|
||||||
|
// DON'T use WriteUTF8FileAtomic, which will write to a temporary file
|
||||||
|
// then rename that file to the final filename. That actually lets us
|
||||||
|
// overwrite the elevate file's contents even when unelevated, because
|
||||||
|
// we're effectively deleting the original file, then renaming a
|
||||||
|
// different file in it's place.
|
||||||
|
//
|
||||||
|
// We're not worried about someone else doing that though, if they do
|
||||||
|
// that with the wrong permissions, then we'll just ignore the file and
|
||||||
|
// start over.
|
||||||
|
WriteUTF8File(_elevatedPath, content, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteUTF8FileAtomic(_sharedPath, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,21 +16,30 @@ Abstract:
|
||||||
#include "WindowLayout.g.h"
|
#include "WindowLayout.g.h"
|
||||||
|
|
||||||
#include <inc/cppwinrt_utils.h>
|
#include <inc/cppwinrt_utils.h>
|
||||||
#include <til/mutex.h>
|
|
||||||
#include <til/throttled_func.h>
|
|
||||||
#include "FileUtils.h"
|
|
||||||
#include <JsonUtils.h>
|
#include <JsonUtils.h>
|
||||||
|
|
||||||
|
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
|
{
|
||||||
|
// If a property is Shared, then it'll be stored in `state.json`, and used
|
||||||
|
// in both elevated and unelevated instances of the Terminal. If a property
|
||||||
|
// is marked Local, then it will have separate values for elevated and
|
||||||
|
// unelevated instances.
|
||||||
|
enum FileSource : int
|
||||||
|
{
|
||||||
|
Shared = 0x1,
|
||||||
|
Local = 0x2
|
||||||
|
};
|
||||||
|
DEFINE_ENUM_FLAG_OPERATORS(FileSource);
|
||||||
|
|
||||||
// This macro generates all getters and setters for ApplicationState.
|
// This macro generates all getters and setters for ApplicationState.
|
||||||
// It provides X with the following arguments:
|
// It provides X with the following arguments:
|
||||||
// (type, function name, JSON key, ...variadic construction arguments)
|
// (source, type, function name, JSON key, ...variadic construction arguments)
|
||||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
#define MTSM_APPLICATION_STATE_FIELDS(X) \
|
||||||
{
|
X(FileSource::Shared, std::unordered_set<winrt::guid>, GeneratedProfiles, "generatedProfiles") \
|
||||||
#define MTSM_APPLICATION_STATE_FIELDS(X) \
|
X(FileSource::Local, Windows::Foundation::Collections::IVector<Model::WindowLayout>, PersistedWindowLayouts, "persistedWindowLayouts") \
|
||||||
X(std::unordered_set<winrt::guid>, GeneratedProfiles, "generatedProfiles") \
|
X(FileSource::Shared, Windows::Foundation::Collections::IVector<hstring>, RecentCommands, "recentCommands") \
|
||||||
X(Windows::Foundation::Collections::IVector<Model::WindowLayout>, PersistedWindowLayouts, "persistedWindowLayouts") \
|
X(FileSource::Shared, Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage>, DismissedMessages, "dismissedMessages") \
|
||||||
X(Windows::Foundation::Collections::IVector<hstring>, RecentCommands, "recentCommands") \
|
X(FileSource::Local, Windows::Foundation::Collections::IVector<hstring>, AllowedCommandlines, "allowedCommandlines")
|
||||||
X(Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage>, DismissedMessages, "dismissedMessages")
|
|
||||||
|
|
||||||
struct WindowLayout : WindowLayoutT<WindowLayout>
|
struct WindowLayout : WindowLayoutT<WindowLayout>
|
||||||
{
|
{
|
||||||
|
@ -44,23 +53,26 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
friend ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<Model::WindowLayout>;
|
friend ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<Model::WindowLayout>;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ApplicationState : ApplicationStateT<ApplicationState>
|
struct ApplicationState : public ApplicationStateT<ApplicationState>
|
||||||
{
|
{
|
||||||
static Microsoft::Terminal::Settings::Model::ApplicationState SharedInstance();
|
static Microsoft::Terminal::Settings::Model::ApplicationState SharedInstance();
|
||||||
|
|
||||||
ApplicationState(std::filesystem::path path) noexcept;
|
ApplicationState(const std::filesystem::path& stateRoot) noexcept;
|
||||||
~ApplicationState();
|
~ApplicationState();
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
void Reload() const noexcept;
|
void Reload() const noexcept;
|
||||||
void Reset() noexcept;
|
void Reset() noexcept;
|
||||||
|
|
||||||
|
void FromJson(const Json::Value& root, FileSource parseSource) const noexcept;
|
||||||
|
Json::Value ToJson(FileSource parseSource) const noexcept;
|
||||||
|
|
||||||
// General getters/setters
|
// General getters/setters
|
||||||
winrt::hstring FilePath() const noexcept;
|
bool IsStatePath(const winrt::hstring& filename);
|
||||||
|
|
||||||
// State getters/setters
|
// State getters/setters
|
||||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \
|
||||||
type name() const noexcept; \
|
type name() const noexcept; \
|
||||||
void name(const type& value) noexcept;
|
void name(const type& value) noexcept;
|
||||||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||||
#undef MTSM_APPLICATION_STATE_GEN
|
#undef MTSM_APPLICATION_STATE_GEN
|
||||||
|
@ -68,21 +80,24 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
private:
|
private:
|
||||||
struct state_t
|
struct state_t
|
||||||
{
|
{
|
||||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) std::optional<type> name{ __VA_ARGS__ };
|
||||||
std::optional<type> name{ __VA_ARGS__ }; \
|
|
||||||
bool name##Changed = false;
|
|
||||||
|
|
||||||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||||
#undef MTSM_APPLICATION_STATE_GEN
|
#undef MTSM_APPLICATION_STATE_GEN
|
||||||
};
|
};
|
||||||
|
til::shared_mutex<state_t> _state;
|
||||||
|
std::filesystem::path _sharedPath;
|
||||||
|
std::filesystem::path _elevatedPath;
|
||||||
|
til::throttled_func_trailing<> _throttler;
|
||||||
|
|
||||||
Json::Value _getRoot(const winrt::Microsoft::Terminal::Settings::Model::locked_hfile& file) const noexcept;
|
void _write() const noexcept;
|
||||||
void _write() noexcept;
|
|
||||||
void _read() const noexcept;
|
void _read() const noexcept;
|
||||||
|
|
||||||
std::filesystem::path _path;
|
Json::Value _toJsonWithBlob(Json::Value& root, FileSource parseSource) const noexcept;
|
||||||
til::shared_mutex<state_t> _state;
|
|
||||||
til::throttled_func_trailing<> _throttler;
|
std::optional<std::string> _readSharedContents() const;
|
||||||
|
void _writeSharedContents(const std::string_view content) const;
|
||||||
|
std::optional<std::string> _readLocalContents() const;
|
||||||
|
void _writeLocalContents(const std::string_view content) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,15 @@ namespace Microsoft.Terminal.Settings.Model
|
||||||
void Reload();
|
void Reload();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
String FilePath { get; };
|
Boolean IsStatePath(String filename);
|
||||||
|
|
||||||
Windows.Foundation.Collections.IVector<WindowLayout> PersistedWindowLayouts { get; set; };
|
Windows.Foundation.Collections.IVector<WindowLayout> PersistedWindowLayouts { get; set; };
|
||||||
|
|
||||||
Windows.Foundation.Collections.IVector<String> RecentCommands { get; set; };
|
Windows.Foundation.Collections.IVector<String> RecentCommands { get; set; };
|
||||||
|
|
||||||
Windows.Foundation.Collections.IVector<InfoBarMessage> DismissedMessages { get; set; };
|
Windows.Foundation.Collections.IVector<InfoBarMessage> DismissedMessages { get; set; };
|
||||||
|
|
||||||
|
Windows.Foundation.Collections.IVector<String> AllowedCommandlines { get; set; };
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <WtExeUtils.h>
|
#include <WtExeUtils.h>
|
||||||
|
|
||||||
|
#include <aclapi.h>
|
||||||
|
#include <sddl.h>
|
||||||
|
#include <wil/token_helpers.h>
|
||||||
|
|
||||||
static constexpr std::string_view Utf8Bom{ u8"\uFEFF" };
|
static constexpr std::string_view Utf8Bom{ u8"\uFEFF" };
|
||||||
static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" };
|
static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" };
|
||||||
|
|
||||||
|
@ -39,86 +43,44 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
return baseSettingsPath;
|
return baseSettingsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
locked_hfile OpenFileReadSharedLocked(const std::filesystem::path& path)
|
// Function Description:
|
||||||
|
// - Checks the permissions on this file, to make sure it can only be opened
|
||||||
|
// for writing by admins. We will be checking to see if the file is owned
|
||||||
|
// by the Builtin\Administrators group. If it's not, then it was likely
|
||||||
|
// tampered with.
|
||||||
|
// Arguments:
|
||||||
|
// - handle: a HANDLE to the file to check
|
||||||
|
// Return Value:
|
||||||
|
// - true if it had the expected permissions. False otherwise.
|
||||||
|
static bool _isOwnedByAdministrators(const HANDLE& handle)
|
||||||
{
|
{
|
||||||
wil::unique_hfile file{ CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr) };
|
// If the file is owned by the administrators group, trust the
|
||||||
THROW_LAST_ERROR_IF(!file);
|
// administrators instead of checking the DACL permissions. It's simpler
|
||||||
// just lock the entire file
|
// and more flexible.
|
||||||
OVERLAPPED sOverlapped;
|
|
||||||
sOverlapped.Offset = 0;
|
wil::unique_hlocal_security_descriptor sd;
|
||||||
sOverlapped.OffsetHigh = 0;
|
PSID psidOwner{ nullptr };
|
||||||
// Shared lock
|
// The psidOwner pointer references the security descriptor, so it
|
||||||
THROW_LAST_ERROR_IF(!LockFileEx(file.get(),
|
// doesn't have to be freed separate from sd.
|
||||||
0, // lock shared, wait to return until lock is obtained
|
const auto status = GetSecurityInfo(handle,
|
||||||
0, // reserved, does nothing
|
SE_FILE_OBJECT,
|
||||||
INT_MAX, // lock INT_MAX bytes
|
OWNER_SECURITY_INFORMATION,
|
||||||
0, // higher-order bytes, if our state file is greater than 2GB I guess this will be a problem
|
&psidOwner,
|
||||||
&sOverlapped));
|
nullptr,
|
||||||
return { std::move(file), sOverlapped };
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
wil::out_param_ptr<PSECURITY_DESCRIPTOR*>(sd));
|
||||||
|
THROW_IF_WIN32_ERROR(status);
|
||||||
|
|
||||||
|
wil::unique_any_psid psidAdmins{ nullptr };
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(
|
||||||
|
ConvertStringSidToSidW(L"BA", wil::out_param_ptr<PSID*>(psidAdmins)));
|
||||||
|
|
||||||
|
return EqualSid(psidOwner, psidAdmins.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
locked_hfile OpenFileRWExclusiveLocked(const std::filesystem::path& path)
|
|
||||||
{
|
|
||||||
wil::unique_hfile file{ CreateFileW(path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr) };
|
|
||||||
THROW_LAST_ERROR_IF(!file);
|
|
||||||
// just lock the entire file
|
|
||||||
OVERLAPPED sOverlapped;
|
|
||||||
sOverlapped.Offset = 0;
|
|
||||||
sOverlapped.OffsetHigh = 0;
|
|
||||||
// Shared lock
|
|
||||||
THROW_LAST_ERROR_IF(!LockFileEx(file.get(),
|
|
||||||
LOCKFILE_EXCLUSIVE_LOCK, // lock exclusive, wait to return until lock is obtained
|
|
||||||
0, // reserved, does nothing
|
|
||||||
INT_MAX, // lock INT_MAX bytes
|
|
||||||
0, // higher-order bytes, if our state file is greater than 2GB I guess this will be a problem
|
|
||||||
&sOverlapped));
|
|
||||||
return { std::move(file), sOverlapped };
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ReadUTF8FileLocked(const locked_hfile& file)
|
|
||||||
{
|
|
||||||
const auto fileSize = GetFileSize(file.get(), nullptr);
|
|
||||||
THROW_LAST_ERROR_IF(fileSize == INVALID_FILE_SIZE);
|
|
||||||
|
|
||||||
// By making our buffer just slightly larger we can detect if
|
|
||||||
// the file size changed and we've failed to read the full file.
|
|
||||||
std::string buffer(static_cast<size_t>(fileSize) + 1, '\0');
|
|
||||||
DWORD bytesRead = 0;
|
|
||||||
THROW_IF_WIN32_BOOL_FALSE(ReadFile(file.get(), buffer.data(), gsl::narrow<DWORD>(buffer.size()), &bytesRead, nullptr));
|
|
||||||
|
|
||||||
// As mentioned before our buffer was allocated oversized.
|
|
||||||
buffer.resize(bytesRead);
|
|
||||||
|
|
||||||
if (til::starts_with(buffer, Utf8Bom))
|
|
||||||
{
|
|
||||||
// Yeah this memmove()s the entire content.
|
|
||||||
// But I don't really want to deal with UTF8 BOMs any more than necessary,
|
|
||||||
// as basically not a single editor writes a BOM for UTF8.
|
|
||||||
buffer.erase(0, Utf8Bom.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteUTF8FileLocked(const locked_hfile& file, const std::string_view& content)
|
|
||||||
{
|
|
||||||
// truncate the file because we want to overwrite it
|
|
||||||
SetFilePointer(file.get(), 0, nullptr, FILE_BEGIN);
|
|
||||||
THROW_IF_WIN32_BOOL_FALSE(SetEndOfFile(file.get()));
|
|
||||||
|
|
||||||
const auto fileSize = gsl::narrow<DWORD>(content.size());
|
|
||||||
DWORD bytesWritten = 0;
|
|
||||||
THROW_IF_WIN32_BOOL_FALSE(WriteFile(file.get(), content.data(), fileSize, &bytesWritten, nullptr));
|
|
||||||
|
|
||||||
if (bytesWritten != fileSize)
|
|
||||||
{
|
|
||||||
THROW_WIN32_MSG(ERROR_WRITE_FAULT, "failed to write whole file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tries to read a file somewhat atomically without locking it.
|
// Tries to read a file somewhat atomically without locking it.
|
||||||
// Strips the UTF8 BOM if it exists.
|
// Strips the UTF8 BOM if it exists.
|
||||||
std::string ReadUTF8File(const std::filesystem::path& path)
|
std::string ReadUTF8File(const std::filesystem::path& path, const bool elevatedOnly)
|
||||||
{
|
{
|
||||||
// From some casual observations we can determine that:
|
// From some casual observations we can determine that:
|
||||||
// * ReadFile() always returns the requested amount of data (unless the file is smaller)
|
// * ReadFile() always returns the requested amount of data (unless the file is smaller)
|
||||||
|
@ -126,9 +88,40 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
// -> Lets add a retry-loop just in case, to not fail if the file size changed while reading.
|
// -> Lets add a retry-loop just in case, to not fail if the file size changed while reading.
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
wil::unique_hfile file{ CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr) };
|
wil::unique_hfile file{ CreateFileW(path.c_str(),
|
||||||
|
GENERIC_READ,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
nullptr,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
nullptr) };
|
||||||
THROW_LAST_ERROR_IF(!file);
|
THROW_LAST_ERROR_IF(!file);
|
||||||
|
|
||||||
|
// Open the file _first_, then check if it has the right
|
||||||
|
// permissions. This prevents a "Time-of-check to time-of-use"
|
||||||
|
// vulnerability where a malicious exe could delete the file and
|
||||||
|
// replace it between us checking the permissions, and reading the
|
||||||
|
// contents. We've got a handle to the file now, which means we're
|
||||||
|
// going to read the contents of that instance of the file
|
||||||
|
// regardless. If someone replaces the file on us before we get to
|
||||||
|
// the GetSecurityInfo call below, then only the subsequent call to
|
||||||
|
// ReadUTF8File will notice it.
|
||||||
|
if (elevatedOnly)
|
||||||
|
{
|
||||||
|
const bool hadExpectedPermissions{ _isOwnedByAdministrators(file.get()) };
|
||||||
|
if (!hadExpectedPermissions)
|
||||||
|
{
|
||||||
|
// Close the handle
|
||||||
|
file.reset();
|
||||||
|
|
||||||
|
// delete the file. It's been compromised.
|
||||||
|
LOG_LAST_ERROR_IF(!DeleteFile(path.c_str()));
|
||||||
|
|
||||||
|
// Exit early, because obviously there's nothing to read from the deleted file.
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const auto fileSize = GetFileSize(file.get(), nullptr);
|
const auto fileSize = GetFileSize(file.get(), nullptr);
|
||||||
THROW_LAST_ERROR_IF(fileSize == INVALID_FILE_SIZE);
|
THROW_LAST_ERROR_IF(fileSize == INVALID_FILE_SIZE);
|
||||||
|
|
||||||
|
@ -166,11 +159,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as ReadUTF8File, but returns an empty optional, if the file couldn't be opened.
|
// Same as ReadUTF8File, but returns an empty optional, if the file couldn't be opened.
|
||||||
std::optional<std::string> ReadUTF8FileIfExists(const std::filesystem::path& path)
|
std::optional<std::string> ReadUTF8FileIfExists(const std::filesystem::path& path, const bool elevatedOnly)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return { ReadUTF8File(path) };
|
return { ReadUTF8File(path, elevatedOnly) };
|
||||||
}
|
}
|
||||||
catch (const wil::ResultException& exception)
|
catch (const wil::ResultException& exception)
|
||||||
{
|
{
|
||||||
|
@ -183,9 +176,70 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteUTF8File(const std::filesystem::path& path, const std::string_view& content)
|
void WriteUTF8File(const std::filesystem::path& path,
|
||||||
|
const std::string_view& content,
|
||||||
|
const bool elevatedOnly)
|
||||||
{
|
{
|
||||||
wil::unique_hfile file{ CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr) };
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
// stash the security descriptor here, so it will stay in context until
|
||||||
|
// after the call to CreateFile. If it gets cleaned up before that, then
|
||||||
|
// CreateFile will fail
|
||||||
|
wil::unique_hlocal_security_descriptor sd;
|
||||||
|
if (elevatedOnly)
|
||||||
|
{
|
||||||
|
// Initialize the security descriptor so only admins can write the
|
||||||
|
// file. We'll initialize the SECURITY_DESCRIPTOR with a
|
||||||
|
// single entry (ACE) -- a mandatory label (i.e. a
|
||||||
|
// LABEL_SECURITY_INFORMATION) that sets the file integrity level to
|
||||||
|
// "high", with a no-write-up policy.
|
||||||
|
//
|
||||||
|
// When accessed from a security context at a lower integrity level,
|
||||||
|
// the no-write-up policy filters out rights that aren't in the
|
||||||
|
// object type's generic read and execute set (for the file type,
|
||||||
|
// that's FILE_GENERIC_READ | FILE_GENERIC_EXECUTE).
|
||||||
|
//
|
||||||
|
// Another option we considered here was manually setting the ACLs
|
||||||
|
// on this file such that Builtin\Admins could read&write the file,
|
||||||
|
// and all users could only read.
|
||||||
|
//
|
||||||
|
// Big thanks to @eryksun in GH#11222 for helping with this. This
|
||||||
|
// alternative method was chosen because it's considerably simpler.
|
||||||
|
|
||||||
|
// The required security descriptor can be created easily from the
|
||||||
|
// SDDL string: "S:(ML;;NW;;;HI)"
|
||||||
|
// (i.e. SACL:mandatory label;;no write up;;;high integrity level)
|
||||||
|
unsigned long cb;
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(
|
||||||
|
ConvertStringSecurityDescriptorToSecurityDescriptor(L"S:(ML;;NW;;;HI)",
|
||||||
|
SDDL_REVISION_1,
|
||||||
|
wil::out_param_ptr<PSECURITY_DESCRIPTOR*>(sd),
|
||||||
|
&cb));
|
||||||
|
|
||||||
|
// Initialize a security attributes structure.
|
||||||
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
sa.lpSecurityDescriptor = sd.get();
|
||||||
|
sa.bInheritHandle = false;
|
||||||
|
|
||||||
|
// If we're running in an elevated context, when this file is
|
||||||
|
// created, it will automatically be owned by
|
||||||
|
// Builtin\Administrators, which will pass the above
|
||||||
|
// _isOwnedByAdministrators check.
|
||||||
|
//
|
||||||
|
// Programs running in an elevated context will be free to write the
|
||||||
|
// file, and unelevated processes will be able to read the file. An
|
||||||
|
// unelevated process could always delete the file and rename a new
|
||||||
|
// file in it's place (a la the way `vim.exe` saves files), but if
|
||||||
|
// they do that, the new file _won't_ be owned by Administrators,
|
||||||
|
// failing the above check.
|
||||||
|
}
|
||||||
|
|
||||||
|
wil::unique_hfile file{ CreateFileW(path.c_str(),
|
||||||
|
GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||||
|
elevatedOnly ? &sa : nullptr,
|
||||||
|
CREATE_ALWAYS,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
nullptr) };
|
||||||
THROW_LAST_ERROR_IF(!file);
|
THROW_LAST_ERROR_IF(!file);
|
||||||
|
|
||||||
const auto fileSize = gsl::narrow<DWORD>(content.size());
|
const auto fileSize = gsl::narrow<DWORD>(content.size());
|
||||||
|
@ -198,7 +252,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteUTF8FileAtomic(const std::filesystem::path& path, const std::string_view& content)
|
void WriteUTF8FileAtomic(const std::filesystem::path& path,
|
||||||
|
const std::string_view& content)
|
||||||
{
|
{
|
||||||
// GH#10787: rename() will replace symbolic links themselves and not the path they point at.
|
// GH#10787: rename() will replace symbolic links themselves and not the path they point at.
|
||||||
// It's thus important that we first resolve them before generating temporary path.
|
// It's thus important that we first resolve them before generating temporary path.
|
||||||
|
|
|
@ -1,41 +1,11 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||||
{
|
{
|
||||||
// I couldn't find a wil helper for this so I made it myself
|
|
||||||
class locked_hfile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
wil::unique_hfile file;
|
|
||||||
OVERLAPPED lockedRegion;
|
|
||||||
|
|
||||||
~locked_hfile()
|
|
||||||
{
|
|
||||||
if (file)
|
|
||||||
{
|
|
||||||
// Need to unlock the file before it is closed
|
|
||||||
UnlockFileEx(file.get(), 0, INT_MAX, 0, &lockedRegion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE get() const noexcept
|
|
||||||
{
|
|
||||||
return file.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::filesystem::path GetBaseSettingsPath();
|
std::filesystem::path GetBaseSettingsPath();
|
||||||
|
std::string ReadUTF8File(const std::filesystem::path& path, const bool elevatedOnly = false);
|
||||||
locked_hfile OpenFileReadSharedLocked(const std::filesystem::path& path);
|
std::optional<std::string> ReadUTF8FileIfExists(const std::filesystem::path& path, const bool elevatedOnly = false);
|
||||||
locked_hfile OpenFileRWExclusiveLocked(const std::filesystem::path& path);
|
void WriteUTF8File(const std::filesystem::path& path, const std::string_view& content, const bool elevatedOnly = false);
|
||||||
std::string ReadUTF8FileLocked(const locked_hfile& file);
|
|
||||||
void WriteUTF8FileLocked(const locked_hfile& file, const std::string_view& content);
|
|
||||||
|
|
||||||
std::string ReadUTF8File(const std::filesystem::path& path);
|
|
||||||
std::optional<std::string> ReadUTF8FileIfExists(const std::filesystem::path& path);
|
|
||||||
void WriteUTF8File(const std::filesystem::path& path, const std::string_view& content);
|
|
||||||
void WriteUTF8FileAtomic(const std::filesystem::path& path, const std::string_view& content);
|
void WriteUTF8FileAtomic(const std::filesystem::path& path, const std::string_view& content);
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,7 +382,6 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
||||||
struct ConversionTrait<std::unordered_map<std::string, T>>
|
struct ConversionTrait<std::unordered_map<std::string, T>>
|
||||||
{
|
{
|
||||||
std::unordered_map<std::string, T> FromJson(const Json::Value& json) const
|
std::unordered_map<std::string, T> FromJson(const Json::Value& json) const
|
||||||
|
|
|
@ -73,7 +73,8 @@ Author(s):
|
||||||
X(hstring, Icon, "icon", L"\uE756") \
|
X(hstring, Icon, "icon", L"\uE756") \
|
||||||
X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Graceful) \
|
X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Graceful) \
|
||||||
X(hstring, TabTitle, "tabTitle") \
|
X(hstring, TabTitle, "tabTitle") \
|
||||||
X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible)
|
X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible) \
|
||||||
|
X(bool, UseAtlasEngine, "experimental.useAtlasEngine", false)
|
||||||
|
|
||||||
#define MTSM_FONT_SETTINGS(X) \
|
#define MTSM_FONT_SETTINGS(X) \
|
||||||
X(hstring, FontFace, "face", DEFAULT_FONT_FACE) \
|
X(hstring, FontFace, "face", DEFAULT_FONT_FACE) \
|
||||||
|
|
|
@ -197,9 +197,29 @@
|
||||||
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
|
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
|
||||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
|
||||||
<!-- For whatever reason, we can't include the TerminalControl and
|
<!-- For whatever reason, we can't include the TerminalControl and
|
||||||
TerminalSettings projects' winmds via project references. So we'll have to
|
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>
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- Manually add references to each of our dependent winmds. Mark them as
|
<!-- Manually add references to each of our dependent winmds. Mark them as
|
||||||
|
@ -266,4 +286,5 @@
|
||||||
</Target>
|
</Target>
|
||||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||||
<Import Project="..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets" Condition="Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" />
|
<Import Project="..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets" Condition="Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" />
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -79,5 +79,6 @@ namespace Microsoft.Terminal.Settings.Model
|
||||||
INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput);
|
INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput);
|
||||||
INHERITABLE_PROFILE_SETTING(Boolean, AltGrAliasing);
|
INHERITABLE_PROFILE_SETTING(Boolean, AltGrAliasing);
|
||||||
INHERITABLE_PROFILE_SETTING(BellStyle, BellStyle);
|
INHERITABLE_PROFILE_SETTING(BellStyle, BellStyle);
|
||||||
|
INHERITABLE_PROFILE_SETTING(Boolean, UseAtlasEngine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,6 +275,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
|
|
||||||
// Fill in the remaining properties from the profile
|
// Fill in the remaining properties from the profile
|
||||||
_ProfileName = profile.Name();
|
_ProfileName = profile.Name();
|
||||||
|
_ProfileSource = profile.Source();
|
||||||
_UseAcrylic = profile.UseAcrylic();
|
_UseAcrylic = profile.UseAcrylic();
|
||||||
|
|
||||||
_FontFace = profile.FontInfo().FontFace();
|
_FontFace = profile.FontInfo().FontFace();
|
||||||
|
@ -297,6 +298,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
_SuppressApplicationTitle = profile.SuppressApplicationTitle();
|
_SuppressApplicationTitle = profile.SuppressApplicationTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_UseAtlasEngine = profile.UseAtlasEngine();
|
||||||
_ScrollState = profile.ScrollState();
|
_ScrollState = profile.ScrollState();
|
||||||
|
|
||||||
_AntialiasingMode = profile.AntialiasingMode();
|
_AntialiasingMode = profile.AntialiasingMode();
|
||||||
|
|
|
@ -119,6 +119,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
// ------------------------ End of Core Settings -----------------------
|
// ------------------------ End of Core Settings -----------------------
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileName);
|
INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileName);
|
||||||
|
INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileSource);
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::TerminalSettings, bool, UseAcrylic, false);
|
INHERITABLE_SETTING(Model::TerminalSettings, bool, UseAcrylic, false);
|
||||||
INHERITABLE_SETTING(Model::TerminalSettings, double, Opacity, UseAcrylic() ? 0.5 : 1.0);
|
INHERITABLE_SETTING(Model::TerminalSettings, double, Opacity, UseAcrylic() ? 0.5 : 1.0);
|
||||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, Padding, DEFAULT_PADDING);
|
INHERITABLE_SETTING(Model::TerminalSettings, hstring, Padding, DEFAULT_PADDING);
|
||||||
|
@ -146,6 +148,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, EnvironmentVariables);
|
INHERITABLE_SETTING(Model::TerminalSettings, hstring, EnvironmentVariables);
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::ScrollbarState, ScrollState, Microsoft::Terminal::Control::ScrollbarState::Visible);
|
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::ScrollbarState, ScrollState, Microsoft::Terminal::Control::ScrollbarState::Visible);
|
||||||
|
INHERITABLE_SETTING(Model::TerminalSettings, bool, UseAtlasEngine, false);
|
||||||
|
|
||||||
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
|
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
|
||||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
|
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
|
||||||
<!-- Private:false and ReferenceOutputAssembly:false, in combination with
|
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
|
||||||
the manual reference to TerminalControl.winmd below make sure that this
|
the manual reference to TerminalControl.winmd below make sure that this
|
||||||
project will compile correct, and that we won't roll up the TermControl
|
project will compile correct, and that we won't roll up the TermControl
|
||||||
xbf's into the packaging project twice. -->
|
xbf's into the packaging project twice. -->
|
||||||
|
|
|
@ -53,3 +53,6 @@ TRACELOGGING_DECLARE_PROVIDER(g_hSettingsModelProvider);
|
||||||
|
|
||||||
// Manually include til after we include Windows.Foundation to give it winrt superpowers
|
// Manually include til after we include Windows.Foundation to give it winrt superpowers
|
||||||
#include "til.h"
|
#include "til.h"
|
||||||
|
|
||||||
|
#include <til/mutex.h>
|
||||||
|
#include <til/throttled_func.h>
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace ControlUnitTests
|
||||||
// ------------------------ End of Core Settings -----------------------
|
// ------------------------ End of Core Settings -----------------------
|
||||||
|
|
||||||
WINRT_PROPERTY(winrt::hstring, ProfileName);
|
WINRT_PROPERTY(winrt::hstring, ProfileName);
|
||||||
|
WINRT_PROPERTY(winrt::hstring, ProfileSource);
|
||||||
WINRT_PROPERTY(bool, UseAcrylic, false);
|
WINRT_PROPERTY(bool, UseAcrylic, false);
|
||||||
WINRT_PROPERTY(double, Opacity, .5);
|
WINRT_PROPERTY(double, Opacity, .5);
|
||||||
WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
|
WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
|
||||||
|
@ -75,6 +76,7 @@ namespace ControlUnitTests
|
||||||
WINRT_PROPERTY(winrt::hstring, EnvironmentVariables);
|
WINRT_PROPERTY(winrt::hstring, EnvironmentVariables);
|
||||||
|
|
||||||
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible);
|
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible);
|
||||||
|
WINRT_PROPERTY(bool, UseAtlasEngine, false);
|
||||||
|
|
||||||
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
|
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
|
||||||
|
|
||||||
|
|
|
@ -96,9 +96,10 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final
|
||||||
auto& g = ServiceLocator::LocateGlobals();
|
auto& g = ServiceLocator::LocateGlobals();
|
||||||
auto& gci = g.getConsoleInformation();
|
auto& gci = g.getConsoleInformation();
|
||||||
|
|
||||||
gci.SetDefaultForegroundColor(INVALID_COLOR);
|
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR);
|
||||||
gci.SetDefaultBackgroundColor(INVALID_COLOR);
|
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, INVALID_COLOR);
|
||||||
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
|
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
|
||||||
|
gci.CalculateDefaultColorIndices();
|
||||||
|
|
||||||
m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight);
|
m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight);
|
||||||
auto& currentBuffer = gci.GetActiveOutputBuffer();
|
auto& currentBuffer = gci.GetActiveOutputBuffer();
|
||||||
|
|
|
@ -59,7 +59,6 @@ void TerminalApiTest::SetColorTableEntry()
|
||||||
VERIFY_IS_TRUE(term.SetColorTableEntry(128, 100));
|
VERIFY_IS_TRUE(term.SetColorTableEntry(128, 100));
|
||||||
VERIFY_IS_TRUE(term.SetColorTableEntry(255, 100));
|
VERIFY_IS_TRUE(term.SetColorTableEntry(255, 100));
|
||||||
|
|
||||||
VERIFY_IS_FALSE(term.SetColorTableEntry(256, 100));
|
|
||||||
VERIFY_IS_FALSE(term.SetColorTableEntry(512, 100));
|
VERIFY_IS_FALSE(term.SetColorTableEntry(512, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +270,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlink()
|
||||||
auto& stateMachine = *(term._stateMachine);
|
auto& stateMachine = *(term._stateMachine);
|
||||||
|
|
||||||
// Process the opening osc 8 sequence
|
// Process the opening osc 8 sequence
|
||||||
stateMachine.ProcessString(L"\x1b]8;;test.url\x9c");
|
stateMachine.ProcessString(L"\x1b]8;;test.url\x1b\\");
|
||||||
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
|
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
|
||||||
|
|
||||||
|
@ -281,7 +280,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlink()
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
|
||||||
|
|
||||||
// Process the closing osc 8 sequences
|
// Process the closing osc 8 sequences
|
||||||
stateMachine.ProcessString(L"\x1b]8;;\x9c");
|
stateMachine.ProcessString(L"\x1b]8;;\x1b\\");
|
||||||
VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink());
|
VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +296,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomId()
|
||||||
auto& stateMachine = *(term._stateMachine);
|
auto& stateMachine = *(term._stateMachine);
|
||||||
|
|
||||||
// Process the opening osc 8 sequence
|
// Process the opening osc 8 sequence
|
||||||
stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x9c");
|
stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x1b\\");
|
||||||
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
|
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
|
||||||
|
@ -309,7 +308,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomId()
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
|
||||||
|
|
||||||
// Process the closing osc 8 sequences
|
// Process the closing osc 8 sequences
|
||||||
stateMachine.ProcessString(L"\x1b]8;;\x9c");
|
stateMachine.ProcessString(L"\x1b]8;;\x1b\\");
|
||||||
VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink());
|
VERIFY_IS_FALSE(tbi.GetCurrentAttributes().IsHyperlink());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +324,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomIdDifferentUri()
|
||||||
auto& stateMachine = *(term._stateMachine);
|
auto& stateMachine = *(term._stateMachine);
|
||||||
|
|
||||||
// Process the opening osc 8 sequence
|
// Process the opening osc 8 sequence
|
||||||
stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x9c");
|
stateMachine.ProcessString(L"\x1b]8;id=myId;test.url\x1b\\");
|
||||||
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
|
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"test.url");
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"test.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
|
||||||
|
@ -333,7 +332,7 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomIdDifferentUri()
|
||||||
const auto oldAttributes{ tbi.GetCurrentAttributes() };
|
const auto oldAttributes{ tbi.GetCurrentAttributes() };
|
||||||
|
|
||||||
// Send any other text
|
// Send any other text
|
||||||
stateMachine.ProcessString(L"\x1b]8;id=myId;other.url\x9c");
|
stateMachine.ProcessString(L"\x1b]8;id=myId;other.url\x1b\\");
|
||||||
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
|
VERIFY_IS_TRUE(tbi.GetCurrentAttributes().IsHyperlink());
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"other.url");
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(tbi.GetCurrentAttributes().GetHyperlinkId()), L"other.url");
|
||||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"other.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
|
VERIFY_ARE_EQUAL(tbi.GetHyperlinkId(L"other.url", L"myId"), tbi.GetCurrentAttributes().GetHyperlinkId());
|
||||||
|
@ -356,58 +355,58 @@ void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress()
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||||
|
|
||||||
// Set some values for taskbar state and progress through state machine
|
// Set some values for taskbar state and progress through state machine
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;1;50\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;1;50\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(50));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(50));
|
||||||
|
|
||||||
// Reset to 0
|
// Reset to 0
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;0;0\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;0;0\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||||
|
|
||||||
// Set an out of bounds value for state
|
// Set an out of bounds value for state
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;5;50\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;5;50\x1b\\");
|
||||||
// Nothing should have changed (dispatch should have returned false)
|
// Nothing should have changed (dispatch should have returned false)
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||||
|
|
||||||
// Set an out of bounds value for progress
|
// Set an out of bounds value for progress
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;1;999\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;1;999\x1b\\");
|
||||||
// Progress should have been clamped to 100
|
// Progress should have been clamped to 100
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(100));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(100));
|
||||||
|
|
||||||
// Don't specify any params
|
// Don't specify any params
|
||||||
stateMachine.ProcessString(L"\x1b]9;4\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4\x1b\\");
|
||||||
// State and progress should both be reset to 0
|
// State and progress should both be reset to 0
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||||
|
|
||||||
// Specify additional params
|
// Specify additional params
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;1;80;123\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;1;80;123\x1b\\");
|
||||||
// Additional params should be ignored, state and progress still set normally
|
// Additional params should be ignored, state and progress still set normally
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
||||||
|
|
||||||
// Edge cases + trailing semicolon testing
|
// Edge cases + trailing semicolon testing
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;2;\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;2;\x1b\\");
|
||||||
// String should be processed correctly despite the trailing semicolon,
|
// String should be processed correctly despite the trailing semicolon,
|
||||||
// taskbar progress should remain unchanged from previous value
|
// taskbar progress should remain unchanged from previous value
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;3;75\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;3;75\x1b\\");
|
||||||
// Given progress value should be ignored because this is the indeterminate state,
|
// Given progress value should be ignored because this is the indeterminate state,
|
||||||
// so the progress value should remain unchanged
|
// so the progress value should remain unchanged
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(3));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(3));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;0;50\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;0;50\x1b\\");
|
||||||
// Taskbar progress should be 0 (the given value should be ignored)
|
// Taskbar progress should be 0 (the given value should be ignored)
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;4;2;\x9c");
|
stateMachine.ProcessString(L"\x1b]9;4;2;\x1b\\");
|
||||||
// String should be processed correctly despite the trailing semicolon,
|
// String should be processed correctly despite the trailing semicolon,
|
||||||
// taskbar progress should be set to a 'minimum', non-zero value
|
// taskbar progress should be set to a 'minimum', non-zero value
|
||||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2));
|
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2));
|
||||||
|
@ -427,45 +426,45 @@ void TerminalCoreUnitTests::TerminalApiTest::SetWorkingDirectory()
|
||||||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
||||||
|
|
||||||
// Invalid sequences should not change CWD
|
// Invalid sequences should not change CWD
|
||||||
stateMachine.ProcessString(L"\x1b]9;9\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9\x1b\\");
|
||||||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9\"\x1b\\");
|
||||||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9\"C:\\\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9\"C:\\\"\x1b\\");
|
||||||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
||||||
|
|
||||||
// Valid sequences should change CWD
|
// Valid sequences should change CWD
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\\"\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\");
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\Program Files\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\Program Files\"\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files");
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;\"D:\\中文\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;\"D:\\中文\"\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文");
|
||||||
|
|
||||||
// Test OSC 9;9 sequences without quotation marks
|
// Test OSC 9;9 sequences without quotation marks
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;C:\\\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;C:\\\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\");
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;C:\\Program Files\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;C:\\Program Files\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files");
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;D:\\中文\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;D:\\中文\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文");
|
||||||
|
|
||||||
// These OSC 9;9 sequences will result in invalid CWD. We shouldn't crash on these.
|
// These OSC 9;9 sequences will result in invalid CWD. We shouldn't crash on these.
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;\"\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"");
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;\"\"\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\"");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\"");
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"");
|
||||||
|
|
||||||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\"\x9c");
|
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\"\x1b\\");
|
||||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\"");
|
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\"");
|
||||||
}
|
}
|
||||||
|
|
|
@ -845,8 +845,30 @@ winrt::Windows::Foundation::IAsyncAction AppHost::_SaveWindowLayouts()
|
||||||
|
|
||||||
if (_logic.ShouldUsePersistedLayout())
|
if (_logic.ShouldUsePersistedLayout())
|
||||||
{
|
{
|
||||||
const auto layoutJsons = _windowManager.GetAllWindowLayouts();
|
try
|
||||||
_logic.SaveWindowLayoutJsons(layoutJsons);
|
{
|
||||||
|
TraceLoggingWrite(g_hWindowsTerminalProvider,
|
||||||
|
"AppHost_SaveWindowLayouts_Collect",
|
||||||
|
TraceLoggingDescription("Logged when collecting window state"),
|
||||||
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
|
const auto layoutJsons = _windowManager.GetAllWindowLayouts();
|
||||||
|
TraceLoggingWrite(g_hWindowsTerminalProvider,
|
||||||
|
"AppHost_SaveWindowLayouts_Save",
|
||||||
|
TraceLoggingDescription("Logged when writing window state"),
|
||||||
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
|
_logic.SaveWindowLayoutJsons(layoutJsons);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LOG_CAUGHT_EXCEPTION();
|
||||||
|
TraceLoggingWrite(g_hWindowsTerminalProvider,
|
||||||
|
"AppHost_SaveWindowLayouts_Failed",
|
||||||
|
TraceLoggingDescription("An error occurred when collecting or writing window state"),
|
||||||
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
co_return;
|
co_return;
|
||||||
|
@ -867,6 +889,12 @@ winrt::fire_and_forget AppHost::_SaveWindowLayoutsRepeat()
|
||||||
// per 10 seconds, if a save is requested by another source simultaneously.
|
// per 10 seconds, if a save is requested by another source simultaneously.
|
||||||
if (_getWindowLayoutThrottler.has_value())
|
if (_getWindowLayoutThrottler.has_value())
|
||||||
{
|
{
|
||||||
|
TraceLoggingWrite(g_hWindowsTerminalProvider,
|
||||||
|
"AppHost_requestGetLayout",
|
||||||
|
TraceLoggingDescription("Logged when triggering a throttled write of the window state"),
|
||||||
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
|
|
||||||
_getWindowLayoutThrottler.value()();
|
_getWindowLayoutThrottler.value()();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,23 @@
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</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="$(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')" />
|
<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')" />
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Dependencies>
|
<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" />
|
||||||
</Dependencies>
|
</Dependencies>
|
||||||
|
|
||||||
<Resources>
|
<Resources>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<Dependencies>
|
<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" />
|
||||||
</Dependencies>
|
</Dependencies>
|
||||||
|
|
||||||
<Resources>
|
<Resources>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<Description>TAEF Packaged Cwa FullTrust Application Host Process</Description>
|
<Description>TAEF Packaged Cwa FullTrust Application Host Process</Description>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Dependencies>
|
<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" 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" />
|
<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>
|
</Dependencies>
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.19041.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.22000.0</WindowsTargetPlatformVersion>
|
||||||
<WindowsTargetPlatformMinVersion Condition="'$(WindowsTargetPlatformMinVersion)' == ''">10.0.18362.0</WindowsTargetPlatformMinVersion>
|
<WindowsTargetPlatformMinVersion Condition="'$(WindowsTargetPlatformMinVersion)' == ''">10.0.18362.0</WindowsTargetPlatformMinVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -79,4 +79,14 @@
|
||||||
<!-- This feature will not ship to Stable until it is complete. -->
|
<!-- This feature will not ship to Stable until it is complete. -->
|
||||||
<alwaysDisabledReleaseTokens />
|
<alwaysDisabledReleaseTokens />
|
||||||
</feature>
|
</feature>
|
||||||
|
|
||||||
|
<feature>
|
||||||
|
<name>Feature_AtlasEngine</name>
|
||||||
|
<description>If enabled, AtlasEngine and the experimental.useAtlasEngine setting are compiled into the project</description>
|
||||||
|
<stage>AlwaysEnabled</stage>
|
||||||
|
<alwaysDisabledBrandingTokens>
|
||||||
|
<brandingToken>Release</brandingToken>
|
||||||
|
<brandingToken>WindowsInbox</brandingToken>
|
||||||
|
</alwaysDisabledBrandingTokens>
|
||||||
|
</feature>
|
||||||
</featureStaging>
|
</featureStaging>
|
||||||
|
|
|
@ -219,36 +219,6 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
|
||||||
return pInputBuffer;
|
return pInputBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Return the default foreground color of the console. If the settings are
|
|
||||||
// configured to have a default foreground color (separate from the color
|
|
||||||
// table), this will return that value. Otherwise it will return the value
|
|
||||||
// from the colortable corresponding to our default attributes.
|
|
||||||
// Arguments:
|
|
||||||
// - <none>
|
|
||||||
// Return Value:
|
|
||||||
// - the default foreground color of the console.
|
|
||||||
COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
|
|
||||||
{
|
|
||||||
const auto fg = GetDefaultForegroundColor();
|
|
||||||
return fg != INVALID_COLOR ? fg : GetLegacyColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Return the default background color of the console. If the settings are
|
|
||||||
// configured to have a default background color (separate from the color
|
|
||||||
// table), this will return that value. Otherwise it will return the value
|
|
||||||
// from the colortable corresponding to our default attributes.
|
|
||||||
// Arguments:
|
|
||||||
// - <none>
|
|
||||||
// Return Value:
|
|
||||||
// - the default background color of the console.
|
|
||||||
COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
|
|
||||||
{
|
|
||||||
const auto bg = GetDefaultBackgroundColor();
|
|
||||||
return bg != INVALID_COLOR ? bg : GetLegacyColorTableEntry((LOBYTE(GetFillAttribute()) & BG_ATTRS) >> 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Get the colors of a particular text attribute, using our color table,
|
// - Get the colors of a particular text attribute, using our color table,
|
||||||
// and our configured default attributes.
|
// and our configured default attributes.
|
||||||
|
@ -257,26 +227,12 @@ COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - The color values of the attribute's foreground and background.
|
// - The color values of the attribute's foreground and background.
|
||||||
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr) const noexcept
|
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr) const noexcept
|
||||||
{
|
|
||||||
return LookupAttributeColors(attr, GetDefaultForeground(), GetDefaultBackground());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Get the colors of a particular text attribute, using our color table,
|
|
||||||
// and the given default color values.
|
|
||||||
// Arguments:
|
|
||||||
// - attr: the TextAttribute to retrieve the foreground and background color of.
|
|
||||||
// - defaultFg: the COLORREF to use for a default foreground color.
|
|
||||||
// - defaultBg: the COLORREF to use for a default background color.
|
|
||||||
// Return Value:
|
|
||||||
// - The color values of the attribute's foreground and background.
|
|
||||||
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept
|
|
||||||
{
|
{
|
||||||
_blinkingState.RecordBlinkingUsage(attr);
|
_blinkingState.RecordBlinkingUsage(attr);
|
||||||
return attr.CalculateRgbColors(
|
return attr.CalculateRgbColors(
|
||||||
GetColorTable(),
|
GetColorTable(),
|
||||||
defaultFg,
|
GetDefaultForegroundIndex(),
|
||||||
defaultBg,
|
GetDefaultBackgroundIndex(),
|
||||||
IsScreenReversed(),
|
IsScreenReversed(),
|
||||||
_blinkingState.IsBlinkingFaint());
|
_blinkingState.IsBlinkingFaint());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,9 @@
|
||||||
<ProjectReference Include="..\..\renderer\base\lib\base.vcxproj">
|
<ProjectReference Include="..\..\renderer\base\lib\base.vcxproj">
|
||||||
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj">
|
||||||
|
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
|
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
|
||||||
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
|
|
@ -38,6 +38,9 @@
|
||||||
<ProjectReference Include="..\..\renderer\base\lib\base.vcxproj">
|
<ProjectReference Include="..\..\renderer\base\lib\base.vcxproj">
|
||||||
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj">
|
||||||
|
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
|
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
|
||||||
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
@ -71,6 +74,7 @@
|
||||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
|
@ -2320,9 +2320,6 @@ void ReadStringWithReadConsoleInputAHelper(HANDLE hIn, PCSTR pszExpectedText, si
|
||||||
|
|
||||||
while (cchRead < cchExpectedText)
|
while (cchRead < cchExpectedText)
|
||||||
{
|
{
|
||||||
// expected read is either the size of the buffer or the number of characters remaining, whichever is smaller.
|
|
||||||
DWORD const dwReadExpected = (DWORD)std::min(cbBuffer, cchExpectedText - cchRead);
|
|
||||||
|
|
||||||
DWORD dwRead;
|
DWORD dwRead;
|
||||||
if (!VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleInputA(hIn, irRead, (DWORD)cbBuffer, &dwRead), L"Attempt to read input into buffer."))
|
if (!VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleInputA(hIn, irRead, (DWORD)cbBuffer, &dwRead), L"Attempt to read input into buffer."))
|
||||||
{
|
{
|
||||||
|
|
|
@ -143,7 +143,7 @@
|
||||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>copy $(SolutionDir)\dep\WinAppDriver\* $(OutDir)\</PostBuildEvent>
|
<PostBuildEvent>copy "$(SolutionDir)\dep\WinAppDriver\*" "$(OutDir)\"</PostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets" Condition="Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" />
|
<Import Project="..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets" Condition="Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" />
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
@ -152,4 +152,4 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets'))" />
|
<Error Condition="!Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets'))" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1499,12 +1499,6 @@ void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
|
||||||
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetType(cursorType);
|
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetType(cursorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
|
|
||||||
const COLORREF cursorColor)
|
|
||||||
{
|
|
||||||
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetColor(cursorColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
|
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
|
||||||
const std::wstring_view uri,
|
const std::wstring_view uri,
|
||||||
const std::wstring_view params)
|
const std::wstring_view params)
|
||||||
|
@ -1963,115 +1957,6 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
|
||||||
screenInfo.GetActiveBuffer().MoveToBottom();
|
screenInfo.GetActiveBuffer().MoveToBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Retrieve the color table value at the specified index.
|
|
||||||
// Arguments:
|
|
||||||
// - index: the index in the table to retrieve.
|
|
||||||
// - value: receives the RGB value for the color at that index in the table.
|
|
||||||
// Return Value:
|
|
||||||
// - E_INVALIDARG if index is >= 256, else S_OK
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateGetColorTableEntry(const size_t index, COLORREF& value) noexcept
|
|
||||||
{
|
|
||||||
RETURN_HR_IF(E_INVALIDARG, index >= 256);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Globals& g = ServiceLocator::LocateGlobals();
|
|
||||||
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
|
|
||||||
|
|
||||||
value = gci.GetColorTableEntry(index);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
CATCH_RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Sets the color table value in index to the color specified in value.
|
|
||||||
// Can be used to set the 256-color table as well as the 16-color table.
|
|
||||||
// Arguments:
|
|
||||||
// - index: the index in the table to change.
|
|
||||||
// - value: the new RGB value to use for that index in the color table.
|
|
||||||
// Return Value:
|
|
||||||
// - E_INVALIDARG if index is >= 256, else S_OK
|
|
||||||
// Notes:
|
|
||||||
// Does not take a buffer parameter. The color table for a console and for
|
|
||||||
// terminals as well is global, not per-screen-buffer.
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateSetColorTableEntry(const size_t index, const COLORREF value) noexcept
|
|
||||||
{
|
|
||||||
RETURN_HR_IF(E_INVALIDARG, index >= 256);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Globals& g = ServiceLocator::LocateGlobals();
|
|
||||||
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
|
|
||||||
|
|
||||||
gci.SetColorTableEntry(index, value);
|
|
||||||
|
|
||||||
// Update the screen colors if we're not a pty
|
|
||||||
// No need to force a redraw in pty mode.
|
|
||||||
if (g.pRender && !gci.IsInVtIoMode())
|
|
||||||
{
|
|
||||||
g.pRender->TriggerRedrawAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
CATCH_RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Sets the default foreground color to the color specified in value.
|
|
||||||
// Arguments:
|
|
||||||
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
|
|
||||||
// Return Value:
|
|
||||||
// - S_OK
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Globals& g = ServiceLocator::LocateGlobals();
|
|
||||||
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
|
|
||||||
|
|
||||||
gci.SetDefaultForegroundColor(value);
|
|
||||||
|
|
||||||
// Update the screen colors if we're not a pty
|
|
||||||
// No need to force a redraw in pty mode.
|
|
||||||
if (g.pRender && !gci.IsInVtIoMode())
|
|
||||||
{
|
|
||||||
g.pRender->TriggerRedrawAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
CATCH_RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Sets the default background color to the color specified in value.
|
|
||||||
// Arguments:
|
|
||||||
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
|
|
||||||
// Return Value:
|
|
||||||
// - S_OK
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Globals& g = ServiceLocator::LocateGlobals();
|
|
||||||
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
|
|
||||||
|
|
||||||
gci.SetDefaultBackgroundColor(value);
|
|
||||||
|
|
||||||
// Update the screen colors if we're not a pty
|
|
||||||
// No need to force a redraw in pty mode.
|
|
||||||
if (g.pRender && !gci.IsInVtIoMode())
|
|
||||||
{
|
|
||||||
g.pRender->TriggerRedrawAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
CATCH_RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - A private API call for filling a region of the screen buffer.
|
// - A private API call for filling a region of the screen buffer.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
|
|
@ -36,8 +36,6 @@ void DoSrvPrivateUseMainScreenBuffer(SCREEN_INFORMATION& screenInfo);
|
||||||
|
|
||||||
void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
|
void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
|
||||||
const CursorType cursorType);
|
const CursorType cursorType);
|
||||||
void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
|
|
||||||
const COLORREF cursorColor);
|
|
||||||
|
|
||||||
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
|
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
|
||||||
const std::wstring_view uri,
|
const std::wstring_view uri,
|
||||||
|
@ -63,13 +61,6 @@ void DoSrvPrivateInsertLines(const size_t count);
|
||||||
|
|
||||||
void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo);
|
void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo);
|
||||||
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateGetColorTableEntry(const size_t index, COLORREF& value) noexcept;
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateSetColorTableEntry(const size_t index, const COLORREF value) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] HRESULT DoSrvPrivateFillRegion(SCREEN_INFORMATION& screenInfo,
|
[[nodiscard]] HRESULT DoSrvPrivateFillRegion(SCREEN_INFORMATION& screenInfo,
|
||||||
const COORD startPosition,
|
const COORD startPosition,
|
||||||
const size_t fillLength,
|
const size_t fillLength,
|
||||||
|
|
|
@ -22,10 +22,7 @@ Revision History:
|
||||||
#include "ConsoleArguments.hpp"
|
#include "ConsoleArguments.hpp"
|
||||||
#include "ApiRoutines.h"
|
#include "ApiRoutines.h"
|
||||||
|
|
||||||
#include "../renderer/inc/IRenderData.hpp"
|
#include "../renderer/base/Renderer.hpp"
|
||||||
#include "../renderer/inc/IRenderEngine.hpp"
|
|
||||||
#include "../renderer/inc/IRenderer.hpp"
|
|
||||||
#include "../renderer/inc/IFontDefaultList.hpp"
|
|
||||||
|
|
||||||
#include "../server/DeviceComm.h"
|
#include "../server/DeviceComm.h"
|
||||||
#include "../server/ConDrvDeviceComm.h"
|
#include "../server/ConDrvDeviceComm.h"
|
||||||
|
@ -62,7 +59,7 @@ public:
|
||||||
|
|
||||||
std::vector<wchar_t> WordDelimiters;
|
std::vector<wchar_t> WordDelimiters;
|
||||||
|
|
||||||
Microsoft::Console::Render::IRenderer* pRender;
|
Microsoft::Console::Render::Renderer* pRender;
|
||||||
|
|
||||||
Microsoft::Console::Render::IFontDefaultList* pFontDefaultList;
|
Microsoft::Console::Render::IFontDefaultList* pFontDefaultList;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
using namespace Microsoft::Console;
|
using namespace Microsoft::Console;
|
||||||
using Microsoft::Console::Interactivity::ServiceLocator;
|
using Microsoft::Console::Interactivity::ServiceLocator;
|
||||||
|
using Microsoft::Console::VirtualTerminal::StateMachine;
|
||||||
using Microsoft::Console::VirtualTerminal::TerminalInput;
|
using Microsoft::Console::VirtualTerminal::TerminalInput;
|
||||||
|
|
||||||
WriteBuffer::WriteBuffer(_In_ Microsoft::Console::IIoProvider& io) :
|
WriteBuffer::WriteBuffer(_In_ Microsoft::Console::IIoProvider& io) :
|
||||||
|
@ -263,22 +264,35 @@ bool ConhostInternalGetSet::SetInputMode(const TerminalInput::Mode mode, const b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - Sets the terminal emulation mode to either ANSI-compatible or VT52.
|
// - Sets the various StateMachine parser modes.
|
||||||
// PrivateSetAnsiMode is an internal-only "API" call that the vt commands can execute,
|
// SetParserMode is an internal-only "API" call that the vt commands can execute,
|
||||||
// but it is not represented as a function call on out public API surface.
|
// but it is not represented as a function call on out public API surface.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - ansiMode - set to true to enable the ANSI mode, false for VT52 mode.
|
// - mode - the parser mode to change.
|
||||||
|
// - enabled - set to true to enable the mode, false to disable it.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - true if successful. false otherwise.
|
// - true if successful. false otherwise.
|
||||||
bool ConhostInternalGetSet::PrivateSetAnsiMode(const bool ansiMode)
|
bool ConhostInternalGetSet::SetParserMode(const StateMachine::Mode mode, const bool enabled)
|
||||||
{
|
{
|
||||||
auto& stateMachine = _io.GetActiveOutputBuffer().GetStateMachine();
|
auto& stateMachine = _io.GetActiveOutputBuffer().GetStateMachine();
|
||||||
stateMachine.SetAnsiMode(ansiMode);
|
stateMachine.SetParserMode(mode, enabled);
|
||||||
auto& terminalInput = _io.GetActiveInputBuffer()->GetTerminalInput();
|
|
||||||
terminalInput.SetInputMode(TerminalInput::Mode::Ansi, ansiMode);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Routine Description:
|
||||||
|
// - Retrieves the various StateMachine parser modes.
|
||||||
|
// GetParserMode is an internal-only "API" call that the vt commands can execute,
|
||||||
|
// but it is not represented as a function call on out public API surface.
|
||||||
|
// Arguments:
|
||||||
|
// - mode - the parser mode to query.
|
||||||
|
// Return Value:
|
||||||
|
// - true if the mode is enabled. false if disabled.
|
||||||
|
bool ConhostInternalGetSet::GetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode) const
|
||||||
|
{
|
||||||
|
auto& stateMachine = _io.GetActiveOutputBuffer().GetStateMachine();
|
||||||
|
return stateMachine.GetParserMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - Connects the PrivateSetScreenMode call directly into our Driver Message servicing call inside Conhost.exe
|
// - Connects the PrivateSetScreenMode call directly into our Driver Message servicing call inside Conhost.exe
|
||||||
// PrivateSetScreenMode is an internal-only "API" call that the vt commands can execute,
|
// PrivateSetScreenMode is an internal-only "API" call that the vt commands can execute,
|
||||||
|
@ -538,21 +552,6 @@ bool ConhostInternalGetSet::PrivateSuppressResizeRepaint()
|
||||||
return SUCCEEDED(DoSrvPrivateSuppressResizeRepaint());
|
return SUCCEEDED(DoSrvPrivateSuppressResizeRepaint());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - Connects the SetCursorStyle call directly into our Driver Message servicing call inside Conhost.exe
|
|
||||||
// SetCursorStyle is an internal-only "API" call that the vt commands can execute,
|
|
||||||
// but it is not represented as a function call on our public API surface.
|
|
||||||
// Arguments:
|
|
||||||
// - cursorColor: The color to change the cursor to. INVALID_COLOR will revert
|
|
||||||
// it to the legacy inverting behavior.
|
|
||||||
// Return Value:
|
|
||||||
// - true if successful (see DoSrvSetCursorStyle). false otherwise.
|
|
||||||
bool ConhostInternalGetSet::SetCursorColor(const COLORREF cursorColor)
|
|
||||||
{
|
|
||||||
DoSrvSetCursorColor(_io.GetActiveOutputBuffer(), cursorColor);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - Connects the IsConsolePty call directly into our Driver Message servicing call inside Conhost.exe
|
// - Connects the IsConsolePty call directly into our Driver Message servicing call inside Conhost.exe
|
||||||
// - NOTE: This ONE method behaves differently! The rest of the methods on this
|
// - NOTE: This ONE method behaves differently! The rest of the methods on this
|
||||||
|
@ -594,54 +593,61 @@ bool ConhostInternalGetSet::MoveToBottom() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Connects the PrivateGetColorTableEntry call directly into our Driver Message servicing
|
// - Retrieves the value in the colortable at the specified index.
|
||||||
// call inside Conhost.exe
|
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - index: the index in the table to retrieve.
|
// - tableIndex: the index of the color table to retrieve.
|
||||||
// - value: receives the RGB value for the color at that index in the table.
|
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - true if successful (see DoSrvPrivateGetColorTableEntry). false otherwise.
|
// - the COLORREF value for the color at that index in the table.
|
||||||
bool ConhostInternalGetSet::PrivateGetColorTableEntry(const size_t index, COLORREF& value) const noexcept
|
COLORREF ConhostInternalGetSet::GetColorTableEntry(const size_t tableIndex) const noexcept
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return SUCCEEDED(DoSrvPrivateGetColorTableEntry(index, value));
|
auto& g = ServiceLocator::LocateGlobals();
|
||||||
|
auto& gci = g.getConsoleInformation();
|
||||||
|
|
||||||
|
return gci.GetColorTableEntry(tableIndex);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return INVALID_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Connects the PrivateSetColorTableEntry call directly into our Driver Message servicing
|
// - Updates the value in the colortable at index tableIndex to the new color
|
||||||
// call inside Conhost.exe
|
// color. color is a COLORREF, format 0x00BBGGRR.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - index: the index in the table to change.
|
// - tableIndex: the index of the color table to update.
|
||||||
// - value: the new RGB value to use for that index in the color table.
|
// - color: the new COLORREF to use as that color table value.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - true if successful (see DoSrvPrivateSetColorTableEntry). false otherwise.
|
// - true if successful. false otherwise.
|
||||||
bool ConhostInternalGetSet::PrivateSetColorTableEntry(const size_t index, const COLORREF value) const noexcept
|
bool ConhostInternalGetSet::SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return SUCCEEDED(DoSrvPrivateSetColorTableEntry(index, value));
|
auto& g = ServiceLocator::LocateGlobals();
|
||||||
}
|
auto& gci = g.getConsoleInformation();
|
||||||
|
|
||||||
// Method Description:
|
gci.SetColorTableEntry(tableIndex, color);
|
||||||
// - Connects the PrivateSetDefaultForeground call directly into our Driver Message servicing
|
|
||||||
// call inside Conhost.exe
|
|
||||||
// Arguments:
|
|
||||||
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
|
|
||||||
// Return Value:
|
|
||||||
// - true if successful (see DoSrvPrivateSetDefaultForegroundColor). false otherwise.
|
|
||||||
bool ConhostInternalGetSet::PrivateSetDefaultForeground(const COLORREF value) const noexcept
|
|
||||||
{
|
|
||||||
return SUCCEEDED(DoSrvPrivateSetDefaultForegroundColor(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
// If we're setting the default foreground or background colors
|
||||||
// - Connects the PrivateSetDefaultBackground call directly into our Driver Message servicing
|
// we need to make sure the index is correctly set as well.
|
||||||
// call inside Conhost.exe
|
if (tableIndex == TextColor::DEFAULT_FOREGROUND)
|
||||||
// Arguments:
|
{
|
||||||
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
|
gci.SetDefaultForegroundIndex(TextColor::DEFAULT_FOREGROUND);
|
||||||
// Return Value:
|
}
|
||||||
// - true if successful (see DoSrvPrivateSetDefaultBackgroundColor). false otherwise.
|
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
|
||||||
bool ConhostInternalGetSet::PrivateSetDefaultBackground(const COLORREF value) const noexcept
|
{
|
||||||
{
|
gci.SetDefaultBackgroundIndex(TextColor::DEFAULT_BACKGROUND);
|
||||||
return SUCCEEDED(DoSrvPrivateSetDefaultBackgroundColor(value));
|
}
|
||||||
|
|
||||||
|
// Update the screen colors if we're not a pty
|
||||||
|
// No need to force a redraw in pty mode.
|
||||||
|
if (g.pRender && !gci.IsInVtIoMode())
|
||||||
|
{
|
||||||
|
g.pRender->TriggerRedrawAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
CATCH_RETURN_FALSE()
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - Connects the PrivateFillRegion call directly into our Driver Message servicing
|
// - Connects the PrivateFillRegion call directly into our Driver Message servicing
|
||||||
|
|
|
@ -73,8 +73,9 @@ public:
|
||||||
const SMALL_RECT& window) override;
|
const SMALL_RECT& window) override;
|
||||||
|
|
||||||
bool SetInputMode(const Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) override;
|
bool SetInputMode(const Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) override;
|
||||||
|
bool SetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode, const bool enabled) override;
|
||||||
|
bool GetParserMode(const Microsoft::Console::VirtualTerminal::StateMachine::Mode mode) const override;
|
||||||
|
|
||||||
bool PrivateSetAnsiMode(const bool ansiMode) override;
|
|
||||||
bool PrivateSetScreenMode(const bool reverseMode) override;
|
bool PrivateSetScreenMode(const bool reverseMode) override;
|
||||||
bool PrivateSetAutoWrapMode(const bool wrapAtEOL) override;
|
bool PrivateSetAutoWrapMode(const bool wrapAtEOL) override;
|
||||||
|
|
||||||
|
@ -100,7 +101,6 @@ public:
|
||||||
|
|
||||||
bool GetUserDefaultCursorStyle(CursorType& style) override;
|
bool GetUserDefaultCursorStyle(CursorType& style) override;
|
||||||
bool SetCursorStyle(CursorType const style) override;
|
bool SetCursorStyle(CursorType const style) override;
|
||||||
bool SetCursorColor(COLORREF const color) override;
|
|
||||||
|
|
||||||
bool PrivateRefreshWindow() override;
|
bool PrivateRefreshWindow() override;
|
||||||
|
|
||||||
|
@ -118,12 +118,8 @@ public:
|
||||||
|
|
||||||
bool MoveToBottom() const override;
|
bool MoveToBottom() const override;
|
||||||
|
|
||||||
bool PrivateGetColorTableEntry(const size_t index, COLORREF& value) const noexcept override;
|
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
|
||||||
bool PrivateSetColorTableEntry(const size_t index, const COLORREF value) const noexcept override;
|
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
|
||||||
|
|
||||||
bool PrivateSetDefaultForeground(const COLORREF value) const noexcept override;
|
|
||||||
|
|
||||||
bool PrivateSetDefaultBackground(const COLORREF value) const noexcept override;
|
|
||||||
|
|
||||||
bool PrivateFillRegion(const COORD startPosition,
|
bool PrivateFillRegion(const COORD startPosition,
|
||||||
const size_t fillLength,
|
const size_t fillLength,
|
||||||
|
|
|
@ -110,8 +110,6 @@ void RenderData::UnlockConsole() noexcept
|
||||||
const TextAttribute RenderData::GetDefaultBrushColors() noexcept
|
const TextAttribute RenderData::GetDefaultBrushColors() noexcept
|
||||||
{
|
{
|
||||||
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||||
_defaultForeground = gci.GetDefaultForeground();
|
|
||||||
_defaultBackground = gci.GetDefaultBackground();
|
|
||||||
return gci.GetActiveOutputBuffer().GetAttributes();
|
return gci.GetActiveOutputBuffer().GetAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,8 +224,7 @@ ULONG RenderData::GetCursorPixelWidth() const noexcept
|
||||||
COLORREF RenderData::GetCursorColor() const noexcept
|
COLORREF RenderData::GetCursorColor() const noexcept
|
||||||
{
|
{
|
||||||
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||||
const auto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
|
return gci.GetColorTableEntry(TextColor::CURSOR_COLOR);
|
||||||
return cursor.GetColor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
|
@ -364,7 +361,7 @@ const std::vector<size_t> RenderData::GetPatternId(const COORD /*location*/) con
|
||||||
std::pair<COLORREF, COLORREF> RenderData::GetAttributeColors(const TextAttribute& attr) const noexcept
|
std::pair<COLORREF, COLORREF> RenderData::GetAttributeColors(const TextAttribute& attr) const noexcept
|
||||||
{
|
{
|
||||||
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||||
return gci.LookupAttributeColors(attr, _defaultForeground, _defaultBackground);
|
return gci.LookupAttributeColors(attr);
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,4 @@ public:
|
||||||
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr);
|
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr);
|
||||||
const bool IsUiaDataInitialized() const noexcept override { return true; }
|
const bool IsUiaDataInitialized() const noexcept override { return true; }
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
private:
|
|
||||||
COLORREF _defaultForeground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 7);
|
|
||||||
COLORREF _defaultBackground = gsl::at(Microsoft::Console::Utils::CampbellColorTable(), 0);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -123,7 +123,6 @@ SCREEN_INFORMATION::~SCREEN_INFORMATION()
|
||||||
pScreen->_renderTarget);
|
pScreen->_renderTarget);
|
||||||
|
|
||||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||||
pScreen->_textBuffer->GetCursor().SetColor(gci.GetCursorColor());
|
|
||||||
pScreen->_textBuffer->GetCursor().SetType(gci.GetCursorType());
|
pScreen->_textBuffer->GetCursor().SetType(gci.GetCursorType());
|
||||||
|
|
||||||
const NTSTATUS status = pScreen->_InitializeOutputStateMachine();
|
const NTSTATUS status = pScreen->_InitializeOutputStateMachine();
|
||||||
|
@ -1630,29 +1629,6 @@ void SCREEN_INFORMATION::SetCursorInformation(const ULONG Size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - This routine sets the cursor color. Also updates the cursor information of
|
|
||||||
// this buffer's main buffer, if this buffer is an alt buffer.
|
|
||||||
// Arguments:
|
|
||||||
// - Color - The new color to set the cursor to
|
|
||||||
// - setMain - If true, propagate change to main buffer as well.
|
|
||||||
// Return Value:
|
|
||||||
// - None
|
|
||||||
void SCREEN_INFORMATION::SetCursorColor(const unsigned int Color, const bool setMain) noexcept
|
|
||||||
{
|
|
||||||
Cursor& cursor = _textBuffer->GetCursor();
|
|
||||||
|
|
||||||
cursor.SetColor(Color);
|
|
||||||
|
|
||||||
// If we're an alt buffer, DON'T propagate this setting up to the main buffer.
|
|
||||||
// We don't want to pollute that buffer with this state,
|
|
||||||
// UNLESS we're getting called from the propsheet, then we DO want to update this.
|
|
||||||
if (_psiMainBuffer && setMain)
|
|
||||||
{
|
|
||||||
_psiMainBuffer->SetCursorColor(Color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - This routine sets the cursor shape both in the data
|
// - This routine sets the cursor shape both in the data
|
||||||
// structures and on the screen. Also updates the cursor information of
|
// structures and on the screen. Also updates the cursor information of
|
||||||
|
@ -1908,7 +1884,7 @@ const SCREEN_INFORMATION& SCREEN_INFORMATION::GetMainBuffer() const
|
||||||
auto& myCursor = GetTextBuffer().GetCursor();
|
auto& myCursor = GetTextBuffer().GetCursor();
|
||||||
auto* const createdBuffer = *ppsiNewScreenBuffer;
|
auto* const createdBuffer = *ppsiNewScreenBuffer;
|
||||||
auto& altCursor = createdBuffer->GetTextBuffer().GetCursor();
|
auto& altCursor = createdBuffer->GetTextBuffer().GetCursor();
|
||||||
altCursor.SetStyle(myCursor.GetSize(), myCursor.GetColor(), myCursor.GetType());
|
altCursor.SetStyle(myCursor.GetSize(), myCursor.GetType());
|
||||||
altCursor.SetIsVisible(myCursor.IsVisible());
|
altCursor.SetIsVisible(myCursor.IsVisible());
|
||||||
altCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed());
|
altCursor.SetBlinkingAllowed(myCursor.IsBlinkingAllowed());
|
||||||
// The new position should match the viewport-relative position of the main buffer.
|
// The new position should match the viewport-relative position of the main buffer.
|
||||||
|
@ -2006,7 +1982,7 @@ void SCREEN_INFORMATION::UseMainScreenBuffer()
|
||||||
// Copy the alt buffer's cursor style and visibility back to the main buffer.
|
// Copy the alt buffer's cursor style and visibility back to the main buffer.
|
||||||
const auto& altCursor = psiAlt->GetTextBuffer().GetCursor();
|
const auto& altCursor = psiAlt->GetTextBuffer().GetCursor();
|
||||||
auto& mainCursor = psiMain->GetTextBuffer().GetCursor();
|
auto& mainCursor = psiMain->GetTextBuffer().GetCursor();
|
||||||
mainCursor.SetStyle(altCursor.GetSize(), altCursor.GetColor(), altCursor.GetType());
|
mainCursor.SetStyle(altCursor.GetSize(), altCursor.GetType());
|
||||||
mainCursor.SetIsVisible(altCursor.IsVisible());
|
mainCursor.SetIsVisible(altCursor.IsVisible());
|
||||||
mainCursor.SetBlinkingAllowed(altCursor.IsBlinkingAllowed());
|
mainCursor.SetBlinkingAllowed(altCursor.IsBlinkingAllowed());
|
||||||
|
|
||||||
|
|
|
@ -189,8 +189,6 @@ public:
|
||||||
void SetCursorInformation(const ULONG Size,
|
void SetCursorInformation(const ULONG Size,
|
||||||
const bool Visible) noexcept;
|
const bool Visible) noexcept;
|
||||||
|
|
||||||
void SetCursorColor(const unsigned int Color, const bool setMain = false) noexcept;
|
|
||||||
|
|
||||||
void SetCursorType(const CursorType Type, const bool setMain = false) noexcept;
|
void SetCursorType(const CursorType Type, const bool setMain = false) noexcept;
|
||||||
|
|
||||||
void SetCursorDBMode(const bool DoubleCursor);
|
void SetCursorDBMode(const bool DoubleCursor);
|
||||||
|
|
|
@ -16,7 +16,6 @@ Selection::Selection() :
|
||||||
_fSelectionVisible(false),
|
_fSelectionVisible(false),
|
||||||
_ulSavedCursorSize(0),
|
_ulSavedCursorSize(0),
|
||||||
_fSavedCursorVisible(false),
|
_fSavedCursorVisible(false),
|
||||||
_savedCursorColor(INVALID_COLOR),
|
|
||||||
_savedCursorType(CursorType::Legacy),
|
_savedCursorType(CursorType::Legacy),
|
||||||
_dwSelectionFlags(0),
|
_dwSelectionFlags(0),
|
||||||
_fLineSelection(true),
|
_fLineSelection(true),
|
||||||
|
|
|
@ -174,7 +174,6 @@ private:
|
||||||
COORD _coordSavedCursorPosition;
|
COORD _coordSavedCursorPosition;
|
||||||
ULONG _ulSavedCursorSize;
|
ULONG _ulSavedCursorSize;
|
||||||
bool _fSavedCursorVisible;
|
bool _fSavedCursorVisible;
|
||||||
COLORREF _savedCursorColor;
|
|
||||||
CursorType _savedCursorType;
|
CursorType _savedCursorType;
|
||||||
|
|
||||||
#ifdef UNIT_TESTING
|
#ifdef UNIT_TESTING
|
||||||
|
|
|
@ -168,7 +168,6 @@ void Selection::_SaveCursorData(const Cursor& cursor) noexcept
|
||||||
_coordSavedCursorPosition = cursor.GetPosition();
|
_coordSavedCursorPosition = cursor.GetPosition();
|
||||||
_ulSavedCursorSize = cursor.GetSize();
|
_ulSavedCursorSize = cursor.GetSize();
|
||||||
_fSavedCursorVisible = cursor.IsVisible();
|
_fSavedCursorVisible = cursor.IsVisible();
|
||||||
_savedCursorColor = cursor.GetColor();
|
|
||||||
_savedCursorType = cursor.GetType();
|
_savedCursorType = cursor.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +181,6 @@ void Selection::_RestoreDataToCursor(Cursor& cursor) noexcept
|
||||||
{
|
{
|
||||||
cursor.SetSize(_ulSavedCursorSize);
|
cursor.SetSize(_ulSavedCursorSize);
|
||||||
cursor.SetIsVisible(_fSavedCursorVisible);
|
cursor.SetIsVisible(_fSavedCursorVisible);
|
||||||
cursor.SetColor(_savedCursorColor);
|
|
||||||
cursor.SetType(_savedCursorType);
|
cursor.SetType(_savedCursorType);
|
||||||
cursor.SetIsOn(true);
|
cursor.SetIsOn(true);
|
||||||
cursor.SetPosition(_coordSavedCursorPosition);
|
cursor.SetPosition(_coordSavedCursorPosition);
|
||||||
|
|
|
@ -124,10 +124,7 @@ public:
|
||||||
COOKED_READ_DATA& CookedReadData() noexcept;
|
COOKED_READ_DATA& CookedReadData() noexcept;
|
||||||
void SetCookedReadData(COOKED_READ_DATA* readData) noexcept;
|
void SetCookedReadData(COOKED_READ_DATA* readData) noexcept;
|
||||||
|
|
||||||
COLORREF GetDefaultForeground() const noexcept;
|
|
||||||
COLORREF GetDefaultBackground() const noexcept;
|
|
||||||
std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr) const noexcept;
|
std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr) const noexcept;
|
||||||
std::pair<COLORREF, COLORREF> LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept;
|
|
||||||
|
|
||||||
void SetTitle(const std::wstring_view newTitle);
|
void SetTitle(const std::wstring_view newTitle);
|
||||||
void SetTitlePrefix(const std::wstring_view newTitlePrefix);
|
void SetTitlePrefix(const std::wstring_view newTitlePrefix);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue