Compare commits

..

3 commits

Author SHA1 Message Date
Leonard Hecker 0bde7f4fd3 Fix AltGr not working in the settings UI (#11808)
Since the settings UI's input fields behave similarly to the terminal's input,
`TerminalPage::_KeyDownHandler` also needs to behave similarly to
`TermControl::_KeyHandler`. This commit copies all relevant code
over from the latter into the former, including the suppression
of AltGr keys for keychord/action handling.

## PR Checklist
* [x] Closes #11788
* [x] I work here
* [x] Tests added/passed

## Validation Steps Performed
* Use a German keyboard layout
* Open 2 regular tabs and 1 settings tab and focus an input field
* AltGr+2 produces the character ² ✔️
* Ctrl+Alt+2 opens the second tab ✔️

(cherry picked from commit 80f8383860)
2021-11-23 23:38:02 +01:00
Leonard Hecker 39b72f78c3 Fixed VsDevCmd command line quoting (#11554)
(cherry picked from commit 5cd9663269)
2021-10-20 21:59:10 +02:00
PankajBhojwani 89674ac4fb Updating PGO branch 2021-10-19 17:29:16 -07:00
292 changed files with 4476 additions and 7585 deletions

View file

@ -10,21 +10,14 @@ body:
- type: input
attributes:
label: Windows Terminal version
placeholder: "1.7.3651.0"
label: Windows Terminal version (or Windows build number)
placeholder: "10.0.19042.0, 1.7.3651.0"
description: |
You can find the version in the about dialog, or by running `wt -v` at the commandline.
If you are reporting an issue in Windows Terminal, you can find the version in the about dialog.
If you are reporting an issue with the Windows Console, please run `ver` or `[Environment]::OSVersion`.
validations:
required: false
- type: input
attributes:
label: Windows build number
placeholder: "10.0.19042.0"
description: |
Please run `ver` or `[Environment]::OSVersion`.
validations:
required: false
required: true
- type: textarea
attributes:

View file

@ -1,14 +1,12 @@
admins
apc
Apc
bsd
calt
ccmp
changelog
cybersecurity
Apc
clickable
clig
copyable
cybersecurity
dalet
dcs
Dcs
@ -32,22 +30,20 @@ hyperlink
hyperlinking
hyperlinks
img
inlined
It'd
kje
liga
lje
Llast
Lmid
locl
lorem
Llast
Lmid
Lorigin
maxed
mkmk
mnt
mru
nje
noreply
nje
ogonek
ok'd
overlined

View file

@ -1,7 +1,5 @@
ACCEPTFILES
ACCESSDENIED
acl
aclapi
alignas
alignof
APPLYTOSUBMENUS
@ -11,7 +9,6 @@ BUILDBRANCH
BUILDMSG
BUILDNUMBER
BYPOSITION
BYCOMMAND
charconv
CLASSNOTAVAILABLE
cmdletbinding
@ -19,11 +16,9 @@ COLORPROPERTY
colspan
COMDLG
comparand
commandlinetoargv
cstdint
CXICON
CYICON
Dacl
dataobject
dcomp
DERR
@ -90,7 +85,6 @@ LSHIFT
MENUCOMMAND
MENUDATA
MENUINFO
MENUITEMINFOW
memicmp
mptt
mov
@ -120,19 +114,15 @@ OSVERSIONINFOEXW
otms
OUTLINETEXTMETRICW
overridable
PACL
PAGESCROLL
PEXPLICIT
PICKFOLDERS
pmr
ptstr
rcx
REGCLS
RETURNCMD
rfind
roundf
RSHIFT
SACL
schandle
semver
serializer
@ -169,8 +159,6 @@ toupper
TTask
TVal
UChar
UFIELD
ULARGE
UPDATEINIFILE
userenv
wcsstr

View file

@ -9,7 +9,6 @@ Diviness
dsafa
duhowett
ekg
eryksun
ethanschoonover
Firefox
Gatta

View file

@ -61,14 +61,12 @@ SUMS$
^src/host/runft\.bat$
^src/host/runut\.bat$
^src/interactivity/onecore/BgfxEngine\.
^src/renderer/atlas/
^src/renderer/wddmcon/WddmConRenderer\.
^src/terminal/adapter/ut_adapter/run\.bat$
^src/terminal/parser/delfuzzpayload\.bat$
^src/terminal/parser/ft_fuzzer/run\.bat$
^src/terminal/parser/ft_fuzzer/VTCommandFuzzer\.cpp$
^src/terminal/parser/ft_fuzzwrapper/run\.bat$
^src/terminal/parser/ut_parser/Base64Test.cpp$
^src/terminal/parser/ut_parser/run\.bat$
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
^src/tools/lnkd/lnkd\.bat$

View file

@ -508,7 +508,6 @@ dealloc
Debian
debolden
debugtype
DECAC
DECALN
DECANM
DECAUPSS
@ -939,7 +938,6 @@ GTP
guc
gui
guidatom
guiddef
GValue
GWL
GWLP
@ -1537,7 +1535,6 @@ NOCOLOR
NOCOMM
NOCONTEXTHELP
NOCOPYBITS
nodefaultlib
nodiscard
NODUP
noexcept
@ -2235,7 +2232,6 @@ STARTWPARMSW
Statusline
stdafx
STDAPI
stdc
stdcall
stdcpp
stderr

View file

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

View file

@ -17,7 +17,7 @@
"Microsoft.Net.Component.4.5.TargetingPack",
"Microsoft.VisualStudio.Component.DiagnosticTools",
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
"Microsoft.VisualStudio.Component.Windows10SDK.22000",
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
"Microsoft.VisualStudio.Component.VC.CoreIde",
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",

View file

@ -99,29 +99,15 @@ If you don't have any additional info/context to add but would like to indicate
## Contributing fixes / features
If you're able & willing to help fix issues and/or implement features, we'd love your contribution!
The best place to start is the list of ["Easy Starter"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+label%3A%22Easy+Starter%22+) issues. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue your interested in and hop in!
Generally, we categorize issues in the following way, which is largely derived from our old internal work tracking system:
* ["Bugs"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Bug%22+) are parts of the Terminal & Console that are not quite working the right way. There's code to already support some scenario, but it's not quite working right. Fixing these is generally a matter of debugging the broken functionality and fixing the wrong code.
* ["Tasks"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Task%22+) are usually new pieces of functionality that aren't yet implemented for the Terminal/Console. These are usually smaller features, which we believe
- could be a single, atomic PR
- Don't require much design consideration, or we've already written the spec for the larger feature they belong to.
* ["Features"](https://github.com/microsoft/terminal/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Feature%22+) are larger pieces of new functionality. These are usually things we believe would require larger discussion of how they should be implemented, or they'll require some complicated new settings. They might just be features that are composed of many individual tasks. Often times, with features, we like to have a spec written before development work is started, to make sure we're all on the same page (see below).
Bugs and tasks are obviously the easiest to get started with, but don't feel afraid of features either! We've had some community members contribute some amazing "feature"-level work to the Terminal (albeit, with lots of discussion 😄).
Often, we like to assign issues that generally belong to somebody's area of expertise to the team member that owns that area. This doesn't mean the community can't jump in -- they should reach out and have a chat with the assignee to see if it'd okay to take. If an issue's been assigned more than a month ago, there's a good chance it's fair game to try yourself.
For those able & willing to help fix issues and/or implement features ...
### To Spec or not to Spec
Some issues/features may be quick and simple to describe and understand. For such scenarios, once a team member has agreed with your approach, skip ahead to the section headed "Fork, Branch, and Create your PR", below.
Small issues that do not require a spec will be labelled `Issue-Bug` or `Issue-Task`.
Small issues that do not require a spec will be labelled Issue-Bug or Issue-Task.
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled `Issue-Feature`. More often than not, we'll add such features to the ["Specification Tracker" project](https://github.com/microsoft/terminal/projects/1).
However, some issues/features will require careful thought & formal design before implementation. For these scenarios, we'll request that a spec is written and the associated issue will be labeled Issue-Feature.
Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.

View file

@ -400,8 +400,6 @@ 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
@ -3341,46 +3339,6 @@ 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
@ -3480,7 +3438,6 @@ 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}

View file

@ -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](https://www.runasradio.com/Shows/Show/645)
Turner](http://www.runasradio.com/Shows/Show/645)
* Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps
on the Windows
Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54)

View file

@ -63,14 +63,8 @@
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 &quot;&amp;&apos;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&apos; -Path &apos;%(FeatureFlagFile.FullPath)&apos; -Branding $(_WTBrandingName)&quot;"
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command &quot;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&quot; -Path &quot;%(FeatureFlagFile.FullPath)&quot; -Branding $(_WTBrandingName)"
ConsoleToMsBuild="true"
StandardOutputImportance="low">
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />

View file

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

View file

@ -8,7 +8,7 @@ Param(
[Parameter(HelpMessage="Path to Windows Kit")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0"
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0"
)
$ErrorActionPreference = "Stop"

View file

@ -5,7 +5,7 @@
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
<XesBaseYearForStoreVersion>2021</XesBaseYearForStoreVersion>
<VersionMajor>1</VersionMajor>
<VersionMinor>13</VersionMinor>
<VersionMinor>12</VersionMinor>
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
</PropertyGroup>
</Project>

View file

@ -4,7 +4,7 @@
Introducing exceptions to an existing non-exception-based codebase can be perilous. The console was originally written
in C at a time when C++ was relatively unused in the Windows operating system. As part of our project to modernize the
Windows console, we converted to use C++, but still had an aversion to using exception-based error handling in
our code for fear that it might introduce unexpected failures. However, the STL and other libraries like it are so useful that
our code for fear that it introduce unexpected failures. However, the STL and other libraries like it are so useful that
sometimes it's significantly simpler to use them. Given that, we have a set of rules that we follow when considering
exception use.

View file

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

View file

@ -1478,11 +1478,6 @@
"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.",

View file

@ -268,7 +268,7 @@ Today, if the deserialization of `CascadiaSettings` encounters any errors, an ex
To get around this issue, when `CascadiaSettings` encounters a serialization error, it must internally record
any pertinent information for that error, and return the simple `CascadiaSettings` as if nothing happened.
The consumer must then call `CascadiaSettings::GetErrors()` and `CascadiaSettings::GetWarnings()` to properly
understand whether an error occurred and how to present that to the user.
understand whether an error ocurred and how to present that to the user.
#### TerminalApp: Loading and Reloading Changes

View file

@ -2,7 +2,7 @@
## Overview
This document outlines the roadmap towards delivering Windows Terminal 2.0.
This document outlines the roadmap towards delivering Windows Terminal 2.0 by Winter 2021.
## Milestones
@ -31,9 +31,9 @@ Below is the schedule for when milestones will be included in release builds of
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | [Windows Terminal Preview 1.9 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-9-release/) |
| 2021-07-14 | [1.10] in Windows Terminal Preview<br>[1.9] in Windows Terminal | [Windows Terminal Preview 1.10 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-10-release/) |
| 2021-08-31 | [1.11] in Windows Terminal Preview<br>[1.10] in Windows Terminal | [Windows Terminal Preview 1.11 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-11-release/) |
| 2021-10-20 | [1.12] in Windows Terminal Preview<br>[1.11] in Windows Terminal | [Windows Terminal Preview 1.12 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-12-release/) |
| | 2.0 RC in Windows Terminal Preview<br>2.0 RC in Windows Terminal | |
| | [2.0] in Windows Terminal Preview<br>[2.0] in Windows Terminal | |
| 2021-10-31 | 1.12 in Windows Terminal Preview<br>1.11 in Windows Terminal | |
| 2021-11-30 | 2.0 RC in Windows Terminal Preview<br>2.0 RC in Windows Terminal | |
| 2021-12-31 | [2.0] in Windows Terminal Preview<br>[2.0] in Windows Terminal | |
## Issue Triage & Prioritization
@ -49,32 +49,28 @@ The following are a list of the key scenarios we're aiming to deliver for Termin
> 👉 Note: There are many other features that don't fit within 2.0, but will be re-assessed and prioritized for 3.0, the plan for which will be published in 2021.
| Priority\* | Scenario | Description/Notes | State |
| ---------- | -------- | ----------------- | ----- |
| 0 | Settings UI | A user interface that connects to settings.json. This provides a way for people to edit their settings without having to edit a JSON file.<br><br>Issue: [#1564]<br>Specs: [#6720], [#6904]<br>Implementation: [#7283], [#7370], [#8048] | ✔️ |
| 0 | Command palette | A popup menu to list possible actions and commands.<br><br>Issues: [#5400], [#2046]<br>Spec: [#2193]<br>Implementation: [#6635] | ✔️ |
| 1 | Tab tear-off | The ability to tear a tab out of the current window and spawn a new window or attach it to a separate window.<br><br>Issue: [#1256], [#5000]<br>Spec: [#2080], [#7240] | 📝 |
| 1 | Clickable links | Hyperlinking any links that appear in the text buffer. When clicking on the link, the link will open in your default browser.<br><br>Issue: [#574]<br>Implementation: [#7251] | ✔️ |
| 1 | Default terminal | If a command-line application is spawned, it should open in Windows Terminal (if installed) or your preferred terminal<br><br>Issue: [#492]<br>Spec: [#2080], [#7414] | ✔️ |
| 1 | Overall theme support | Tab coloring, title bar coloring, pane border coloring, pane border width, definition of what makes a theme<br><br>Issue: [#3327]<br>Spec: [#5772] | 🦶 |
| 1 | Open profile elevated | Configure profiles to always open elevated (if Terminal was run unelevated)<br><br>Issue: [#5000], [#632]<br>Spec: [#8455] | 📝 |
| 1 | Open tab in existing window | Open new tabs in existing Terminal windows<br><br>Issue: [#5000], [#4472]<br>Spec: [#8135] | ✔️ |
| 1 | Traditional opacity | Have a transparent background without the acrylic blur.<br><br>Issue: [#603] | ✔️ |
| 2 | SnapOnOutput, scroll lock | Pause output or scrolling on click.<br><br>Issue: [#980]<br>Spec: [#2529]<br>Implementation: [#6062] | ✔️ |
| 2 | Infinite scrollback | Have an infinite history for the text buffer.<br><br>Issue: [#1410] | 🦶 |
| 2 | Pane management | All issues listed out in the original issue. Some features include pane resizing with mouse, pane zooming, and opening a pane by prompting which profile to use.<br><br>Issue: [#1000] | 📝 |
| 2 | Theme marketplace | Marketplace for creation and distribution of themes.<br>Dependent on overall theming | 🦶 |
| 2 | Jump list | Show profiles from task bar (on right click)/start menu.<br><br>Issue: [#576]<br>Implementation: [#7515] | ✔️ |
| 2 | Open with multiple tabs | A setting that allows Windows Terminal to launch with a specific tab configuration (not using only command line arguments).<br><br>Issue: [#756] | ✔️ |
| 3 | Open in Windows Terminal | Functionality to right click on a file or folder and select Open in Windows Terminal.<br><br>Issue: [#1060]<br>Implementation: [#6100] | ✔️ |
| 3 | Session restoration | Launch Windows Terminal and the previous session is restored with the proper tab and pane configuration and starting directories.<br><br>Issues: [#961], [#960], [#766] | ✔️ |
| 3 | Quake mode | Provide a quick launch terminal that appears and disappears when a hotkey is pressed.<br><br>Issue: [#653] | ✔️ |
| 3 | Settings migration infrastructure | Migrate people's settings without breaking them. Hand-in-hand with settings UI. | 🦶 |
| 3 | Pointer bindings | Provide settings that can be bound to the mouse.<br><br>Issue: [#1553] | 🦶 |
* 📝: The feature is currently in progress
* ✔️: The feature is complete and shipped in a Preview build
* 🦶: The feature is at risk of being punted to a future release cycle (beyond 2.0)
| Priority\* | Scenario | Description/Notes |
| ---------- | -------- | ----------------- |
| 0 | Settings UI | A user interface that connects to settings.json. This provides a way for people to edit their settings without having to edit a JSON file.<br><br>Issue: [#1564]<br>Specs: [#6720], [#6904]<br>Implementation: [#7283], [#7370], [#8048] |
| 0 | Command palette | A popup menu to list possible actions and commands.<br><br>Issues: [#5400], [#2046]<br>Spec: [#2193]<br>Implementation: [#6635] |
| 1 | Tab tear-off | The ability to tear a tab out of the current window and spawn a new window or attach it to a separate window.<br><br>Issue: [#1256], [#5000]<br>Spec: [#2080], [#7240] |
| 1 | Clickable links | Hyperlinking any links that appear in the text buffer. When clicking on the link, the link will open in your default browser.<br><br>Issue: [#574]<br>Implementation: [#7251] |
| 1 | Default terminal | If a command-line application is spawned, it should open in Windows Terminal (if installed) or your preferred terminal<br><br>Issue: [#492]<br>Spec: [#2080], [#7414] |
| 1 | Overall theme support | Tab coloring, title bar coloring, pane border coloring, pane border width, definition of what makes a theme<br><br>Issue: [#3327]<br>Spec: [#5772] |
| 1 | Open profile elevated | Configure profiles to always open elevated (if Terminal was run unelevated)<br><br>Issue: [#5000], [#632]<br>Spec: [#8455] |
| 1 | Open tab in existing window | Open new tabs in existing Terminal windows<br><br>Issue: [#5000], [#4472]<br>Spec: [#8135] |
| 1 | Traditional opacity | Have a transparent background without the acrylic blur.<br><br>Issue: [#603] <br>**Current State**: Blocked on WinUI 3.0 |
| 2 | SnapOnOutput, scroll lock | Pause output or scrolling on click.<br><br>Issue: [#980]<br>Spec: [#2529]<br>Implementation: [#6062] |
| 2 | Infinite scrollback | Have an infinite history for the text buffer.<br><br>Issue: [#1410] |
| 2 | Pane management | All issues listed out in the original issue. Some features include pane resizing with mouse, pane zooming, and opening a pane by prompting which profile to use.<br><br>Issue: [#1000] |
| 2 | Theme marketplace | Marketplace for creation and distribution of themes.<br>Dependent on overall theming |
| 2 | Jump list | Show profiles from task bar (on right click)/start menu.<br><br>Issue: [#576]<br>Implementation: [#7515] |
| 2 | Open with multiple tabs | A setting that allows Windows Terminal to launch with a specific tab configuration (not using only command line arguments).<br><br>Issue: [#756] |
| 3 | Open in Windows Terminal | Functionality to right click on a file or folder and select Open in Windows Terminal.<br><br>Issue: [#1060]<br>Implementation: [#6100] |
| 3 | Session restoration | Launch Windows Terminal and the previous session is restored with the proper tab and pane configuration and starting directories.<br><br>Issues: [#961], [#960], [#766] |
| 3 | Quake mode | Provide a quick launch terminal that appears and disappears when a hotkey is pressed.<br><br>Issue: [#653] |
| 3 | Settings migration infrastructure | Migrate people's settings without breaking them. Hand-in-hand with settings UI. |
| 3 | Pointer bindings | Provide settings that can be bound to the mouse.<br><br>Issue: [#1553] |
Feature Notes:
@ -95,8 +91,6 @@ Feature Notes:
[1.9]: https://github.com/microsoft/terminal/milestone/34
[1.10]: https://github.com/microsoft/terminal/milestone/35
[1.11]: https://github.com/microsoft/terminal/milestone/36
[1.12]: https://github.com/microsoft/terminal/milestone/38
[1.13]: https://github.com/microsoft/terminal/milestone/39
[2.0]: https://github.com/microsoft/terminal/milestone/22
[#1564]: https://github.com/microsoft/terminal/issues/1564
[#6720]: https://github.com/microsoft/terminal/pull/6720

View file

@ -23,7 +23,7 @@
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>EchoCon</RootNamespace>
<WindowsTargetPlatformVersion>10.0.22000.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.19041.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>

View file

@ -27,7 +27,7 @@
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>

View file

@ -118,23 +118,6 @@
<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')" />

View file

@ -12,30 +12,8 @@ static_assert(alignof(TextAttribute) == 2);
// Ensure that we can memcpy() and memmove() the struct for performance.
static_assert(std::is_trivially_copyable_v<TextAttribute>);
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);
BYTE TextAttribute::s_legacyDefaultForeground = 7;
BYTE TextAttribute::s_legacyDefaultBackground = 0;
// Routine Description:
// - Sets the legacy attributes which map to and from the default colors.
@ -45,22 +23,8 @@ std::array<TextColor, 16> TextAttribute::s_legacyBackgroundColorMap = s_initLega
// - 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:
@ -91,13 +55,13 @@ TextAttribute TextAttribute::StripErroneousVT16VersionsOfLegacyDefaults(const Te
const auto bg{ attribute.GetBackground() };
auto copy{ attribute };
if (fg.IsIndex16() &&
attribute.IsBold() == WI_IsFlagSet(s_ansiDefaultForeground, FOREGROUND_INTENSITY) &&
fg.GetIndex() == (s_ansiDefaultForeground & ~FOREGROUND_INTENSITY))
attribute.IsBold() == WI_IsFlagSet(s_legacyDefaultForeground, FOREGROUND_INTENSITY) &&
fg.GetIndex() == (s_legacyDefaultForeground & ~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_ansiDefaultBackground)
if (bg.IsIndex16() && bg.GetIndex() == s_legacyDefaultBackground)
{
copy.SetDefaultBackground();
}
@ -128,22 +92,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.
// - defaultFgIndex: the color table index of the default foreground color.
// - defaultBgIndex: the color table index of the default background color.
// - defaultFgColor: the default foreground color rgb value.
// - defaultBgColor: the default background color rgb value.
// - 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, TextColor::TABLE_SIZE>& colorTable,
const size_t defaultFgIndex,
const size_t defaultBgIndex,
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
const COLORREF defaultFgColor,
const COLORREF defaultBgColor,
const bool reverseScreenMode,
const bool blinkingIsFaint,
const bool boldIsBright) const noexcept
{
auto fg = _foreground.GetColor(colorTable, defaultFgIndex, boldIsBright && IsBold());
auto bg = _background.GetColor(colorTable, defaultBgIndex);
auto fg = _foreground.GetColor(colorTable, defaultFgColor, boldIsBright && IsBold());
auto bg = _background.GetColor(colorTable, defaultBgColor);
if (IsFaint() || (IsBlinking() && blinkingIsFaint))
{
fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two.

View file

@ -41,8 +41,8 @@ public:
explicit constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
_foreground{ s_LegacyIndexOrDefault(wLegacyAttr & FG_ATTRS, s_legacyDefaultForeground) },
_background{ s_LegacyIndexOrDefault((wLegacyAttr & BG_ATTRS) >> 4, s_legacyDefaultBackground) },
_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, TextColor::TABLE_SIZE>& colorTable,
const size_t defaultFgIndex,
const size_t defaultBgIndex,
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
const COLORREF defaultFgColor,
const COLORREF defaultBgColor,
const bool reverseScreenMode = false,
const bool blinkingIsFaint = false,
const bool boldIsBright = true) const noexcept;
@ -167,8 +167,13 @@ public:
}
private:
static std::array<TextColor, 16> s_legacyForegroundColorMap;
static std::array<TextColor, 16> s_legacyBackgroundColorMap;
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;
uint16_t _wAttrLegacy; // sizeof: 2, alignof: 2
uint16_t _hyperlinkId; // sizeof: 2, alignof: 2

View file

@ -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, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 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,16 +139,14 @@ void TextColor::SetDefault() noexcept
// Arguments:
// - colorTable: The table of colors we should use to look up the value of
// an indexed attribute from.
// - defaultIndex: The color table index to use if we're a default attribute.
// - defaultColor: The color value 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, TextColor::TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten) const noexcept
COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten) const noexcept
{
if (IsDefault())
{
const auto defaultColor = til::at(colorTable, defaultIndex);
if (brighten)
{
// See MSFT:20266024 for context on this fix.
@ -254,7 +252,11 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept
{
return defaultIndex;
}
else if (IsIndex16() || IsIndex256())
else if (IsIndex16())
{
return GetIndex();
}
else if (IsIndex256())
{
return til::at(Index256ToIndex16, GetIndex());
}

View file

@ -48,28 +48,6 @@ 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 },
@ -108,7 +86,7 @@ public:
void SetIndex(const BYTE index, const bool isIndex256) noexcept;
void SetDefault() noexcept;
COLORREF GetColor(const std::array<COLORREF, TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten = false) const noexcept;
COLORREF GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten = false) const noexcept;
BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept;
constexpr BYTE GetIndex() const noexcept
@ -118,16 +96,6 @@ 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
{

View file

@ -27,7 +27,9 @@ Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
_fDeferCursorRedraw(false),
_fHaveDeferredCursorRedraw(false),
_ulSize(ulSize),
_cursorType(CursorType::Legacy)
_cursorType(CursorType::Legacy),
_fUseColor(false),
_color(s_InvertCursorColor)
{
}
@ -141,9 +143,10 @@ void Cursor::SetSize(const ULONG ulSize) noexcept
_RedrawCursor();
}
void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept
void Cursor::SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept
{
_ulSize = ulSize;
_color = color;
_cursorType = type;
_RedrawCursor();
@ -282,6 +285,7 @@ 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
@ -331,6 +335,21 @@ 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;

View file

@ -24,6 +24,7 @@ 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
@ -50,6 +51,8 @@ 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;
@ -64,7 +67,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 CursorType type) noexcept;
void SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept;
void SetPosition(const COORD cPosition) noexcept;
void SetXPosition(const int NewX) noexcept;
@ -81,6 +84,7 @@ public:
COORD GetDelayedAtPosition() const noexcept;
bool IsDelayedEOLWrap() const noexcept;
void SetColor(const unsigned int color) noexcept;
void SetType(const CursorType type) noexcept;
private:
@ -113,4 +117,6 @@ private:
void _RedrawCursorAlways() noexcept;
CursorType _cursorType;
bool _fUseColor;
COLORREF _color;
};

View file

@ -24,11 +24,9 @@ class TextAttributeTests
TEST_METHOD(TestRoundtripDefaultColors);
TEST_METHOD(TestBoldAsBright);
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;
std::array<COLORREF, 256> _colorTable;
COLORREF _defaultFg = RGB(1, 2, 3);
COLORREF _defaultBg = RGB(4, 5, 6);
};
bool TextAttributeTests::ClassSetup()
@ -49,8 +47,6 @@ 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;
}
@ -136,17 +132,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo());
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));
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));
// 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, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
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));
// reset the reverse video
attr.SetReverseVideo(false);
@ -155,17 +151,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// while the background and getters stay the same
attr.SetFaint(true);
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));
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));
// 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, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
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));
// reset the reverse video and faint attributes
attr.SetReverseVideo(false);
@ -175,17 +171,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// background, while getters stay the same
attr.SetInvisible(true);
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));
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));
// 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, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
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));
}
void TextAttributeTests::TestReverseDefaultColors()
@ -198,34 +194,34 @@ void TextAttributeTests::TestReverseDefaultColors()
// values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo());
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));
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));
// 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, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
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));
attr.SetForeground(red);
VERIFY_IS_TRUE(attr.IsReverseVideo());
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));
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));
attr.Invert();
VERIFY_IS_FALSE(attr.IsReverseVideo());
attr.SetDefaultForeground();
attr.SetBackground(green);
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));
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));
}
void TextAttributeTests::TestRoundtripDefaultColors()
@ -241,7 +237,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(TextColor::DARK_GREEN);
textAttribute.SetIndexedBackground256(BACKGROUND_GREEN >> 4);
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
Log::Comment(L"Default foreground text color should map back to legacy default index.");
@ -249,7 +245,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
Log::Comment(L"Background legacy default index should map to default text color.");
legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault;
textAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
textAttribute.SetIndexedForeground256(FOREGROUND_GREEN);
textAttribute.SetDefaultBackground();
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
@ -281,43 +277,43 @@ void TextAttributeTests::TestBoldAsBright()
// values when not bold
VERIFY_IS_FALSE(attr.IsBold());
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));
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));
// 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, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
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));
attr.SetIndexedForeground(TextColor::DARK_BLACK);
attr.SetIndexedForeground(0);
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, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, 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, _defaultFgIndex, _defaultBgIndex, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetIndexedBackground(TextColor::DARK_GREEN);
attr.SetIndexedBackground(2);
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, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
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));
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, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
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));
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
attr.SetBold(true);
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
attr.SetIndexedForeground(8);
VERIFY_IS_TRUE(attr.IsBold());
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));
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));
}

View file

@ -23,11 +23,9 @@ class TextColorTests
TEST_METHOD(TestRgbColor);
TEST_METHOD(TestChangeColor);
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;
std::array<COLORREF, 256> _colorTable;
COLORREF _defaultFg = RGB(1, 2, 3);
COLORREF _defaultBg = RGB(4, 5, 6);
};
bool TextColorTests::ClassSetup()
@ -48,8 +46,6 @@ 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;
}
@ -61,16 +57,16 @@ void TextColorTests::TestDefaultColor()
VERIFY_IS_FALSE(defaultColor.IsLegacy());
VERIFY_IS_FALSE(defaultColor.IsRgb());
auto color = defaultColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = defaultColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = defaultColor.GetColor(_colorTable, _defaultFgIndex, true);
color = defaultColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, false);
color = defaultColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_defaultBg, color);
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, true);
color = defaultColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_defaultBg, color);
}
@ -82,16 +78,16 @@ void TextColorTests::TestDarkIndexColor()
VERIFY_IS_TRUE(indexColor.IsLegacy());
VERIFY_IS_FALSE(indexColor.IsRgb());
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
color = indexColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
color = indexColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
color = indexColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}
@ -103,16 +99,16 @@ void TextColorTests::TestBrightIndexColor()
VERIFY_IS_TRUE(indexColor.IsLegacy());
VERIFY_IS_FALSE(indexColor.IsRgb());
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
color = indexColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
color = indexColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
color = indexColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}
@ -125,16 +121,16 @@ void TextColorTests::TestRgbColor()
VERIFY_IS_FALSE(rgbColor.IsLegacy());
VERIFY_IS_TRUE(rgbColor.IsRgb());
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(myColor, color);
}
@ -147,55 +143,55 @@ void TextColorTests::TestChangeColor()
VERIFY_IS_FALSE(rgbColor.IsLegacy());
VERIFY_IS_TRUE(rgbColor.IsRgb());
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(myColor, color);
rgbColor.SetDefault();
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_defaultBg, color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_defaultBg, color);
rgbColor.SetIndex(7, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
rgbColor.SetIndex(15, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}

View file

@ -61,26 +61,13 @@
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
<ItemGroup>
<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>
<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" />
</ItemGroup>
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">

View file

@ -26,7 +26,7 @@
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>

View file

@ -27,7 +27,7 @@
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>

View file

@ -27,7 +27,7 @@
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>

View file

@ -80,7 +80,7 @@ namespace SettingsModelLocalTests
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
const auto campbellSpan = gsl::make_span(expectedCampbellTable);
Utils::InitializeColorTable(campbellSpan);
Utils::InitializeCampbellColorTable(campbellSpan);
Utils::SetColorTableAlpha(campbellSpan, 0);
for (size_t i = 0; i < expectedCampbellTable.size(); i++)

View file

@ -7,9 +7,7 @@
#include "../TerminalSettingsModel/CascadiaSettings.h"
#include "JsonTestClass.h"
#include "TestUtils.h"
#include <defaults.h>
#include <userDefaults.h>
using namespace Microsoft::Console;
using namespace WEX::Logging;
@ -72,7 +70,6 @@ namespace SettingsModelLocalTests
TEST_METHOD(TestCloneInheritanceTree);
TEST_METHOD(TestValidDefaults);
TEST_METHOD(TestInheritedCommand);
TEST_METHOD(LoadFragmentsWithMultipleUpdates);
private:
static winrt::com_ptr<implementation::CascadiaSettings> createSettings(const std::string_view& userJSON)
@ -1982,34 +1979,4 @@ namespace SettingsModelLocalTests
VERIFY_IS_NULL(actualKeyChord);
}
}
// This test ensures GH#11597 doesn't regress.
void DeserializationTests::LoadFragmentsWithMultipleUpdates()
{
static constexpr std::wstring_view fragmentSource{ L"fragment" };
static constexpr std::string_view fragmentJson{ R"({
"profiles": [
{
"updates": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
"cursorShape": "filledBox"
},
{
"updates": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
"cursorShape": "filledBox"
},
{
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"commandline": "cmd.exe"
}
]
})" };
implementation::SettingsLoader loader{ std::string_view{}, DefaultJson };
loader.MergeInboxIntoUserSettings();
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
loader.FinalizeLayering();
VERIFY_IS_FALSE(loader.duplicateProfile);
VERIFY_ARE_EQUAL(3u, loader.userSettings.profiles.size());
}
}

View file

@ -97,7 +97,6 @@ namespace SettingsModelLocalTests
"confirmCloseAllTabs": true,
"largePasteWarning": true,
"multiLinePasteWarning": true,
"trimPaste": true,
"experimental.input.forceVT": false,
"experimental.rendering.forceFullRepaint": false,

View file

@ -508,7 +508,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
result = RunOnUIThread([&page]() {
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, 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, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, 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, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Right, SplitType::Duplicate, 0.5f, nullptr);
secondId = tab->_activePane->Id().value();
});
Sleep(250);
@ -862,7 +862,7 @@ namespace TerminalAppLocalTests
// | 3 | |
// | | |
// -------------------
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, 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, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
fourthId = tab->_activePane->Id().value();
});

View file

@ -28,7 +28,7 @@
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>

View file

@ -9,7 +9,7 @@
<uap:SupportedUsers>multiple</uap:SupportedUsers>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />

View file

@ -239,8 +239,8 @@ HRESULT HwndTerminal::Initialize()
_terminal->SetBackgroundCallback([](auto) {});
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12));
_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204));
_terminal->SetDefaultBackground(RGB(12, 12, 12));
_terminal->SetDefaultForeground(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->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground);
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground);
publicTerminal->_terminal->SetDefaultForeground(theme.DefaultForeground);
publicTerminal->_terminal->SetDefaultBackground(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 noexcept
COORD HwndTerminal::GetFontSize() const
{
return _actualFont.GetSize();
}

View file

@ -128,7 +128,7 @@ private:
void _SendCharEvent(wchar_t ch, WORD scanCode, WORD flags) noexcept;
// Inherited via IControlAccessibilityInfo
COORD GetFontSize() const noexcept override;
COORD GetFontSize() const override;
RECT GetBounds() const noexcept override;
double GetScaleFactor() const noexcept override;
void ChangeViewport(const SMALL_RECT NewWindow) override;

View file

@ -29,9 +29,6 @@
<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>

View file

@ -174,9 +174,10 @@ 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()),
_MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
realArgs.TerminalArgs());
args.Handled(true);
}
}
@ -555,7 +556,7 @@ namespace winrt::TerminalApp::implementation
auto actions = winrt::single_threaded_vector<ActionAndArgs>(std::move(
TerminalPage::ConvertExecuteCommandlineToActions(realArgs)));
if (actions.Size() != 0)
if (_startupActions.Size() != 0)
{
actionArgs.Handled(true);
ProcessStartupActions(actions, false);

View file

@ -12,8 +12,6 @@
#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;
@ -133,6 +131,38 @@ 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:
@ -184,7 +214,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 = ::Microsoft::Console::Utils::IsElevated();
_isElevated = _isUserAdmin();
_root = winrt::make_self<TerminalPage>();
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
@ -304,9 +334,6 @@ 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",
@ -880,6 +907,8 @@ 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,
@ -888,29 +917,14 @@ 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()](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() };
[this, settingsBasename = settingsPath.filename(), stateBasename = statePath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
const auto modifiedBasename = std::filesystem::path{ fileModified }.filename();
if (modifiedBasename == settingsBasename)
{
_reloadSettings->Run();
}
else if (ApplicationState::SharedInstance().IsStatePath(modifiedBasename))
else if (modifiedBasename == stateBasename)
{
_reloadState();
}
@ -1037,11 +1051,6 @@ 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
@ -1548,11 +1557,6 @@ namespace winrt::TerminalApp::implementation
return _root->IsQuakeWindow();
}
void AppLogic::RequestExitFullscreen()
{
_root->SetFullscreen(false);
}
bool AppLogic::GetMinimizeToNotificationArea()
{
if constexpr (Feature_NotificationIcon::IsEnabled())

View file

@ -5,7 +5,6 @@
#include "AppLogic.g.h"
#include "FindTargetWindowResult.g.h"
#include "SystemMenuChangeArgs.g.h"
#include "Jumplist.h"
#include "LanguageProfileNotifier.h"
#include "TerminalPage.h"
@ -36,17 +35,6 @@ 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:
@ -91,7 +79,6 @@ 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();
@ -126,7 +113,6 @@ 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 };
@ -177,7 +163,6 @@ namespace winrt::TerminalApp::implementation
void _RegisterSettingsChange();
fire_and_forget _DispatchReloadSettings();
void _ReloadSettings();
void _OpenSettingsUI();
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);

View file

@ -19,20 +19,6 @@ 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();
@ -74,7 +60,6 @@ namespace TerminalApp
void SetPersistedLayoutIdx(UInt32 idx);
void SetNumberOfOpenWindows(UInt64 num);
void RenameFailed();
void RequestExitFullscreen();
Boolean IsQuakeWindow();
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
@ -125,6 +110,5 @@ 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;
}
}

View file

@ -2351,32 +2351,35 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
}
// Method Description:
// - The same as above, except this takes in the pane directly instead of a
// profile and control to make a pane with
// - 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.
// Arguments:
// - splitType: what type of split we want to create.
// - splitSize: the desired size of the split
// - newPane: the new pane
// - profile: The profile to associate with the newly created pane.
// - control: A TermControl to use in 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,
std::shared_ptr<Pane> newPane)
const Profile& profile,
const TermControl& control)
{
if (!_lastActive)
{
if (_firstChild && _firstChild->_HasFocusedChild())
{
return _firstChild->Split(splitType, splitSize, newPane);
return _firstChild->Split(splitType, splitSize, profile, control);
}
else if (_secondChild && _secondChild->_HasFocusedChild())
{
return _secondChild->Split(splitType, splitSize, newPane);
return _secondChild->Split(splitType, splitSize, profile, control);
}
return { nullptr, nullptr };
}
auto newPane = std::make_shared<Pane>(profile, control);
return _Split(splitType, splitSize, newPane);
}

View file

@ -110,7 +110,8 @@ public:
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> pane);
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
const winrt::Microsoft::Terminal::Control::TermControl& control);
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,

View file

@ -68,7 +68,7 @@ namespace winrt::TerminalApp::implementation
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection));
_CreateNewTabWithProfileAndSettings(profile, settings, existingConnection);
const uint32_t tabCount = _tabs.Size();
const bool usedManualProfile = (newTerminalArgs != nullptr) &&
@ -244,6 +244,58 @@ 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.
@ -313,14 +365,28 @@ 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));
const auto runtimeTabText{ tab.GetTabText() };
if (!runtimeTabText.empty())
if (auto profile = tab.GetFocusedProfile())
{
if (auto newTab{ _GetFocusedTabImpl() })
// 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)
{
newTab->SetTabText(runtimeTabText);
settingsCreateResult.DefaultSettings().StartingDirectory(workingDirectory);
}
_CreateNewTabWithProfileAndSettings(profile, settingsCreateResult);
const auto runtimeTabText{ tab.GetTabText() };
if (!runtimeTabText.empty())
{
if (auto newTab{ _GetFocusedTabImpl() })
{
newTab->SetTabText(runtimeTabText);
}
}
}
}
@ -336,7 +402,7 @@ namespace winrt::TerminalApp::implementation
try
{
_SetFocusedTab(tab);
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
_SplitPane(tab, SplitDirection::Automatic, SplitType::Duplicate);
}
CATCH_LOG();
}

View file

@ -318,29 +318,7 @@
</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
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>
manually include the winmds as References below -->
</ItemGroup>
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See

View file

@ -3,35 +3,37 @@
#include "pch.h"
#include "TerminalPage.h"
#include "TerminalPage.g.cpp"
#include "RenameWindowRequestedArgs.g.cpp"
#include "Utils.h"
#include "../../types/inc/utils.hpp"
#include <filesystem>
#include <inc/WindowingBehavior.h>
#include <LibraryResources.h>
#include <TerminalCore/ControlKeyStates.hpp>
#include <til/latch.h>
#include "../../types/inc/utils.hpp"
#include "TerminalPage.g.cpp"
#include <winrt/Windows.Storage.h>
#include "TabRowControl.h"
#include "ColorHelper.h"
#include "DebugTapConnection.h"
#include "SettingsTab.h"
#include "TabRowControl.h"
#include "RenameWindowRequestedArgs.g.cpp"
#include "../inc/WindowingBehavior.h"
#include <til/latch.h>
#include <TerminalCore/ControlKeyStates.hpp>
using namespace winrt;
using namespace winrt::Microsoft::Terminal::Control;
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 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 ::TerminalApp;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Terminal::Core;
@ -300,7 +302,10 @@ 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;
}
@ -847,7 +852,14 @@ namespace winrt::TerminalApp::implementation
WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
if (shiftPressed && !debugTap)
if (altPressed && !debugTap)
{
this->_SplitPane(SplitDirection::Automatic,
SplitType::Manual,
0.5f,
newTerminalArgs);
}
else if (shiftPressed && !debugTap)
{
// Manually fill in the evaluated profile.
if (newTerminalArgs.ProfileIndex() != nullptr)
@ -863,17 +875,7 @@ namespace winrt::TerminalApp::implementation
}
else
{
const auto newPane = _MakePane(newTerminalArgs);
if (altPressed && !debugTap)
{
this->_SplitPane(SplitDirection::Automatic,
0.5f,
newPane);
}
else
{
_CreateNewTabFromPane(newPane);
}
LOG_IF_FAILED(this->_OpenNewTab(newTerminalArgs));
}
}
@ -1609,15 +1611,18 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Split the focused pane either horizontally or vertically, and place the
// given pane accordingly in the tree
// given TermControl into the newly created pane.
// 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.
// - splitSize: the size of the split
// - 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.
void TerminalPage::_SplitPane(const SplitDirection splitDirection,
const SplitType splitMode,
const float splitSize,
std::shared_ptr<Pane> newPane)
const NewTerminalArgs& newTerminalArgs)
{
const auto focusedTab{ _GetFocusedTabImpl() };
@ -1627,52 +1632,101 @@ namespace winrt::TerminalApp::implementation
return;
}
_SplitPane(*focusedTab, splitDirection, splitSize, newPane);
_SplitPane(*focusedTab, splitDirection, splitMode, splitSize, newTerminalArgs);
}
// Method Description:
// - Split the focused pane of the given tab, either horizontally or vertically, and place the
// given pane accordingly
// given TermControl into the newly created pane.
// 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.
// - splitSize: the size of the split
// - 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.
void TerminalPage::_SplitPane(TerminalTab& tab,
const SplitDirection splitDirection,
const SplitType splitMode,
const float splitSize,
std::shared_ptr<Pane> newPane)
const NewTerminalArgs& newTerminalArgs)
{
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)
try
{
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
}
TerminalSettingsCreateResult controlSettings{ nullptr };
Profile profile{ nullptr };
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())
if (splitMode == SplitType::Duplicate)
{
control.Focus(FocusState::Programmatic);
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);
}
}
CATCH_LOG();
}
// Method Description:
@ -1941,22 +1995,6 @@ namespace winrt::TerminalApp::implementation
}
}
if (_settings.GlobalSettings().TrimPaste())
{
std::wstring_view textView{ text };
const auto pos = textView.find_last_not_of(L"\t\n\v\f\r ");
if (pos == textView.npos)
{
// Text is all white space, nothing to paste
co_return;
}
else if (const auto toRemove = textView.size() - 1 - pos; toRemove > 0)
{
textView.remove_suffix(toRemove);
text = { textView };
}
}
bool warnMultiLine = _settings.GlobalSettings().WarnAboutMultiLinePaste();
if (warnMultiLine)
{
@ -2180,7 +2218,7 @@ namespace winrt::TerminalApp::implementation
{
if (target == SettingsTarget::SettingsUI)
{
OpenSettingsUI();
_OpenSettingsUI();
}
else
{
@ -2257,96 +2295,6 @@ 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
@ -2656,7 +2604,9 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalPage::ToggleFullscreen()
{
SetFullscreen(!_isFullscreen);
_isFullscreen = !_isFullscreen;
_UpdateTabView();
_FullscreenChangedHandlers(*this, nullptr);
}
// Method Description:
@ -2873,17 +2823,6 @@ 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.
@ -2911,7 +2850,7 @@ namespace winrt::TerminalApp::implementation
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, connection));
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
// Request a summon of this window to the foreground
_SummonWindowRequestedHandlers(*this, nullptr);
@ -2927,7 +2866,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)
@ -3545,7 +3484,7 @@ namespace winrt::TerminalApp::implementation
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
OpenSettingsUI();
_OpenSettingsUI();
}
// Method Description:

View file

@ -88,7 +88,6 @@ 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);
@ -127,8 +126,6 @@ namespace winrt::TerminalApp::implementation
bool IsQuakeWindow() const noexcept;
bool IsElevated() const noexcept;
void OpenSettingsUI();
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
// -------------------------------- WinRT Events ---------------------------------
@ -217,6 +214,7 @@ 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);
@ -306,12 +304,14 @@ 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 float splitSize,
std::shared_ptr<Pane> newPane);
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);
void _SplitPane(TerminalTab& tab,
const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> newPane);
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);
void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
void _ToggleSplitOrientation();
@ -358,10 +358,6 @@ 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);
@ -377,6 +373,8 @@ namespace winrt::TerminalApp::implementation
void _UnZoomIfNeeded();
void _OpenSettingsUI();
static int _ComputeScrollDelta(ScrollDirection scrollDirection, const uint32_t rowsToScroll);
static uint32_t _ReadSystemRowsToScroll();

View file

@ -15,7 +15,6 @@
<Grid x:Name="Root"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
@ -23,50 +22,8 @@
<local:TabRowControl x:Name="TabRow"
Grid.Row="0" />
<StackPanel Grid.Row="1">
<mux:InfoBar x:Name="KeyboardServiceWarningInfoBar"
x:Load="False"
IsClosable="True"
IsIconVisible="True"
IsOpen="False"
Message="{x:Bind KeyboardServiceDisabledText, Mode=OneWay}"
Severity="Warning">
<mux:InfoBar.ActionButton>
<Button x:Uid="InfoBarDismissButton"
Click="_KeyboardServiceWarningInfoDismissHandler" />
</mux:InfoBar.ActionButton>
</mux:InfoBar>
<mux:InfoBar x:Name="CloseOnExitInfoBar"
x:Uid="CloseOnExitInfoBar"
x:Load="False"
IsClosable="True"
IsIconVisible="True"
IsOpen="False"
Severity="Informational">
<mux:InfoBar.ActionButton>
<Button x:Uid="InfoBarDismissButton"
Click="_CloseOnExitInfoDismissHandler" />
</mux:InfoBar.ActionButton>
</mux:InfoBar>
<mux:InfoBar x:Name="SetAsDefaultInfoBar"
x:Uid="SetAsDefaultInfoBar"
x:Load="False"
CloseButtonClick="_SetAsDefaultDismissHandler"
IsClosable="True"
IsIconVisible="True"
IsOpen="False"
Severity="Informational">
<mux:InfoBar.ActionButton>
<HyperlinkButton x:Uid="SetAsDefaultTip_OpenSettingsLink"
Click="_SetAsDefaultOpenSettingsHandler" />
</mux:InfoBar.ActionButton>
</mux:InfoBar>
</StackPanel>
<Grid x:Name="TabContent"
Grid.Row="2"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
@ -153,11 +110,53 @@
</ContentDialog>
<local:CommandPalette x:Name="CommandPalette"
Grid.Row="2"
Grid.Row="1"
VerticalAlignment="Stretch"
PreviewKeyDown="_KeyDownHandler"
Visibility="Collapsed" />
<StackPanel>
<mux:InfoBar x:Name="KeyboardServiceWarningInfoBar"
x:Load="False"
IsClosable="True"
IsIconVisible="True"
IsOpen="False"
Message="{x:Bind KeyboardServiceDisabledText, Mode=OneWay}"
Severity="Warning">
<mux:InfoBar.ActionButton>
<Button x:Uid="InfoBarDismissButton"
Click="_KeyboardServiceWarningInfoDismissHandler" />
</mux:InfoBar.ActionButton>
</mux:InfoBar>
<mux:InfoBar x:Name="CloseOnExitInfoBar"
x:Uid="CloseOnExitInfoBar"
x:Load="False"
IsClosable="True"
IsIconVisible="True"
IsOpen="False"
Severity="Informational">
<mux:InfoBar.ActionButton>
<Button x:Uid="InfoBarDismissButton"
Click="_CloseOnExitInfoDismissHandler" />
</mux:InfoBar.ActionButton>
</mux:InfoBar>
<mux:InfoBar x:Name="SetAsDefaultInfoBar"
x:Uid="SetAsDefaultInfoBar"
x:Load="False"
CloseButtonClick="_SetAsDefaultDismissHandler"
IsClosable="True"
IsIconVisible="True"
IsOpen="False"
Severity="Informational">
<mux:InfoBar.ActionButton>
<HyperlinkButton x:Uid="SetAsDefaultTip_OpenSettingsLink"
Click="_SetAsDefaultOpenSettingsHandler" />
</mux:InfoBar.ActionButton>
</mux:InfoBar>
</StackPanel>
<!--
A TeachingTip with IsLightDismissEnabled="True" will immediately
dismiss itself if the window is unfocused (In Xaml Islands). This is

View file

@ -25,6 +25,18 @@ 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;
@ -52,9 +64,8 @@ namespace winrt::TerminalApp::implementation
// focus the first one.
if (_activePane == nullptr)
{
const auto firstPane = _rootPane->FindPane(firstId);
firstPane->SetActive();
_activePane = firstPane;
_rootPane->FocusPane(firstId);
_activePane = _rootPane->GetActivePane();
}
// If the focused pane is a leaf, add it to the MRU panes
if (const auto id = _activePane->Id())
@ -492,48 +503,39 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Split the focused pane in our tree of panes, and place the
// given pane into the tree of panes according to the split
// given TermControl into the newly created pane.
// Arguments:
// - 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
// - 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.
// Return Value:
// - <none>
void TerminalTab::SplitPane(SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> pane)
const Profile& profile,
TermControl& control)
{
// 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, pane);
auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control);
// 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

View file

@ -21,6 +21,7 @@ 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
@ -39,7 +40,8 @@ namespace winrt::TerminalApp::implementation
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> newPane);
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
winrt::Microsoft::Terminal::Control::TermControl& control);
void ToggleSplitOrientation();
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);

View file

@ -68,22 +68,5 @@
</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>

View file

@ -429,9 +429,8 @@ 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, static_cast<unsigned int>(hr)),
fmt::format(_errorFormat, hr),
_commandline) };
_TerminalOutputHandlers(failureText);
@ -458,7 +457,6 @@ 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);

View file

@ -97,39 +97,4 @@
</Link>
</ItemDefinitionGroup>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
<!--
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>
</Project>

View file

@ -3,18 +3,16 @@
#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"
@ -204,8 +202,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const double actualHeight,
const double compositionScale)
{
assert(_settings);
_panelWidth = actualWidth;
_panelHeight = actualHeight;
_compositionScale = compositionScale;
@ -226,16 +222,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return false;
}
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());
// Set up the DX Engine
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
_renderer->AddRenderEngine(dxEngine.get());
_renderEngine = std::move(dxEngine);
// 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
@ -281,12 +271,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
_updateAntiAliasingMode();
_updateAntiAliasingMode(_renderEngine.get());
// 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.
const auto backgroundIsOpaque = _settings.Opacity() == 1.0 && _settings.BackgroundImage().empty();
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.Opacity()));
THROW_IF_FAILED(_renderEngine->Enable());
@ -627,7 +616,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
_updateAntiAliasingMode();
_updateAntiAliasingMode(_renderEngine.get());
// Refresh our font with the renderer
const auto actualFontOldSize = _actualFont.GetSize();
@ -661,24 +650,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void ControlCore::_updateAntiAliasingMode()
void ControlCore::_updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine)
{
D2D1_TEXT_ANTIALIAS_MODE mode;
// Update DxEngine's AntialiasingMode
switch (_settings.AntialiasingMode())
{
case TextAntialiasingMode::Cleartype:
mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
break;
case TextAntialiasingMode::Aliased:
mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
break;
case TextAntialiasingMode::Grayscale:
default:
mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
break;
}
_renderEngine->SetAntialiasingMode(mode);
}
// Method Description:
@ -1089,7 +1076,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::color ControlCore::BackgroundColor() const
{
return _terminal->GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
return _terminal->GetDefaultBackground();
}
// Method Description:
@ -1309,8 +1296,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_renderEngine)
{
auto lock = _terminal->LockForWriting();
const auto backgroundIsOpaque = opacity == 1.0 && _settings.BackgroundImage().empty();
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(opacity));
}
}

View file

@ -15,8 +15,11 @@
#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"
@ -185,7 +188,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::IRenderEngine> _renderEngine{ nullptr };
std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr };
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr };
IControlSettings _settings{ nullptr };
@ -245,7 +248,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
#pragma endregion
void _raiseReadOnlyWarning();
void _updateAntiAliasingMode();
void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine);
void _connectionOutputHandler(const hstring& hstr);
void _updateHoveredCell(const std::optional<til::point> terminalPosition);

View file

@ -22,7 +22,6 @@
#include "cppwinrt_utils.h"
#include "ControlCore.h"
#include "../../renderer/uia/UiaRenderer.hpp"
namespace ControlUnitTests
{

View file

@ -27,11 +27,10 @@ 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;

View file

@ -141,12 +141,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
#pragma endregion
#pragma region IControlAccessibilityInfo
COORD InteractivityAutomationPeer::GetFontSize() const noexcept
COORD InteractivityAutomationPeer::GetFontSize() const
{
return til::size{ til::math::rounding, _interactivity->Core().FontSize() };
}
RECT InteractivityAutomationPeer::GetBounds() const noexcept
RECT InteractivityAutomationPeer::GetBounds() const
{
return _controlBounds;
}
@ -159,12 +159,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return S_OK;
}
RECT InteractivityAutomationPeer::GetPadding() const noexcept
RECT InteractivityAutomationPeer::GetPadding() const
{
return _controlPadding;
}
double InteractivityAutomationPeer::GetScaleFactor() const noexcept
double InteractivityAutomationPeer::GetScaleFactor() const
{
return DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
}

View file

@ -62,10 +62,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
#pragma region IControlAccessibilityInfo Pattern
// Inherited via IControlAccessibilityInfo
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 COORD GetFontSize() const override;
virtual RECT GetBounds() const override;
virtual RECT GetPadding() const override;
virtual double GetScaleFactor() const override;
virtual void ChangeViewport(SMALL_RECT NewWindow) override;
virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override;
#pragma endregion

View file

@ -3,16 +3,17 @@
#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 "../../renderer/atlas/AtlasEngine.h"
#include "../../types/inc/Utils.hpp"
#include "TermControl.g.cpp"
#include "TermControlAutomationPeer.h"
using namespace ::Microsoft::Console::Types;
using namespace ::Microsoft::Console::VirtualTerminal;
@ -296,7 +297,37 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
_SetBackgroundImage(newAppearance);
if (!newAppearance.BackgroundImage().empty())
{
Windows::Foundation::Uri imageUri{ newAppearance.BackgroundImage() };
// Check if the image brush is already pointing to the image
// in the modified settings; if it isn't (or isn't there),
// set a new image source for the brush
auto imageSource = BackgroundImage().Source().try_as<Media::Imaging::BitmapImage>();
if (imageSource == nullptr ||
imageSource.UriSource() == nullptr ||
imageSource.UriSource().RawUri() != imageUri.RawUri())
{
// Note that BitmapImage handles the image load asynchronously,
// which is especially important since the image
// may well be both large and somewhere out on the
// internet.
Media::Imaging::BitmapImage image(imageUri);
BackgroundImage().Source(image);
}
// Apply stretch, opacity and alignment settings
BackgroundImage().Stretch(newAppearance.BackgroundImageStretchMode());
BackgroundImage().Opacity(newAppearance.BackgroundImageOpacity());
BackgroundImage().HorizontalAlignment(newAppearance.BackgroundImageHorizontalAlignment());
BackgroundImage().VerticalAlignment(newAppearance.BackgroundImageVerticalAlignment());
}
else
{
BackgroundImage().Source(nullptr);
}
// Update our control settings
const auto bg = newAppearance.DefaultBackground();
@ -381,57 +412,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
// Method Description:
// - Sets background image and applies its settings (stretch, opacity and alignment)
// - Checks path validity
// Arguments:
// - newAppearance
// Return Value:
// - <none>
void TermControl::_SetBackgroundImage(const IControlAppearance& newAppearance)
{
if (newAppearance.BackgroundImage().empty())
{
BackgroundImage().Source(nullptr);
return;
}
Windows::Foundation::Uri imageUri{ nullptr };
try
{
imageUri = Windows::Foundation::Uri{ newAppearance.BackgroundImage() };
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
BackgroundImage().Source(nullptr);
return;
}
// Check if the image brush is already pointing to the image
// in the modified settings; if it isn't (or isn't there),
// set a new image source for the brush
auto imageSource = BackgroundImage().Source().try_as<Media::Imaging::BitmapImage>();
if (imageSource == nullptr ||
imageSource.UriSource() == nullptr ||
imageSource.UriSource().RawUri() != imageUri.RawUri())
{
// Note that BitmapImage handles the image load asynchronously,
// which is especially important since the image
// may well be both large and somewhere out on the
// internet.
Media::Imaging::BitmapImage image(imageUri);
BackgroundImage().Source(image);
}
// Apply stretch, opacity and alignment settings
BackgroundImage().Stretch(newAppearance.BackgroundImageStretchMode());
BackgroundImage().Opacity(newAppearance.BackgroundImageOpacity());
BackgroundImage().HorizontalAlignment(newAppearance.BackgroundImageHorizontalAlignment());
BackgroundImage().VerticalAlignment(newAppearance.BackgroundImageVerticalAlignment());
}
// Method Description:
// - Set up each layer's brush used to display the control's background.
// - Respects the settings for acrylic, background image and opacity from
@ -1830,7 +1810,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const winrt::Windows::Foundation::Size initialSize{ cols, rows };
return GetProposedDimensions(settings, dpi, initialSize);
return GetProposedDimensions(initialSize,
settings.FontSize(),
settings.FontWeight(),
settings.FontFace(),
settings.ScrollState(),
settings.Padding(),
dpi);
}
// Function Description:
@ -1851,15 +1837,16 @@ 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(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars)
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)
{
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
@ -1868,39 +1855,28 @@ 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>(fontSize) }, CP_UTF8, false };
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast<short>(fontHeight) }, 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/AtlasEngine.
// instantiating a DxEngine
// GH#10211 - UNDER NO CIRCUMSTANCE should this fail. If it does, the
// whole app will crash instantaneously on launch, which is no good.
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();
}
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
LOG_IF_FAILED(dxEngine->UpdateDpi(dpi));
LOG_IF_FAILED(dxEngine->UpdateFont(desiredFont, actualFont));
const auto actualFontSize = actualFont.GetSize();
const auto scale = dxEngine->GetScaling();
const auto fontSize = 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 * actualFontSize.X;
double width = cols * fontSize.X;
// Reserve additional space if scrollbar is intended to be visible
if (scrollState == ScrollbarState::Visible)
@ -1908,7 +1884,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
width += scrollbarSize;
}
double height = rows * actualFontSize.Y;
double height = rows * fontSize.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);
@ -1968,7 +1944,13 @@ 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(_settings, dpi, minSize);
return GetProposedDimensions(minSize,
_settings.FontSize(),
_settings.FontWeight(),
_settings.FontFace(),
_settings.ScrollState(),
_settings.Padding(),
dpi);
}
}
@ -2271,42 +2253,6 @@ 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();
@ -2319,7 +2265,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
allPaths += fullPath;
}
_core.PasteText(winrt::hstring{ allPaths });
}
}

View file

@ -92,7 +92,13 @@ 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(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars);
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);
void BellLightOn();
@ -196,7 +202,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _UpdateSettingsFromUIThread(IControlSettings newSettings);
void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance);
void _ApplyUISettings(const IControlSettings&);
void _SetBackgroundImage(const IControlAppearance& newAppearance);
void _InitializeBackgroundBrush();
void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args);

View file

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

View file

@ -3,7 +3,6 @@
#pragma once
#include "../../terminal/adapter/DispatchTypes.hpp"
#include "../../terminal/input/terminalInput.hpp"
#include "../../buffer/out/TextAttribute.hpp"
#include "../../types/inc/Viewport.hpp"
@ -40,14 +39,24 @@ namespace Microsoft::Terminal::Core
virtual bool WarningBell() noexcept = 0;
virtual bool SetWindowTitle(std::wstring_view title) 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 SetColorTableEntry(const size_t tableIndex, const DWORD 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 SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;
virtual bool SetDefaultForeground(const DWORD color) noexcept = 0;
virtual bool SetDefaultBackground(const DWORD color) noexcept = 0;
virtual bool EnableWin32InputMode(const bool win32InputMode) noexcept = 0;
virtual bool SetCursorKeysMode(const bool applicationMode) noexcept = 0;
virtual bool SetKeypadMode(const bool applicationMode) noexcept = 0;
virtual bool SetScreenMode(const bool reverseMode) noexcept = 0;
virtual bool EnableVT200MouseMode(const bool enabled) noexcept = 0;
virtual bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableSGRExtendedMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableButtonEventMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableAnyEventMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableAlternateScrollMode(const bool enabled) noexcept = 0;
virtual bool EnableXtermBracketedPasteMode(const bool enabled) noexcept = 0;
virtual bool IsXtermBracketedPasteModeEnabled() const = 0;

View file

@ -41,6 +41,8 @@ Terminal::Terminal() :
_mutableViewport{ Viewport::Empty() },
_title{},
_colorTable{},
_defaultFg{ RGB(255, 255, 255) },
_defaultBg{ ARGB(0, 0, 0, 0) },
_screenReversed{ false },
_pfnWriteInput{ nullptr },
_scrollOffset{ 0 },
@ -59,14 +61,6 @@ 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)
{
@ -79,10 +73,6 @@ 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)
@ -182,13 +172,9 @@ 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
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;
til::color newBackgroundColor{ appearance.DefaultBackground() };
_defaultBg = newBackgroundColor.with_alpha(0);
_defaultFg = appearance.DefaultForeground();
_intenseIsBright = appearance.IntenseIsBright();
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
@ -227,7 +213,9 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
if (_buffer)
{
_buffer->GetCursor().SetStyle(appearance.CursorHeight(), cursorShape);
_buffer->GetCursor().SetStyle(appearance.CursorHeight(),
til::color{ appearance.CursorColor() },
cursorShape);
}
_defaultCursorShape = cursorShape;
@ -1222,7 +1210,9 @@ try
{
const gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
// First set up the basic 256 colors
Utils::InitializeColorTable(tableView);
Utils::Initialize256ColorTable(tableView);
// Then use fill the first 16 values with the Campbell scheme
Utils::InitializeCampbellColorTable(tableView);
// Then make sure all the values have an alpha of 255
Utils::SetColorTableAlpha(tableView, 0xff);
}

View file

@ -106,13 +106,22 @@ 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;
bool EnableWin32InputMode(const bool win32InputMode) noexcept override;
bool SetCursorKeysMode(const bool applicationMode) noexcept override;
bool SetKeypadMode(const bool applicationMode) noexcept override;
bool SetScreenMode(const bool reverseMode) noexcept override;
bool EnableVT200MouseMode(const bool enabled) noexcept override;
bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept override;
bool EnableSGRExtendedMouseMode(const bool enabled) noexcept override;
bool EnableButtonEventMouseMode(const bool enabled) noexcept override;
bool EnableAnyEventMouseMode(const bool enabled) noexcept override;
bool EnableAlternateScrollMode(const bool enabled) noexcept override;
bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override;
bool IsXtermBracketedPasteModeEnabled() const noexcept override;
@ -210,6 +219,7 @@ public:
void ClearPatternTree() noexcept;
const std::optional<til::color> GetTabColor() const noexcept;
til::color GetDefaultBackground() const noexcept;
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
@ -278,7 +288,9 @@ private:
std::optional<til::color> _startingTabColor;
// This is still stored as a COLORREF because it interacts with some code in ConTypes
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
til::color _defaultFg;
til::color _defaultBg;
CursorType _defaultCursorShape;
bool _screenReversed;
mutable Microsoft::Console::Render::BlinkingState _blinkingState;

View file

@ -69,6 +69,14 @@ 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:
@ -362,22 +370,6 @@ 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.
@ -391,11 +383,6 @@ try
{
_colorTable.at(tableIndex) = color;
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
{
_pfnBackgroundColorChanged(color);
}
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
@ -455,14 +442,64 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
return true;
}
bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
// 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
{
_terminalInput->SetInputMode(mode, enabled);
_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::EnableWin32InputMode(const bool win32InputMode) noexcept
{
_terminalInput->ChangeWin32InputMode(win32InputMode);
return true;
}
bool Terminal::SetCursorKeysMode(const bool applicationMode) noexcept
{
_terminalInput->ChangeCursorKeysMode(applicationMode);
return true;
}
bool Terminal::SetKeypadMode(const bool applicationMode) noexcept
{
_terminalInput->ChangeKeypadMode(applicationMode);
return true;
}
bool Terminal::SetScreenMode(const bool reverseMode) noexcept
try
{
@ -474,6 +511,42 @@ try
}
CATCH_RETURN_FALSE()
bool Terminal::EnableVT200MouseMode(const bool enabled) noexcept
{
_terminalInput->EnableDefaultTracking(enabled);
return true;
}
bool Terminal::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
{
_terminalInput->SetUtf8ExtendedMode(enabled);
return true;
}
bool Terminal::EnableSGRExtendedMouseMode(const bool enabled) noexcept
{
_terminalInput->SetSGRExtendedMode(enabled);
return true;
}
bool Terminal::EnableButtonEventMouseMode(const bool enabled) noexcept
{
_terminalInput->EnableButtonEventTracking(enabled);
return true;
}
bool Terminal::EnableAnyEventMouseMode(const bool enabled) noexcept
{
_terminalInput->EnableAnyEventTracking(enabled);
return true;
}
bool Terminal::EnableAlternateScrollMode(const bool enabled) noexcept
{
_terminalInput->EnableAlternateScroll(enabled);
return true;
}
bool Terminal::EnableXtermBracketedPasteMode(const bool enabled) noexcept
{
_bracketedPasteMode = enabled;

View file

@ -227,7 +227,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
try
{
return _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color);
return _terminalApi.SetCursorColor(color);
}
CATCH_LOG_RETURN_FALSE()
@ -247,7 +247,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
try
{
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color);
return _terminalApi.SetDefaultForeground(color);
}
CATCH_LOG_RETURN_FALSE()
@ -260,7 +260,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
try
{
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color);
return _terminalApi.SetDefaultBackground(color);
}
CATCH_LOG_RETURN_FALSE()
@ -321,9 +321,9 @@ CATCH_LOG_RETURN_FALSE()
// - applicationMode - set to true to enable Application Mode Input, false for Numeric Mode Input.
// Return Value:
// - True if handled successfully. False otherwise.
bool TerminalDispatch::SetKeypadMode(const bool applicationMode) noexcept
bool TerminalDispatch::SetKeypadMode(const bool fApplicationMode) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::Keypad, applicationMode);
_terminalApi.SetKeypadMode(fApplicationMode);
return true;
}
@ -334,7 +334,7 @@ bool TerminalDispatch::SetKeypadMode(const bool applicationMode) noexcept
// - True if handled successfully. False otherwise.
bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::CursorKey, applicationMode);
_terminalApi.SetCursorKeysMode(applicationMode);
return true;
}
@ -359,7 +359,7 @@ bool TerminalDispatch::SetScreenMode(const bool reverseMode) noexcept
// - True if handled successfully. False otherwise.
bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::Win32, win32Mode);
_terminalApi.EnableWin32InputMode(win32Mode);
return true;
}
@ -371,7 +371,7 @@ bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::DefaultMouseTracking, enabled);
_terminalApi.EnableVT200MouseMode(enabled);
return true;
}
@ -384,7 +384,7 @@ bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::Utf8MouseEncoding, enabled);
_terminalApi.EnableUTF8ExtendedMouseMode(enabled);
return true;
}
@ -397,7 +397,7 @@ bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::SgrMouseEncoding, enabled);
_terminalApi.EnableSGRExtendedMouseMode(enabled);
return true;
}
@ -409,7 +409,7 @@ bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, enabled);
_terminalApi.EnableButtonEventMouseMode(enabled);
return true;
}
@ -422,7 +422,7 @@ bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, enabled);
_terminalApi.EnableAnyEventMouseMode(enabled);
return true;
}
@ -435,7 +435,7 @@ bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) noexcept
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableAlternateScroll(const bool enabled) noexcept
{
_terminalApi.SetInputMode(TerminalInput::Mode::AlternateScroll, enabled);
_terminalApi.EnableAlternateScrollMode(enabled);
return true;
}

View file

@ -7,6 +7,29 @@
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)
@ -146,100 +169,100 @@ bool TerminalDispatch::SetGraphicsRendition(const VTParameters options) noexcept
attr.SetOverlined(false);
break;
case ForegroundBlack:
attr.SetIndexedForeground(TextColor::DARK_BLACK);
attr.SetIndexedForeground(DARK_BLACK);
break;
case ForegroundBlue:
attr.SetIndexedForeground(TextColor::DARK_BLUE);
attr.SetIndexedForeground(DARK_BLUE);
break;
case ForegroundGreen:
attr.SetIndexedForeground(TextColor::DARK_GREEN);
attr.SetIndexedForeground(DARK_GREEN);
break;
case ForegroundCyan:
attr.SetIndexedForeground(TextColor::DARK_CYAN);
attr.SetIndexedForeground(DARK_CYAN);
break;
case ForegroundRed:
attr.SetIndexedForeground(TextColor::DARK_RED);
attr.SetIndexedForeground(DARK_RED);
break;
case ForegroundMagenta:
attr.SetIndexedForeground(TextColor::DARK_MAGENTA);
attr.SetIndexedForeground(DARK_MAGENTA);
break;
case ForegroundYellow:
attr.SetIndexedForeground(TextColor::DARK_YELLOW);
attr.SetIndexedForeground(DARK_YELLOW);
break;
case ForegroundWhite:
attr.SetIndexedForeground(TextColor::DARK_WHITE);
attr.SetIndexedForeground(DARK_WHITE);
break;
case BackgroundBlack:
attr.SetIndexedBackground(TextColor::DARK_BLACK);
attr.SetIndexedBackground(DARK_BLACK);
break;
case BackgroundBlue:
attr.SetIndexedBackground(TextColor::DARK_BLUE);
attr.SetIndexedBackground(DARK_BLUE);
break;
case BackgroundGreen:
attr.SetIndexedBackground(TextColor::DARK_GREEN);
attr.SetIndexedBackground(DARK_GREEN);
break;
case BackgroundCyan:
attr.SetIndexedBackground(TextColor::DARK_CYAN);
attr.SetIndexedBackground(DARK_CYAN);
break;
case BackgroundRed:
attr.SetIndexedBackground(TextColor::DARK_RED);
attr.SetIndexedBackground(DARK_RED);
break;
case BackgroundMagenta:
attr.SetIndexedBackground(TextColor::DARK_MAGENTA);
attr.SetIndexedBackground(DARK_MAGENTA);
break;
case BackgroundYellow:
attr.SetIndexedBackground(TextColor::DARK_YELLOW);
attr.SetIndexedBackground(DARK_YELLOW);
break;
case BackgroundWhite:
attr.SetIndexedBackground(TextColor::DARK_WHITE);
attr.SetIndexedBackground(DARK_WHITE);
break;
case BrightForegroundBlack:
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
attr.SetIndexedForeground(BRIGHT_BLACK);
break;
case BrightForegroundBlue:
attr.SetIndexedForeground(TextColor::BRIGHT_BLUE);
attr.SetIndexedForeground(BRIGHT_BLUE);
break;
case BrightForegroundGreen:
attr.SetIndexedForeground(TextColor::BRIGHT_GREEN);
attr.SetIndexedForeground(BRIGHT_GREEN);
break;
case BrightForegroundCyan:
attr.SetIndexedForeground(TextColor::BRIGHT_CYAN);
attr.SetIndexedForeground(BRIGHT_CYAN);
break;
case BrightForegroundRed:
attr.SetIndexedForeground(TextColor::BRIGHT_RED);
attr.SetIndexedForeground(BRIGHT_RED);
break;
case BrightForegroundMagenta:
attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA);
attr.SetIndexedForeground(BRIGHT_MAGENTA);
break;
case BrightForegroundYellow:
attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW);
attr.SetIndexedForeground(BRIGHT_YELLOW);
break;
case BrightForegroundWhite:
attr.SetIndexedForeground(TextColor::BRIGHT_WHITE);
attr.SetIndexedForeground(BRIGHT_WHITE);
break;
case BrightBackgroundBlack:
attr.SetIndexedBackground(TextColor::BRIGHT_BLACK);
attr.SetIndexedBackground(BRIGHT_BLACK);
break;
case BrightBackgroundBlue:
attr.SetIndexedBackground(TextColor::BRIGHT_BLUE);
attr.SetIndexedBackground(BRIGHT_BLUE);
break;
case BrightBackgroundGreen:
attr.SetIndexedBackground(TextColor::BRIGHT_GREEN);
attr.SetIndexedBackground(BRIGHT_GREEN);
break;
case BrightBackgroundCyan:
attr.SetIndexedBackground(TextColor::BRIGHT_CYAN);
attr.SetIndexedBackground(BRIGHT_CYAN);
break;
case BrightBackgroundRed:
attr.SetIndexedBackground(TextColor::BRIGHT_RED);
attr.SetIndexedBackground(BRIGHT_RED);
break;
case BrightBackgroundMagenta:
attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA);
attr.SetIndexedBackground(BRIGHT_MAGENTA);
break;
case BrightBackgroundYellow:
attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW);
attr.SetIndexedBackground(BRIGHT_YELLOW);
break;
case BrightBackgroundWhite:
attr.SetIndexedBackground(TextColor::BRIGHT_WHITE);
attr.SetIndexedBackground(BRIGHT_WHITE);
break;
case ForegroundExtended:
i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true);

View file

@ -37,9 +37,6 @@
<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>

View file

@ -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, TextColor::DEFAULT_FOREGROUND);
colors.second = fgTextColor.GetColor(_colorTable, _defaultFg);
}
else
{
colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
colors.second = bgTextColor.GetColor(_colorTable, TextColor::DEFAULT_BACKGROUND);
colors.second = bgTextColor.GetColor(_colorTable, _defaultBg);
}
}
else
{
colors = attr.CalculateRgbColors(_colorTable,
TextColor::DEFAULT_FOREGROUND,
TextColor::DEFAULT_BACKGROUND,
_defaultFg,
_defaultBg,
_screenReversed,
_blinkingState.IsBlinkingFaint(),
_intenseIsBright);
@ -135,7 +135,7 @@ CursorType Terminal::GetCursorStyle() const noexcept
COLORREF Terminal::GetCursorColor() const noexcept
{
return _colorTable.at(TextColor::CURSOR_COLOR);
return _buffer->GetCursor().GetColor();
}
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] = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
colorTableWithDefaults[DefaultFgIndex] = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
colorTableWithDefaults[DefaultBgIndex] = _defaultBg;
colorTableWithDefaults[DefaultFgIndex] = _defaultFg;
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
{
const auto fg = til::at(colorTableWithDefaults, fgIndex);

View file

@ -220,7 +220,7 @@
<TextBox IsEnabled="{x:Bind local:Converters.StringsAreNotEqual('desktopWallpaper', Appearance.BackgroundImagePath), Mode=OneWay}"
IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind local:Converters.StringOrEmptyIfPlaceholder('desktopWallpaper', Appearance.BackgroundImagePath), Mode=TwoWay, BindBack=Appearance.SetBackgroundImagePath}" />
Text="{x:Bind local:Converters.StringFallBackToEmptyString('desktopWallpaper', Appearance.BackgroundImagePath), Mode=TwoWay, BindBack=Appearance.SetBackgroundImagePath}" />
<Button x:Uid="Profile_BackgroundImageBrowse"
Click="BackgroundImage_Click"
IsEnabled="{x:Bind local:Converters.StringsAreNotEqual('desktopWallpaper', Appearance.BackgroundImagePath), Mode=OneWay}"

View file

@ -1,4 +1,4 @@
#include "pch.h"
#include "pch.h"
#include "Converters.h"
#if __has_include("Converters.g.cpp")
#include "Converters.g.cpp"
@ -99,16 +99,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
return value.empty() ? winrt::Windows::UI::Xaml::Visibility::Collapsed : winrt::Windows::UI::Xaml::Visibility::Visible;
}
// Method Description:
// - Returns the value string, unless it matches the placeholder in which case the empty string.
// Arguments:
// - placeholder - the placeholder string.
// - value - the value string.
// Return Value:
// - The value string, unless it matches the placeholder in which case the empty string.
winrt::hstring Converters::StringOrEmptyIfPlaceholder(winrt::hstring placeholder, winrt::hstring value)
winrt::hstring Converters::StringFallBackToEmptyString(winrt::hstring expected, winrt::hstring actual)
{
return placeholder == value ? L"" : value;
return expected == actual ? expected : L"";
}
}

View file

@ -21,7 +21,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
static double PercentageValueToPercentage(double value);
static bool StringsAreNotEqual(winrt::hstring expected, winrt::hstring actual);
static winrt::Windows::UI::Xaml::Visibility StringNotEmptyToVisibility(winrt::hstring value);
static winrt::hstring StringOrEmptyIfPlaceholder(winrt::hstring placeholder, winrt::hstring value);
static winrt::hstring StringFallBackToEmptyString(winrt::hstring expected, winrt::hstring actual);
};
}

View file

@ -20,6 +20,6 @@ namespace Microsoft.Terminal.Settings.Editor
static Double PercentageValueToPercentage(Double value);
static Boolean StringsAreNotEqual(String expected, String actual);
static Windows.UI.Xaml.Visibility StringNotEmptyToVisibility(String value);
static String StringOrEmptyIfPlaceholder(String placeholder, String value);
static String StringFallBackToEmptyString(String expected, String actual);
}
}

View file

@ -45,11 +45,6 @@
<ToggleSwitch IsOn="{x:Bind State.Globals.TrimBlockSelection, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Trim Paste -->
<local:SettingContainer x:Uid="Globals_TrimPaste">
<ToggleSwitch IsOn="{x:Bind State.Globals.TrimPaste, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Word Delimiters -->
<local:SettingContainer x:Uid="Globals_WordDelimiters">
<TextBox IsSpellCheckEnabled="False"

View file

@ -8,6 +8,7 @@
#include "Interaction.h"
#include "Rendering.h"
#include "Actions.h"
#include "ReadOnlyActions.h"
#include "Profiles.h"
#include "GlobalAppearance.h"
#include "ColorSchemes.h"
@ -292,7 +293,21 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
else if (clickedItemTag == actionsTag)
{
contentFrame().Navigate(xaml_typename<Editor::Actions>(), winrt::make<ActionsPageNavigationState>(_settingsClone));
if constexpr (Feature_EditableActionsPage::IsEnabled())
{
contentFrame().Navigate(xaml_typename<Editor::Actions>(), winrt::make<ActionsPageNavigationState>(_settingsClone));
}
else
{
auto actionsState{ winrt::make<ReadOnlyActionsPageNavigationState>(_settingsClone) };
actionsState.OpenJson([weakThis = get_weak()](auto&&, auto&& arg) {
if (auto self{ weakThis.get() })
{
self->_OpenJsonHandlers(nullptr, arg);
}
});
contentFrame().Navigate(xaml_typename<Editor::ReadOnlyActions>(), actionsState);
}
}
else if (clickedItemTag == globalProfileTag)
{

View file

@ -77,6 +77,9 @@
<DependentUpon>Appearances.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="ReadOnlyActions.h">
<DependentUpon>ReadOnlyActions.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="Rendering.h">
<DependentUpon>Rendering.xaml</DependentUpon>
</ClInclude>
@ -118,6 +121,9 @@
<Page Include="Profiles.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="ReadOnlyActions.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Appearances.xaml">
<SubType>Designer</SubType>
</Page>
@ -171,6 +177,9 @@
<DependentUpon>Appearances.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="ReadOnlyActions.cpp">
<DependentUpon>ReadOnlyActions.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="Rendering.cpp">
<DependentUpon>Rendering.xaml</DependentUpon>
</ClCompile>
@ -214,6 +223,10 @@
<DependentUpon>Interaction.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="ReadOnlyActions.idl">
<DependentUpon>ReadOnlyActions.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="Rendering.idl">
<DependentUpon>Rendering.xaml</DependentUpon>
<SubType>Code</SubType>

View file

@ -40,6 +40,7 @@
<Page Include="Actions.xaml" />
<Page Include="SettingContainerStyle.xaml" />
<Page Include="AddProfile.xaml" />
<Page Include="ReadOnlyActions.xaml" />
<Page Include="KeyChordListener.xaml" />
</ItemGroup>
</Project>

View file

@ -3,7 +3,6 @@
#include "pch.h"
#include "Profiles.h"
#include "PreviewConnection.h"
#include "Profiles.g.cpp"
#include "EnumEntry.h"
@ -11,54 +10,6 @@
#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;
@ -156,7 +107,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
reinterpret_cast<::IUnknown**>(factory.put())));
// get the font collection; subscribe to updates
const auto fontCollection = NearbyCollection(factory.get());
com_ptr<IDWriteFontCollection> fontCollection;
THROW_IF_FAILED(factory->GetSystemFontCollection(fontCollection.put(), TRUE));
for (UINT32 i = 0; i < fontCollection->GetFontFamilyCount(); ++i)
{
@ -294,9 +246,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
return _profile.HasUnfocusedAppearance();
}
bool ProfileViewModel::EditableUnfocusedAppearance() const noexcept
bool ProfileViewModel::EditableUnfocusedAppearance()
{
return Feature_EditableUnfocusedAppearance::IsEnabled();
if constexpr (Feature_EditableUnfocusedAppearance::IsEnabled())
{
return true;
}
return false;
}
bool ProfileViewModel::ShowUnfocusedAppearance()
@ -330,11 +286,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
return _unfocusedAppearanceViewModel;
}
bool ProfileViewModel::AtlasEngineAvailable() const noexcept
{
return Feature_AtlasEngine::IsEnabled();
}
bool ProfileViewModel::UseParentProcessDirectory()
{
return StartingDirectory().empty();

View file

@ -33,8 +33,7 @@ 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);
}
@ -61,12 +60,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Editor::AppearanceViewModel DefaultAppearance();
Editor::AppearanceViewModel UnfocusedAppearance();
bool HasUnfocusedAppearance();
bool EditableUnfocusedAppearance() const noexcept;
bool EditableUnfocusedAppearance();
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);
@ -86,6 +85,8 @@ 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);
@ -95,7 +96,6 @@ 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;

View file

@ -32,7 +32,6 @@ 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();
@ -54,6 +53,8 @@ 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);
@ -62,7 +63,6 @@ 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

View file

@ -319,7 +319,7 @@
</StackPanel>
<StackPanel>
<StackPanel Orientation="Horizontal"
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance}">
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance, Mode=OneWay}">
<TextBlock x:Uid="Profile_UnfocusedAppearanceTextBlock"
Style="{StaticResource TitleTextBlockStyle}" />
<Button x:Uid="Profile_CreateUnfocusedAppearanceButton"
@ -477,15 +477,6 @@
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>

View file

@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "ReadOnlyActions.h"
#include "ReadOnlyActions.g.cpp"
#include "ReadOnlyActionsPageNavigationState.g.cpp"
#include "EnumEntry.h"
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Microsoft::Terminal::Settings::Model;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
ReadOnlyActions::ReadOnlyActions()
{
InitializeComponent();
_filteredActions = winrt::single_threaded_observable_vector<Command>();
}
void ReadOnlyActions::OnNavigatedTo(const NavigationEventArgs& e)
{
_State = e.Parameter().as<Editor::ReadOnlyActionsPageNavigationState>();
std::vector<Command> keyBindingList;
for (const auto& [_, command] : _State.Settings().GlobalSettings().ActionMap().NameMap())
{
// Filter out nested commands, and commands that aren't bound to a
// key. This page is currently just for displaying the actions that
// _are_ bound to keys.
if (command.HasNestedCommands() || !command.Keys())
{
continue;
}
keyBindingList.push_back(command);
}
std::sort(begin(keyBindingList), end(keyBindingList), CommandComparator{});
_filteredActions = single_threaded_observable_vector<Command>(std::move(keyBindingList));
}
Collections::IObservableVector<Command> ReadOnlyActions::FilteredActions()
{
return _filteredActions;
}
void ReadOnlyActions::_OpenSettingsClick(const IInspectable& /*sender*/,
const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/)
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
const bool altPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) ||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
const auto target = altPressed ? SettingsTarget::DefaultsFile : SettingsTarget::SettingsFile;
_State.RequestOpenJson(target);
}
}

View file

@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "ReadOnlyActions.g.h"
#include "ReadOnlyActionsPageNavigationState.g.h"
#include "Utils.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct CommandComparator
{
bool operator()(const Model::Command& lhs, const Model::Command& rhs) const
{
return lhs.Name() < rhs.Name();
}
};
struct ReadOnlyActionsPageNavigationState : ReadOnlyActionsPageNavigationStateT<ReadOnlyActionsPageNavigationState>
{
public:
ReadOnlyActionsPageNavigationState(const Model::CascadiaSettings& settings) :
_Settings{ settings } {}
void RequestOpenJson(const Model::SettingsTarget target)
{
_OpenJsonHandlers(nullptr, target);
}
WINRT_PROPERTY(Model::CascadiaSettings, Settings, nullptr)
TYPED_EVENT(OpenJson, Windows::Foundation::IInspectable, Model::SettingsTarget);
};
struct ReadOnlyActions : public HasScrollViewer<ReadOnlyActions>, ReadOnlyActionsT<ReadOnlyActions>
{
public:
ReadOnlyActions();
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Model::Command> FilteredActions();
WINRT_PROPERTY(Editor::ReadOnlyActionsPageNavigationState, State, nullptr);
private:
friend struct ReadOnlyActionsT<ReadOnlyActions>; // for Xaml to bind events
Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Model::Command> _filteredActions{ nullptr };
void _OpenSettingsClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
};
}
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(ReadOnlyActions);
}

View file

@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "EnumEntry.idl";
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass ReadOnlyActionsPageNavigationState
{
Microsoft.Terminal.Settings.Model.CascadiaSettings Settings;
void RequestOpenJson(Microsoft.Terminal.Settings.Model.SettingsTarget target);
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.SettingsTarget> OpenJson;
};
[default_interface] runtimeclass ReadOnlyActions : Windows.UI.Xaml.Controls.Page
{
ReadOnlyActions();
ReadOnlyActionsPageNavigationState State { get; };
IObservableVector<Microsoft.Terminal.Settings.Model.Command> FilteredActions { get; };
}
}

View file

@ -0,0 +1,222 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Page x:Class="Microsoft.Terminal.Settings.Editor.ReadOnlyActions"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<!--
Template for actions. This is _heavily_ copied from the command
palette, with modifications:
* We don't need to use a HighlightedTextControl, because we're
not filtering this list
* We don't need the chevron for nested commands
* We're not displaying the icon
* We're binding directly to a Command, not a FilteredCommand
If we wanted to reuse the command palette's list more directly,
that's theoretically possible, but then it would need to be
lifted out of TerminalApp and either moved into the
TerminalSettingsEditor or moved to it's own project consumed by
both TSE and TerminalApp.
-->
<DataTemplate x:Key="GeneralItemTemplate"
x:DataType="SettingsModel:Command">
<!--
This HorizontalContentAlignment="Stretch" is important
to make sure it takes the entire width of the line
-->
<ListViewItem HorizontalContentAlignment="Stretch"
AutomationProperties.AcceleratorKey="{x:Bind KeyChordText, Mode=OneWay}"
AutomationProperties.Name="{x:Bind Name, Mode=OneWay}">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<!-- command label -->
<ColumnDefinition Width="*" />
<!-- key chord -->
<ColumnDefinition Width="32" />
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
HorizontalAlignment="Left"
Text="{x:Bind Name, Mode=OneWay}" />
<!--
Inexplicably, we don't need to set the
AutomationProperties to Raw here, unlike in the
CommandPalette. We're not quite sure why.
-->
<Border Grid.Column="1"
Padding="2,0,2,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Style="{ThemeResource KeyChordBorderStyle}">
<TextBlock FontSize="12"
Style="{ThemeResource KeyChordTextBlockStyle}"
Text="{x:Bind KeyChordText, Mode=OneWay}" />
</Border>
</Grid>
</ListViewItem>
</DataTemplate>
<!-- These resources again, HEAVILY copied from the command palette -->
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<!-- TextBox colors ! -->
<SolidColorBrush x:Key="TextControlBackground"
Color="#333333" />
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush"
Color="#B5B5B5" />
<SolidColorBrush x:Key="TextControlForeground"
Color="#B5B5B5" />
<SolidColorBrush x:Key="TextControlBorderBrush"
Color="#404040" />
<SolidColorBrush x:Key="TextControlButtonForeground"
Color="#B5B5B5" />
<SolidColorBrush x:Key="TextControlBackgroundPointerOver"
Color="#404040" />
<SolidColorBrush x:Key="TextControlForegroundPointerOver"
Color="#FFFFFF" />
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver"
Color="#404040" />
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver"
Color="#FF4343" />
<SolidColorBrush x:Key="TextControlBackgroundFocused"
Color="#333333" />
<SolidColorBrush x:Key="TextControlForegroundFocused"
Color="#FFFFFF" />
<SolidColorBrush x:Key="TextControlBorderBrushFocused"
Color="#404040" />
<SolidColorBrush x:Key="TextControlButtonForegroundPressed"
Color="#FFFFFF" />
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed"
Color="#FF4343" />
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<!-- TextBox colors ! -->
<SolidColorBrush x:Key="TextControlBackground"
Color="#CCCCCC" />
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush"
Color="#636363" />
<SolidColorBrush x:Key="TextControlBorderBrush"
Color="#636363" />
<SolidColorBrush x:Key="TextControlButtonForeground"
Color="#636363" />
<SolidColorBrush x:Key="TextControlBackgroundPointerOver"
Color="#DADADA" />
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver"
Color="#636363" />
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver"
Color="#FF4343" />
<SolidColorBrush x:Key="TextControlBackgroundFocused"
Color="#CCCCCC" />
<SolidColorBrush x:Key="TextControlBorderBrushFocused"
Color="#636363" />
<SolidColorBrush x:Key="TextControlButtonForegroundPressed"
Color="#FFFFFF" />
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed"
Color="#FF4343" />
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border" />
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Page.Resources>
<ScrollViewer ViewChanging="ViewChanging">
<StackPanel Style="{StaticResource SettingsStackStyle}">
<TextBlock x:Uid="Globals_KeybindingsDisclaimer"
Style="{StaticResource DisclaimerStyle}" />
<!--
The Nav_OpenJSON resource just so happens to have a .Content
and .Tooltip that are _exactly_ what we're looking for here.
-->
<HyperlinkButton x:Uid="Nav_OpenJSON"
Click="_OpenSettingsClick" />
<!-- Keybindings -->
<!--
NOTE: Globals_Keybindings.Header is not defined, because that
would result in the page having "Keybindings" displayed twice, which
looks quite redundant
-->
<ContentPresenter x:Uid="Globals_Keybindings"
Margin="0">
<ListView HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AllowDrop="False"
CanReorderItems="False"
IsItemClickEnabled="False"
ItemTemplate="{StaticResource GeneralItemTemplate}"
ItemsSource="{x:Bind FilteredActions, Mode=OneWay}"
SelectionMode="None" />
</ContentPresenter>
</StackPanel>
</ScrollViewer>
</Page>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@ -247,10 +247,6 @@
<value>Remove trailing white-space in rectangular selection</value>
<comment>Header for a control to toggle whether a text selected with block selection should be trimmed of white spaces when copied to the clipboard, or not.</comment>
</data>
<data name="Globals_TrimPaste.Header" xml:space="preserve">
<value>Remove trailing white-space when pasting</value>
<comment>Header for a control to toggle whether pasted text should be trimmed of white spaces, or not.</comment>
</data>
<data name="Globals_KeybindingsDisclaimer.Text" xml:space="preserve">
<value>Below are the currently bound keys, which can be modified by editing the JSON settings file.</value>
<comment>A disclaimer located at the top of the actions page that presents the list of keybindings.</comment>
@ -927,10 +923,6 @@
<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>

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// pch.h
@ -51,7 +51,8 @@
#include <shlobj.h>
#include <shobjidl_core.h>
#include <dwrite_3.h>
#include <dwrite.h>
#include <dwrite_1.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View file

@ -16,6 +16,17 @@ 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" };
@ -27,17 +38,22 @@ 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;
#define APPEARANCE_SETTINGS_COPY(type, name, jsonKey, ...) \
appearance->_##name = source->_##name;
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_COPY)
#undef APPEARANCE_SETTINGS_COPY
appearance->_AdjustIndistinguishableColors = source->_AdjustIndistinguishableColors;
return appearance;
}
@ -49,13 +65,19 @@ 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;
}
@ -76,14 +98,19 @@ 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()

View file

@ -19,7 +19,6 @@ 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
@ -36,16 +35,26 @@ 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);
#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
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, AdjustIndistinguishableColors, true);
private:
winrt::weak_ref<Profile> _sourceProfile;

View file

@ -9,11 +9,8 @@
#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" };
@ -88,9 +85,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return trait.FromJson(root);
}
ApplicationState::ApplicationState(const std::filesystem::path& stateRoot) noexcept :
_sharedPath{ stateRoot / stateFileName },
_elevatedPath{ stateRoot / elevatedStateFileName },
// 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) },
_throttler{ std::chrono::seconds(1), [this]() { _write(); } }
{
_read();
@ -99,21 +102,9 @@ 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.
@ -122,13 +113,34 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_read();
}
bool ApplicationState::IsStatePath(const winrt::hstring& filename)
// Returns the state.json path on the disk.
winrt::hstring ApplicationState::FilePath() const noexcept
{
static const auto sharedPath{ _sharedPath.filename() };
static const auto elevatedPath{ _elevatedPath.filename() };
return filename == sharedPath || filename == elevatedPath;
return winrt::hstring{ _path.wstring() };
}
// 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
@ -144,58 +156,57 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void ApplicationState::Reset() noexcept
try
{
LOG_LAST_ERROR_IF(!DeleteFile(_sharedPath.c_str()));
LOG_LAST_ERROR_IF(!DeleteFile(_elevatedPath.c_str()));
LOG_LAST_ERROR_IF(!DeleteFile(_path.c_str()));
*_state.lock() = {};
}
CATCH_LOG()
// Deserializes the state.json and user-state (or elevated-state if
// elevated) into this ApplicationState.
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.
// * 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
{
std::string errs;
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
auto state = _state.lock();
const auto file = OpenFileReadSharedLocked(_path);
// 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);
}
}
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
}
CATCH_LOG()
@ -203,191 +214,29 @@ 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() const noexcept
void ApplicationState::_write() noexcept
try
{
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())
// re-read the state so that we can only update the properties that were changed.
Json::Value root{};
{
std::string errs;
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
Json::Value root;
auto state = _state.lock();
const auto file = OpenFileRWExclusiveLocked(_path);
root = _getRoot(file);
// 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)));
#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
// 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)));
Json::StreamWriterBuilder wbuilder;
const auto content = Json::writeString(wbuilder, root);
WriteUTF8FileLocked(file, content);
}
}
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);
}
}
}

View file

@ -16,30 +16,21 @@ 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:
// (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")
// (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")
struct WindowLayout : WindowLayoutT<WindowLayout>
{
@ -53,26 +44,23 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
friend ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<Model::WindowLayout>;
};
struct ApplicationState : public ApplicationStateT<ApplicationState>
struct ApplicationState : ApplicationStateT<ApplicationState>
{
static Microsoft::Terminal::Settings::Model::ApplicationState SharedInstance();
ApplicationState(const std::filesystem::path& stateRoot) noexcept;
ApplicationState(std::filesystem::path path) 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
bool IsStatePath(const winrt::hstring& filename);
winrt::hstring FilePath() const noexcept;
// State getters/setters
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \
type name() const noexcept; \
#define MTSM_APPLICATION_STATE_GEN(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
@ -80,24 +68,21 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
private:
struct state_t
{
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) std::optional<type> name{ __VA_ARGS__ };
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
std::optional<type> name{ __VA_ARGS__ }; \
bool name##Changed = false;
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;
void _write() const noexcept;
Json::Value _getRoot(const winrt::Microsoft::Terminal::Settings::Model::locked_hfile& file) const noexcept;
void _write() noexcept;
void _read() const noexcept;
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;
std::filesystem::path _path;
til::shared_mutex<state_t> _state;
til::throttled_func_trailing<> _throttler;
};
}

View file

@ -30,15 +30,12 @@ namespace Microsoft.Terminal.Settings.Model
void Reload();
void Reset();
Boolean IsStatePath(String filename);
String FilePath { get; };
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; };
}
}

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