Compare commits
59 commits
dev/pabhoj
...
main
Author | SHA1 | Date | |
---|---|---|---|
f2386de422 | |||
80f8383860 | |||
bb71179a24 | |||
df06c54e70 | |||
a98d18c030 | |||
dc01926e3e | |||
6ad848e158 | |||
ea456cf121 | |||
442432ea15 | |||
fc85bdf314 | |||
a68b0d4f08 | |||
6742965bb8 | |||
131f5d2b32 | |||
7bfaad4592 | |||
c455418659 | |||
c79334ffbb | |||
2353349fe5 | |||
f6965aeb53 | |||
d5974f4c91 | |||
3fc82c2d4b | |||
305255c658 | |||
7db7ba1ac9 | |||
89c2b6d580 | |||
92643c1d34 | |||
e591d29000 | |||
88d58d313a | |||
87182554c8 | |||
5ff412fe6e | |||
30f7f2082b | |||
e6b871da47 | |||
f9c0f86705 | |||
86da0e041f | |||
a89b66f770 | |||
f9b97c4880 | |||
a74c37bbcd | |||
55dbda02a5 | |||
7aae2e9100 | |||
74d21afacf | |||
52b4bb760f | |||
b604117421 | |||
761203d95e | |||
4241d1c19e | |||
ab6ba9bdbb | |||
8826cc028b | |||
d3ca0e7878 | |||
726b428184 | |||
27e042b784 | |||
3667678df1 | |||
a7ce93a357 | |||
b90f3605a2 | |||
95cc7d9625 | |||
1cedac6a33 | |||
dc865529b5 | |||
d26353bb32 | |||
431d51de4c | |||
184919fb24 | |||
01b5195275 | |||
dfda41074d | |||
26f4b0eacb |
19
.github/ISSUE_TEMPLATE/Bug_Report.yml
vendored
19
.github/ISSUE_TEMPLATE/Bug_Report.yml
vendored
|
@ -10,14 +10,21 @@ body:
|
|||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Windows Terminal version (or Windows build number)
|
||||
placeholder: "10.0.19042.0, 1.7.3651.0"
|
||||
label: Windows Terminal version
|
||||
placeholder: "1.7.3651.0"
|
||||
description: |
|
||||
If you are reporting an issue in Windows Terminal, you can find the version in the about dialog.
|
||||
|
||||
If you are reporting an issue with the Windows Console, please run `ver` or `[Environment]::OSVersion`.
|
||||
You can find the version in the about dialog, or by running `wt -v` at the commandline.
|
||||
validations:
|
||||
required: true
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Windows build number
|
||||
placeholder: "10.0.19042.0"
|
||||
description: |
|
||||
Please run `ver` or `[Environment]::OSVersion`.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
|
14
.github/actions/spelling/allow/allow.txt
vendored
14
.github/actions/spelling/allow/allow.txt
vendored
|
@ -1,12 +1,14 @@
|
|||
admins
|
||||
apc
|
||||
Apc
|
||||
bsd
|
||||
calt
|
||||
ccmp
|
||||
changelog
|
||||
cybersecurity
|
||||
Apc
|
||||
clickable
|
||||
clig
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
dcs
|
||||
Dcs
|
||||
|
@ -30,20 +32,22 @@ hyperlink
|
|||
hyperlinking
|
||||
hyperlinks
|
||||
img
|
||||
inlined
|
||||
It'd
|
||||
kje
|
||||
liga
|
||||
lje
|
||||
locl
|
||||
lorem
|
||||
Llast
|
||||
Lmid
|
||||
locl
|
||||
lorem
|
||||
Lorigin
|
||||
maxed
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
noreply
|
||||
nje
|
||||
noreply
|
||||
ogonek
|
||||
ok'd
|
||||
overlined
|
||||
|
|
12
.github/actions/spelling/allow/apis.txt
vendored
12
.github/actions/spelling/allow/apis.txt
vendored
|
@ -1,5 +1,7 @@
|
|||
ACCEPTFILES
|
||||
ACCESSDENIED
|
||||
acl
|
||||
aclapi
|
||||
alignas
|
||||
alignof
|
||||
APPLYTOSUBMENUS
|
||||
|
@ -9,6 +11,7 @@ BUILDBRANCH
|
|||
BUILDMSG
|
||||
BUILDNUMBER
|
||||
BYPOSITION
|
||||
BYCOMMAND
|
||||
charconv
|
||||
CLASSNOTAVAILABLE
|
||||
cmdletbinding
|
||||
|
@ -16,9 +19,11 @@ COLORPROPERTY
|
|||
colspan
|
||||
COMDLG
|
||||
comparand
|
||||
commandlinetoargv
|
||||
cstdint
|
||||
CXICON
|
||||
CYICON
|
||||
Dacl
|
||||
dataobject
|
||||
dcomp
|
||||
DERR
|
||||
|
@ -85,6 +90,7 @@ LSHIFT
|
|||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
memicmp
|
||||
mptt
|
||||
mov
|
||||
|
@ -114,15 +120,19 @@ OSVERSIONINFOEXW
|
|||
otms
|
||||
OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
ptstr
|
||||
rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
schandle
|
||||
semver
|
||||
serializer
|
||||
|
@ -159,6 +169,8 @@ toupper
|
|||
TTask
|
||||
TVal
|
||||
UChar
|
||||
UFIELD
|
||||
ULARGE
|
||||
UPDATEINIFILE
|
||||
userenv
|
||||
wcsstr
|
||||
|
|
1
.github/actions/spelling/allow/names.txt
vendored
1
.github/actions/spelling/allow/names.txt
vendored
|
@ -9,6 +9,7 @@ Diviness
|
|||
dsafa
|
||||
duhowett
|
||||
ekg
|
||||
eryksun
|
||||
ethanschoonover
|
||||
Firefox
|
||||
Gatta
|
||||
|
|
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/runut\.bat$
|
||||
^src/interactivity/onecore/BgfxEngine\.
|
||||
^src/renderer/atlas/
|
||||
^src/renderer/wddmcon/WddmConRenderer\.
|
||||
^src/terminal/adapter/ut_adapter/run\.bat$
|
||||
^src/terminal/parser/delfuzzpayload\.bat$
|
||||
|
|
1
.github/actions/spelling/expect/expect.txt
vendored
1
.github/actions/spelling/expect/expect.txt
vendored
|
@ -508,6 +508,7 @@ dealloc
|
|||
Debian
|
||||
debolden
|
||||
debugtype
|
||||
DECAC
|
||||
DECALN
|
||||
DECANM
|
||||
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.w3.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
|
||||
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.]*
|
||||
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.+]*
|
||||
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
|
||||
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"Microsoft.Net.Component.4.5.TargetingPack",
|
||||
"Microsoft.VisualStudio.Component.DiagnosticTools",
|
||||
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.22000",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
|
||||
"Microsoft.VisualStudio.Component.VC.CoreIde",
|
||||
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
|
||||
|
|
|
@ -99,15 +99,29 @@ If you don't have any additional info/context to add but would like to indicate
|
|||
|
||||
## Contributing fixes / features
|
||||
|
||||
For those able & willing to help fix issues and/or implement features ...
|
||||
If you're able & willing to help fix issues and/or implement features, we'd love your contribution!
|
||||
|
||||
The best place to start is the list of ["Easy Starter"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+label%3A%22Easy+Starter%22+) issues. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue your interested in and hop in!
|
||||
|
||||
Generally, we categorize issues in the following way, which is largely derived from our old internal work tracking system:
|
||||
* ["Bugs"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Bug%22+) are parts of the Terminal & Console that are not quite working the right way. There's code to already support some scenario, but it's not quite working right. Fixing these is generally a matter of debugging the broken functionality and fixing the wrong code.
|
||||
* ["Tasks"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Task%22+) are usually new pieces of functionality that aren't yet implemented for the Terminal/Console. These are usually smaller features, which we believe
|
||||
- could be a single, atomic PR
|
||||
- Don't require much design consideration, or we've already written the spec for the larger feature they belong to.
|
||||
* ["Features"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Feature%22+) are larger pieces of new functionality. These are usually things we believe would require larger discussion of how they should be implemented, or they'll require some complicated new settings. They might just be features that are composed of many individual tasks. Often times, with features, we like to have a spec written before development work is started, to make sure we're all on the same page (see below).
|
||||
|
||||
Bugs and tasks are obviously the easiest to get started with, but don't feel afraid of features either! We've had some community members contribute some amazing "feature"-level work to the Terminal (albeit, with lots of discussion 😄).
|
||||
|
||||
|
||||
Often, we like to assign issues that generally belong to somebody's area of expertise to the team member that owns that area. This doesn't mean the community can't jump in -- they should reach out and have a chat with the assignee to see if it'd okay to take. If an issue's been assigned more than a month ago, there's a good chance it's fair game to try yourself.
|
||||
|
||||
### To Spec or not to Spec
|
||||
|
||||
Some issues/features may be quick and simple to describe and understand. For such scenarios, once a team member has agreed with your approach, skip ahead to the section headed "Fork, Branch, and Create your PR", below.
|
||||
|
||||
Small issues that do not require a spec will be labelled Issue-Bug or Issue-Task.
|
||||
Small issues that do not require a spec will be labelled `Issue-Bug` or `Issue-Task`.
|
||||
|
||||
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled Issue-Feature.
|
||||
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled `Issue-Feature`. More often than not, we'll add such features to the ["Specification Tracker" project](https://github.com/microsoft/terminal/projects/1).
|
||||
|
||||
Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.
|
||||
|
||||
|
|
|
@ -400,6 +400,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests",
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererAtlas", "src\renderer\atlas\atlas.vcxproj", "{8222900C-8B6C-452A-91AC-BE95DB04B95F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
AuditMode|Any CPU = AuditMode|Any CPU
|
||||
|
@ -3339,6 +3341,46 @@ Global
|
|||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.Build.0 = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.ActiveCfg = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.Build.0 = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -3438,6 +3480,7 @@ Global
|
|||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
|
||||
|
|
|
@ -214,7 +214,7 @@ resources useful and interesting:
|
|||
* Windows Terminal Launch: [Build 2019
|
||||
Session](https://www.youtube.com/watch?v=KMudkRcwjCw)
|
||||
* Run As Radio: [Show 645 - Windows Terminal with Richard
|
||||
Turner](http://www.runasradio.com/Shows/Show/645)
|
||||
Turner](https://www.runasradio.com/Shows/Show/645)
|
||||
* Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps
|
||||
on the Windows
|
||||
Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54)
|
||||
|
|
|
@ -63,8 +63,14 @@
|
|||
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
|
||||
DependsOnTargets="_GenerateBranchAndBrandingCache">
|
||||
<MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" />
|
||||
<!-- This commandline is escaped like:
|
||||
|
||||
powershell -Command "&'$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1' -Path '%(FeatureFlagFile.FullPath)'' -Branding $(_WTBrandingName)"
|
||||
|
||||
which was the only way I could find to get it to obey spaces in the SolutionDir
|
||||
-->
|
||||
<Exec
|
||||
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command "$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1" -Path "%(FeatureFlagFile.FullPath)" -Branding $(_WTBrandingName)"
|
||||
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command "&'$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1' -Path '%(FeatureFlagFile.FullPath)' -Branding $(_WTBrandingName)""
|
||||
ConsoleToMsBuild="true"
|
||||
StandardOutputImportance="low">
|
||||
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />
|
||||
|
|
|
@ -22,7 +22,7 @@ Param(
|
|||
[Parameter(HelpMessage="Path to makeappx.exe")]
|
||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||
[string]
|
||||
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86\MakeAppx.exe"
|
||||
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86\MakeAppx.exe"
|
||||
)
|
||||
|
||||
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {
|
||||
|
|
|
@ -8,7 +8,7 @@ Param(
|
|||
[Parameter(HelpMessage="Path to Windows Kit")]
|
||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||
[string]
|
||||
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0"
|
||||
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
|
|
@ -380,7 +380,7 @@ Here's the AppxManifest we're using:
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
</Dependencies>
|
||||
|
@ -517,7 +517,7 @@ This is because of a few key lines we already put in the appxmanifest:
|
|||
|
||||
```xml
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
</Dependencies>
|
||||
|
|
|
@ -1478,6 +1478,11 @@
|
|||
"description": "When set to true, trailing white-spaces will be removed from text in rectangular (block) selection while copied to your clipboard. When set to false, the white-spaces will be preserved.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"trimPaste": {
|
||||
"default": true,
|
||||
"description": "When enabled, the Terminal will automatically trim trailing whitespace characters when pasting text",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.detectURLs": {
|
||||
"default": true,
|
||||
"description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.",
|
||||
|
|
|
@ -268,7 +268,7 @@ Today, if the deserialization of `CascadiaSettings` encounters any errors, an ex
|
|||
To get around this issue, when `CascadiaSettings` encounters a serialization error, it must internally record
|
||||
any pertinent information for that error, and return the simple `CascadiaSettings` as if nothing happened.
|
||||
The consumer must then call `CascadiaSettings::GetErrors()` and `CascadiaSettings::GetWarnings()` to properly
|
||||
understand whether an error ocurred and how to present that to the user.
|
||||
understand whether an error occurred and how to present that to the user.
|
||||
|
||||
|
||||
#### TerminalApp: Loading and Reloading Changes
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>EchoCon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.22000.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
|
@ -163,4 +163,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
|
|
|
@ -118,6 +118,23 @@
|
|||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
BODGY
|
||||
|
||||
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
|
||||
executable we put in the package. But we DON'T produce a winmd. This makes the
|
||||
FastUpToDate check fail every time, and leads to the whole wapproj build
|
||||
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
|
||||
|
||||
Setting GenerateWindowsMetadata=false is enough to tell the build system that
|
||||
we don't produce one, and get it off our backs.
|
||||
-->
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
|
|
|
@ -12,8 +12,30 @@ static_assert(alignof(TextAttribute) == 2);
|
|||
// Ensure that we can memcpy() and memmove() the struct for performance.
|
||||
static_assert(std::is_trivially_copyable_v<TextAttribute>);
|
||||
|
||||
BYTE TextAttribute::s_legacyDefaultForeground = 7;
|
||||
BYTE TextAttribute::s_legacyDefaultBackground = 0;
|
||||
namespace
|
||||
{
|
||||
constexpr std::array<TextColor, 16> s_initLegacyColorMap(const BYTE defaultIndex)
|
||||
{
|
||||
std::array<TextColor, 16> legacyColorMap;
|
||||
for (auto i = 0u; i < legacyColorMap.size(); i++)
|
||||
{
|
||||
const auto legacyIndex = TextColor::TransposeLegacyIndex(i);
|
||||
gsl::at(legacyColorMap, i) = i == defaultIndex ? TextColor{} : TextColor{ legacyIndex, true };
|
||||
}
|
||||
return legacyColorMap;
|
||||
}
|
||||
|
||||
BYTE s_legacyDefaultForeground = 7;
|
||||
BYTE s_legacyDefaultBackground = 0;
|
||||
BYTE s_ansiDefaultForeground = 7;
|
||||
BYTE s_ansiDefaultBackground = 0;
|
||||
}
|
||||
|
||||
// These maps allow for an efficient conversion from a legacy attribute index
|
||||
// to a TextColor with the corresponding ANSI index, also taking into account
|
||||
// the legacy index values that need to be converted to a default TextColor.
|
||||
std::array<TextColor, 16> TextAttribute::s_legacyForegroundColorMap = s_initLegacyColorMap(7);
|
||||
std::array<TextColor, 16> TextAttribute::s_legacyBackgroundColorMap = s_initLegacyColorMap(0);
|
||||
|
||||
// Routine Description:
|
||||
// - Sets the legacy attributes which map to and from the default colors.
|
||||
|
@ -23,8 +45,22 @@ BYTE TextAttribute::s_legacyDefaultBackground = 0;
|
|||
// - None
|
||||
void TextAttribute::SetLegacyDefaultAttributes(const WORD defaultAttributes) noexcept
|
||||
{
|
||||
// First we reset the current default color map entries to what they should
|
||||
// be for a regular translation from a legacy index to an ANSI TextColor.
|
||||
gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{ s_ansiDefaultForeground, true };
|
||||
gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{ s_ansiDefaultBackground, true };
|
||||
|
||||
// Then we save the new default attribute values and their corresponding
|
||||
// ANSI translations. We use the latter values to more efficiently handle
|
||||
// the "VT Quirk" conversion below.
|
||||
s_legacyDefaultForeground = defaultAttributes & FG_ATTRS;
|
||||
s_legacyDefaultBackground = (defaultAttributes & BG_ATTRS) >> 4;
|
||||
s_ansiDefaultForeground = TextColor::TransposeLegacyIndex(s_legacyDefaultForeground);
|
||||
s_ansiDefaultBackground = TextColor::TransposeLegacyIndex(s_legacyDefaultBackground);
|
||||
|
||||
// Finally we set the new default color map entries.
|
||||
gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{};
|
||||
gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{};
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -55,13 +91,13 @@ TextAttribute TextAttribute::StripErroneousVT16VersionsOfLegacyDefaults(const Te
|
|||
const auto bg{ attribute.GetBackground() };
|
||||
auto copy{ attribute };
|
||||
if (fg.IsIndex16() &&
|
||||
attribute.IsBold() == WI_IsFlagSet(s_legacyDefaultForeground, FOREGROUND_INTENSITY) &&
|
||||
fg.GetIndex() == (s_legacyDefaultForeground & ~FOREGROUND_INTENSITY))
|
||||
attribute.IsBold() == WI_IsFlagSet(s_ansiDefaultForeground, FOREGROUND_INTENSITY) &&
|
||||
fg.GetIndex() == (s_ansiDefaultForeground & ~FOREGROUND_INTENSITY))
|
||||
{
|
||||
// We don't want to turn 1;37m into 39m (or even 1;39m), as this was meant to mimic a legacy color.
|
||||
copy.SetDefaultForeground();
|
||||
}
|
||||
if (bg.IsIndex16() && bg.GetIndex() == s_legacyDefaultBackground)
|
||||
if (bg.IsIndex16() && bg.GetIndex() == s_ansiDefaultBackground)
|
||||
{
|
||||
copy.SetDefaultBackground();
|
||||
}
|
||||
|
@ -92,22 +128,22 @@ bool TextAttribute::IsLegacy() const noexcept
|
|||
// - Calculates rgb colors based off of current color table and active modification attributes.
|
||||
// Arguments:
|
||||
// - colorTable: the current color table rgb values.
|
||||
// - defaultFgColor: the default foreground color rgb value.
|
||||
// - defaultBgColor: the default background color rgb value.
|
||||
// - defaultFgIndex: the color table index of the default foreground color.
|
||||
// - defaultBgIndex: the color table index of the default background color.
|
||||
// - reverseScreenMode: true if the screen mode is reversed.
|
||||
// - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false)
|
||||
// - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true)
|
||||
// Return Value:
|
||||
// - the foreground and background colors that should be displayed.
|
||||
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
|
||||
const COLORREF defaultFgColor,
|
||||
const COLORREF defaultBgColor,
|
||||
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
|
||||
const size_t defaultFgIndex,
|
||||
const size_t defaultBgIndex,
|
||||
const bool reverseScreenMode,
|
||||
const bool blinkingIsFaint,
|
||||
const bool boldIsBright) const noexcept
|
||||
{
|
||||
auto fg = _foreground.GetColor(colorTable, defaultFgColor, boldIsBright && IsBold());
|
||||
auto bg = _background.GetColor(colorTable, defaultBgColor);
|
||||
auto fg = _foreground.GetColor(colorTable, defaultFgIndex, boldIsBright && IsBold());
|
||||
auto bg = _background.GetColor(colorTable, defaultBgIndex);
|
||||
if (IsFaint() || (IsBlinking() && blinkingIsFaint))
|
||||
{
|
||||
fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two.
|
||||
|
|
|
@ -41,8 +41,8 @@ public:
|
|||
|
||||
explicit constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
|
||||
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
|
||||
_foreground{ s_LegacyIndexOrDefault(wLegacyAttr & FG_ATTRS, s_legacyDefaultForeground) },
|
||||
_background{ s_LegacyIndexOrDefault((wLegacyAttr & BG_ATTRS) >> 4, s_legacyDefaultBackground) },
|
||||
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
|
||||
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
|
||||
_extendedAttrs{ ExtendedAttributes::Normal },
|
||||
_hyperlinkId{ 0 }
|
||||
{
|
||||
|
@ -64,9 +64,9 @@ public:
|
|||
static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept;
|
||||
WORD GetLegacyAttributes() const noexcept;
|
||||
|
||||
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
|
||||
const COLORREF defaultFgColor,
|
||||
const COLORREF defaultBgColor,
|
||||
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
|
||||
const size_t defaultFgIndex,
|
||||
const size_t defaultBgIndex,
|
||||
const bool reverseScreenMode = false,
|
||||
const bool blinkingIsFaint = false,
|
||||
const bool boldIsBright = true) const noexcept;
|
||||
|
@ -167,13 +167,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
static constexpr TextColor s_LegacyIndexOrDefault(const BYTE requestedIndex, const BYTE defaultIndex)
|
||||
{
|
||||
return requestedIndex == defaultIndex ? TextColor{} : TextColor{ requestedIndex, true };
|
||||
}
|
||||
|
||||
static BYTE s_legacyDefaultForeground;
|
||||
static BYTE s_legacyDefaultBackground;
|
||||
static std::array<TextColor, 16> s_legacyForegroundColorMap;
|
||||
static std::array<TextColor, 16> s_legacyBackgroundColorMap;
|
||||
|
||||
uint16_t _wAttrLegacy; // sizeof: 2, alignof: 2
|
||||
uint16_t _hyperlinkId; // sizeof: 2, alignof: 2
|
||||
|
|
|
@ -32,7 +32,7 @@ constexpr std::array<BYTE, 256> CompressedRgbToIndex16 = {
|
|||
// A table mapping indexed colors from the 256-color palette,
|
||||
// down to one of the 16 colors in the legacy palette.
|
||||
constexpr std::array<BYTE, 256> Index256ToIndex16 = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15,
|
||||
0, 1, 1, 1, 9, 9, 2, 1, 1, 1, 1, 1, 2, 2, 3, 3,
|
||||
3, 3, 2, 2, 11, 11, 3, 3, 10, 10, 11, 11, 11, 11, 10, 10,
|
||||
10, 10, 11, 11, 5, 5, 5, 5, 1, 1, 8, 8, 1, 1, 9, 9,
|
||||
|
@ -139,14 +139,16 @@ void TextColor::SetDefault() noexcept
|
|||
// Arguments:
|
||||
// - colorTable: The table of colors we should use to look up the value of
|
||||
// an indexed attribute from.
|
||||
// - defaultColor: The color value to use if we're a default attribute.
|
||||
// - defaultIndex: The color table index to use if we're a default attribute.
|
||||
// - brighten: if true, we'll brighten a dark color table index.
|
||||
// Return Value:
|
||||
// - a COLORREF containing the real value of this TextColor.
|
||||
COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten) const noexcept
|
||||
COLORREF TextColor::GetColor(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten) const noexcept
|
||||
{
|
||||
if (IsDefault())
|
||||
{
|
||||
const auto defaultColor = til::at(colorTable, defaultIndex);
|
||||
|
||||
if (brighten)
|
||||
{
|
||||
// See MSFT:20266024 for context on this fix.
|
||||
|
@ -252,11 +254,7 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept
|
|||
{
|
||||
return defaultIndex;
|
||||
}
|
||||
else if (IsIndex16())
|
||||
{
|
||||
return GetIndex();
|
||||
}
|
||||
else if (IsIndex256())
|
||||
else if (IsIndex16() || IsIndex256())
|
||||
{
|
||||
return til::at(Index256ToIndex16, GetIndex());
|
||||
}
|
||||
|
|
|
@ -48,6 +48,28 @@ enum class ColorType : BYTE
|
|||
struct TextColor
|
||||
{
|
||||
public:
|
||||
static constexpr BYTE DARK_BLACK = 0;
|
||||
static constexpr BYTE DARK_RED = 1;
|
||||
static constexpr BYTE DARK_GREEN = 2;
|
||||
static constexpr BYTE DARK_YELLOW = 3;
|
||||
static constexpr BYTE DARK_BLUE = 4;
|
||||
static constexpr BYTE DARK_MAGENTA = 5;
|
||||
static constexpr BYTE DARK_CYAN = 6;
|
||||
static constexpr BYTE DARK_WHITE = 7;
|
||||
static constexpr BYTE BRIGHT_BLACK = 8;
|
||||
static constexpr BYTE BRIGHT_RED = 9;
|
||||
static constexpr BYTE BRIGHT_GREEN = 10;
|
||||
static constexpr BYTE BRIGHT_YELLOW = 11;
|
||||
static constexpr BYTE BRIGHT_BLUE = 12;
|
||||
static constexpr BYTE BRIGHT_MAGENTA = 13;
|
||||
static constexpr BYTE BRIGHT_CYAN = 14;
|
||||
static constexpr BYTE BRIGHT_WHITE = 15;
|
||||
|
||||
static constexpr size_t DEFAULT_FOREGROUND = 256;
|
||||
static constexpr size_t DEFAULT_BACKGROUND = 257;
|
||||
static constexpr size_t CURSOR_COLOR = 258;
|
||||
static constexpr size_t TABLE_SIZE = 259;
|
||||
|
||||
constexpr TextColor() noexcept :
|
||||
_meta{ ColorType::IsDefault },
|
||||
_red{ 0 },
|
||||
|
@ -86,7 +108,7 @@ public:
|
|||
void SetIndex(const BYTE index, const bool isIndex256) noexcept;
|
||||
void SetDefault() noexcept;
|
||||
|
||||
COLORREF GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten = false) const noexcept;
|
||||
COLORREF GetColor(const std::array<COLORREF, TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten = false) const noexcept;
|
||||
BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept;
|
||||
|
||||
constexpr BYTE GetIndex() const noexcept
|
||||
|
@ -96,6 +118,16 @@ public:
|
|||
|
||||
COLORREF GetRGB() const noexcept;
|
||||
|
||||
static constexpr BYTE TransposeLegacyIndex(const size_t index)
|
||||
{
|
||||
// When converting a 16-color index in the legacy Windows order to or
|
||||
// from an ANSI-compatible order, we need to swap the bits in positions
|
||||
// 0 and 2. We do this by XORing the index with 00000101, but only if
|
||||
// one (but not both) of those bit positions is set.
|
||||
const auto oneBitSet = (index ^ (index >> 2)) & 1;
|
||||
return gsl::narrow_cast<BYTE>(index ^ oneBitSet ^ (oneBitSet << 2));
|
||||
}
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
|
|
|
@ -27,9 +27,7 @@ Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
|
|||
_fDeferCursorRedraw(false),
|
||||
_fHaveDeferredCursorRedraw(false),
|
||||
_ulSize(ulSize),
|
||||
_cursorType(CursorType::Legacy),
|
||||
_fUseColor(false),
|
||||
_color(s_InvertCursorColor)
|
||||
_cursorType(CursorType::Legacy)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -143,10 +141,9 @@ void Cursor::SetSize(const ULONG ulSize) noexcept
|
|||
_RedrawCursor();
|
||||
}
|
||||
|
||||
void Cursor::SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept
|
||||
void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept
|
||||
{
|
||||
_ulSize = ulSize;
|
||||
_color = color;
|
||||
_cursorType = type;
|
||||
|
||||
_RedrawCursor();
|
||||
|
@ -285,7 +282,6 @@ void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
|
|||
// Size will be handled separately in the resize operation.
|
||||
//_ulSize = OtherCursor._ulSize;
|
||||
_cursorType = OtherCursor._cursorType;
|
||||
_color = OtherCursor._color;
|
||||
}
|
||||
|
||||
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
|
||||
|
@ -335,21 +331,6 @@ const CursorType Cursor::GetType() const noexcept
|
|||
return _cursorType;
|
||||
}
|
||||
|
||||
const bool Cursor::IsUsingColor() const noexcept
|
||||
{
|
||||
return GetColor() != INVALID_COLOR;
|
||||
}
|
||||
|
||||
const COLORREF Cursor::GetColor() const noexcept
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
void Cursor::SetColor(const unsigned int color) noexcept
|
||||
{
|
||||
_color = gsl::narrow_cast<COLORREF>(color);
|
||||
}
|
||||
|
||||
void Cursor::SetType(const CursorType type) noexcept
|
||||
{
|
||||
_cursorType = type;
|
||||
|
|
|
@ -24,7 +24,6 @@ class TextBuffer;
|
|||
class Cursor final
|
||||
{
|
||||
public:
|
||||
static const unsigned int s_InvertCursorColor = INVALID_COLOR;
|
||||
// the following values are used to create the textmode cursor.
|
||||
static constexpr unsigned int CURSOR_SMALL_SIZE = 25; // large enough to be one pixel on a six pixel font
|
||||
|
||||
|
@ -51,8 +50,6 @@ public:
|
|||
COORD GetPosition() const noexcept;
|
||||
|
||||
const CursorType GetType() const noexcept;
|
||||
const bool IsUsingColor() const noexcept;
|
||||
const COLORREF GetColor() const noexcept;
|
||||
|
||||
void StartDeferDrawing() noexcept;
|
||||
bool IsDeferDrawing() noexcept;
|
||||
|
@ -67,7 +64,7 @@ public:
|
|||
void SetIsPopupShown(const bool fIsPopupShown) noexcept;
|
||||
void SetDelay(const bool fDelay) noexcept;
|
||||
void SetSize(const ULONG ulSize) noexcept;
|
||||
void SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept;
|
||||
void SetStyle(const ULONG ulSize, const CursorType type) noexcept;
|
||||
|
||||
void SetPosition(const COORD cPosition) noexcept;
|
||||
void SetXPosition(const int NewX) noexcept;
|
||||
|
@ -84,7 +81,6 @@ public:
|
|||
COORD GetDelayedAtPosition() const noexcept;
|
||||
bool IsDelayedEOLWrap() const noexcept;
|
||||
|
||||
void SetColor(const unsigned int color) noexcept;
|
||||
void SetType(const CursorType type) noexcept;
|
||||
|
||||
private:
|
||||
|
@ -117,6 +113,4 @@ private:
|
|||
void _RedrawCursorAlways() noexcept;
|
||||
|
||||
CursorType _cursorType;
|
||||
bool _fUseColor;
|
||||
COLORREF _color;
|
||||
};
|
||||
|
|
|
@ -24,9 +24,11 @@ class TextAttributeTests
|
|||
TEST_METHOD(TestRoundtripDefaultColors);
|
||||
TEST_METHOD(TestBoldAsBright);
|
||||
|
||||
std::array<COLORREF, 256> _colorTable;
|
||||
COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||
const COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
const COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
|
||||
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
|
||||
};
|
||||
|
||||
bool TextAttributeTests::ClassSetup()
|
||||
|
@ -47,6 +49,8 @@ bool TextAttributeTests::ClassSetup()
|
|||
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
|
||||
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
|
||||
_colorTable[15] = RGB(242, 242, 242); // White
|
||||
_colorTable[_defaultFgIndex] = _defaultFg;
|
||||
_colorTable[_defaultBgIndex] = _defaultBg;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -132,17 +136,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
|||
// values when reverse video is not set
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// reset the reverse video
|
||||
attr.SetReverseVideo(false);
|
||||
|
@ -151,17 +155,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
|||
// while the background and getters stay the same
|
||||
attr.SetFaint(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched, and the background fainter, while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// reset the reverse video and faint attributes
|
||||
attr.SetReverseVideo(false);
|
||||
|
@ -171,17 +175,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
|||
// background, while getters stay the same
|
||||
attr.SetInvisible(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// with reverse video set, the calculated background value should match
|
||||
// the foreground, while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
}
|
||||
|
||||
void TextAttributeTests::TestReverseDefaultColors()
|
||||
|
@ -194,34 +198,34 @@ void TextAttributeTests::TestReverseDefaultColors()
|
|||
// values when reverse video is not set
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
attr.SetForeground(red);
|
||||
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
|
||||
attr.Invert();
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
attr.SetDefaultForeground();
|
||||
attr.SetBackground(green);
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
|
||||
}
|
||||
|
||||
void TextAttributeTests::TestRoundtripDefaultColors()
|
||||
|
@ -237,7 +241,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
|
|||
Log::Comment(L"Foreground legacy default index should map to default text color.");
|
||||
legacyAttribute = fgLegacyDefault | BACKGROUND_GREEN;
|
||||
textAttribute.SetDefaultForeground();
|
||||
textAttribute.SetIndexedBackground256(BACKGROUND_GREEN >> 4);
|
||||
textAttribute.SetIndexedBackground256(TextColor::DARK_GREEN);
|
||||
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
|
||||
|
||||
Log::Comment(L"Default foreground text color should map back to legacy default index.");
|
||||
|
@ -245,7 +249,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
|
|||
|
||||
Log::Comment(L"Background legacy default index should map to default text color.");
|
||||
legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault;
|
||||
textAttribute.SetIndexedForeground256(FOREGROUND_GREEN);
|
||||
textAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
|
||||
textAttribute.SetDefaultBackground();
|
||||
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
|
||||
|
||||
|
@ -277,43 +281,43 @@ void TextAttributeTests::TestBoldAsBright()
|
|||
// values when not bold
|
||||
VERIFY_IS_FALSE(attr.IsBold());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
// with bold set, calculated foreground/background values shouldn't change for the default colors.
|
||||
attr.SetBold(true);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
attr.SetIndexedForeground(0);
|
||||
attr.SetIndexedForeground(TextColor::DARK_BLACK);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
|
||||
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
|
||||
Log::Comment(L"Foreground should be dark black when bold is bright is disabled");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
attr.SetIndexedBackground(2);
|
||||
attr.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
|
||||
Log::Comment(L"background should be unaffected by 'bold is bright'");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
attr.SetBold(false);
|
||||
VERIFY_IS_FALSE(attr.IsBold());
|
||||
Log::Comment(L"when not bold, 'bold is bright' changes nothing");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
|
||||
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
|
||||
attr.SetBold(true);
|
||||
attr.SetIndexedForeground(8);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
|
||||
}
|
||||
|
|
|
@ -23,9 +23,11 @@ class TextColorTests
|
|||
TEST_METHOD(TestRgbColor);
|
||||
TEST_METHOD(TestChangeColor);
|
||||
|
||||
std::array<COLORREF, 256> _colorTable;
|
||||
COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||
const COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
const COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
|
||||
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
|
||||
};
|
||||
|
||||
bool TextColorTests::ClassSetup()
|
||||
|
@ -46,6 +48,8 @@ bool TextColorTests::ClassSetup()
|
|||
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
|
||||
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
|
||||
_colorTable[15] = RGB(242, 242, 242); // White
|
||||
_colorTable[_defaultFgIndex] = _defaultFg;
|
||||
_colorTable[_defaultBgIndex] = _defaultBg;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -57,16 +61,16 @@ void TextColorTests::TestDefaultColor()
|
|||
VERIFY_IS_FALSE(defaultColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(defaultColor.IsRgb());
|
||||
|
||||
auto color = defaultColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = defaultColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = defaultColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
}
|
||||
|
||||
|
@ -78,16 +82,16 @@ void TextColorTests::TestDarkIndexColor()
|
|||
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(indexColor.IsRgb());
|
||||
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
||||
|
@ -99,16 +103,16 @@ void TextColorTests::TestBrightIndexColor()
|
|||
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(indexColor.IsRgb());
|
||||
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
||||
|
@ -121,16 +125,16 @@ void TextColorTests::TestRgbColor()
|
|||
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
||||
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
||||
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
}
|
||||
|
||||
|
@ -143,55 +147,55 @@ void TextColorTests::TestChangeColor()
|
|||
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
||||
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
||||
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
rgbColor.SetDefault();
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
rgbColor.SetIndex(7, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
rgbColor.SetIndex(15, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
|
|
@ -61,13 +61,26 @@
|
|||
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
|
||||
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WindowsTerminal\WindowsTerminal.vcxproj" />
|
||||
<ProjectReference Include="..\..\host\exe\Host.EXE.vcxproj" />
|
||||
<ProjectReference Include="..\..\host\proxy\Host.Proxy.vcxproj" />
|
||||
<ProjectReference Include="..\TerminalAzBridge\TerminalAzBridge.vcxproj" />
|
||||
<ProjectReference Include="..\ShellExtension\WindowsTerminalShellExt.vcxproj" />
|
||||
<ProjectReference Include="..\wt\wt.vcxproj" />
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj">
|
||||
<Project>{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj">
|
||||
<Project>{067F0A06-FCB7-472C-96E9-B03B54E8E18D}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj">
|
||||
<Project>{f2ed628a-db22-446f-a081-4cc845b51a2b}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\wt\wt.vcxproj">
|
||||
<Project>{506fd703-baa7-4f6e-9361-64f550ec8fca}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\host\exe\Host.EXE.vcxproj">
|
||||
<Project>{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\host\proxy\Host.Proxy.vcxproj">
|
||||
<Project>{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace SettingsModelLocalTests
|
|||
|
||||
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
|
||||
const auto campbellSpan = gsl::make_span(expectedCampbellTable);
|
||||
Utils::InitializeCampbellColorTable(campbellSpan);
|
||||
Utils::InitializeColorTable(campbellSpan);
|
||||
Utils::SetColorTableAlpha(campbellSpan, 0);
|
||||
|
||||
for (size_t i = 0; i < expectedCampbellTable.size(); i++)
|
||||
|
|
|
@ -508,7 +508,7 @@ namespace TerminalAppLocalTests
|
|||
|
||||
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
|
@ -526,7 +526,7 @@ namespace TerminalAppLocalTests
|
|||
|
||||
Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
|
@ -844,7 +844,7 @@ namespace TerminalAppLocalTests
|
|||
// | 1 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Right, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
secondId = tab->_activePane->Id().value();
|
||||
});
|
||||
Sleep(250);
|
||||
|
@ -862,7 +862,7 @@ namespace TerminalAppLocalTests
|
|||
// | 3 | |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
// Split again to make the 3rd tab
|
||||
thirdId = tab->_activePane->Id().value();
|
||||
|
@ -882,7 +882,7 @@ namespace TerminalAppLocalTests
|
|||
// | 3 | 4 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
|
||||
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
fourthId = tab->_activePane->Id().value();
|
||||
});
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
|
||||
</Dependencies>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<uap:SupportedUsers>multiple</uap:SupportedUsers>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
|
|
|
@ -239,8 +239,8 @@ HRESULT HwndTerminal::Initialize()
|
|||
_terminal->SetBackgroundCallback([](auto) {});
|
||||
|
||||
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
|
||||
_terminal->SetDefaultBackground(RGB(12, 12, 12));
|
||||
_terminal->SetDefaultForeground(RGB(204, 204, 204));
|
||||
_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12));
|
||||
_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204));
|
||||
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
|
||||
localPointerToThread->EnablePainting();
|
||||
|
||||
|
@ -781,8 +781,8 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
|
|||
{
|
||||
auto lock = publicTerminal->_terminal->LockForWriting();
|
||||
|
||||
publicTerminal->_terminal->SetDefaultForeground(theme.DefaultForeground);
|
||||
publicTerminal->_terminal->SetDefaultBackground(theme.DefaultBackground);
|
||||
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground);
|
||||
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground);
|
||||
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha);
|
||||
|
||||
// Set the font colors
|
||||
|
@ -977,7 +977,7 @@ void HwndTerminal::_StringPaste(const wchar_t* const pData) noexcept
|
|||
CATCH_LOG();
|
||||
}
|
||||
|
||||
COORD HwndTerminal::GetFontSize() const
|
||||
COORD HwndTerminal::GetFontSize() const noexcept
|
||||
{
|
||||
return _actualFont.GetSize();
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ private:
|
|||
void _SendCharEvent(wchar_t ch, WORD scanCode, WORD flags) noexcept;
|
||||
|
||||
// Inherited via IControlAccessibilityInfo
|
||||
COORD GetFontSize() const override;
|
||||
COORD GetFontSize() const noexcept override;
|
||||
RECT GetBounds() const noexcept override;
|
||||
double GetScaleFactor() const noexcept override;
|
||||
void ChangeViewport(const SMALL_RECT NewWindow) override;
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
<ProjectReference Include="$(SolutionDir)src\types\lib\types.vcxproj">
|
||||
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)src\renderer\atlas\atlas.vcxproj">
|
||||
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)src\renderer\base\lib\base.vcxproj">
|
||||
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
||||
</ProjectReference>
|
||||
|
|
|
@ -174,10 +174,9 @@ namespace winrt::TerminalApp::implementation
|
|||
else if (const auto& realArgs = args.ActionArgs().try_as<SplitPaneArgs>())
|
||||
{
|
||||
_SplitPane(realArgs.SplitDirection(),
|
||||
realArgs.SplitMode(),
|
||||
// This is safe, we're already filtering so the value is (0, 1)
|
||||
::base::saturated_cast<float>(realArgs.SplitSize()),
|
||||
realArgs.TerminalArgs());
|
||||
_MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +555,7 @@ namespace winrt::TerminalApp::implementation
|
|||
auto actions = winrt::single_threaded_vector<ActionAndArgs>(std::move(
|
||||
TerminalPage::ConvertExecuteCommandlineToActions(realArgs)));
|
||||
|
||||
if (_startupActions.Size() != 0)
|
||||
if (actions.Size() != 0)
|
||||
{
|
||||
actionArgs.Handled(true);
|
||||
ProcessStartupActions(actions, false);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <WtExeUtils.h>
|
||||
#include <wil/token_helpers.h >
|
||||
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
using namespace winrt::Windows::ApplicationModel;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
@ -131,38 +133,6 @@ static Documents::Run _BuildErrorRun(const winrt::hstring& text, const ResourceD
|
|||
return textRun;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns whether the user is either a member of the Administrators group or
|
||||
// is currently elevated.
|
||||
// - This will return **FALSE** if the user has UAC disabled entirely, because
|
||||
// there's no separation of power between the user and an admin in that case.
|
||||
// Return Value:
|
||||
// - true if the user is an administrator
|
||||
static bool _isUserAdmin() noexcept
|
||||
try
|
||||
{
|
||||
wil::unique_handle processToken{ GetCurrentProcessToken() };
|
||||
const auto elevationType = wil::get_token_information<TOKEN_ELEVATION_TYPE>(processToken.get());
|
||||
const auto elevationState = wil::get_token_information<TOKEN_ELEVATION>(processToken.get());
|
||||
if (elevationType == TokenElevationTypeDefault && elevationState.TokenIsElevated)
|
||||
{
|
||||
// In this case, the user has UAC entirely disabled. This is sort of
|
||||
// weird, we treat this like the user isn't an admin at all. There's no
|
||||
// separation of powers, so the things we normally want to gate on
|
||||
// "having special powers" doesn't apply.
|
||||
//
|
||||
// See GH#7754, GH#11096
|
||||
return false;
|
||||
}
|
||||
|
||||
return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Function Description:
|
||||
|
@ -214,7 +184,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// The TerminalPage has to be constructed during our construction, to
|
||||
// make sure that there's a terminal page for callers of
|
||||
// SetTitleBarContent
|
||||
_isElevated = _isUserAdmin();
|
||||
_isElevated = ::Microsoft::Console::Utils::IsElevated();
|
||||
_root = winrt::make_self<TerminalPage>();
|
||||
|
||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||
|
@ -334,6 +304,9 @@ namespace winrt::TerminalApp::implementation
|
|||
_RefreshThemeRoutine();
|
||||
_ApplyStartupTaskStateChange();
|
||||
|
||||
auto args = winrt::make_self<SystemMenuChangeArgs>(RS_(L"SettingsMenuItem"), SystemMenuChangeAction::Add, SystemMenuItemHandler(this, &AppLogic::_OpenSettingsUI));
|
||||
_SystemMenuChangeRequestedHandlers(*this, *args);
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"AppCreated",
|
||||
|
@ -907,8 +880,6 @@ namespace winrt::TerminalApp::implementation
|
|||
void AppLogic::_RegisterSettingsChange()
|
||||
{
|
||||
const std::filesystem::path settingsPath{ std::wstring_view{ CascadiaSettings::SettingsPath() } };
|
||||
const std::filesystem::path statePath{ std::wstring_view{ ApplicationState::SharedInstance().FilePath() } };
|
||||
|
||||
_reader.create(
|
||||
settingsPath.parent_path().c_str(),
|
||||
false,
|
||||
|
@ -917,14 +888,29 @@ namespace winrt::TerminalApp::implementation
|
|||
// editors, who will write a temp file, then rename it to be the
|
||||
// actual file you wrote. So listen for that too.
|
||||
wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime,
|
||||
[this, settingsBasename = settingsPath.filename(), stateBasename = statePath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
|
||||
const auto modifiedBasename = std::filesystem::path{ fileModified }.filename();
|
||||
[this, settingsBasename = settingsPath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
|
||||
// DO NOT create a static reference to ApplicationState::SharedInstance here.
|
||||
//
|
||||
// ApplicationState::SharedInstance already caches its own
|
||||
// static ref. If _we_ keep a static ref to the member in
|
||||
// AppState, then our reference will keep ApplicationState alive
|
||||
// after the `ActionToStringMap` gets cleaned up. Then, when we
|
||||
// try to persist the actions in the window state, we won't be
|
||||
// able to. We'll try to look up the action and the map just
|
||||
// won't exist. We'll explode, even though the Terminal is
|
||||
// tearing down anyways. So we'll just die, but still invoke
|
||||
// WinDBG's post-mortem debugger, who won't be able to attach to
|
||||
// the process that's already exiting.
|
||||
//
|
||||
// So DON'T ~give a mouse a cookie~ take a static ref here.
|
||||
|
||||
const winrt::hstring modifiedBasename{ std::filesystem::path{ fileModified }.filename().c_str() };
|
||||
|
||||
if (modifiedBasename == settingsBasename)
|
||||
{
|
||||
_reloadSettings->Run();
|
||||
}
|
||||
else if (modifiedBasename == stateBasename)
|
||||
else if (ApplicationState::SharedInstance().IsStatePath(modifiedBasename))
|
||||
{
|
||||
_reloadState();
|
||||
}
|
||||
|
@ -1051,6 +1037,11 @@ namespace winrt::TerminalApp::implementation
|
|||
_SettingsChangedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
void AppLogic::_OpenSettingsUI()
|
||||
{
|
||||
_root->OpenSettingsUI();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns a pointer to the global shared settings.
|
||||
[[nodiscard]] CascadiaSettings AppLogic::GetSettings() const noexcept
|
||||
|
@ -1557,6 +1548,11 @@ namespace winrt::TerminalApp::implementation
|
|||
return _root->IsQuakeWindow();
|
||||
}
|
||||
|
||||
void AppLogic::RequestExitFullscreen()
|
||||
{
|
||||
_root->SetFullscreen(false);
|
||||
}
|
||||
|
||||
bool AppLogic::GetMinimizeToNotificationArea()
|
||||
{
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "AppLogic.g.h"
|
||||
#include "FindTargetWindowResult.g.h"
|
||||
#include "SystemMenuChangeArgs.g.h"
|
||||
#include "Jumplist.h"
|
||||
#include "LanguageProfileNotifier.h"
|
||||
#include "TerminalPage.h"
|
||||
|
@ -35,6 +36,17 @@ namespace winrt::TerminalApp::implementation
|
|||
FindTargetWindowResult(id, L""){};
|
||||
};
|
||||
|
||||
struct SystemMenuChangeArgs : SystemMenuChangeArgsT<SystemMenuChangeArgs>
|
||||
{
|
||||
WINRT_PROPERTY(winrt::hstring, Name, L"");
|
||||
WINRT_PROPERTY(SystemMenuChangeAction, Action, SystemMenuChangeAction::Add);
|
||||
WINRT_PROPERTY(SystemMenuItemHandler, Handler, nullptr);
|
||||
|
||||
public:
|
||||
SystemMenuChangeArgs(const winrt::hstring& name, SystemMenuChangeAction action, SystemMenuItemHandler handler = nullptr) :
|
||||
_Name{ name }, _Action{ action }, _Handler{ handler } {};
|
||||
};
|
||||
|
||||
struct AppLogic : AppLogicT<AppLogic, IInitializeWithWindow>
|
||||
{
|
||||
public:
|
||||
|
@ -79,6 +91,7 @@ namespace winrt::TerminalApp::implementation
|
|||
void SetPersistedLayoutIdx(const uint32_t idx);
|
||||
void SetNumberOfOpenWindows(const uint64_t num);
|
||||
bool IsQuakeWindow() const noexcept;
|
||||
void RequestExitFullscreen();
|
||||
|
||||
Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
|
||||
bool CenterOnLaunch();
|
||||
|
@ -113,6 +126,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// -------------------------------- WinRT Events ---------------------------------
|
||||
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
|
||||
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs);
|
||||
|
||||
private:
|
||||
bool _isUwp{ false };
|
||||
|
@ -163,6 +177,7 @@ namespace winrt::TerminalApp::implementation
|
|||
void _RegisterSettingsChange();
|
||||
fire_and_forget _DispatchReloadSettings();
|
||||
void _ReloadSettings();
|
||||
void _OpenSettingsUI();
|
||||
|
||||
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);
|
||||
|
||||
|
|
|
@ -19,6 +19,20 @@ namespace TerminalApp
|
|||
String WindowName { get; };
|
||||
};
|
||||
|
||||
delegate void SystemMenuItemHandler();
|
||||
|
||||
enum SystemMenuChangeAction
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SystemMenuChangeArgs {
|
||||
String Name { get; };
|
||||
SystemMenuChangeAction Action { get; };
|
||||
SystemMenuItemHandler Handler { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter
|
||||
{
|
||||
AppLogic();
|
||||
|
@ -60,6 +74,7 @@ namespace TerminalApp
|
|||
void SetPersistedLayoutIdx(UInt32 idx);
|
||||
void SetNumberOfOpenWindows(UInt64 num);
|
||||
void RenameFailed();
|
||||
void RequestExitFullscreen();
|
||||
Boolean IsQuakeWindow();
|
||||
|
||||
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
|
||||
|
@ -110,5 +125,6 @@ namespace TerminalApp
|
|||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2351,35 +2351,32 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Split the focused pane in our tree of panes, and place the given
|
||||
// TermControl into the newly created pane. If we're the focused pane, then
|
||||
// we'll create two new children, and place them side-by-side in our Grid.
|
||||
// - The same as above, except this takes in the pane directly instead of a
|
||||
// profile and control to make a pane with
|
||||
// Arguments:
|
||||
// - splitType: what type of split we want to create.
|
||||
// - profile: The profile to associate with the newly created pane.
|
||||
// - control: A TermControl to use in the new pane.
|
||||
// - splitSize: the desired size of the split
|
||||
// - newPane: the new pane
|
||||
// Return Value:
|
||||
// - The two newly created Panes, with the original pane first
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const Profile& profile,
|
||||
const TermControl& control)
|
||||
std::shared_ptr<Pane> newPane)
|
||||
{
|
||||
if (!_lastActive)
|
||||
{
|
||||
if (_firstChild && _firstChild->_HasFocusedChild())
|
||||
{
|
||||
return _firstChild->Split(splitType, splitSize, profile, control);
|
||||
return _firstChild->Split(splitType, splitSize, newPane);
|
||||
}
|
||||
else if (_secondChild && _secondChild->_HasFocusedChild())
|
||||
{
|
||||
return _secondChild->Split(splitType, splitSize, profile, control);
|
||||
return _secondChild->Split(splitType, splitSize, newPane);
|
||||
}
|
||||
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
auto newPane = std::make_shared<Pane>(profile, control);
|
||||
return _Split(splitType, splitSize, newPane);
|
||||
}
|
||||
|
||||
|
|
|
@ -110,8 +110,7 @@ public:
|
|||
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
std::shared_ptr<Pane> pane);
|
||||
bool ToggleSplitOrientation();
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace winrt::TerminalApp::implementation
|
|||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
|
||||
|
||||
_CreateNewTabWithProfileAndSettings(profile, settings, existingConnection);
|
||||
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection));
|
||||
|
||||
const uint32_t tabCount = _tabs.Size();
|
||||
const bool usedManualProfile = (newTerminalArgs != nullptr) &&
|
||||
|
@ -244,58 +244,6 @@ namespace winrt::TerminalApp::implementation
|
|||
_InitializeTab(newTabImpl);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates a new tab with the given settings. If the tab bar is not being
|
||||
// currently displayed, it will be shown.
|
||||
// Arguments:
|
||||
// - profile: profile settings for this connection
|
||||
// - settings: the TerminalSettings object to use to create the TerminalControl with.
|
||||
// - existingConnection: optionally receives a connection from the outside world instead of attempting to create one
|
||||
void TerminalPage::_CreateNewTabWithProfileAndSettings(const Profile& profile, const TerminalSettingsCreateResult& settings, TerminalConnection::ITerminalConnection existingConnection)
|
||||
{
|
||||
// Initialize the new tab
|
||||
// Create a connection based on the values in our settings object if we weren't given one.
|
||||
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, settings.DefaultSettings());
|
||||
|
||||
// If we had an `existingConnection`, then this is an inbound handoff from somewhere else.
|
||||
// We need to tell it about our size information so it can match the dimensions of what
|
||||
// we are about to present.
|
||||
if (existingConnection)
|
||||
{
|
||||
connection.Resize(settings.DefaultSettings().InitialRows(), settings.DefaultSettings().InitialCols());
|
||||
}
|
||||
|
||||
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
|
||||
if (_settings.GlobalSettings().DebugFeaturesEnabled())
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
||||
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
||||
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
if (bothAltsPressed)
|
||||
{
|
||||
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
// Give term control a child of the settings so that any overrides go in the child
|
||||
// This way, when we do a settings reload we just update the parent and the overrides remain
|
||||
auto term = _InitControl(settings, connection);
|
||||
|
||||
auto newTabImpl = winrt::make_self<TerminalTab>(profile, term);
|
||||
_RegisterTerminalEvents(term);
|
||||
_InitializeTab(newTabImpl);
|
||||
|
||||
if (debugConnection) // this will only be set if global debugging is on and tap is active
|
||||
{
|
||||
auto newControl = _InitControl(settings, debugConnection);
|
||||
_RegisterTerminalEvents(newControl);
|
||||
// Split (auto) with the debug tap.
|
||||
newTabImpl->SplitPane(SplitDirection::Automatic, 0.5f, profile, newControl);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the icon of the currently focused terminal control, and set its
|
||||
// tab's icon to that icon.
|
||||
|
@ -365,28 +313,14 @@ namespace winrt::TerminalApp::implementation
|
|||
// In the future, it may be preferable to just duplicate the
|
||||
// current control's live settings (which will include changes
|
||||
// made through VT).
|
||||
_CreateNewTabFromPane(_MakePane(nullptr, true, nullptr));
|
||||
|
||||
if (auto profile = tab.GetFocusedProfile())
|
||||
const auto runtimeTabText{ tab.GetTabText() };
|
||||
if (!runtimeTabText.empty())
|
||||
{
|
||||
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
||||
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
||||
const auto settingsCreateResult{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
|
||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
||||
if (validWorkingDirectory)
|
||||
if (auto newTab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
settingsCreateResult.DefaultSettings().StartingDirectory(workingDirectory);
|
||||
}
|
||||
|
||||
_CreateNewTabWithProfileAndSettings(profile, settingsCreateResult);
|
||||
|
||||
const auto runtimeTabText{ tab.GetTabText() };
|
||||
if (!runtimeTabText.empty())
|
||||
{
|
||||
if (auto newTab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
newTab->SetTabText(runtimeTabText);
|
||||
}
|
||||
newTab->SetTabText(runtimeTabText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +336,7 @@ namespace winrt::TerminalApp::implementation
|
|||
try
|
||||
{
|
||||
_SetFocusedTab(tab);
|
||||
_SplitPane(tab, SplitDirection::Automatic, SplitType::Duplicate);
|
||||
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
|
|
@ -318,7 +318,29 @@
|
|||
</ProjectReference>
|
||||
<!-- For whatever reason, we can't include the TerminalControl and
|
||||
TerminalSettings projects' winmds via project references. So we'll have to
|
||||
manually include the winmds as References below -->
|
||||
manually include the winmds as References below
|
||||
|
||||
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
|
||||
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
|
||||
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
|
||||
Up-to-date Check will look for the .xaml files from that project in our
|
||||
output, which won't actually be there.
|
||||
|
||||
We do still need to separately reference the winmds manually below, which is annoying.
|
||||
-->
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
|
||||
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
|
||||
the manual reference to TerminalControl.winmd below make sure that this
|
||||
project will compile correct, and that we won't roll up the TermControl
|
||||
xbf's into the packaging project twice. -->
|
||||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj">
|
||||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- This is a hack to get the ARM64 CI build working. See
|
||||
|
|
|
@ -3,38 +3,38 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "TerminalPage.h"
|
||||
#include "Utils.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "TerminalPage.g.cpp"
|
||||
#include "RenameWindowRequestedArgs.g.cpp"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <inc/WindowingBehavior.h>
|
||||
#include <LibraryResources.h>
|
||||
#include <TerminalCore/ControlKeyStates.hpp>
|
||||
#include <til/latch.h>
|
||||
|
||||
#include "TerminalPage.g.cpp"
|
||||
#include <winrt/Windows.Storage.h>
|
||||
|
||||
#include "TabRowControl.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "ColorHelper.h"
|
||||
#include "DebugTapConnection.h"
|
||||
#include "SettingsTab.h"
|
||||
#include "RenameWindowRequestedArgs.g.cpp"
|
||||
#include "../inc/WindowingBehavior.h"
|
||||
|
||||
#include <til/latch.h>
|
||||
#include "TabRowControl.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace ::TerminalApp;
|
||||
using namespace ::Microsoft::Console;
|
||||
using namespace ::Microsoft::Terminal::Core;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });
|
||||
|
@ -300,10 +300,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - true if the ApplicationState should be used.
|
||||
bool TerminalPage::ShouldUsePersistedLayout(CascadiaSettings& settings) const
|
||||
{
|
||||
// GH#5000 Until there is a separate state file for elevated sessions we should just not
|
||||
// save at all while in an elevated window.
|
||||
return Feature_PersistedWindowLayout::IsEnabled() &&
|
||||
!IsElevated() &&
|
||||
settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout;
|
||||
}
|
||||
|
||||
|
@ -850,14 +847,7 @@ namespace winrt::TerminalApp::implementation
|
|||
WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
|
||||
if (altPressed && !debugTap)
|
||||
{
|
||||
this->_SplitPane(SplitDirection::Automatic,
|
||||
SplitType::Manual,
|
||||
0.5f,
|
||||
newTerminalArgs);
|
||||
}
|
||||
else if (shiftPressed && !debugTap)
|
||||
if (shiftPressed && !debugTap)
|
||||
{
|
||||
// Manually fill in the evaluated profile.
|
||||
if (newTerminalArgs.ProfileIndex() != nullptr)
|
||||
|
@ -873,7 +863,17 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_IF_FAILED(this->_OpenNewTab(newTerminalArgs));
|
||||
const auto newPane = _MakePane(newTerminalArgs);
|
||||
if (altPressed && !debugTap)
|
||||
{
|
||||
this->_SplitPane(SplitDirection::Automatic,
|
||||
0.5f,
|
||||
newPane);
|
||||
}
|
||||
else
|
||||
{
|
||||
_CreateNewTabFromPane(newPane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1038,29 +1038,153 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// Called when the users pressed keyBindings while CommandPalette is open.
|
||||
// - Called when the users pressed keyBindings while CommandPalette is open.
|
||||
// - This method is effectively an extract of TermControl::_KeyHandler and TermControl::_TryHandleKeyBinding.
|
||||
// Arguments:
|
||||
// - e: the KeyRoutedEventArgs containing info about the keystroke.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
|
||||
{
|
||||
const auto key = e.OriginalKey();
|
||||
const auto scanCode = e.KeyStatus().ScanCode;
|
||||
const auto coreWindow = CoreWindow::GetForCurrentThread();
|
||||
const auto ctrlDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
|
||||
const auto altDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
|
||||
const auto shiftDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
|
||||
const auto keyStatus = e.KeyStatus();
|
||||
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey());
|
||||
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||
const auto modifiers = _GetPressedModifierKeys();
|
||||
|
||||
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, false, static_cast<int32_t>(key), static_cast<int32_t>(scanCode) };
|
||||
if (const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) })
|
||||
// GH#11076:
|
||||
// For some weird reason we sometimes receive a WM_KEYDOWN
|
||||
// message without vkey or scanCode if a user drags a tab.
|
||||
// The KeyChord constructor has a debug assertion ensuring that all KeyChord
|
||||
// either have a valid vkey/scanCode. This is important, because this prevents
|
||||
// accidential insertion of invalid KeyChords into classes like ActionMap.
|
||||
if (!vkey && !scanCode)
|
||||
{
|
||||
if (CommandPalette().Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
return;
|
||||
}
|
||||
|
||||
// Alt-Numpad# input will send us a character once the user releases
|
||||
// Alt, so we should be ignoring the individual keydowns. The character
|
||||
// will be sent through the TSFInputControl. See GH#1401 for more
|
||||
// details
|
||||
if (modifiers.IsAltPressed() && (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// GH#2235: Terminal::Settings hasn't been modified to differentiate
|
||||
// between AltGr and Ctrl+Alt yet.
|
||||
// -> Don't check for key bindings if this is an AltGr key combination.
|
||||
if (modifiers.IsAltGrPressed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto actionMap = _settings.ActionMap();
|
||||
if (!actionMap)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto cmd = actionMap.GetActionByKeyChord({
|
||||
modifiers.IsCtrlPressed(),
|
||||
modifiers.IsAltPressed(),
|
||||
modifiers.IsShiftPressed(),
|
||||
modifiers.IsWinPressed(),
|
||||
vkey,
|
||||
scanCode,
|
||||
});
|
||||
if (!cmd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_actionDispatch->DoAction(cmd.ActionAndArgs()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
{
|
||||
p.Visibility(Visibility::Collapsed);
|
||||
}
|
||||
|
||||
// Let's assume the user has bound the dead key "^" to a sendInput command that sends "b".
|
||||
// If the user presses the two keys "^a" it'll produce "bâ", despite us marking the key event as handled.
|
||||
// The following is used to manually "consume" such dead keys and clear them from the keyboard state.
|
||||
_ClearKeyboardState(vkey, scanCode);
|
||||
e.Handled(true);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the modifier keys that are currently pressed. This can be used to
|
||||
// find out which modifiers (ctrl, alt, shift) are pressed in events that
|
||||
// don't necessarily include that state.
|
||||
// - This is a copy of TermControl::_GetPressedModifierKeys.
|
||||
// Return Value:
|
||||
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
|
||||
ControlKeyStates TerminalPage::_GetPressedModifierKeys() noexcept
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
// DONT USE
|
||||
// != CoreVirtualKeyStates::None
|
||||
// OR
|
||||
// == CoreVirtualKeyStates::Down
|
||||
// Sometimes with the key down, the state is Down | Locked.
|
||||
// Sometimes with the key up, the state is Locked.
|
||||
// IsFlagSet(Down) is the only correct solution.
|
||||
|
||||
struct KeyModifier
|
||||
{
|
||||
VirtualKey vkey;
|
||||
ControlKeyStates flags;
|
||||
};
|
||||
|
||||
constexpr std::array<KeyModifier, 7> modifiers{ {
|
||||
{ VirtualKey::RightMenu, ControlKeyStates::RightAltPressed },
|
||||
{ VirtualKey::LeftMenu, ControlKeyStates::LeftAltPressed },
|
||||
{ VirtualKey::RightControl, ControlKeyStates::RightCtrlPressed },
|
||||
{ VirtualKey::LeftControl, ControlKeyStates::LeftCtrlPressed },
|
||||
{ VirtualKey::Shift, ControlKeyStates::ShiftPressed },
|
||||
{ VirtualKey::RightWindows, ControlKeyStates::RightWinPressed },
|
||||
{ VirtualKey::LeftWindows, ControlKeyStates::LeftWinPressed },
|
||||
} };
|
||||
|
||||
ControlKeyStates flags;
|
||||
|
||||
for (const auto& mod : modifiers)
|
||||
{
|
||||
const auto state = window.GetKeyState(mod.vkey);
|
||||
const auto isDown = WI_IsFlagSet(state, CoreVirtualKeyStates::Down);
|
||||
|
||||
if (isDown)
|
||||
{
|
||||
CommandPalette().Visibility(Visibility::Collapsed);
|
||||
flags |= mod.flags;
|
||||
}
|
||||
_actionDispatch->DoAction(cmd.ActionAndArgs());
|
||||
e.Handled(true);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Discards currently pressed dead keys.
|
||||
// - This is a copy of TermControl::_ClearKeyboardState.
|
||||
// Arguments:
|
||||
// - vkey: The vkey of the key pressed.
|
||||
// - scanCode: The scan code of the key pressed.
|
||||
void TerminalPage::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
|
||||
{
|
||||
std::array<BYTE, 256> keyState;
|
||||
if (!GetKeyboardState(keyState.data()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// As described in "Sometimes you *want* to interfere with the keyboard's state buffer":
|
||||
// http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
|
||||
// > "The key here is to keep trying to pass stuff to ToUnicode until -1 is not returned."
|
||||
std::array<wchar_t, 16> buffer;
|
||||
while (ToUnicodeEx(vkey, scanCode, keyState.data(), buffer.data(), gsl::narrow_cast<int>(buffer.size()), 0b1, nullptr) < 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1485,18 +1609,15 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
// Method Description:
|
||||
// - Split the focused pane either horizontally or vertically, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// given pane accordingly in the tree
|
||||
// Arguments:
|
||||
// - newPane: the pane to add to our tree of panes
|
||||
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
||||
// new pane should be split from its parent.
|
||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
||||
// - newTerminalArgs: An object that may contain a blob of parameters to
|
||||
// control which profile is created and with possible other
|
||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||
// - splitSize: the size of the split
|
||||
void TerminalPage::_SplitPane(const SplitDirection splitDirection,
|
||||
const SplitType splitMode,
|
||||
const float splitSize,
|
||||
const NewTerminalArgs& newTerminalArgs)
|
||||
std::shared_ptr<Pane> newPane)
|
||||
{
|
||||
const auto focusedTab{ _GetFocusedTabImpl() };
|
||||
|
||||
|
@ -1506,101 +1627,52 @@ namespace winrt::TerminalApp::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
_SplitPane(*focusedTab, splitDirection, splitMode, splitSize, newTerminalArgs);
|
||||
_SplitPane(*focusedTab, splitDirection, splitSize, newPane);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Split the focused pane of the given tab, either horizontally or vertically, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// given pane accordingly
|
||||
// Arguments:
|
||||
// - tab: The tab that is going to be split.
|
||||
// - newPane: the pane to add to our tree of panes
|
||||
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
|
||||
// new pane should be split from its parent.
|
||||
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
||||
// - newTerminalArgs: An object that may contain a blob of parameters to
|
||||
// control which profile is created and with possible other
|
||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||
// - splitSize: the size of the split
|
||||
void TerminalPage::_SplitPane(TerminalTab& tab,
|
||||
const SplitDirection splitDirection,
|
||||
const SplitType splitMode,
|
||||
const float splitSize,
|
||||
const NewTerminalArgs& newTerminalArgs)
|
||||
std::shared_ptr<Pane> newPane)
|
||||
{
|
||||
try
|
||||
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
|
||||
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
|
||||
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
|
||||
|
||||
auto realSplitType = splitDirection;
|
||||
if (realSplitType == SplitDirection::Automatic)
|
||||
{
|
||||
TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||
Profile profile{ nullptr };
|
||||
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
|
||||
}
|
||||
|
||||
if (splitMode == SplitType::Duplicate)
|
||||
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
|
||||
if (!canSplit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_UnZoomIfNeeded();
|
||||
tab.SplitPane(realSplitType, splitSize, newPane);
|
||||
|
||||
// After GH#6586, the control will no longer focus itself
|
||||
// automatically when it's finished being laid out. Manually focus
|
||||
// the control here instead.
|
||||
if (_startupState == StartupState::Initialized)
|
||||
{
|
||||
if (const auto control = _GetActiveControl())
|
||||
{
|
||||
profile = tab.GetFocusedProfile();
|
||||
if (profile)
|
||||
{
|
||||
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
||||
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
||||
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
|
||||
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
|
||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
||||
if (validWorkingDirectory)
|
||||
{
|
||||
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
|
||||
}
|
||||
}
|
||||
// TODO: GH#5047 - In the future, we should get the Profile of
|
||||
// the focused pane, and use that to build a new instance of the
|
||||
// settings so we can duplicate this tab/pane.
|
||||
//
|
||||
// Currently, if the profile doesn't exist anymore in our
|
||||
// settings, we'll silently do nothing.
|
||||
//
|
||||
// In the future, it will be preferable to just duplicate the
|
||||
// current control's settings, but we can't do that currently,
|
||||
// because we won't be able to create a new instance of the
|
||||
// connection without keeping an instance of the original Profile
|
||||
// object around.
|
||||
}
|
||||
if (!profile)
|
||||
{
|
||||
profile = _settings.GetProfileForArgs(newTerminalArgs);
|
||||
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
|
||||
}
|
||||
|
||||
const auto controlConnection = _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
|
||||
|
||||
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
|
||||
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
|
||||
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
|
||||
|
||||
auto realSplitType = splitDirection;
|
||||
if (realSplitType == SplitDirection::Automatic)
|
||||
{
|
||||
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
|
||||
}
|
||||
|
||||
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
|
||||
if (!canSplit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto newControl = _InitControl(controlSettings, controlConnection);
|
||||
|
||||
// Hookup our event handlers to the new terminal
|
||||
_RegisterTerminalEvents(newControl);
|
||||
|
||||
_UnZoomIfNeeded();
|
||||
|
||||
tab.SplitPane(realSplitType, splitSize, profile, newControl);
|
||||
|
||||
// After GH#6586, the control will no longer focus itself
|
||||
// automatically when it's finished being laid out. Manually focus
|
||||
// the control here instead.
|
||||
if (_startupState == StartupState::Initialized)
|
||||
{
|
||||
_GetActiveControl().Focus(FocusState::Programmatic);
|
||||
control.Focus(FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -2108,7 +2180,7 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
if (target == SettingsTarget::SettingsUI)
|
||||
{
|
||||
_OpenSettingsUI();
|
||||
OpenSettingsUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2185,6 +2257,96 @@ namespace winrt::TerminalApp::implementation
|
|||
return term;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates a pane and returns a shared_ptr to it
|
||||
// - The caller should handle where the pane goes after creation,
|
||||
// either to split an already existing pane or to create a new tab with it
|
||||
// Arguments:
|
||||
// - newTerminalArgs: an object that may contain a blob of parameters to
|
||||
// control which profile is created and with possible other
|
||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||
// - duplicate: a boolean to indicate whether the pane we create should be
|
||||
// a duplicate of the currently focused pane
|
||||
// - existingConnection: optionally receives a connection from the outside
|
||||
// world instead of attempting to create one
|
||||
std::shared_ptr<Pane> TerminalPage::_MakePane(const NewTerminalArgs& newTerminalArgs, const bool duplicate, TerminalConnection::ITerminalConnection existingConnection)
|
||||
{
|
||||
TerminalSettingsCreateResult controlSettings{ nullptr };
|
||||
Profile profile{ nullptr };
|
||||
|
||||
if (duplicate)
|
||||
{
|
||||
const auto focusedTab{ _GetFocusedTabImpl() };
|
||||
if (focusedTab)
|
||||
{
|
||||
profile = focusedTab->GetFocusedProfile();
|
||||
if (profile)
|
||||
{
|
||||
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
|
||||
profile = GetClosestProfileForDuplicationOfProfile(profile);
|
||||
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
|
||||
const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
|
||||
const auto validWorkingDirectory = !workingDirectory.empty();
|
||||
if (validWorkingDirectory)
|
||||
{
|
||||
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!profile)
|
||||
{
|
||||
profile = _settings.GetProfileForArgs(newTerminalArgs);
|
||||
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
|
||||
}
|
||||
|
||||
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
|
||||
if (existingConnection)
|
||||
{
|
||||
connection.Resize(controlSettings.DefaultSettings().InitialRows(), controlSettings.DefaultSettings().InitialCols());
|
||||
}
|
||||
|
||||
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
|
||||
if (_settings.GlobalSettings().DebugFeaturesEnabled())
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
||||
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
||||
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
if (bothAltsPressed)
|
||||
{
|
||||
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
const auto control = _InitControl(controlSettings, connection);
|
||||
_RegisterTerminalEvents(control);
|
||||
|
||||
auto resultPane = std::make_shared<Pane>(profile, control);
|
||||
|
||||
if (debugConnection) // this will only be set if global debugging is on and tap is active
|
||||
{
|
||||
auto newControl = _InitControl(controlSettings, debugConnection);
|
||||
_RegisterTerminalEvents(newControl);
|
||||
// Split (auto) with the debug tap.
|
||||
auto debugPane = std::make_shared<Pane>(profile, newControl);
|
||||
|
||||
// Since we're doing this split directly on the pane (instead of going through TerminalTab,
|
||||
// we need to handle the panes 'active' states
|
||||
|
||||
// Set the pane we're splitting to active (otherwise Split will not do anything)
|
||||
resultPane->SetActive();
|
||||
auto [original, _] = resultPane->Split(SplitDirection::Automatic, 0.5f, debugPane);
|
||||
|
||||
// Set the non-debug pane as active
|
||||
resultPane->ClearActive();
|
||||
original->SetActive();
|
||||
}
|
||||
|
||||
return resultPane;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Hook up keybindings, and refresh the UI of the terminal.
|
||||
// This includes update the settings of all the tabs according
|
||||
|
@ -2494,9 +2656,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
void TerminalPage::ToggleFullscreen()
|
||||
{
|
||||
_isFullscreen = !_isFullscreen;
|
||||
_UpdateTabView();
|
||||
_FullscreenChangedHandlers(*this, nullptr);
|
||||
SetFullscreen(!_isFullscreen);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -2713,6 +2873,17 @@ namespace winrt::TerminalApp::implementation
|
|||
return _isAlwaysOnTop;
|
||||
}
|
||||
|
||||
void TerminalPage::SetFullscreen(bool newFullscreen)
|
||||
{
|
||||
if (_isFullscreen == newFullscreen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isFullscreen = newFullscreen;
|
||||
_UpdateTabView();
|
||||
_FullscreenChangedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
HRESULT TerminalPage::_OnNewConnection(const ConptyConnection& connection)
|
||||
{
|
||||
// We need to be on the UI thread in order for _OpenNewTab to run successfully.
|
||||
|
@ -2740,7 +2911,7 @@ namespace winrt::TerminalApp::implementation
|
|||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||
|
||||
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
|
||||
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, connection));
|
||||
|
||||
// Request a summon of this window to the foreground
|
||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||
|
@ -2756,7 +2927,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_OpenSettingsUI()
|
||||
void TerminalPage::OpenSettingsUI()
|
||||
{
|
||||
// If we're holding the settings tab's switch command, don't create a new one, switch to the existing one.
|
||||
if (!_settingsTab)
|
||||
|
@ -3374,7 +3545,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
_OpenSettingsUI();
|
||||
OpenSettingsUI();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -14,12 +14,17 @@
|
|||
|
||||
static constexpr uint32_t DefaultRowsToScroll{ 3 };
|
||||
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
|
||||
// fwdecl unittest classes
|
||||
|
||||
namespace TerminalAppLocalTests
|
||||
{
|
||||
class TabTests;
|
||||
class SettingsTests;
|
||||
};
|
||||
}
|
||||
|
||||
namespace Microsoft::Terminal::Core
|
||||
{
|
||||
class ControlKeyStates;
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
|
@ -83,6 +88,7 @@ namespace winrt::TerminalApp::implementation
|
|||
bool FocusMode() const;
|
||||
bool Fullscreen() const;
|
||||
bool AlwaysOnTop() const;
|
||||
void SetFullscreen(bool);
|
||||
|
||||
void SetStartupActions(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>& actions);
|
||||
|
||||
|
@ -121,6 +127,8 @@ namespace winrt::TerminalApp::implementation
|
|||
bool IsQuakeWindow() const noexcept;
|
||||
bool IsElevated() const noexcept;
|
||||
|
||||
void OpenSettingsUI();
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
|
@ -209,7 +217,6 @@ namespace winrt::TerminalApp::implementation
|
|||
void _OpenNewTabDropdown();
|
||||
HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
void _CreateNewTabFromPane(std::shared_ptr<Pane> pane);
|
||||
void _CreateNewTabWithProfileAndSettings(const Microsoft::Terminal::Settings::Model::Profile& profile, const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettings settings);
|
||||
|
||||
winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);
|
||||
|
@ -223,6 +230,8 @@ namespace winrt::TerminalApp::implementation
|
|||
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||
|
||||
void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
|
||||
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
|
||||
void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) noexcept;
|
||||
void _RegisterActionCallbacks();
|
||||
|
||||
|
@ -297,14 +306,12 @@ namespace winrt::TerminalApp::implementation
|
|||
void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference<uint32_t>& rowsToScroll);
|
||||
|
||||
void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
||||
const float splitSize = 0.5f,
|
||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
||||
const float splitSize,
|
||||
std::shared_ptr<Pane> newPane);
|
||||
void _SplitPane(TerminalTab& tab,
|
||||
const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
|
||||
const float splitSize = 0.5f,
|
||||
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
|
||||
const float splitSize,
|
||||
std::shared_ptr<Pane> newPane);
|
||||
void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||
void _ToggleSplitOrientation();
|
||||
|
||||
|
@ -351,6 +358,10 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::Microsoft::Terminal::Control::TermControl _InitControl(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
|
||||
const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection);
|
||||
|
||||
std::shared_ptr<Pane> _MakePane(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr,
|
||||
const bool duplicate = false,
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
|
||||
|
||||
void _RefreshUIForSettingsReload();
|
||||
|
||||
void _SetNonClientAreaColors(const Windows::UI::Color& selectedTabColor);
|
||||
|
@ -366,8 +377,6 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void _UnZoomIfNeeded();
|
||||
|
||||
void _OpenSettingsUI();
|
||||
|
||||
static int _ComputeScrollDelta(ScrollDirection scrollDirection, const uint32_t rowsToScroll);
|
||||
static uint32_t _ReadSystemRowsToScroll();
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@
|
|||
</ContentDialog>
|
||||
|
||||
<local:CommandPalette x:Name="CommandPalette"
|
||||
Grid.Row="1"
|
||||
Grid.Row="2"
|
||||
VerticalAlignment="Stretch"
|
||||
PreviewKeyDown="_KeyDownHandler"
|
||||
Visibility="Collapsed" />
|
||||
|
|
|
@ -25,18 +25,6 @@ namespace winrt
|
|||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TerminalTab::TerminalTab(const Profile& profile, const TermControl& control)
|
||||
{
|
||||
_rootPane = std::make_shared<Pane>(profile, control, true);
|
||||
|
||||
_rootPane->Id(_nextPaneId);
|
||||
_activePane = _rootPane;
|
||||
_mruPanes.insert(_mruPanes.begin(), _nextPaneId);
|
||||
++_nextPaneId;
|
||||
|
||||
_Setup();
|
||||
}
|
||||
|
||||
TerminalTab::TerminalTab(std::shared_ptr<Pane> rootPane)
|
||||
{
|
||||
_rootPane = rootPane;
|
||||
|
@ -64,8 +52,9 @@ namespace winrt::TerminalApp::implementation
|
|||
// focus the first one.
|
||||
if (_activePane == nullptr)
|
||||
{
|
||||
_rootPane->FocusPane(firstId);
|
||||
_activePane = _rootPane->GetActivePane();
|
||||
const auto firstPane = _rootPane->FindPane(firstId);
|
||||
firstPane->SetActive();
|
||||
_activePane = firstPane;
|
||||
}
|
||||
// If the focused pane is a leaf, add it to the MRU panes
|
||||
if (const auto id = _activePane->Id())
|
||||
|
@ -503,39 +492,48 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
// Method Description:
|
||||
// - Split the focused pane in our tree of panes, and place the
|
||||
// given TermControl into the newly created pane.
|
||||
// given pane into the tree of panes according to the split
|
||||
// Arguments:
|
||||
// - splitType: The type of split we want to create.
|
||||
// - profile: The profile GUID to associate with the newly created pane.
|
||||
// - control: A TermControl to use in the new pane.
|
||||
// - splitType: The type of split we want to create
|
||||
// - splitSize: The size of the split we want to create
|
||||
// - pane: The new pane to add to the tree of panes; note that this pane
|
||||
// could itself be a parent pane/the root node of a tree of panes
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::SplitPane(SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const Profile& profile,
|
||||
TermControl& control)
|
||||
std::shared_ptr<Pane> pane)
|
||||
{
|
||||
// Add the new event handlers to the new pane(s)
|
||||
// and update their ids.
|
||||
pane->WalkTree([&](auto p) {
|
||||
_AttachEventHandlersToPane(p);
|
||||
if (p->_IsLeaf())
|
||||
{
|
||||
p->Id(_nextPaneId);
|
||||
_AttachEventHandlersToControl(p->Id().value(), p->_control);
|
||||
_nextPaneId++;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
|
||||
const auto activePaneId = _activePane->Id();
|
||||
// Depending on which direction will be split, the new pane can be
|
||||
// either the first or second child, but this will always return the
|
||||
// original pane first.
|
||||
auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control);
|
||||
auto [original, newPane] = _activePane->Split(splitType, splitSize, pane);
|
||||
|
||||
// The active pane has an id if it is a leaf
|
||||
if (activePaneId)
|
||||
{
|
||||
original->Id(activePaneId.value());
|
||||
}
|
||||
newPane->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
|
||||
_activePane = original;
|
||||
|
||||
// Add a event handlers to the new panes' GotFocus event. When the pane
|
||||
// gains focus, we'll mark it as the new active pane.
|
||||
_AttachEventHandlersToControl(newPane->Id().value(), control);
|
||||
_AttachEventHandlersToPane(original);
|
||||
_AttachEventHandlersToPane(newPane);
|
||||
|
||||
// Immediately update our tracker of the focused pane now. If we're
|
||||
// splitting panes during startup (from a commandline), then it's
|
||||
|
|
|
@ -21,7 +21,6 @@ namespace winrt::TerminalApp::implementation
|
|||
struct TerminalTab : TerminalTabT<TerminalTab, TabBase>
|
||||
{
|
||||
public:
|
||||
TerminalTab(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile, const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
TerminalTab(std::shared_ptr<Pane> rootPane);
|
||||
|
||||
// Called after construction to perform the necessary setup, which relies on weak_ptr
|
||||
|
@ -40,8 +39,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
std::shared_ptr<Pane> newPane);
|
||||
|
||||
void ToggleSplitOrientation();
|
||||
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
|
||||
|
|
|
@ -68,5 +68,22 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!--
|
||||
BODGY
|
||||
|
||||
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
|
||||
executable we put in the package. But we DON'T produce a winmd. This makes the
|
||||
FastUpToDate check fail every time, and leads to the whole wapproj build
|
||||
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
|
||||
|
||||
Setting GenerateWindowsMetadata=false is enough to tell the build system that
|
||||
we don't produce one, and get it off our backs.
|
||||
-->
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
|
||||
</Project>
|
||||
|
|
|
@ -429,8 +429,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
// EXIT POINT
|
||||
const auto hr = wil::ResultFromCaughtException();
|
||||
|
||||
// GH#11556 - make sure to format the error code to this string as an UNSIGNED int
|
||||
winrt::hstring failureText{ fmt::format(std::wstring_view{ RS_(L"ProcessFailedToLaunch") },
|
||||
fmt::format(_errorFormat, hr),
|
||||
fmt::format(_errorFormat, static_cast<unsigned int>(hr)),
|
||||
_commandline) };
|
||||
_TerminalOutputHandlers(failureText);
|
||||
|
||||
|
@ -457,6 +458,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
{
|
||||
try
|
||||
{
|
||||
// GH#11556 - make sure to format the error code to this string as an UNSIGNED int
|
||||
winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, fmt::format(_errorFormat, status)) };
|
||||
_TerminalOutputHandlers(L"\r\n");
|
||||
_TerminalOutputHandlers(exitText);
|
||||
|
|
|
@ -97,4 +97,39 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
|
||||
<!--
|
||||
BODGY:
|
||||
|
||||
We depend on `cpprest142*.dll`, which comes from our vcpkg dependency. As a
|
||||
part of the vcpkg dependency restore, msbuild will call the `deployBinary()`
|
||||
function in
|
||||
`packages\vcpkg-cpprestsdk.2.10.14\scripts\BuildSystems\msbuild\AppLocal.ps1`.
|
||||
That function does the actual job of copying the file. It copies it outside of
|
||||
MsBuild. MsBuild then, in the `_CopyFilesMarkedCopyLocal` target, determines
|
||||
that it needs to copy `cpprest142*.dll`, because that dll is a member of
|
||||
`@(ReferencesCopiedInThisBuild)`. However, the file's already been copied, so
|
||||
MsBuild never copies it. But that also prevents MsBuild from setting
|
||||
`WroteAtLeastOneFile`, which then means that MsBuild will never create the
|
||||
.CopyComplete file for this project.
|
||||
|
||||
Because that file is missing, MsBuild will never think the project is up to
|
||||
date, and the FastUpToDate check in VS will always force MsBuild to run a pass
|
||||
on this project.
|
||||
|
||||
To mitigate this, we're adding this other target here, which runs after
|
||||
_CopyFilesMarkedCopyLocal, and always creates the CopyUpToDateMarker. This
|
||||
makes the FastUpToDate check succeed.
|
||||
-->
|
||||
|
||||
<Target
|
||||
Name="_Post_CopyFilesMarkedCopyLocal"
|
||||
AfterTargets="_CopyFilesMarkedCopyLocal"
|
||||
Condition="'@(ReferenceCopyLocalPaths)' != ''">
|
||||
|
||||
<Touch Files="@(CopyUpToDateMarker)"
|
||||
AlwaysCreate="true" />
|
||||
</Target>
|
||||
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -3,16 +3,18 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "ControlCore.h"
|
||||
#include <argb.h>
|
||||
|
||||
#include <DefaultSettings.h>
|
||||
#include <unicode.hpp>
|
||||
#include <Utf16Parser.hpp>
|
||||
#include <Utils.h>
|
||||
#include <WinUser.h>
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "EventArgs.h"
|
||||
#include "../../types/inc/GlyphWidth.hpp"
|
||||
#include "../../types/inc/Utils.hpp"
|
||||
#include "../../buffer/out/search.h"
|
||||
#include "../../renderer/atlas/AtlasEngine.h"
|
||||
#include "../../renderer/dx/DxRenderer.hpp"
|
||||
|
||||
#include "ControlCore.g.cpp"
|
||||
|
||||
|
@ -202,6 +204,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const double actualHeight,
|
||||
const double compositionScale)
|
||||
{
|
||||
assert(_settings);
|
||||
|
||||
_panelWidth = actualWidth;
|
||||
_panelHeight = actualHeight;
|
||||
_compositionScale = compositionScale;
|
||||
|
@ -222,10 +226,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return false;
|
||||
}
|
||||
|
||||
// Set up the DX Engine
|
||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
_renderer->AddRenderEngine(dxEngine.get());
|
||||
_renderEngine = std::move(dxEngine);
|
||||
if (Feature_AtlasEngine::IsEnabled() && _settings.UseAtlasEngine())
|
||||
{
|
||||
_renderEngine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
|
||||
}
|
||||
else
|
||||
{
|
||||
_renderEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
}
|
||||
|
||||
_renderer->AddRenderEngine(_renderEngine.get());
|
||||
|
||||
// Initialize our font with the renderer
|
||||
// We don't have to care about DPI. We'll get a change message immediately if it's not 96
|
||||
|
@ -271,11 +281,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
|
||||
|
||||
_updateAntiAliasingMode(_renderEngine.get());
|
||||
_updateAntiAliasingMode();
|
||||
|
||||
// GH#5098: Inform the engine of the opacity of the default text background.
|
||||
// GH#11315: Always do this, even if they don't have acrylic on.
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.Opacity()));
|
||||
const auto backgroundIsOpaque = _settings.Opacity() == 1.0 && _settings.BackgroundImage().empty();
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
|
||||
|
||||
THROW_IF_FAILED(_renderEngine->Enable());
|
||||
|
||||
|
@ -616,7 +627,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
|
||||
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||
|
||||
_updateAntiAliasingMode(_renderEngine.get());
|
||||
_updateAntiAliasingMode();
|
||||
|
||||
// Refresh our font with the renderer
|
||||
const auto actualFontOldSize = _actualFont.GetSize();
|
||||
|
@ -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())
|
||||
{
|
||||
case TextAntialiasingMode::Cleartype:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
|
||||
mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
break;
|
||||
case TextAntialiasingMode::Aliased:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||
break;
|
||||
case TextAntialiasingMode::Grayscale:
|
||||
default:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
break;
|
||||
}
|
||||
|
||||
_renderEngine->SetAntialiasingMode(mode);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1076,7 +1089,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
til::color ControlCore::BackgroundColor() const
|
||||
{
|
||||
return _terminal->GetDefaultBackground();
|
||||
return _terminal->GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1296,7 +1309,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
if (_renderEngine)
|
||||
{
|
||||
auto lock = _terminal->LockForWriting();
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(opacity));
|
||||
const auto backgroundIsOpaque = opacity == 1.0 && _settings.BackgroundImage().empty();
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,11 +15,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "EventArgs.h"
|
||||
#include "ControlCore.g.h"
|
||||
#include "../../renderer/base/Renderer.hpp"
|
||||
#include "../../renderer/dx/DxRenderer.hpp"
|
||||
#include "../../renderer/uia/UiaRenderer.hpp"
|
||||
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
||||
#include "../buffer/out/search.h"
|
||||
#include "cppwinrt_utils.h"
|
||||
|
@ -188,7 +185,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// As _renderer has a dependency on _renderEngine (through a raw pointer)
|
||||
// we must ensure the _renderer is deallocated first.
|
||||
// (C++ class members are destroyed in reverse order.)
|
||||
std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr };
|
||||
std::unique_ptr<::Microsoft::Console::Render::IRenderEngine> _renderEngine{ nullptr };
|
||||
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr };
|
||||
|
||||
IControlSettings _settings{ nullptr };
|
||||
|
@ -248,7 +245,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
#pragma endregion
|
||||
|
||||
void _raiseReadOnlyWarning();
|
||||
void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine);
|
||||
void _updateAntiAliasingMode();
|
||||
void _connectionOutputHandler(const hstring& hstr);
|
||||
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "cppwinrt_utils.h"
|
||||
|
||||
#include "ControlCore.h"
|
||||
#include "../../renderer/uia/UiaRenderer.hpp"
|
||||
|
||||
namespace ControlUnitTests
|
||||
{
|
||||
|
|
|
@ -27,10 +27,11 @@ namespace Microsoft.Terminal.Control
|
|||
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings, Microsoft.Terminal.Control.IControlAppearance
|
||||
{
|
||||
String ProfileName;
|
||||
String ProfileSource;
|
||||
|
||||
Boolean UseAcrylic;
|
||||
ScrollbarState ScrollState;
|
||||
|
||||
Boolean UseAtlasEngine;
|
||||
String FontFace;
|
||||
Int32 FontSize;
|
||||
Windows.UI.Text.FontWeight FontWeight;
|
||||
|
|
|
@ -141,12 +141,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
#pragma endregion
|
||||
|
||||
#pragma region IControlAccessibilityInfo
|
||||
COORD InteractivityAutomationPeer::GetFontSize() const
|
||||
COORD InteractivityAutomationPeer::GetFontSize() const noexcept
|
||||
{
|
||||
return til::size{ til::math::rounding, _interactivity->Core().FontSize() };
|
||||
}
|
||||
|
||||
RECT InteractivityAutomationPeer::GetBounds() const
|
||||
RECT InteractivityAutomationPeer::GetBounds() const noexcept
|
||||
{
|
||||
return _controlBounds;
|
||||
}
|
||||
|
@ -159,12 +159,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
RECT InteractivityAutomationPeer::GetPadding() const
|
||||
RECT InteractivityAutomationPeer::GetPadding() const noexcept
|
||||
{
|
||||
return _controlPadding;
|
||||
}
|
||||
|
||||
double InteractivityAutomationPeer::GetScaleFactor() const
|
||||
double InteractivityAutomationPeer::GetScaleFactor() const noexcept
|
||||
{
|
||||
return DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
||||
}
|
||||
|
|
|
@ -62,10 +62,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
#pragma region IControlAccessibilityInfo Pattern
|
||||
// Inherited via IControlAccessibilityInfo
|
||||
virtual COORD GetFontSize() const override;
|
||||
virtual RECT GetBounds() const override;
|
||||
virtual RECT GetPadding() const override;
|
||||
virtual double GetScaleFactor() const override;
|
||||
virtual COORD GetFontSize() const noexcept override;
|
||||
virtual RECT GetBounds() const noexcept override;
|
||||
virtual RECT GetPadding() const noexcept override;
|
||||
virtual double GetScaleFactor() const noexcept override;
|
||||
virtual void ChangeViewport(SMALL_RECT NewWindow) override;
|
||||
virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override;
|
||||
#pragma endregion
|
||||
|
|
|
@ -3,17 +3,16 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "TermControl.h"
|
||||
#include <argb.h>
|
||||
#include <DefaultSettings.h>
|
||||
|
||||
#include <unicode.hpp>
|
||||
#include <Utf16Parser.hpp>
|
||||
#include <Utils.h>
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "TermControlAutomationPeer.h"
|
||||
#include "../../types/inc/GlyphWidth.hpp"
|
||||
#include "../../types/inc/Utils.hpp"
|
||||
#include "../../renderer/atlas/AtlasEngine.h"
|
||||
|
||||
#include "TermControl.g.cpp"
|
||||
#include "TermControlAutomationPeer.h"
|
||||
|
||||
using namespace ::Microsoft::Console::Types;
|
||||
using namespace ::Microsoft::Console::VirtualTerminal;
|
||||
|
@ -774,12 +773,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_HidePointerCursorHandlers(*this, nullptr);
|
||||
|
||||
const auto ch = e.Character();
|
||||
const auto scanCode = gsl::narrow_cast<WORD>(e.KeyStatus().ScanCode);
|
||||
const auto keyStatus = e.KeyStatus();
|
||||
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||
auto modifiers = _GetPressedModifierKeys();
|
||||
if (e.KeyStatus().IsExtendedKey)
|
||||
|
||||
if (keyStatus.IsExtendedKey)
|
||||
{
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
|
||||
const bool handled = _core.SendCharEvent(ch, scanCode, modifiers);
|
||||
e.Handled(handled);
|
||||
}
|
||||
|
@ -874,6 +876,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||
auto modifiers = _GetPressedModifierKeys();
|
||||
|
||||
if (keyStatus.IsExtendedKey)
|
||||
{
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
|
||||
// GH#11076:
|
||||
// For some weird reason we sometimes receive a WM_KEYDOWN
|
||||
// message without vkey or scanCode if a user drags a tab.
|
||||
|
@ -907,11 +914,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
if (keyStatus.IsExtendedKey)
|
||||
{
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
|
||||
// Alt-Numpad# input will send us a character once the user releases
|
||||
// Alt, so we should be ignoring the individual keydowns. The character
|
||||
// will be sent through the TSFInputControl. See GH#1401 for more
|
||||
|
@ -989,7 +991,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// Arguments:
|
||||
// - vkey: The vkey of the key pressed.
|
||||
// - scanCode: The scan code of the key pressed.
|
||||
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept
|
||||
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
|
||||
{
|
||||
std::array<BYTE, 256> keyState;
|
||||
if (!GetKeyboardState(keyState.data()))
|
||||
|
@ -1828,13 +1830,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
const winrt::Windows::Foundation::Size initialSize{ cols, rows };
|
||||
|
||||
return GetProposedDimensions(initialSize,
|
||||
settings.FontSize(),
|
||||
settings.FontWeight(),
|
||||
settings.FontFace(),
|
||||
settings.ScrollState(),
|
||||
settings.Padding(),
|
||||
dpi);
|
||||
return GetProposedDimensions(settings, dpi, initialSize);
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
@ -1855,16 +1851,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// caller knows what monitor the control is about to appear on.
|
||||
// Return Value:
|
||||
// - a size containing the requested dimensions in pixels.
|
||||
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
|
||||
const int32_t& fontHeight,
|
||||
const winrt::Windows::UI::Text::FontWeight& fontWeight,
|
||||
const winrt::hstring& fontFace,
|
||||
const ScrollbarState& scrollState,
|
||||
const winrt::hstring& padding,
|
||||
const uint32_t dpi)
|
||||
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars)
|
||||
{
|
||||
const auto cols = ::base::saturated_cast<int>(initialSizeInChars.Width);
|
||||
const auto rows = ::base::saturated_cast<int>(initialSizeInChars.Height);
|
||||
const auto fontSize = settings.FontSize();
|
||||
const auto fontWeight = settings.FontWeight();
|
||||
const auto fontFace = settings.FontFace();
|
||||
const auto scrollState = settings.ScrollState();
|
||||
const auto padding = settings.Padding();
|
||||
|
||||
// Initialize our font information.
|
||||
// The font width doesn't terribly matter, we'll only be using the
|
||||
|
@ -1873,28 +1868,39 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// The family is only used to determine if the font is truetype or
|
||||
// not, but DX doesn't use that info at all.
|
||||
// The Codepage is additionally not actually used by the DX engine at all.
|
||||
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast<short>(fontHeight) }, CP_UTF8, false };
|
||||
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast<short>(fontSize) }, CP_UTF8, false };
|
||||
FontInfoDesired desiredFont = { actualFont };
|
||||
|
||||
// Create a DX engine and initialize it with our font and DPI. We'll
|
||||
// then use it to measure how much space the requested rows and columns
|
||||
// will take up.
|
||||
// TODO: MSFT:21254947 - use a static function to do this instead of
|
||||
// instantiating a DxEngine
|
||||
// instantiating a DxEngine/AtlasEngine.
|
||||
// GH#10211 - UNDER NO CIRCUMSTANCE should this fail. If it does, the
|
||||
// whole app will crash instantaneously on launch, which is no good.
|
||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
LOG_IF_FAILED(dxEngine->UpdateDpi(dpi));
|
||||
LOG_IF_FAILED(dxEngine->UpdateFont(desiredFont, actualFont));
|
||||
double scale;
|
||||
if (Feature_AtlasEngine::IsEnabled() && settings.UseAtlasEngine())
|
||||
{
|
||||
auto engine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
|
||||
LOG_IF_FAILED(engine->UpdateDpi(dpi));
|
||||
LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont));
|
||||
scale = engine->GetScaling();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto engine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
LOG_IF_FAILED(engine->UpdateDpi(dpi));
|
||||
LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont));
|
||||
scale = engine->GetScaling();
|
||||
}
|
||||
|
||||
const auto scale = dxEngine->GetScaling();
|
||||
const auto fontSize = actualFont.GetSize();
|
||||
const auto actualFontSize = actualFont.GetSize();
|
||||
|
||||
// UWP XAML scrollbars aren't guaranteed to be the same size as the
|
||||
// ComCtl scrollbars, but it's certainly close enough.
|
||||
const auto scrollbarSize = GetSystemMetricsForDpi(SM_CXVSCROLL, dpi);
|
||||
|
||||
double width = cols * fontSize.X;
|
||||
double width = cols * actualFontSize.X;
|
||||
|
||||
// Reserve additional space if scrollbar is intended to be visible
|
||||
if (scrollState == ScrollbarState::Visible)
|
||||
|
@ -1902,7 +1908,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
width += scrollbarSize;
|
||||
}
|
||||
|
||||
double height = rows * fontSize.Y;
|
||||
double height = rows * actualFontSize.Y;
|
||||
const auto thickness = ParseThicknessFromPadding(padding);
|
||||
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
|
||||
width += scale * (thickness.Left + thickness.Right);
|
||||
|
@ -1962,13 +1968,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
|
||||
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
||||
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
|
||||
return GetProposedDimensions(minSize,
|
||||
_settings.FontSize(),
|
||||
_settings.FontWeight(),
|
||||
_settings.FontFace(),
|
||||
_settings.ScrollState(),
|
||||
_settings.Padding(),
|
||||
dpi);
|
||||
return GetProposedDimensions(_settings, dpi, minSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2063,7 +2063,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// don't necessarily include that state.
|
||||
// Return Value:
|
||||
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
|
||||
ControlKeyStates TermControl::_GetPressedModifierKeys() const
|
||||
ControlKeyStates TermControl::_GetPressedModifierKeys() noexcept
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
// DONT USE
|
||||
|
@ -2271,6 +2271,42 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
|
||||
std::wstring fullPath{ item.Path() };
|
||||
|
||||
// Fix path for WSL
|
||||
if (_settings.ProfileSource() == L"Windows.Terminal.Wsl")
|
||||
{
|
||||
std::replace(fullPath.begin(), fullPath.end(), L'\\', L'/');
|
||||
|
||||
if (fullPath.size() >= 2 && fullPath.at(1) == L':')
|
||||
{
|
||||
// C:/foo/bar -> Cc/foo/bar
|
||||
fullPath.at(1) = til::tolower_ascii(fullPath.at(0));
|
||||
// Cc/foo/bar -> /mnt/c/foo/bar
|
||||
fullPath.replace(0, 1, L"/mnt/");
|
||||
}
|
||||
else
|
||||
{
|
||||
static constexpr std::wstring_view wslPathPrefixes[] = { L"//wsl.localhost/", L"//wsl$/" };
|
||||
for (auto prefix : wslPathPrefixes)
|
||||
{
|
||||
if (til::starts_with(fullPath, prefix))
|
||||
{
|
||||
if (const auto idx = fullPath.find(L'/', prefix.size()); idx != std::wstring::npos)
|
||||
{
|
||||
// //wsl.localhost/Ubuntu-18.04/foo/bar -> /foo/bar
|
||||
fullPath.erase(0, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
// //wsl.localhost/Ubuntu-18.04 -> /
|
||||
fullPath = L"/";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto containsSpaces = std::find(fullPath.begin(),
|
||||
fullPath.end(),
|
||||
L' ') != fullPath.end();
|
||||
|
@ -2283,6 +2319,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
allPaths += fullPath;
|
||||
}
|
||||
|
||||
_core.PasteText(winrt::hstring{ allPaths });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,13 +92,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void Settings(IControlSettings newSettings);
|
||||
|
||||
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi);
|
||||
static Windows::Foundation::Size GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
|
||||
const int32_t& fontSize,
|
||||
const winrt::Windows::UI::Text::FontWeight& fontWeight,
|
||||
const winrt::hstring& fontFace,
|
||||
const ScrollbarState& scrollState,
|
||||
const winrt::hstring& padding,
|
||||
const uint32_t dpi);
|
||||
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars);
|
||||
|
||||
void BellLightOn();
|
||||
|
||||
|
@ -251,9 +245,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
|
||||
|
||||
void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown);
|
||||
::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
|
||||
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
|
||||
bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const;
|
||||
void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept;
|
||||
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
|
||||
bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
|
||||
|
||||
const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition);
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
<ProjectReference Include="..\..\types\lib\types.vcxproj" />
|
||||
<ProjectReference Include="..\..\buffer\out\lib\bufferout.vcxproj" />
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\renderer\base\lib\base.vcxproj" />
|
||||
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj" />
|
||||
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj" />
|
||||
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj" />
|
||||
<ProjectReference Include="..\..\terminal\parser\lib\parser.vcxproj" />
|
||||
|
|
|
@ -40,13 +40,10 @@ namespace Microsoft::Terminal::Core
|
|||
virtual bool WarningBell() noexcept = 0;
|
||||
virtual bool SetWindowTitle(std::wstring_view title) noexcept = 0;
|
||||
|
||||
virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept = 0;
|
||||
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept = 0;
|
||||
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept = 0;
|
||||
|
||||
virtual bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept = 0;
|
||||
virtual bool SetCursorColor(const DWORD color) noexcept = 0;
|
||||
|
||||
virtual bool SetDefaultForeground(const DWORD color) noexcept = 0;
|
||||
virtual bool SetDefaultBackground(const DWORD color) noexcept = 0;
|
||||
|
||||
virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;
|
||||
|
||||
|
|
|
@ -41,8 +41,6 @@ Terminal::Terminal() :
|
|||
_mutableViewport{ Viewport::Empty() },
|
||||
_title{},
|
||||
_colorTable{},
|
||||
_defaultFg{ RGB(255, 255, 255) },
|
||||
_defaultBg{ ARGB(0, 0, 0, 0) },
|
||||
_screenReversed{ false },
|
||||
_pfnWriteInput{ nullptr },
|
||||
_scrollOffset{ 0 },
|
||||
|
@ -61,6 +59,14 @@ Terminal::Terminal() :
|
|||
|
||||
_stateMachine = std::make_unique<StateMachine>(std::move(engine));
|
||||
|
||||
// Until we have a true pass-through mode (GH#1173), the decision as to
|
||||
// whether C1 controls are interpreted or not is made at the conhost level.
|
||||
// If they are being filtered out, then we will simply never receive them.
|
||||
// But if they are being accepted by conhost, there's a chance they may get
|
||||
// passed through in some situations, so it's important that our state
|
||||
// machine is always prepared to accept them.
|
||||
_stateMachine->SetParserMode(StateMachine::Mode::AcceptC1, true);
|
||||
|
||||
auto passAlongInput = [&](std::deque<std::unique_ptr<IInputEvent>>& inEventsToWrite) {
|
||||
if (!_pfnWriteInput)
|
||||
{
|
||||
|
@ -73,6 +79,10 @@ Terminal::Terminal() :
|
|||
_terminalInput = std::make_unique<TerminalInput>(passAlongInput);
|
||||
|
||||
_InitializeColorTable();
|
||||
|
||||
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = RGB(255, 255, 255);
|
||||
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = ARGB(0, 0, 0, 0);
|
||||
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
|
||||
}
|
||||
|
||||
void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, IRenderTarget& renderTarget)
|
||||
|
@ -172,9 +182,13 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
|||
{
|
||||
// Set the default background as transparent to prevent the
|
||||
// DX layer from overwriting the background image or acrylic effect
|
||||
til::color newBackgroundColor{ appearance.DefaultBackground() };
|
||||
_defaultBg = newBackgroundColor.with_alpha(0);
|
||||
_defaultFg = appearance.DefaultForeground();
|
||||
const til::color newBackgroundColor{ appearance.DefaultBackground() };
|
||||
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = newBackgroundColor.with_alpha(0);
|
||||
const til::color newForegroundColor{ appearance.DefaultForeground() };
|
||||
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = newForegroundColor;
|
||||
const til::color newCursorColor{ appearance.CursorColor() };
|
||||
_colorTable.at(TextColor::CURSOR_COLOR) = newCursorColor;
|
||||
|
||||
_intenseIsBright = appearance.IntenseIsBright();
|
||||
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
|
||||
|
||||
|
@ -213,9 +227,7 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
|||
|
||||
if (_buffer)
|
||||
{
|
||||
_buffer->GetCursor().SetStyle(appearance.CursorHeight(),
|
||||
til::color{ appearance.CursorColor() },
|
||||
cursorShape);
|
||||
_buffer->GetCursor().SetStyle(appearance.CursorHeight(), cursorShape);
|
||||
}
|
||||
|
||||
_defaultCursorShape = cursorShape;
|
||||
|
@ -1210,9 +1222,7 @@ try
|
|||
{
|
||||
const gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
|
||||
// First set up the basic 256 colors
|
||||
Utils::Initialize256ColorTable(tableView);
|
||||
// Then use fill the first 16 values with the Campbell scheme
|
||||
Utils::InitializeCampbellColorTable(tableView);
|
||||
Utils::InitializeColorTable(tableView);
|
||||
// Then make sure all the values have an alpha of 255
|
||||
Utils::SetColorTableAlpha(tableView, 0xff);
|
||||
}
|
||||
|
|
|
@ -106,11 +106,9 @@ public:
|
|||
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
|
||||
bool WarningBell() noexcept override;
|
||||
bool SetWindowTitle(std::wstring_view title) noexcept override;
|
||||
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
|
||||
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
|
||||
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
|
||||
bool SetCursorColor(const COLORREF color) noexcept override;
|
||||
bool SetDefaultForeground(const COLORREF color) noexcept override;
|
||||
bool SetDefaultBackground(const COLORREF color) noexcept override;
|
||||
|
||||
bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
|
||||
|
||||
|
@ -212,7 +210,6 @@ public:
|
|||
void ClearPatternTree() noexcept;
|
||||
|
||||
const std::optional<til::color> GetTabColor() const noexcept;
|
||||
til::color GetDefaultBackground() const noexcept;
|
||||
|
||||
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
|
||||
|
||||
|
@ -281,9 +278,7 @@ private:
|
|||
std::optional<til::color> _startingTabColor;
|
||||
|
||||
// This is still stored as a COLORREF because it interacts with some code in ConTypes
|
||||
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
|
||||
til::color _defaultFg;
|
||||
til::color _defaultBg;
|
||||
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
|
||||
CursorType _defaultCursorShape;
|
||||
bool _screenReversed;
|
||||
mutable Microsoft::Console::Render::BlinkingState _blinkingState;
|
||||
|
|
|
@ -69,14 +69,6 @@ COORD Terminal::GetCursorPosition() noexcept
|
|||
return newPos;
|
||||
}
|
||||
|
||||
bool Terminal::SetCursorColor(const COLORREF color) noexcept
|
||||
try
|
||||
{
|
||||
_buffer->GetCursor().SetColor(color);
|
||||
return true;
|
||||
}
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Moves the cursor down one line, and possibly also to the leftmost column.
|
||||
// Arguments:
|
||||
|
@ -370,6 +362,22 @@ try
|
|||
}
|
||||
CATCH_RETURN_FALSE()
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the value in the colortable at the specified index.
|
||||
// Arguments:
|
||||
// - tableIndex: the index of the color table to retrieve.
|
||||
// Return Value:
|
||||
// - the COLORREF value for the color at that index in the table.
|
||||
COLORREF Terminal::GetColorTableEntry(const size_t tableIndex) const noexcept
|
||||
try
|
||||
{
|
||||
return _colorTable.at(tableIndex);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return INVALID_COLOR;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the value in the colortable at index tableIndex to the new color
|
||||
// color. color is a COLORREF, format 0x00BBGGRR.
|
||||
|
@ -383,6 +391,11 @@ try
|
|||
{
|
||||
_colorTable.at(tableIndex) = color;
|
||||
|
||||
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
|
||||
{
|
||||
_pfnBackgroundColorChanged(color);
|
||||
}
|
||||
|
||||
// Repaint everything - the colors might have changed
|
||||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
return true;
|
||||
|
@ -442,46 +455,6 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
|
|||
return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the default foreground color from a COLORREF, format 0x00BBGGRR.
|
||||
// Arguments:
|
||||
// - color: the new COLORREF to use as the default foreground color
|
||||
// Return Value:
|
||||
// - true
|
||||
bool Terminal::SetDefaultForeground(const COLORREF color) noexcept
|
||||
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
|
||||
try
|
||||
{
|
||||
|
|
|
@ -227,7 +227,7 @@ CATCH_LOG_RETURN_FALSE()
|
|||
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
|
||||
try
|
||||
{
|
||||
return _terminalApi.SetCursorColor(color);
|
||||
return _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color);
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
|
||||
|
@ -247,7 +247,7 @@ CATCH_LOG_RETURN_FALSE()
|
|||
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
|
||||
try
|
||||
{
|
||||
return _terminalApi.SetDefaultForeground(color);
|
||||
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color);
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
|
||||
|
@ -260,7 +260,7 @@ CATCH_LOG_RETURN_FALSE()
|
|||
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
|
||||
try
|
||||
{
|
||||
return _terminalApi.SetDefaultBackground(color);
|
||||
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color);
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
|
||||
|
|
|
@ -7,29 +7,6 @@
|
|||
using namespace Microsoft::Console::VirtualTerminal;
|
||||
using namespace Microsoft::Console::VirtualTerminal::DispatchTypes;
|
||||
|
||||
// clang-format off
|
||||
const BYTE RED_ATTR = 0x01;
|
||||
const BYTE GREEN_ATTR = 0x02;
|
||||
const BYTE BLUE_ATTR = 0x04;
|
||||
const BYTE BRIGHT_ATTR = 0x08;
|
||||
const BYTE DARK_BLACK = 0;
|
||||
const BYTE DARK_RED = RED_ATTR;
|
||||
const BYTE DARK_GREEN = GREEN_ATTR;
|
||||
const BYTE DARK_YELLOW = RED_ATTR | GREEN_ATTR;
|
||||
const BYTE DARK_BLUE = BLUE_ATTR;
|
||||
const BYTE DARK_MAGENTA = RED_ATTR | BLUE_ATTR;
|
||||
const BYTE DARK_CYAN = GREEN_ATTR | BLUE_ATTR;
|
||||
const BYTE DARK_WHITE = RED_ATTR | GREEN_ATTR | BLUE_ATTR;
|
||||
const BYTE BRIGHT_BLACK = BRIGHT_ATTR;
|
||||
const BYTE BRIGHT_RED = BRIGHT_ATTR | RED_ATTR;
|
||||
const BYTE BRIGHT_GREEN = BRIGHT_ATTR | GREEN_ATTR;
|
||||
const BYTE BRIGHT_YELLOW = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR;
|
||||
const BYTE BRIGHT_BLUE = BRIGHT_ATTR | BLUE_ATTR;
|
||||
const BYTE BRIGHT_MAGENTA = BRIGHT_ATTR | RED_ATTR | BLUE_ATTR;
|
||||
const BYTE BRIGHT_CYAN = BRIGHT_ATTR | GREEN_ATTR | BLUE_ATTR;
|
||||
const BYTE BRIGHT_WHITE = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR | BLUE_ATTR;
|
||||
// clang-format on
|
||||
|
||||
// Routine Description:
|
||||
// - Helper to parse extended graphics options, which start with 38 (FG) or 48 (BG)
|
||||
// These options are followed by either a 2 (RGB) or 5 (xterm index)
|
||||
|
@ -169,100 +146,100 @@ bool TerminalDispatch::SetGraphicsRendition(const VTParameters options) noexcept
|
|||
attr.SetOverlined(false);
|
||||
break;
|
||||
case ForegroundBlack:
|
||||
attr.SetIndexedForeground(DARK_BLACK);
|
||||
attr.SetIndexedForeground(TextColor::DARK_BLACK);
|
||||
break;
|
||||
case ForegroundBlue:
|
||||
attr.SetIndexedForeground(DARK_BLUE);
|
||||
attr.SetIndexedForeground(TextColor::DARK_BLUE);
|
||||
break;
|
||||
case ForegroundGreen:
|
||||
attr.SetIndexedForeground(DARK_GREEN);
|
||||
attr.SetIndexedForeground(TextColor::DARK_GREEN);
|
||||
break;
|
||||
case ForegroundCyan:
|
||||
attr.SetIndexedForeground(DARK_CYAN);
|
||||
attr.SetIndexedForeground(TextColor::DARK_CYAN);
|
||||
break;
|
||||
case ForegroundRed:
|
||||
attr.SetIndexedForeground(DARK_RED);
|
||||
attr.SetIndexedForeground(TextColor::DARK_RED);
|
||||
break;
|
||||
case ForegroundMagenta:
|
||||
attr.SetIndexedForeground(DARK_MAGENTA);
|
||||
attr.SetIndexedForeground(TextColor::DARK_MAGENTA);
|
||||
break;
|
||||
case ForegroundYellow:
|
||||
attr.SetIndexedForeground(DARK_YELLOW);
|
||||
attr.SetIndexedForeground(TextColor::DARK_YELLOW);
|
||||
break;
|
||||
case ForegroundWhite:
|
||||
attr.SetIndexedForeground(DARK_WHITE);
|
||||
attr.SetIndexedForeground(TextColor::DARK_WHITE);
|
||||
break;
|
||||
case BackgroundBlack:
|
||||
attr.SetIndexedBackground(DARK_BLACK);
|
||||
attr.SetIndexedBackground(TextColor::DARK_BLACK);
|
||||
break;
|
||||
case BackgroundBlue:
|
||||
attr.SetIndexedBackground(DARK_BLUE);
|
||||
attr.SetIndexedBackground(TextColor::DARK_BLUE);
|
||||
break;
|
||||
case BackgroundGreen:
|
||||
attr.SetIndexedBackground(DARK_GREEN);
|
||||
attr.SetIndexedBackground(TextColor::DARK_GREEN);
|
||||
break;
|
||||
case BackgroundCyan:
|
||||
attr.SetIndexedBackground(DARK_CYAN);
|
||||
attr.SetIndexedBackground(TextColor::DARK_CYAN);
|
||||
break;
|
||||
case BackgroundRed:
|
||||
attr.SetIndexedBackground(DARK_RED);
|
||||
attr.SetIndexedBackground(TextColor::DARK_RED);
|
||||
break;
|
||||
case BackgroundMagenta:
|
||||
attr.SetIndexedBackground(DARK_MAGENTA);
|
||||
attr.SetIndexedBackground(TextColor::DARK_MAGENTA);
|
||||
break;
|
||||
case BackgroundYellow:
|
||||
attr.SetIndexedBackground(DARK_YELLOW);
|
||||
attr.SetIndexedBackground(TextColor::DARK_YELLOW);
|
||||
break;
|
||||
case BackgroundWhite:
|
||||
attr.SetIndexedBackground(DARK_WHITE);
|
||||
attr.SetIndexedBackground(TextColor::DARK_WHITE);
|
||||
break;
|
||||
case BrightForegroundBlack:
|
||||
attr.SetIndexedForeground(BRIGHT_BLACK);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
|
||||
break;
|
||||
case BrightForegroundBlue:
|
||||
attr.SetIndexedForeground(BRIGHT_BLUE);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_BLUE);
|
||||
break;
|
||||
case BrightForegroundGreen:
|
||||
attr.SetIndexedForeground(BRIGHT_GREEN);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_GREEN);
|
||||
break;
|
||||
case BrightForegroundCyan:
|
||||
attr.SetIndexedForeground(BRIGHT_CYAN);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_CYAN);
|
||||
break;
|
||||
case BrightForegroundRed:
|
||||
attr.SetIndexedForeground(BRIGHT_RED);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_RED);
|
||||
break;
|
||||
case BrightForegroundMagenta:
|
||||
attr.SetIndexedForeground(BRIGHT_MAGENTA);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
|
||||
break;
|
||||
case BrightForegroundYellow:
|
||||
attr.SetIndexedForeground(BRIGHT_YELLOW);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
|
||||
break;
|
||||
case BrightForegroundWhite:
|
||||
attr.SetIndexedForeground(BRIGHT_WHITE);
|
||||
attr.SetIndexedForeground(TextColor::BRIGHT_WHITE);
|
||||
break;
|
||||
case BrightBackgroundBlack:
|
||||
attr.SetIndexedBackground(BRIGHT_BLACK);
|
||||
attr.SetIndexedBackground(TextColor::BRIGHT_BLACK);
|
||||
break;
|
||||
case BrightBackgroundBlue:
|
||||
attr.SetIndexedBackground(BRIGHT_BLUE);
|
||||
attr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
|
||||
break;
|
||||
case BrightBackgroundGreen:
|
||||
attr.SetIndexedBackground(BRIGHT_GREEN);
|
||||
attr.SetIndexedBackground(TextColor::BRIGHT_GREEN);
|
||||
break;
|
||||
case BrightBackgroundCyan:
|
||||
attr.SetIndexedBackground(BRIGHT_CYAN);
|
||||
attr.SetIndexedBackground(TextColor::BRIGHT_CYAN);
|
||||
break;
|
||||
case BrightBackgroundRed:
|
||||
attr.SetIndexedBackground(BRIGHT_RED);
|
||||
attr.SetIndexedBackground(TextColor::BRIGHT_RED);
|
||||
break;
|
||||
case BrightBackgroundMagenta:
|
||||
attr.SetIndexedBackground(BRIGHT_MAGENTA);
|
||||
attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
|
||||
break;
|
||||
case BrightBackgroundYellow:
|
||||
attr.SetIndexedBackground(BRIGHT_YELLOW);
|
||||
attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
|
||||
break;
|
||||
case BrightBackgroundWhite:
|
||||
attr.SetIndexedBackground(BRIGHT_WHITE);
|
||||
attr.SetIndexedBackground(TextColor::BRIGHT_WHITE);
|
||||
break;
|
||||
case ForegroundExtended:
|
||||
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
<ProjectReference Include="$(OpenConsoleDir)src\terminal\parser\lib\parser.vcxproj">
|
||||
<Project>{3ae13314-1939-4dfa-9c14-38ca0834050c}</Project>
|
||||
</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">
|
||||
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
||||
</ProjectReference>
|
||||
|
|
|
@ -73,19 +73,19 @@ std::pair<COLORREF, COLORREF> Terminal::GetAttributeColors(const TextAttribute&
|
|||
if (attr.IsReverseVideo() ^ _screenReversed)
|
||||
{
|
||||
colors.first = _adjustedForegroundColors[fgIndex][bgIndex];
|
||||
colors.second = fgTextColor.GetColor(_colorTable, _defaultFg);
|
||||
colors.second = fgTextColor.GetColor(_colorTable, TextColor::DEFAULT_FOREGROUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
|
||||
colors.second = bgTextColor.GetColor(_colorTable, _defaultBg);
|
||||
colors.second = bgTextColor.GetColor(_colorTable, TextColor::DEFAULT_BACKGROUND);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
colors = attr.CalculateRgbColors(_colorTable,
|
||||
_defaultFg,
|
||||
_defaultBg,
|
||||
TextColor::DEFAULT_FOREGROUND,
|
||||
TextColor::DEFAULT_BACKGROUND,
|
||||
_screenReversed,
|
||||
_blinkingState.IsBlinkingFaint(),
|
||||
_intenseIsBright);
|
||||
|
@ -135,7 +135,7 @@ CursorType Terminal::GetCursorStyle() const noexcept
|
|||
|
||||
COLORREF Terminal::GetCursorColor() const noexcept
|
||||
{
|
||||
return _buffer->GetCursor().GetColor();
|
||||
return _colorTable.at(TextColor::CURSOR_COLOR);
|
||||
}
|
||||
|
||||
bool Terminal::IsCursorDoubleWidth() const
|
||||
|
@ -312,8 +312,8 @@ void Terminal::_MakeAdjustedColorArray()
|
|||
// to include the default background and default foreground colors
|
||||
std::array<COLORREF, 18> colorTableWithDefaults;
|
||||
std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults));
|
||||
colorTableWithDefaults[DefaultBgIndex] = _defaultBg;
|
||||
colorTableWithDefaults[DefaultFgIndex] = _defaultFg;
|
||||
colorTableWithDefaults[DefaultBgIndex] = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
|
||||
colorTableWithDefaults[DefaultFgIndex] = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
|
||||
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
|
||||
{
|
||||
const auto fg = til::at(colorTableWithDefaults, fgIndex);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "Profiles.h"
|
||||
|
||||
#include "PreviewConnection.h"
|
||||
#include "Profiles.g.cpp"
|
||||
#include "EnumEntry.h"
|
||||
|
@ -10,6 +11,54 @@
|
|||
#include <LibraryResources.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::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
|
@ -107,8 +156,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
reinterpret_cast<::IUnknown**>(factory.put())));
|
||||
|
||||
// get the font collection; subscribe to updates
|
||||
com_ptr<IDWriteFontCollection> fontCollection;
|
||||
THROW_IF_FAILED(factory->GetSystemFontCollection(fontCollection.put(), TRUE));
|
||||
const auto fontCollection = NearbyCollection(factory.get());
|
||||
|
||||
for (UINT32 i = 0; i < fontCollection->GetFontFamilyCount(); ++i)
|
||||
{
|
||||
|
@ -246,13 +294,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
return _profile.HasUnfocusedAppearance();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::EditableUnfocusedAppearance()
|
||||
bool ProfileViewModel::EditableUnfocusedAppearance() const noexcept
|
||||
{
|
||||
if constexpr (Feature_EditableUnfocusedAppearance::IsEnabled())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return Feature_EditableUnfocusedAppearance::IsEnabled();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::ShowUnfocusedAppearance()
|
||||
|
@ -286,6 +330,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
return _unfocusedAppearanceViewModel;
|
||||
}
|
||||
|
||||
bool ProfileViewModel::AtlasEngineAvailable() const noexcept
|
||||
{
|
||||
return Feature_AtlasEngine::IsEnabled();
|
||||
}
|
||||
|
||||
bool ProfileViewModel::UseParentProcessDirectory()
|
||||
{
|
||||
return StartingDirectory().empty();
|
||||
|
|
|
@ -33,7 +33,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
// only works on Win11. So we'll use that.
|
||||
//
|
||||
// Remove when we can remove the rest of GH#11285
|
||||
if (value < 100.0 && winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings::IsDefaultTerminalAvailable())
|
||||
if (value < 100.0 &&
|
||||
!winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings::IsDefaultTerminalAvailable())
|
||||
{
|
||||
UseAcrylic(true);
|
||||
}
|
||||
|
@ -60,12 +61,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
Editor::AppearanceViewModel DefaultAppearance();
|
||||
Editor::AppearanceViewModel UnfocusedAppearance();
|
||||
bool HasUnfocusedAppearance();
|
||||
bool EditableUnfocusedAppearance();
|
||||
bool EditableUnfocusedAppearance() const noexcept;
|
||||
bool ShowUnfocusedAppearance();
|
||||
|
||||
void CreateUnfocusedAppearance(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
|
||||
const IHostedInWindow& windowRoot);
|
||||
void DeleteUnfocusedAppearance();
|
||||
bool AtlasEngineAvailable() const noexcept;
|
||||
|
||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||
|
||||
|
@ -85,8 +86,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, StartingDirectory);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, ForceFullRepaintRendering);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, SoftwareRendering);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Foreground);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
|
||||
|
@ -96,6 +95,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, BellStyle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, UseAtlasEngine);
|
||||
|
||||
private:
|
||||
Model::Profile _profile;
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
Boolean EditableUnfocusedAppearance { get; };
|
||||
Boolean ShowUnfocusedAppearance { get; };
|
||||
AppearanceViewModel UnfocusedAppearance { get; };
|
||||
Boolean AtlasEngineAvailable { get; };
|
||||
|
||||
void CreateUnfocusedAppearance(Windows.Foundation.Collections.IMapView<String, Microsoft.Terminal.Settings.Model.ColorScheme> Schemes, IHostedInWindow WindowRoot);
|
||||
void DeleteUnfocusedAppearance();
|
||||
|
@ -53,8 +54,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ForceFullRepaintRendering);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SoftwareRendering);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Foreground);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Background);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, SelectionBackground);
|
||||
|
@ -63,6 +62,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.BellStyle, BellStyle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAtlasEngine);
|
||||
}
|
||||
|
||||
runtimeclass DeleteProfileEventArgs
|
||||
|
|
|
@ -319,7 +319,7 @@
|
|||
</StackPanel>
|
||||
<StackPanel>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance, Mode=OneWay}">
|
||||
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance}">
|
||||
<TextBlock x:Uid="Profile_UnfocusedAppearanceTextBlock"
|
||||
Style="{StaticResource TitleTextBlockStyle}" />
|
||||
<Button x:Uid="Profile_CreateUnfocusedAppearanceButton"
|
||||
|
@ -477,6 +477,15 @@
|
|||
IsChecked="{x:Bind IsBellStyleFlagSet(4), BindBack=SetBellStyleTaskbar, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</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>
|
||||
</ScrollViewer>
|
||||
</PivotItem>
|
||||
|
|
|
@ -927,6 +927,10 @@
|
|||
<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>
|
||||
</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">
|
||||
<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>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
// pch.h
|
||||
|
@ -51,8 +51,7 @@
|
|||
|
||||
#include <shlobj.h>
|
||||
#include <shobjidl_core.h>
|
||||
#include <dwrite.h>
|
||||
#include <dwrite_1.h>
|
||||
#include <dwrite_3.h>
|
||||
|
||||
// Manually include til after we include Windows.Foundation to give it winrt superpowers
|
||||
#include "til.h"
|
||||
|
|
|
@ -16,17 +16,6 @@ static constexpr std::string_view ForegroundKey{ "foreground" };
|
|||
static constexpr std::string_view BackgroundKey{ "background" };
|
||||
static constexpr std::string_view SelectionBackgroundKey{ "selectionBackground" };
|
||||
static constexpr std::string_view CursorColorKey{ "cursorColor" };
|
||||
static constexpr std::string_view CursorShapeKey{ "cursorShape" };
|
||||
static constexpr std::string_view CursorHeightKey{ "cursorHeight" };
|
||||
static constexpr std::string_view BackgroundImageKey{ "backgroundImage" };
|
||||
static constexpr std::string_view ColorSchemeKey{ "colorScheme" };
|
||||
static constexpr std::string_view BackgroundImageOpacityKey{ "backgroundImageOpacity" };
|
||||
static constexpr std::string_view BackgroundImageStretchModeKey{ "backgroundImageStretchMode" };
|
||||
static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageAlignment" };
|
||||
static constexpr std::string_view RetroTerminalEffectKey{ "experimental.retroTerminalEffect" };
|
||||
static constexpr std::string_view PixelShaderPathKey{ "experimental.pixelShaderPath" };
|
||||
static constexpr std::string_view IntenseTextStyleKey{ "intenseTextStyle" };
|
||||
static constexpr std::string_view AdjustIndistinguishableColorsKey{ "adjustIndistinguishableColors" };
|
||||
static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" };
|
||||
static constexpr std::string_view OpacityKey{ "opacity" };
|
||||
|
||||
|
@ -38,22 +27,17 @@ AppearanceConfig::AppearanceConfig(winrt::weak_ref<Profile> sourceProfile) :
|
|||
winrt::com_ptr<AppearanceConfig> AppearanceConfig::CopyAppearance(const AppearanceConfig* source, winrt::weak_ref<Profile> sourceProfile)
|
||||
{
|
||||
auto appearance{ winrt::make_self<AppearanceConfig>(std::move(sourceProfile)) };
|
||||
appearance->_BackgroundImagePath = source->_BackgroundImagePath;
|
||||
appearance->_BackgroundImageOpacity = source->_BackgroundImageOpacity;
|
||||
appearance->_BackgroundImageStretchMode = source->_BackgroundImageStretchMode;
|
||||
appearance->_ColorSchemeName = source->_ColorSchemeName;
|
||||
appearance->_Foreground = source->_Foreground;
|
||||
appearance->_Background = source->_Background;
|
||||
appearance->_SelectionBackground = source->_SelectionBackground;
|
||||
appearance->_CursorColor = source->_CursorColor;
|
||||
appearance->_CursorShape = source->_CursorShape;
|
||||
appearance->_CursorHeight = source->_CursorHeight;
|
||||
appearance->_BackgroundImageAlignment = source->_BackgroundImageAlignment;
|
||||
appearance->_RetroTerminalEffect = source->_RetroTerminalEffect;
|
||||
appearance->_PixelShaderPath = source->_PixelShaderPath;
|
||||
appearance->_IntenseTextStyle = source->_IntenseTextStyle;
|
||||
appearance->_Opacity = source->_Opacity;
|
||||
appearance->_AdjustIndistinguishableColors = source->_AdjustIndistinguishableColors;
|
||||
|
||||
#define APPEARANCE_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||
appearance->_##name = source->_##name;
|
||||
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_COPY)
|
||||
#undef APPEARANCE_SETTINGS_COPY
|
||||
|
||||
return appearance;
|
||||
}
|
||||
|
||||
|
@ -65,19 +49,13 @@ Json::Value AppearanceConfig::ToJson() const
|
|||
JsonUtils::SetValueForKey(json, BackgroundKey, _Background);
|
||||
JsonUtils::SetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
|
||||
JsonUtils::SetValueForKey(json, CursorColorKey, _CursorColor);
|
||||
JsonUtils::SetValueForKey(json, ColorSchemeKey, _ColorSchemeName);
|
||||
JsonUtils::SetValueForKey(json, CursorHeightKey, _CursorHeight);
|
||||
JsonUtils::SetValueForKey(json, CursorShapeKey, _CursorShape);
|
||||
JsonUtils::SetValueForKey(json, BackgroundImageKey, _BackgroundImagePath);
|
||||
JsonUtils::SetValueForKey(json, BackgroundImageOpacityKey, _BackgroundImageOpacity);
|
||||
JsonUtils::SetValueForKey(json, BackgroundImageStretchModeKey, _BackgroundImageStretchMode);
|
||||
JsonUtils::SetValueForKey(json, BackgroundImageAlignmentKey, _BackgroundImageAlignment);
|
||||
JsonUtils::SetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
|
||||
JsonUtils::SetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
|
||||
JsonUtils::SetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
|
||||
JsonUtils::SetValueForKey(json, AdjustIndistinguishableColorsKey, _AdjustIndistinguishableColors);
|
||||
JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
||||
|
||||
#define APPEARANCE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::SetValueForKey(json, jsonKey, _##name);
|
||||
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_TO_JSON)
|
||||
#undef APPEARANCE_SETTINGS_TO_JSON
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
@ -98,19 +76,14 @@ void AppearanceConfig::LayerJson(const Json::Value& json)
|
|||
JsonUtils::GetValueForKey(json, BackgroundKey, _Background);
|
||||
JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
|
||||
JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor);
|
||||
JsonUtils::GetValueForKey(json, CursorHeightKey, _CursorHeight);
|
||||
JsonUtils::GetValueForKey(json, ColorSchemeKey, _ColorSchemeName);
|
||||
JsonUtils::GetValueForKey(json, CursorShapeKey, _CursorShape);
|
||||
JsonUtils::GetValueForKey(json, BackgroundImageKey, _BackgroundImagePath);
|
||||
JsonUtils::GetValueForKey(json, BackgroundImageOpacityKey, _BackgroundImageOpacity);
|
||||
JsonUtils::GetValueForKey(json, BackgroundImageStretchModeKey, _BackgroundImageStretchMode);
|
||||
JsonUtils::GetValueForKey(json, BackgroundImageAlignmentKey, _BackgroundImageAlignment);
|
||||
JsonUtils::GetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
|
||||
JsonUtils::GetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
|
||||
JsonUtils::GetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
|
||||
JsonUtils::GetValueForKey(json, AdjustIndistinguishableColorsKey, _AdjustIndistinguishableColors);
|
||||
|
||||
JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
|
||||
JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
||||
|
||||
#define APPEARANCE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::GetValueForKey(json, jsonKey, _##name);
|
||||
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_LAYER_JSON)
|
||||
#undef APPEARANCE_SETTINGS_LAYER_JSON
|
||||
}
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile()
|
||||
|
|
|
@ -19,6 +19,7 @@ Author(s):
|
|||
#include "AppearanceConfig.g.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "IInheritable.h"
|
||||
#include "MTSMSettings.h"
|
||||
#include <DefaultSettings.h>
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
@ -35,26 +36,16 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
winrt::hstring ExpandedBackgroundImagePath();
|
||||
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, ConvergedAlignment, BackgroundImageAlignment, ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center);
|
||||
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, ColorSchemeName, L"Campbell");
|
||||
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, Foreground, nullptr);
|
||||
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, Background, nullptr);
|
||||
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, SelectionBackground, nullptr);
|
||||
INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, CursorColor, nullptr);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::CursorStyle, CursorShape, Microsoft::Terminal::Core::CursorStyle::Bar);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, BackgroundImagePath);
|
||||
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, double, BackgroundImageOpacity, 1.0);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch::UniformToFill);
|
||||
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, RetroTerminalEffect, false);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, PixelShaderPath, L"");
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, Model::IntenseStyle, IntenseTextStyle, Model::IntenseStyle::Bright);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0);
|
||||
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, AdjustIndistinguishableColors, true);
|
||||
#define APPEARANCE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, type, name, ##__VA_ARGS__)
|
||||
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_INITIALIZE)
|
||||
#undef APPEARANCE_SETTINGS_INITIALIZE
|
||||
|
||||
private:
|
||||
winrt::weak_ref<Profile> _sourceProfile;
|
||||
|
|
|
@ -9,8 +9,11 @@
|
|||
#include "ActionAndArgs.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "FileUtils.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
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 InitialPositionKey{ "initialPosition" };
|
||||
static constexpr std::string_view InitialSizeKey{ "initialSize" };
|
||||
|
@ -85,15 +88,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
return trait.FromJson(root);
|
||||
}
|
||||
|
||||
// Returns the application-global ApplicationState object.
|
||||
Microsoft::Terminal::Settings::Model::ApplicationState ApplicationState::SharedInstance()
|
||||
{
|
||||
static auto state = winrt::make_self<ApplicationState>(GetBaseSettingsPath() / stateFileName);
|
||||
return *state;
|
||||
}
|
||||
|
||||
ApplicationState::ApplicationState(std::filesystem::path path) noexcept :
|
||||
_path{ std::move(path) },
|
||||
ApplicationState::ApplicationState(const std::filesystem::path& stateRoot) noexcept :
|
||||
_sharedPath{ stateRoot / stateFileName },
|
||||
_elevatedPath{ stateRoot / elevatedStateFileName },
|
||||
_throttler{ std::chrono::seconds(1), [this]() { _write(); } }
|
||||
{
|
||||
_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.
|
||||
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,
|
||||
// but instead force it to run as soon as possible and wait for it to complete.
|
||||
_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.
|
||||
|
@ -113,34 +122,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
_read();
|
||||
}
|
||||
|
||||
// Returns the state.json path on the disk.
|
||||
winrt::hstring ApplicationState::FilePath() const noexcept
|
||||
bool ApplicationState::IsStatePath(const winrt::hstring& filename)
|
||||
{
|
||||
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:
|
||||
// - 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
|
||||
|
@ -156,57 +144,58 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
void ApplicationState::Reset() noexcept
|
||||
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() = {};
|
||||
}
|
||||
CATCH_LOG()
|
||||
|
||||
Json::Value ApplicationState::_getRoot(const locked_hfile& file) const noexcept
|
||||
{
|
||||
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.
|
||||
// Deserializes the state.json and user-state (or elevated-state if
|
||||
// elevated) into this ApplicationState.
|
||||
// * 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.
|
||||
void ApplicationState::_read() const noexcept
|
||||
try
|
||||
{
|
||||
auto state = _state.lock();
|
||||
const auto file = OpenFileReadSharedLocked(_path);
|
||||
std::string errs;
|
||||
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
|
||||
|
||||
auto root = _getRoot(file);
|
||||
// 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.
|
||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
||||
if (!state->name##Changed) \
|
||||
{ \
|
||||
state->name = JsonUtils::GetValueForKey<std::optional<type>>(root, key); \
|
||||
}
|
||||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||
#undef MTSM_APPLICATION_STATE_GEN
|
||||
// First get shared state out of `state.json`.
|
||||
const auto sharedData = _readSharedContents().value_or(std::string{});
|
||||
if (!sharedData.empty())
|
||||
{
|
||||
Json::Value root;
|
||||
if (!reader->parse(sharedData.data(), sharedData.data() + sharedData.size(), &root, &errs))
|
||||
{
|
||||
throw winrt::hresult_error(WEB_E_INVALID_JSON_STRING, winrt::to_hstring(errs));
|
||||
}
|
||||
|
||||
// - If we're elevated, we want to only load the Shared properties
|
||||
// from state.json. We'll then load the Local props from
|
||||
// `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()
|
||||
|
||||
|
@ -214,29 +203,191 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
// * Errors are only logged.
|
||||
// * _state->_writeScheduled is set to false, signaling our
|
||||
// setters that _synchronize() needs to be called again.
|
||||
void ApplicationState::_write() noexcept
|
||||
void ApplicationState::_write() const noexcept
|
||||
try
|
||||
{
|
||||
// re-read the state so that we can only update the properties that were changed.
|
||||
Json::Value root{};
|
||||
Json::StreamWriterBuilder wbuilder;
|
||||
|
||||
// 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();
|
||||
const auto file = OpenFileRWExclusiveLocked(_path);
|
||||
root = _getRoot(file);
|
||||
std::string errs;
|
||||
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
|
||||
Json::Value root;
|
||||
|
||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
||||
if (state->name##Changed) \
|
||||
{ \
|
||||
JsonUtils::SetValueForKey(root, key, state->name); \
|
||||
state->name##Changed = false; \
|
||||
}
|
||||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||
#undef MTSM_APPLICATION_STATE_GEN
|
||||
// First load the contents of state.json into a json blob. This will
|
||||
// contain the Shared properties and the unelevated instance's Local
|
||||
// properties.
|
||||
const auto sharedData = _readSharedContents().value_or(std::string{});
|
||||
if (!sharedData.empty())
|
||||
{
|
||||
if (!reader->parse(sharedData.data(), sharedData.data() + sharedData.size(), &root, &errs))
|
||||
{
|
||||
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;
|
||||
const auto content = Json::writeString(wbuilder, root);
|
||||
WriteUTF8FileLocked(file, content);
|
||||
// Finally, write our Local properties back to elevated-state.json
|
||||
_writeLocalContents(Json::writeString(wbuilder, ToJson(FileSource::Local)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're unelevated, this is easy. Just write everything back out.
|
||||
_writeLocalContents(Json::writeString(wbuilder, ToJson(FileSource::Local | FileSource::Shared)));
|
||||
}
|
||||
}
|
||||
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 <inc/cppwinrt_utils.h>
|
||||
#include <til/mutex.h>
|
||||
#include <til/throttled_func.h>
|
||||
#include "FileUtils.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.
|
||||
// It provides X with the following arguments:
|
||||
// (type, function name, JSON key, ...variadic construction arguments)
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
#define MTSM_APPLICATION_STATE_FIELDS(X) \
|
||||
X(std::unordered_set<winrt::guid>, GeneratedProfiles, "generatedProfiles") \
|
||||
X(Windows::Foundation::Collections::IVector<Model::WindowLayout>, PersistedWindowLayouts, "persistedWindowLayouts") \
|
||||
X(Windows::Foundation::Collections::IVector<hstring>, RecentCommands, "recentCommands") \
|
||||
X(Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage>, DismissedMessages, "dismissedMessages")
|
||||
// (source, type, function name, JSON key, ...variadic construction arguments)
|
||||
#define MTSM_APPLICATION_STATE_FIELDS(X) \
|
||||
X(FileSource::Shared, std::unordered_set<winrt::guid>, GeneratedProfiles, "generatedProfiles") \
|
||||
X(FileSource::Local, Windows::Foundation::Collections::IVector<Model::WindowLayout>, PersistedWindowLayouts, "persistedWindowLayouts") \
|
||||
X(FileSource::Shared, Windows::Foundation::Collections::IVector<hstring>, RecentCommands, "recentCommands") \
|
||||
X(FileSource::Shared, Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage>, DismissedMessages, "dismissedMessages") \
|
||||
X(FileSource::Local, Windows::Foundation::Collections::IVector<hstring>, AllowedCommandlines, "allowedCommandlines")
|
||||
|
||||
struct WindowLayout : WindowLayoutT<WindowLayout>
|
||||
{
|
||||
|
@ -44,23 +53,26 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
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();
|
||||
|
||||
ApplicationState(std::filesystem::path path) noexcept;
|
||||
ApplicationState(const std::filesystem::path& stateRoot) noexcept;
|
||||
~ApplicationState();
|
||||
|
||||
// Methods
|
||||
void Reload() const noexcept;
|
||||
void Reset() noexcept;
|
||||
|
||||
void FromJson(const Json::Value& root, FileSource parseSource) const noexcept;
|
||||
Json::Value ToJson(FileSource parseSource) const noexcept;
|
||||
|
||||
// General getters/setters
|
||||
winrt::hstring FilePath() const noexcept;
|
||||
bool IsStatePath(const winrt::hstring& filename);
|
||||
|
||||
// State getters/setters
|
||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
||||
type name() const noexcept; \
|
||||
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \
|
||||
type name() const noexcept; \
|
||||
void name(const type& value) noexcept;
|
||||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||
#undef MTSM_APPLICATION_STATE_GEN
|
||||
|
@ -68,21 +80,24 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
private:
|
||||
struct state_t
|
||||
{
|
||||
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
|
||||
std::optional<type> name{ __VA_ARGS__ }; \
|
||||
bool name##Changed = false;
|
||||
|
||||
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) std::optional<type> name{ __VA_ARGS__ };
|
||||
MTSM_APPLICATION_STATE_FIELDS(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() noexcept;
|
||||
void _write() const noexcept;
|
||||
void _read() const noexcept;
|
||||
|
||||
std::filesystem::path _path;
|
||||
til::shared_mutex<state_t> _state;
|
||||
til::throttled_func_trailing<> _throttler;
|
||||
Json::Value _toJsonWithBlob(Json::Value& root, FileSource parseSource) const noexcept;
|
||||
|
||||
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 Reset();
|
||||
|
||||
String FilePath { get; };
|
||||
Boolean IsStatePath(String filename);
|
||||
|
||||
Windows.Foundation.Collections.IVector<WindowLayout> PersistedWindowLayouts { get; set; };
|
||||
|
||||
Windows.Foundation.Collections.IVector<String> RecentCommands { get; set; };
|
||||
|
||||
Windows.Foundation.Collections.IVector<InfoBarMessage> DismissedMessages { get; set; };
|
||||
|
||||
Windows.Foundation.Collections.IVector<String> AllowedCommandlines { get; set; };
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -287,8 +287,6 @@ Model::Profile CascadiaSettings::DuplicateProfile(const Model::Profile& source)
|
|||
DUPLICATE_SETTING_MACRO(Commandline);
|
||||
DUPLICATE_SETTING_MACRO(StartingDirectory);
|
||||
DUPLICATE_SETTING_MACRO(AntialiasingMode);
|
||||
DUPLICATE_SETTING_MACRO(ForceFullRepaintRendering);
|
||||
DUPLICATE_SETTING_MACRO(SoftwareRendering);
|
||||
DUPLICATE_SETTING_MACRO(HistorySize);
|
||||
DUPLICATE_SETTING_MACRO(SnapOnInput);
|
||||
DUPLICATE_SETTING_MACRO(AltGrAliasing);
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
#include <shlobj.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::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" };
|
||||
|
||||
|
@ -39,86 +43,44 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
|||
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) };
|
||||
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(),
|
||||
0, // lock shared, 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 };
|
||||
// If the file is owned by the administrators group, trust the
|
||||
// administrators instead of checking the DACL permissions. It's simpler
|
||||
// and more flexible.
|
||||
|
||||
wil::unique_hlocal_security_descriptor sd;
|
||||
PSID psidOwner{ nullptr };
|
||||
// The psidOwner pointer references the security descriptor, so it
|
||||
// doesn't have to be freed separate from sd.
|
||||
const auto status = GetSecurityInfo(handle,
|
||||
SE_FILE_OBJECT,
|
||||
OWNER_SECURITY_INFORMATION,
|
||||
&psidOwner,
|
||||
nullptr,
|
||||
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.
|
||||
// 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:
|
||||
// * 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.
|
||||
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);
|
||||
|
||||
// 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);
|
||||
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.
|
||||
std::optional<std::string> ReadUTF8FileIfExists(const std::filesystem::path& path)
|
||||
std::optional<std::string> ReadUTF8FileIfExists(const std::filesystem::path& path, const bool elevatedOnly)
|
||||
{
|
||||
try
|
||||
{
|
||||
return { ReadUTF8File(path) };
|
||||
return { ReadUTF8File(path, elevatedOnly) };
|
||||
}
|
||||
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);
|
||||
|
||||
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.
|
||||
// It's thus important that we first resolve them before generating temporary path.
|
||||
|
|
|
@ -1,41 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
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();
|
||||
|
||||
locked_hfile OpenFileReadSharedLocked(const std::filesystem::path& path);
|
||||
locked_hfile OpenFileRWExclusiveLocked(const std::filesystem::path& path);
|
||||
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);
|
||||
std::string ReadUTF8File(const std::filesystem::path& path, const bool elevatedOnly = false);
|
||||
std::optional<std::string> ReadUTF8FileIfExists(const std::filesystem::path& path, const bool elevatedOnly = false);
|
||||
void WriteUTF8File(const std::filesystem::path& path, const std::string_view& content, const bool elevatedOnly = false);
|
||||
void WriteUTF8FileAtomic(const std::filesystem::path& path, const std::string_view& content);
|
||||
}
|
||||
|
|
|
@ -12,11 +12,6 @@ using namespace Microsoft::Terminal::Settings::Model;
|
|||
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
||||
|
||||
static constexpr std::string_view FontInfoKey{ "font" };
|
||||
static constexpr std::string_view FontFaceKey{ "face" };
|
||||
static constexpr std::string_view FontSizeKey{ "size" };
|
||||
static constexpr std::string_view FontWeightKey{ "weight" };
|
||||
static constexpr std::string_view FontFeaturesKey{ "features" };
|
||||
static constexpr std::string_view FontAxesKey{ "axes" };
|
||||
static constexpr std::string_view LegacyFontFaceKey{ "fontFace" };
|
||||
static constexpr std::string_view LegacyFontSizeKey{ "fontSize" };
|
||||
static constexpr std::string_view LegacyFontWeightKey{ "fontWeight" };
|
||||
|
@ -29,11 +24,12 @@ winrt::Microsoft::Terminal::Settings::Model::implementation::FontConfig::FontCon
|
|||
winrt::com_ptr<FontConfig> FontConfig::CopyFontInfo(const FontConfig* source, winrt::weak_ref<Profile> sourceProfile)
|
||||
{
|
||||
auto fontInfo{ winrt::make_self<FontConfig>(std::move(sourceProfile)) };
|
||||
fontInfo->_FontFace = source->_FontFace;
|
||||
fontInfo->_FontSize = source->_FontSize;
|
||||
fontInfo->_FontWeight = source->_FontWeight;
|
||||
fontInfo->_FontAxes = source->_FontAxes;
|
||||
fontInfo->_FontFeatures = source->_FontFeatures;
|
||||
|
||||
#define FONT_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||
fontInfo->_##name = source->_##name;
|
||||
MTSM_FONT_SETTINGS(FONT_SETTINGS_COPY)
|
||||
#undef FONT_SETTINGS_COPY
|
||||
|
||||
return fontInfo;
|
||||
}
|
||||
|
||||
|
@ -41,11 +37,10 @@ Json::Value FontConfig::ToJson() const
|
|||
{
|
||||
Json::Value json{ Json::ValueType::objectValue };
|
||||
|
||||
JsonUtils::SetValueForKey(json, FontFaceKey, _FontFace);
|
||||
JsonUtils::SetValueForKey(json, FontSizeKey, _FontSize);
|
||||
JsonUtils::SetValueForKey(json, FontWeightKey, _FontWeight);
|
||||
JsonUtils::SetValueForKey(json, FontAxesKey, _FontAxes);
|
||||
JsonUtils::SetValueForKey(json, FontFeaturesKey, _FontFeatures);
|
||||
#define FONT_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::SetValueForKey(json, jsonKey, _##name);
|
||||
MTSM_FONT_SETTINGS(FONT_SETTINGS_TO_JSON)
|
||||
#undef FONT_SETTINGS_TO_JSON
|
||||
|
||||
return json;
|
||||
}
|
||||
|
@ -69,11 +64,10 @@ void FontConfig::LayerJson(const Json::Value& json)
|
|||
{
|
||||
// A font object is defined, use that
|
||||
const auto fontInfoJson = json[JsonKey(FontInfoKey)];
|
||||
JsonUtils::GetValueForKey(fontInfoJson, FontFaceKey, _FontFace);
|
||||
JsonUtils::GetValueForKey(fontInfoJson, FontSizeKey, _FontSize);
|
||||
JsonUtils::GetValueForKey(fontInfoJson, FontWeightKey, _FontWeight);
|
||||
JsonUtils::GetValueForKey(fontInfoJson, FontFeaturesKey, _FontFeatures);
|
||||
JsonUtils::GetValueForKey(fontInfoJson, FontAxesKey, _FontAxes);
|
||||
#define FONT_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::GetValueForKey(fontInfoJson, jsonKey, _##name);
|
||||
MTSM_FONT_SETTINGS(FONT_SETTINGS_LAYER_JSON)
|
||||
#undef FONT_SETTINGS_LAYER_JSON
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@ Author(s):
|
|||
#include "pch.h"
|
||||
#include "FontConfig.g.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "MTSMSettings.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
#include "IInheritable.h"
|
||||
#include <DefaultSettings.h>
|
||||
|
@ -39,11 +40,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
Model::Profile SourceProfile();
|
||||
|
||||
INHERITABLE_SETTING(Model::FontConfig, hstring, FontFace, DEFAULT_FONT_FACE);
|
||||
INHERITABLE_SETTING(Model::FontConfig, int32_t, FontSize, DEFAULT_FONT_SIZE);
|
||||
INHERITABLE_SETTING(Model::FontConfig, Windows::UI::Text::FontWeight, FontWeight, DEFAULT_FONT_WEIGHT);
|
||||
INHERITABLE_SETTING(Model::FontConfig, IFontAxesMap, FontAxes);
|
||||
INHERITABLE_SETTING(Model::FontConfig, IFontFeatureMap, FontFeatures);
|
||||
#define FONT_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
|
||||
INHERITABLE_SETTING(Model::FontConfig, type, name, ##__VA_ARGS__)
|
||||
MTSM_FONT_SETTINGS(FONT_SETTINGS_INITIALIZE)
|
||||
#undef FONT_SETTINGS_INITIALIZE
|
||||
|
||||
private:
|
||||
winrt::weak_ref<Profile> _sourceProfile;
|
||||
|
|
|
@ -18,48 +18,7 @@ using namespace winrt::Microsoft::UI::Xaml::Controls;
|
|||
static constexpr std::string_view LegacyKeybindingsKey{ "keybindings" };
|
||||
static constexpr std::string_view ActionsKey{ "actions" };
|
||||
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
|
||||
static constexpr std::string_view AlwaysShowTabsKey{ "alwaysShowTabs" };
|
||||
static constexpr std::string_view InitialRowsKey{ "initialRows" };
|
||||
static constexpr std::string_view InitialColsKey{ "initialCols" };
|
||||
static constexpr std::string_view InitialPositionKey{ "initialPosition" };
|
||||
static constexpr std::string_view CenterOnLaunchKey{ "centerOnLaunch" };
|
||||
static constexpr std::string_view ShowTitleInTitlebarKey{ "showTerminalTitleInTitlebar" };
|
||||
static constexpr std::string_view LanguageKey{ "language" };
|
||||
static constexpr std::string_view ThemeKey{ "theme" };
|
||||
static constexpr std::string_view TabWidthModeKey{ "tabWidthMode" };
|
||||
static constexpr std::string_view UseAcrylicInTabRowKey{ "useAcrylicInTabRow" };
|
||||
static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" };
|
||||
static constexpr std::string_view WordDelimitersKey{ "wordDelimiters" };
|
||||
static constexpr std::string_view InputServiceWarningKey{ "inputServiceWarning" };
|
||||
static constexpr std::string_view CopyOnSelectKey{ "copyOnSelect" };
|
||||
static constexpr std::string_view CopyFormattingKey{ "copyFormatting" };
|
||||
static constexpr std::string_view WarnAboutLargePasteKey{ "largePasteWarning" };
|
||||
static constexpr std::string_view WarnAboutMultiLinePasteKey{ "multiLinePasteWarning" };
|
||||
static constexpr std::string_view TrimPasteKey{ "trimPaste" };
|
||||
static constexpr std::string_view LaunchModeKey{ "launchMode" };
|
||||
static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" };
|
||||
static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" };
|
||||
static constexpr std::string_view EnableStartupTaskKey{ "startOnUserLogin" };
|
||||
static constexpr std::string_view FirstWindowPreferenceKey{ "firstWindowPreference" };
|
||||
static constexpr std::string_view AlwaysOnTopKey{ "alwaysOnTop" };
|
||||
static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" };
|
||||
static constexpr std::string_view TabSwitcherModeKey{ "tabSwitcherMode" };
|
||||
static constexpr std::string_view DisableAnimationsKey{ "disableAnimations" };
|
||||
static constexpr std::string_view StartupActionsKey{ "startupActions" };
|
||||
static constexpr std::string_view FocusFollowMouseKey{ "focusFollowMouse" };
|
||||
static constexpr std::string_view WindowingBehaviorKey{ "windowingBehavior" };
|
||||
static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" };
|
||||
static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" };
|
||||
static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" };
|
||||
static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSources" };
|
||||
static constexpr std::string_view ShowAdminShieldKey{ "showAdminShield" };
|
||||
|
||||
static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };
|
||||
|
||||
static constexpr std::string_view ForceFullRepaintRenderingKey{ "experimental.rendering.forceFullRepaint" };
|
||||
static constexpr std::string_view SoftwareRenderingKey{ "experimental.rendering.software" };
|
||||
static constexpr std::string_view ForceVTInputKey{ "experimental.input.forceVT" };
|
||||
static constexpr std::string_view DetectURLsKey{ "experimental.detectURLs" };
|
||||
|
||||
// Method Description:
|
||||
// - Copies any extraneous data from the parent before completing a CreateChild call
|
||||
|
@ -86,45 +45,6 @@ void GlobalAppSettings::_FinalizeInheritance()
|
|||
winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
||||
{
|
||||
auto globals{ winrt::make_self<GlobalAppSettings>() };
|
||||
globals->_InitialRows = _InitialRows;
|
||||
globals->_InitialCols = _InitialCols;
|
||||
globals->_AlwaysShowTabs = _AlwaysShowTabs;
|
||||
globals->_ShowTitleInTitlebar = _ShowTitleInTitlebar;
|
||||
globals->_ConfirmCloseAllTabs = _ConfirmCloseAllTabs;
|
||||
globals->_Language = _Language;
|
||||
globals->_Theme = _Theme;
|
||||
globals->_TabWidthMode = _TabWidthMode;
|
||||
globals->_UseAcrylicInTabRow = _UseAcrylicInTabRow;
|
||||
globals->_ShowTabsInTitlebar = _ShowTabsInTitlebar;
|
||||
globals->_WordDelimiters = _WordDelimiters;
|
||||
globals->_InputServiceWarning = _InputServiceWarning;
|
||||
globals->_CopyOnSelect = _CopyOnSelect;
|
||||
globals->_CopyFormatting = _CopyFormatting;
|
||||
globals->_WarnAboutLargePaste = _WarnAboutLargePaste;
|
||||
globals->_WarnAboutMultiLinePaste = _WarnAboutMultiLinePaste;
|
||||
globals->_TrimPaste = _TrimPaste;
|
||||
globals->_InitialPosition = _InitialPosition;
|
||||
globals->_CenterOnLaunch = _CenterOnLaunch;
|
||||
globals->_LaunchMode = _LaunchMode;
|
||||
globals->_SnapToGridOnResize = _SnapToGridOnResize;
|
||||
globals->_ForceFullRepaintRendering = _ForceFullRepaintRendering;
|
||||
globals->_SoftwareRendering = _SoftwareRendering;
|
||||
globals->_ForceVTInput = _ForceVTInput;
|
||||
globals->_DebugFeaturesEnabled = _DebugFeaturesEnabled;
|
||||
globals->_StartOnUserLogin = _StartOnUserLogin;
|
||||
globals->_FirstWindowPreference = _FirstWindowPreference;
|
||||
globals->_AlwaysOnTop = _AlwaysOnTop;
|
||||
globals->_TabSwitcherMode = _TabSwitcherMode;
|
||||
globals->_DisableAnimations = _DisableAnimations;
|
||||
globals->_StartupActions = _StartupActions;
|
||||
globals->_FocusFollowMouse = _FocusFollowMouse;
|
||||
globals->_WindowingBehavior = _WindowingBehavior;
|
||||
globals->_TrimBlockSelection = _TrimBlockSelection;
|
||||
globals->_DetectURLs = _DetectURLs;
|
||||
globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea;
|
||||
globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon;
|
||||
globals->_DisabledProfileSources = _DisabledProfileSources;
|
||||
globals->_ShowAdminShield = _ShowAdminShield;
|
||||
|
||||
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
|
||||
|
||||
|
@ -132,6 +52,11 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
|||
globals->_actionMap = _actionMap->Copy();
|
||||
globals->_keybindingsWarnings = _keybindingsWarnings;
|
||||
|
||||
#define GLOBAL_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||
globals->_##name = _##name;
|
||||
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_COPY)
|
||||
#undef GLOBAL_SETTINGS_COPY
|
||||
|
||||
if (_colorSchemes)
|
||||
{
|
||||
for (auto kv : _colorSchemes)
|
||||
|
@ -189,51 +114,15 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::FromJson(const Json::Value&
|
|||
void GlobalAppSettings::LayerJson(const Json::Value& json)
|
||||
{
|
||||
JsonUtils::GetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile);
|
||||
JsonUtils::GetValueForKey(json, AlwaysShowTabsKey, _AlwaysShowTabs);
|
||||
JsonUtils::GetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs);
|
||||
JsonUtils::GetValueForKey(json, InitialRowsKey, _InitialRows);
|
||||
JsonUtils::GetValueForKey(json, InitialColsKey, _InitialCols);
|
||||
JsonUtils::GetValueForKey(json, InitialPositionKey, _InitialPosition);
|
||||
JsonUtils::GetValueForKey(json, CenterOnLaunchKey, _CenterOnLaunch);
|
||||
JsonUtils::GetValueForKey(json, ShowTitleInTitlebarKey, _ShowTitleInTitlebar);
|
||||
JsonUtils::GetValueForKey(json, ShowTabsInTitlebarKey, _ShowTabsInTitlebar);
|
||||
JsonUtils::GetValueForKey(json, WordDelimitersKey, _WordDelimiters);
|
||||
JsonUtils::GetValueForKey(json, CopyOnSelectKey, _CopyOnSelect);
|
||||
JsonUtils::GetValueForKey(json, InputServiceWarningKey, _InputServiceWarning);
|
||||
JsonUtils::GetValueForKey(json, CopyFormattingKey, _CopyFormatting);
|
||||
JsonUtils::GetValueForKey(json, WarnAboutLargePasteKey, _WarnAboutLargePaste);
|
||||
JsonUtils::GetValueForKey(json, WarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste);
|
||||
JsonUtils::GetValueForKey(json, TrimPasteKey, _TrimPaste);
|
||||
JsonUtils::GetValueForKey(json, FirstWindowPreferenceKey, _FirstWindowPreference);
|
||||
JsonUtils::GetValueForKey(json, LaunchModeKey, _LaunchMode);
|
||||
JsonUtils::GetValueForKey(json, LanguageKey, _Language);
|
||||
JsonUtils::GetValueForKey(json, ThemeKey, _Theme);
|
||||
JsonUtils::GetValueForKey(json, TabWidthModeKey, _TabWidthMode);
|
||||
JsonUtils::GetValueForKey(json, UseAcrylicInTabRowKey, _UseAcrylicInTabRow);
|
||||
JsonUtils::GetValueForKey(json, SnapToGridOnResizeKey, _SnapToGridOnResize);
|
||||
// GetValueForKey will only override the current value if the key exists
|
||||
JsonUtils::GetValueForKey(json, DebugFeaturesKey, _DebugFeaturesEnabled);
|
||||
JsonUtils::GetValueForKey(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering);
|
||||
JsonUtils::GetValueForKey(json, SoftwareRenderingKey, _SoftwareRendering);
|
||||
JsonUtils::GetValueForKey(json, ForceVTInputKey, _ForceVTInput);
|
||||
JsonUtils::GetValueForKey(json, EnableStartupTaskKey, _StartOnUserLogin);
|
||||
JsonUtils::GetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop);
|
||||
// GH#8076 - when adding enum values to this key, we also changed it from
|
||||
// "useTabSwitcher" to "tabSwitcherMode". Continue supporting
|
||||
// "useTabSwitcher", but prefer "tabSwitcherMode"
|
||||
JsonUtils::GetValueForKey(json, LegacyUseTabSwitcherModeKey, _TabSwitcherMode);
|
||||
JsonUtils::GetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode);
|
||||
JsonUtils::GetValueForKey(json, DisableAnimationsKey, _DisableAnimations);
|
||||
JsonUtils::GetValueForKey(json, StartupActionsKey, _StartupActions);
|
||||
JsonUtils::GetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse);
|
||||
JsonUtils::GetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior);
|
||||
JsonUtils::GetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection);
|
||||
JsonUtils::GetValueForKey(json, DetectURLsKey, _DetectURLs);
|
||||
JsonUtils::GetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
||||
JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
JsonUtils::GetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
|
||||
|
||||
JsonUtils::GetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield);
|
||||
#define GLOBAL_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::GetValueForKey(json, jsonKey, _##name);
|
||||
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_LAYER_JSON)
|
||||
#undef GLOBAL_SETTINGS_LAYER_JSON
|
||||
|
||||
static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey };
|
||||
for (const auto& jsonKey : bindingsKeys)
|
||||
|
@ -293,48 +182,12 @@ Json::Value GlobalAppSettings::ToJson() const
|
|||
{
|
||||
Json::Value json{ Json::ValueType::objectValue };
|
||||
|
||||
// clang-format off
|
||||
JsonUtils::SetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile);
|
||||
JsonUtils::SetValueForKey(json, AlwaysShowTabsKey, _AlwaysShowTabs);
|
||||
JsonUtils::SetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs);
|
||||
JsonUtils::SetValueForKey(json, InitialRowsKey, _InitialRows);
|
||||
JsonUtils::SetValueForKey(json, InitialColsKey, _InitialCols);
|
||||
JsonUtils::SetValueForKey(json, InitialPositionKey, _InitialPosition);
|
||||
JsonUtils::SetValueForKey(json, CenterOnLaunchKey, _CenterOnLaunch);
|
||||
JsonUtils::SetValueForKey(json, ShowTitleInTitlebarKey, _ShowTitleInTitlebar);
|
||||
JsonUtils::SetValueForKey(json, ShowTabsInTitlebarKey, _ShowTabsInTitlebar);
|
||||
JsonUtils::SetValueForKey(json, WordDelimitersKey, _WordDelimiters);
|
||||
JsonUtils::SetValueForKey(json, InputServiceWarningKey, _InputServiceWarning);
|
||||
JsonUtils::SetValueForKey(json, CopyOnSelectKey, _CopyOnSelect);
|
||||
JsonUtils::SetValueForKey(json, CopyFormattingKey, _CopyFormatting);
|
||||
JsonUtils::SetValueForKey(json, WarnAboutLargePasteKey, _WarnAboutLargePaste);
|
||||
JsonUtils::SetValueForKey(json, WarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste);
|
||||
JsonUtils::SetValueForKey(json, TrimPasteKey, _TrimPaste);
|
||||
JsonUtils::SetValueForKey(json, FirstWindowPreferenceKey, _FirstWindowPreference);
|
||||
JsonUtils::SetValueForKey(json, LaunchModeKey, _LaunchMode);
|
||||
JsonUtils::SetValueForKey(json, LanguageKey, _Language);
|
||||
JsonUtils::SetValueForKey(json, ThemeKey, _Theme);
|
||||
JsonUtils::SetValueForKey(json, TabWidthModeKey, _TabWidthMode);
|
||||
JsonUtils::SetValueForKey(json, UseAcrylicInTabRowKey, _UseAcrylicInTabRow);
|
||||
JsonUtils::SetValueForKey(json, SnapToGridOnResizeKey, _SnapToGridOnResize);
|
||||
JsonUtils::SetValueForKey(json, DebugFeaturesKey, _DebugFeaturesEnabled);
|
||||
JsonUtils::SetValueForKey(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering);
|
||||
JsonUtils::SetValueForKey(json, SoftwareRenderingKey, _SoftwareRendering);
|
||||
JsonUtils::SetValueForKey(json, ForceVTInputKey, _ForceVTInput);
|
||||
JsonUtils::SetValueForKey(json, EnableStartupTaskKey, _StartOnUserLogin);
|
||||
JsonUtils::SetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop);
|
||||
JsonUtils::SetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode);
|
||||
JsonUtils::SetValueForKey(json, DisableAnimationsKey, _DisableAnimations);
|
||||
JsonUtils::SetValueForKey(json, StartupActionsKey, _StartupActions);
|
||||
JsonUtils::SetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse);
|
||||
JsonUtils::SetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior);
|
||||
JsonUtils::SetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection);
|
||||
JsonUtils::SetValueForKey(json, DetectURLsKey, _DetectURLs);
|
||||
JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
||||
JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
JsonUtils::SetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
|
||||
JsonUtils::SetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield);
|
||||
// clang-format on
|
||||
JsonUtils::SetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile);
|
||||
|
||||
#define GLOBAL_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::SetValueForKey(json, jsonKey, _##name);
|
||||
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_TO_JSON)
|
||||
#undef GLOBAL_SETTINGS_TO_JSON
|
||||
|
||||
json[JsonKey(ActionsKey)] = _actionMap->ToJson();
|
||||
return json;
|
||||
|
|
|
@ -17,6 +17,7 @@ Author(s):
|
|||
|
||||
#include "GlobalAppSettings.g.h"
|
||||
#include "IInheritable.h"
|
||||
#include "MTSMSettings.h"
|
||||
|
||||
#include "ActionMap.h"
|
||||
#include "Command.h"
|
||||
|
@ -61,46 +62,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
DisableAnimations(!invertedDisableAnimationsValue);
|
||||
}
|
||||
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, int32_t, InitialRows, DEFAULT_ROWS);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, int32_t, InitialCols, DEFAULT_COLS);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowTabs, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowTitleInTitlebar, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ConfirmCloseAllTabs, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, Language);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::UI::Xaml::ElementTheme, Theme, winrt::Windows::UI::Xaml::ElementTheme::Default);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, UseAcrylicInTabRow, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowTabsInTitlebar, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, CopyOnSelect, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, InputServiceWarning, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, WarnAboutLargePaste, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, WarnAboutMultiLinePaste, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, TrimPaste, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::LaunchPosition, InitialPosition, nullptr, nullptr);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, CenterOnLaunch, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::FirstWindowPreference, FirstWindowPreference, FirstWindowPreference::DefaultProfile);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::LaunchMode, LaunchMode, LaunchMode::DefaultMode);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, SnapToGridOnResize, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ForceFullRepaintRendering, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, SoftwareRendering, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ForceVTInput, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DebugFeaturesEnabled, debugFeaturesDefault);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, StartOnUserLogin, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysOnTop, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::TabSwitcherMode, TabSwitcherMode, Model::TabSwitcherMode::InOrder);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DisableAnimations, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, StartupActions, L"");
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, FocusFollowMouse, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::WindowingMode, WindowingBehavior, Model::WindowingMode::UseNew);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, TrimBlockSelection, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DetectURLs, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, MinimizeToNotificationArea, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, nullptr);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowAdminShield, true);
|
||||
|
||||
#define GLOBAL_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, type, name, ##__VA_ARGS__)
|
||||
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_INITIALIZE)
|
||||
#undef GLOBAL_SETTINGS_INITIALIZE
|
||||
|
||||
private:
|
||||
#ifdef NDEBUG
|
||||
|
|
|
@ -382,7 +382,6 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
struct ConversionTrait<std::unordered_map<std::string, T>>
|
||||
{
|
||||
std::unordered_map<std::string, T> FromJson(const Json::Value& json) const
|
||||
|
|
97
src/cascadia/TerminalSettingsModel/MTSMSettings.h
Normal file
97
src/cascadia/TerminalSettingsModel/MTSMSettings.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- MTSMSettings.h
|
||||
|
||||
Abstract:
|
||||
- Contains most of the settings within Terminal Settings Model (global, profile, font, appearance)
|
||||
- To add a new setting to any one of those classes, simply add it to the respective list below, following the macro format
|
||||
|
||||
Author(s):
|
||||
- Pankaj Bhojwani - October 2021
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
// Macro format (defaultArgs are optional):
|
||||
// (type, name, jsonKey, defaultArgs)
|
||||
|
||||
#define MTSM_GLOBAL_SETTINGS(X) \
|
||||
X(int32_t, InitialRows, "initialRows", 30) \
|
||||
X(int32_t, InitialCols, "initialCols", 80) \
|
||||
X(hstring, WordDelimiters, "wordDelimiters", DEFAULT_WORD_DELIMITERS) \
|
||||
X(bool, CopyOnSelect, "copyOnSelect", false) \
|
||||
X(bool, FocusFollowMouse, "focusFollowMouse", false) \
|
||||
X(bool, ForceFullRepaintRendering, "experimental.rendering.forceFullRepaint", false) \
|
||||
X(bool, SoftwareRendering, "experimental.rendering.software", false) \
|
||||
X(bool, ForceVTInput, "experimental.input.forceVT", false) \
|
||||
X(bool, TrimBlockSelection, "trimBlockSelection", false) \
|
||||
X(bool, DetectURLs, "experimental.detectURLs", true) \
|
||||
X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \
|
||||
X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \
|
||||
X(bool, ConfirmCloseAllTabs, "confirmCloseAllTabs", true) \
|
||||
X(hstring, Language, "language") \
|
||||
X(winrt::Windows::UI::Xaml::ElementTheme, Theme, "theme", winrt::Windows::UI::Xaml::ElementTheme::Default) \
|
||||
X(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, "tabWidthMode", winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal) \
|
||||
X(bool, UseAcrylicInTabRow, "useAcrylicInTabRow", false) \
|
||||
X(bool, ShowTabsInTitlebar, "showTabsInTitlebar", true) \
|
||||
X(bool, InputServiceWarning, "inputServiceWarning", true) \
|
||||
X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, "copyFormatting", 0) \
|
||||
X(bool, WarnAboutLargePaste, "largePasteWarning", true) \
|
||||
X(bool, WarnAboutMultiLinePaste, "multiLinePasteWarning", true) \
|
||||
X(Model::LaunchPosition, InitialPosition, "initialPosition", nullptr, nullptr) \
|
||||
X(bool, CenterOnLaunch, "centerOnLaunch", false) \
|
||||
X(Model::FirstWindowPreference, FirstWindowPreference, "firstWindowPreference", FirstWindowPreference::DefaultProfile) \
|
||||
X(Model::LaunchMode, LaunchMode, "launchMode", LaunchMode::DefaultMode) \
|
||||
X(bool, SnapToGridOnResize, "snapToGridOnResize", true) \
|
||||
X(bool, DebugFeaturesEnabled, "debugFeatures", debugFeaturesDefault) \
|
||||
X(bool, StartOnUserLogin, "startOnUserLogin", false) \
|
||||
X(bool, AlwaysOnTop, "alwaysOnTop", false) \
|
||||
X(Model::TabSwitcherMode, TabSwitcherMode, "tabSwitcherMode", Model::TabSwitcherMode::InOrder) \
|
||||
X(bool, DisableAnimations, "disableAnimations", false) \
|
||||
X(hstring, StartupActions, "startupActions", L"") \
|
||||
X(Model::WindowingMode, WindowingBehavior, "windowingBehavior", Model::WindowingMode::UseNew) \
|
||||
X(bool, MinimizeToNotificationArea, "minimizeToNotificationArea", false) \
|
||||
X(bool, AlwaysShowNotificationIcon, "alwaysShowNotificationIcon", false) \
|
||||
X(winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, "disabledProfileSources", nullptr) \
|
||||
X(bool, ShowAdminShield, "showAdminShield", true) \
|
||||
X(bool, TrimPaste, "trimPaste", true)
|
||||
|
||||
#define MTSM_PROFILE_SETTINGS(X) \
|
||||
X(int32_t, HistorySize, "historySize", DEFAULT_HISTORY_SIZE) \
|
||||
X(bool, SnapOnInput, "snapOnInput", true) \
|
||||
X(bool, AltGrAliasing, "altGrAliasing", true) \
|
||||
X(bool, UseAcrylic, "useAcrylic", false) \
|
||||
X(hstring, Commandline, "commandline", L"%SystemRoot%\\System32\\cmd.exe") \
|
||||
X(Microsoft::Terminal::Control::ScrollbarState, ScrollState, "scrollbarState", Microsoft::Terminal::Control::ScrollbarState::Visible) \
|
||||
X(Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, "antialiasingMode", Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
|
||||
X(hstring, StartingDirectory, "startingDirectory") \
|
||||
X(bool, SuppressApplicationTitle, "suppressApplicationTitle", false) \
|
||||
X(guid, ConnectionType, "connectionType") \
|
||||
X(hstring, Icon, "icon", L"\uE756") \
|
||||
X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Graceful) \
|
||||
X(hstring, TabTitle, "tabTitle") \
|
||||
X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible) \
|
||||
X(bool, UseAtlasEngine, "experimental.useAtlasEngine", false)
|
||||
|
||||
#define MTSM_FONT_SETTINGS(X) \
|
||||
X(hstring, FontFace, "face", DEFAULT_FONT_FACE) \
|
||||
X(int32_t, FontSize, "size", DEFAULT_FONT_SIZE) \
|
||||
X(winrt::Windows::UI::Text::FontWeight, FontWeight, "weight", DEFAULT_FONT_WEIGHT) \
|
||||
X(IFontAxesMap, FontAxes, "axes") \
|
||||
X(IFontFeatureMap, FontFeatures, "features")
|
||||
|
||||
#define MTSM_APPEARANCE_SETTINGS(X) \
|
||||
X(Core::CursorStyle, CursorShape, "cursorShape", Core::CursorStyle::Bar) \
|
||||
X(uint32_t, CursorHeight, "cursorHeight", DEFAULT_CURSOR_HEIGHT) \
|
||||
X(double, BackgroundImageOpacity, "backgroundImageOpacity", 1.0) \
|
||||
X(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, "backgroundImageStretchMode", winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill) \
|
||||
X(bool, RetroTerminalEffect, "experimental.retroTerminalEffect", false) \
|
||||
X(hstring, PixelShaderPath, "experimental.pixelShaderPath") \
|
||||
X(ConvergedAlignment, BackgroundImageAlignment, "backgroundImageAlignment", ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center) \
|
||||
X(hstring, ColorSchemeName, "colorScheme", L"Campbell") \
|
||||
X(hstring, BackgroundImagePath, "backgroundImage") \
|
||||
X(Model::IntenseStyle, IntenseTextStyle, "intenseTextStyle", Model::IntenseStyle::Bright) \
|
||||
X(bool, AdjustIndistinguishableColors, "adjustIndistinguishableColors", true)
|
|
@ -50,6 +50,7 @@
|
|||
<DependentUpon>GlobalAppSettings.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IInheritable.h" />
|
||||
<ClInclude Include="MTSMSettings.h" />
|
||||
<ClInclude Include="IDynamicProfileGenerator.h" />
|
||||
<ClInclude Include="JsonUtils.h" />
|
||||
<ClInclude Include="HashUtils.h" />
|
||||
|
@ -196,9 +197,29 @@
|
|||
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
<!-- For whatever reason, we can't include the TerminalControl and
|
||||
TerminalSettings projects' winmds via project references. So we'll have to
|
||||
manually include the winmds as References below -->
|
||||
manually include the winmds as References below
|
||||
|
||||
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
|
||||
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
|
||||
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
|
||||
Up-to-date Check will look for the .xaml files from that project in our
|
||||
output, which won't actually be there.
|
||||
|
||||
We do still need to separately reference the winmds manually below, which is annoying.
|
||||
-->
|
||||
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
|
||||
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
|
||||
the manual reference to TerminalControl.winmd below make sure that this
|
||||
project will compile correct, and that we won't roll up the TermControl
|
||||
xbf's into the packaging project twice. -->
|
||||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- Manually add references to each of our dependent winmds. Mark them as
|
||||
|
@ -265,4 +286,5 @@
|
|||
</Target>
|
||||
<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')" />
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
<Filter>json</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IInheritable.h" />
|
||||
<ClInclude Include="MTSMSettings.h" />
|
||||
<ClInclude Include="IconPathConverter.h" />
|
||||
<ClInclude Include="DefaultTerminal.h" />
|
||||
<ClInclude Include="FileUtils.h" />
|
||||
|
|
|
@ -26,24 +26,9 @@ static constexpr std::string_view GuidKey{ "guid" };
|
|||
static constexpr std::string_view SourceKey{ "source" };
|
||||
static constexpr std::string_view HiddenKey{ "hidden" };
|
||||
|
||||
static constexpr std::string_view TabTitleKey{ "tabTitle" };
|
||||
static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" };
|
||||
static constexpr std::string_view HistorySizeKey{ "historySize" };
|
||||
static constexpr std::string_view SnapOnInputKey{ "snapOnInput" };
|
||||
static constexpr std::string_view AltGrAliasingKey{ "altGrAliasing" };
|
||||
|
||||
static constexpr std::string_view ConnectionTypeKey{ "connectionType" };
|
||||
static constexpr std::string_view CommandlineKey{ "commandline" };
|
||||
static constexpr std::string_view FontInfoKey{ "font" };
|
||||
static constexpr std::string_view UseAcrylicKey{ "useAcrylic" };
|
||||
static constexpr std::string_view ScrollbarStateKey{ "scrollbarState" };
|
||||
static constexpr std::string_view CloseOnExitKey{ "closeOnExit" };
|
||||
static constexpr std::string_view PaddingKey{ "padding" };
|
||||
static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" };
|
||||
static constexpr std::string_view IconKey{ "icon" };
|
||||
static constexpr std::string_view AntialiasingModeKey{ "antialiasingMode" };
|
||||
static constexpr std::string_view TabColorKey{ "tabColor" };
|
||||
static constexpr std::string_view BellStyleKey{ "bellStyle" };
|
||||
static constexpr std::string_view UnfocusedAppearanceKey{ "unfocusedAppearance" };
|
||||
|
||||
Profile::Profile(guid guid) noexcept :
|
||||
|
@ -117,28 +102,17 @@ winrt::com_ptr<Profile> Profile::CopySettings() const
|
|||
profile->_Name = _Name;
|
||||
profile->_Source = _Source;
|
||||
profile->_Hidden = _Hidden;
|
||||
profile->_Icon = _Icon;
|
||||
profile->_CloseOnExit = _CloseOnExit;
|
||||
profile->_TabTitle = _TabTitle;
|
||||
profile->_TabColor = _TabColor;
|
||||
profile->_SuppressApplicationTitle = _SuppressApplicationTitle;
|
||||
profile->_UseAcrylic = _UseAcrylic;
|
||||
profile->_ScrollState = _ScrollState;
|
||||
profile->_Padding = _Padding;
|
||||
profile->_Commandline = _Commandline;
|
||||
profile->_StartingDirectory = _StartingDirectory;
|
||||
profile->_AntialiasingMode = _AntialiasingMode;
|
||||
profile->_ForceFullRepaintRendering = _ForceFullRepaintRendering;
|
||||
profile->_SoftwareRendering = _SoftwareRendering;
|
||||
profile->_HistorySize = _HistorySize;
|
||||
profile->_SnapOnInput = _SnapOnInput;
|
||||
profile->_AltGrAliasing = _AltGrAliasing;
|
||||
profile->_BellStyle = _BellStyle;
|
||||
profile->_ConnectionType = _ConnectionType;
|
||||
profile->_Origin = _Origin;
|
||||
profile->_FontInfo = *fontInfo;
|
||||
profile->_DefaultAppearance = *defaultAppearance;
|
||||
|
||||
#define PROFILE_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||
profile->_##name = _##name;
|
||||
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_COPY)
|
||||
#undef PROFILE_SETTINGS_COPY
|
||||
|
||||
if (_UnfocusedAppearance)
|
||||
{
|
||||
Model::AppearanceConfig unfocused{ nullptr };
|
||||
|
@ -196,31 +170,16 @@ void Profile::LayerJson(const Json::Value& json)
|
|||
JsonUtils::GetValueForKey(json, HiddenKey, _Hidden);
|
||||
JsonUtils::GetValueForKey(json, SourceKey, _Source);
|
||||
|
||||
// TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback"
|
||||
JsonUtils::GetValueForKey(json, HistorySizeKey, _HistorySize);
|
||||
JsonUtils::GetValueForKey(json, SnapOnInputKey, _SnapOnInput);
|
||||
JsonUtils::GetValueForKey(json, AltGrAliasingKey, _AltGrAliasing);
|
||||
JsonUtils::GetValueForKey(json, TabTitleKey, _TabTitle);
|
||||
|
||||
// Control Settings
|
||||
JsonUtils::GetValueForKey(json, ConnectionTypeKey, _ConnectionType);
|
||||
JsonUtils::GetValueForKey(json, CommandlineKey, _Commandline);
|
||||
JsonUtils::GetValueForKey(json, UseAcrylicKey, _UseAcrylic);
|
||||
JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle);
|
||||
JsonUtils::GetValueForKey(json, CloseOnExitKey, _CloseOnExit);
|
||||
|
||||
// Padding was never specified as an integer, but it was a common working mistake.
|
||||
// Allow it to be permissive.
|
||||
JsonUtils::GetValueForKey(json, PaddingKey, _Padding, JsonUtils::OptionalConverter<hstring, JsonUtils::PermissiveStringConverter<std::wstring>>{});
|
||||
|
||||
JsonUtils::GetValueForKey(json, ScrollbarStateKey, _ScrollState);
|
||||
|
||||
JsonUtils::GetValueForKey(json, StartingDirectoryKey, _StartingDirectory);
|
||||
|
||||
JsonUtils::GetValueForKey(json, IconKey, _Icon);
|
||||
JsonUtils::GetValueForKey(json, AntialiasingModeKey, _AntialiasingMode);
|
||||
JsonUtils::GetValueForKey(json, TabColorKey, _TabColor);
|
||||
JsonUtils::GetValueForKey(json, BellStyleKey, _BellStyle);
|
||||
|
||||
#define PROFILE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::GetValueForKey(json, jsonKey, _##name);
|
||||
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_LAYER_JSON)
|
||||
#undef PROFILE_SETTINGS_LAYER_JSON
|
||||
|
||||
if (json.isMember(JsonKey(UnfocusedAppearanceKey)))
|
||||
{
|
||||
|
@ -352,28 +311,15 @@ Json::Value Profile::ToJson() const
|
|||
JsonUtils::SetValueForKey(json, HiddenKey, writeBasicSettings ? Hidden() : _Hidden);
|
||||
JsonUtils::SetValueForKey(json, SourceKey, writeBasicSettings ? Source() : _Source);
|
||||
|
||||
// TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback"
|
||||
JsonUtils::SetValueForKey(json, HistorySizeKey, _HistorySize);
|
||||
JsonUtils::SetValueForKey(json, SnapOnInputKey, _SnapOnInput);
|
||||
JsonUtils::SetValueForKey(json, AltGrAliasingKey, _AltGrAliasing);
|
||||
JsonUtils::SetValueForKey(json, TabTitleKey, _TabTitle);
|
||||
|
||||
// Control Settings
|
||||
JsonUtils::SetValueForKey(json, ConnectionTypeKey, _ConnectionType);
|
||||
JsonUtils::SetValueForKey(json, CommandlineKey, _Commandline);
|
||||
JsonUtils::SetValueForKey(json, UseAcrylicKey, _UseAcrylic);
|
||||
JsonUtils::SetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle);
|
||||
JsonUtils::SetValueForKey(json, CloseOnExitKey, _CloseOnExit);
|
||||
|
||||
// PermissiveStringConverter is unnecessary for serialization
|
||||
JsonUtils::SetValueForKey(json, PaddingKey, _Padding);
|
||||
|
||||
JsonUtils::SetValueForKey(json, ScrollbarStateKey, _ScrollState);
|
||||
JsonUtils::SetValueForKey(json, StartingDirectoryKey, _StartingDirectory);
|
||||
JsonUtils::SetValueForKey(json, IconKey, _Icon);
|
||||
JsonUtils::SetValueForKey(json, AntialiasingModeKey, _AntialiasingMode);
|
||||
JsonUtils::SetValueForKey(json, TabColorKey, _TabColor);
|
||||
JsonUtils::SetValueForKey(json, BellStyleKey, _BellStyle);
|
||||
|
||||
#define PROFILE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::SetValueForKey(json, jsonKey, _##name);
|
||||
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_TO_JSON)
|
||||
#undef PROFILE_SETTINGS_TO_JSON
|
||||
|
||||
// Font settings
|
||||
const auto fontInfoImpl = winrt::get_self<FontConfig>(_FontInfo);
|
||||
|
|
|
@ -46,6 +46,7 @@ Author(s):
|
|||
|
||||
#include "Profile.g.h"
|
||||
#include "IInheritable.h"
|
||||
#include "MTSMSettings.h"
|
||||
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
#include "JsonUtils.h"
|
||||
|
@ -102,43 +103,26 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
void _FinalizeInheritance() override;
|
||||
|
||||
// Special fields
|
||||
WINRT_PROPERTY(bool, Deleted, false);
|
||||
WINRT_PROPERTY(OriginTag, Origin, OriginTag::None);
|
||||
|
||||
WINRT_PROPERTY(guid, Updates);
|
||||
INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source()));
|
||||
|
||||
// Nullable/optional settings
|
||||
INHERITABLE_NULLABLE_SETTING(Model::Profile, Microsoft::Terminal::Core::Color, TabColor, nullptr);
|
||||
INHERITABLE_SETTING(Model::Profile, Model::IAppearanceConfig, UnfocusedAppearance, nullptr);
|
||||
|
||||
// Settings that cannot be put in the macro because of how they are handled in ToJson/LayerJson
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, Name, L"Default");
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, Source);
|
||||
INHERITABLE_SETTING(Model::Profile, bool, Hidden, false);
|
||||
INHERITABLE_SETTING(Model::Profile, guid, ConnectionType);
|
||||
|
||||
// Default Icon: Segoe MDL2 CommandPrompt icon
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, Icon, L"\uE756");
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful);
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, TabTitle);
|
||||
INHERITABLE_NULLABLE_SETTING(Model::Profile, Microsoft::Terminal::Core::Color, TabColor, nullptr);
|
||||
INHERITABLE_SETTING(Model::Profile, bool, SuppressApplicationTitle, false);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, bool, UseAcrylic, false);
|
||||
INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::ScrollbarState, ScrollState, Microsoft::Terminal::Control::ScrollbarState::Visible);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source()));
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, Commandline, L"%SystemRoot%\\System32\\cmd.exe");
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, StartingDirectory);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
|
||||
INHERITABLE_SETTING(Model::Profile, bool, ForceFullRepaintRendering, false);
|
||||
INHERITABLE_SETTING(Model::Profile, bool, SoftwareRendering, false);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, int32_t, HistorySize, DEFAULT_HISTORY_SIZE);
|
||||
INHERITABLE_SETTING(Model::Profile, bool, SnapOnInput, true);
|
||||
INHERITABLE_SETTING(Model::Profile, bool, AltGrAliasing, true);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, Model::BellStyle, BellStyle, BellStyle::Audible);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, Model::IAppearanceConfig, UnfocusedAppearance, nullptr);
|
||||
#define PROFILE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
|
||||
INHERITABLE_SETTING(Model::Profile, type, name, ##__VA_ARGS__)
|
||||
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_INITIALIZE)
|
||||
#undef PROFILE_SETTINGS_INITIALIZE
|
||||
|
||||
private:
|
||||
Model::IAppearanceConfig _DefaultAppearance{ winrt::make<AppearanceConfig>(weak_ref<Model::Profile>(*this)) };
|
||||
|
|
|
@ -74,12 +74,11 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
INHERITABLE_PROFILE_SETTING(IAppearanceConfig, UnfocusedAppearance);
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, ForceFullRepaintRendering);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, SoftwareRendering);
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Int32, HistorySize);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, AltGrAliasing);
|
||||
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
|
||||
_ProfileName = profile.Name();
|
||||
_ProfileSource = profile.Source();
|
||||
_UseAcrylic = profile.UseAcrylic();
|
||||
|
||||
_FontFace = profile.FontInfo().FontFace();
|
||||
|
@ -297,6 +298,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
_SuppressApplicationTitle = profile.SuppressApplicationTitle();
|
||||
}
|
||||
|
||||
_UseAtlasEngine = profile.UseAtlasEngine();
|
||||
_ScrollState = profile.ScrollState();
|
||||
|
||||
_AntialiasingMode = profile.AntialiasingMode();
|
||||
|
|
|
@ -119,6 +119,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
// ------------------------ End of Core Settings -----------------------
|
||||
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileName);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileSource);
|
||||
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, bool, UseAcrylic, false);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, double, Opacity, UseAcrylic() ? 0.5 : 1.0);
|
||||
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, 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);
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
</ProjectReference>
|
||||
|
||||
<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
|
||||
project will compile correct, and that we won't roll up the TermControl
|
||||
xbf's into the packaging project twice. -->
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue