Compare commits

..

10 commits

Author SHA1 Message Date
Leonard Hecker f2386de422
Improve performance and binary size of til::enumset (#11493)
This commit approximately doubles the performance of til::enumset
and reduces it's binary footprint by approximately 1kB.
Most of the binary size can be attributed to exception handling.

Unfortunately this commit removes assertions that the given values are less than
the number of bits in the `underlying_type`. However I believe this to be a good
trade-off as the tests previously only happened at runtime, while tests at
compile time would be highly preferable. Such tests are technically possible,
however MSVC fails to compile (valid) `static_assert`s containing
`static_cast`s over a parameter pack at the time of writing.
With future MSVC versions such checks can be added to this class.

This change was initially discussed in #10492, but was forgotten to
be considered before it was merged. Since the work was already done,
this commit re-introduces the optimization. It's free!

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

## Validation Steps Performed
* Run `printf '\e]8;;http://example.com\e\\This is a link\e]8;;\e\\\n'` in WSL
* A wild dotted line appears ✔️
2021-11-23 18:44:58 +00:00
Leonard Hecker 80f8383860
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 ✔️
2021-11-23 18:30:36 +00:00
James Holderness bb71179a24
Consolidate the color palette APIs (#11784)
This PR merges the default colors and cursor color into the main color
table, enabling us to simplify the `ConGetSet` and `ITerminalApi`
interfaces, with just two methods required for getting and setting any
form of color palette entry.

The is a follow-up to the color table standardization in #11602, and a
another small step towards de-duplicating `AdaptDispatch` and
`TerminalDispatch` for issue #3849. It should also make it easier to
support color queries (#3718) and a configurable bold color (#5682) in
the future.

On the conhost side, default colors could originally be either indexed
positions in the 16-color table, or separate standalone RGB values. With
the new system, the default colors will always be in the color table, so
we just need to track their index positions.

To make this work, those positions need to be calculated at startup
based on the loaded registry/shortcut settings, and updated when
settings are changed (this is handled in
`CalculateDefaultColorIndices`). But the plus side is that it's now much
easier to lookup the default color values for rendering.

For now the default colors in Windows Terminal use hardcoded positions,
because it doesn't need indexed default colors like conhost. But in the
future I'd like to extend the index handling to both terminals, so we
can eventually support the VT525 indexed color operations.

As for the cursor color, that was previously stored in the `Cursor`
class, which meant that it needed to be copied around in various places
where cursors were being instantiated. Now that it's managed separately
in the color table, a lot of that code is no longer required.

## Validation
Some of the unit test initialization code needed to be updated to setup
the color table and default index values as required for the new system.
There were also some adjustments needed to account for API changes, in
particular for methods that now take index values for the default colors
in place of COLORREFs. But for the most part, the essential behavior of
the tests remains unchanged.

I've also run a variety of manual tests looking at the legacy console
APIs as well as the various VT color sequences, and checking that
everything works as expected when color schemes are changed, both in
Windows Terminal and conhost, and in the latter case with both indexed
colors and RGB values.

Closes #11768
2021-11-23 18:28:55 +00:00
Mike Griese df06c54e70
Wrap these commands with quotes (#11807)
I'm pretty exactly following the diff from #917. These paths weren't wrapped in `"`s, so building the solution in a directory with a space in it would explode.

Closes #917.

Turns out, the diff provided by that user wasn't exactly right. I've tested building in a directory with spaces now, and this seems to work. 

Also caught a bug in the Generate Feature Flags script.
2021-11-23 17:01:59 +00:00
Mike Griese a98d18c030
Fix missing .xaml references (#11805)
I'm working on making the FastUpToDate check in Vs work for the Terminal project. This is one of a few PRs in this area.

FastUpToDate lets vs check quickly determine that it doesn't need to do anything for a given project. 

However, a few of our projects don't produce all the right artifacts, or check too many things, and this eventually causes the `wapproj` to rebuild, EVERY TIME YOU F5 in VS. 

This second PR deals with some projects MYSTERIOUSLY depending on the `.xaml` files from `Terminal.Control`, even when they by all accounts shouldn't. TerminalSettingsModel ISN'T EVEN A XAML project, so I have no idea why it thinks it needs these xaml files. The TerminalAppLib project thinking it needs them - makes more sense, but is still confusing. 
Below are my verbatim notes, which led to the solution in this PR. 


```
34>------ Up-To-Date check: Project: Microsoft.Terminal.Settings.Model.Lib, Configuration: Debug x64 ------
34>Project is not up-to-date: build output 'c:\users\migrie\dev\public\terminal\bin\x64\debug\microsoft.terminal.settings.model.lib\microsoft.terminal.control\searchboxcontrol.xaml' is missing
```

* Just copying the xaml files from `bin\x64\debug\microsoft.terminal.control\microsoft.terminal.control\*.xaml` to `bin\x64\debug\microsoft.terminal.settings.model.lib\microsoft.terminal.control` seemed to fix this.
* the .xbfs were already there
* It's very unclear why these were ever needed? They aren't used in the build for `Microsoft.Terminal.Settings.Model.Lib`. They aren't copied as a part of the build either - no .xaml files are copied at all in fact
* [ ] Does TSE have these .xamls in it's output?
* UPDATE: checking out main, and building again - ran into this again. WHY??
* Cleaned again, then built TerminalApp.vcxproj. File is no longer needed? nothing makes sense.


* `obj\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsof.CA5CAD1A.tlog\Microsoft.Terminal.Settings.Model.Lib.write.1u.tlog`:
```
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\SearchBoxControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TermControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TSFInputControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.UI.Xaml\Assets\NoiseAsset_256X256_PNG.png
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\SearchBoxControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TermControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TSFInputControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\SearchBoxControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TermControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TSFInputControl.xbf
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\SearchBoxControl.xaml
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TermControl.xaml
C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TSFInputControl.xaml
```

From the build:
```
18>Target _CopyOutOfDateSourceItemsToOutputDirectory:
18>  Skipping target "_CopyOutOfDateSourceItemsToOutputDirectory" because all output files are up-to-date with respect to the input files.
18>  Input files:
18>      C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Control\Microsoft.Terminal.Control\SearchBoxControl.xbf
18>      C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Control\Microsoft.Terminal.Control\TermControl.xbf
18>      C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Control\Microsoft.Terminal.Control\TSFInputControl.xbf
18>      C:\Users\migrie\dev\public\terminal\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\runtimes\win10-x64\native\Microsoft.UI.Xaml\Assets\NoiseAsset_256X256_PNG.png
18>  Output files:
18>      C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\SearchBoxControl.xbf
18>      C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TermControl.xbf
18>      C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.Terminal.Control\TSFInputControl.xbf
18>      C:\Users\migrie\dev\public\terminal\bin\x64\Debug\Microsoft.Terminal.Settings.Model.Lib\Microsoft.UI.Xaml\Assets\NoiseAsset_256X256_PNG.png
```

* Hmm, `21>Project is not up-to-date: build output 'c:\users\migrie\dev\public\terminal\bin\x64\debug\terminalapplib\microsoft.terminal.control\searchboxcontrol.xaml' is missing`
  as well.
2021-11-23 16:53:05 +00:00
Mike Griese dc01926e3e
Add some details about working on assigned issues (#11802)
That's what the original purpose of #865 was, but I went ahead and added some additiona text, now that we've got more of a flow for github figured out.

Closes #865
2021-11-23 15:21:42 +00:00
Mike Griese 6ad848e158
Prefer Preview VS builds always; use any existing msbuild if it's on the path (#11803)
If msbuild is already on the path, we don't need to look for it.

Also,
> I know what I did. I installed VS 2022, which is a prerelease VS install. `tools\razzle` prefers the stable builds. I think I'm gonna remove that.

* [x] Closes #1313
* [x] Closes #11446
2021-11-23 06:35:21 -06:00
Mike Griese ea456cf121
Fix for missing CopyComplete files in TerminalConnection.vcxproj (#11804)
I'm working on making the FastUpToDate check in Vs work for the Terminal project. This is one of a few PRs in this area.

FastUpToDate lets vs check quickly determine that it doesn't need to do anything for a given project. 

However, a few of our projects don't produce all the right artifacts, or check too many things, and this eventually causes the `wapproj` to rebuild, EVERY TIME YOU F5 in VS. 

This first PR deals with the `.copycomplete` file in `obj\x64\debug\terminalconnection\`. Below are my verbatim notes, which led to the solution in this PR. 








### Problem 1 
* There were missing `.copycomplete` files across the repo. 
  ```
  obj\x64\debug\microsoft.terminal.settings.model.lib\microsoft.terminal.settings.modellib.vcxproj.copycomplete
  obj\x64\debug\microsoft.terminal.settings.model\microsoft.terminal.settings.model.vcxproj.copycomplete
  obj\x64\debug\terminalapplib\terminalapplib.vcxproj.copycomplete
  obj\x64\debug\terminalapp\terminalapp.vcxproj.copycomplete
  obj\x64\debug\terminalconnection\terminalconnection.vcxproj.copycomplete
  ```
  - just making empty files there seemed good enough. 
  - Might be because the CopyLocal target was already there, but the task didn't ever run to create that file? Weird.
* UPDATE: checking out main, and building again - the `.copycomplete`s are gone. So that's something that can be improved.
* The only place I could find a reference was in `"obj\x64\Debug\TerminalConnection\TerminalConnection.vcxproj.FileListAbsolute.txt"`, which will get updated if you remove the line from that file (but no one seemingly writes it or mentiones it in the log)
* Deleting `bin\x64\Debug\TerminalConnection\cpprest142_2_10d.dll` then building the project did copy the file, but it didn't touch the copycomplete. Weird.
* Why does
  - `TerminalConnection` think it needs this
  - `Microsoft.Terminal.Settings.Model.Lib` have one
  - `Microsoft.Terminal.Control*` **NOT** have one


* This file is a [`@(CopyUpToDateMarker)`](https://github.com/dotnet/msbuild/blob/main/src/Tasks/Microsoft.Common.CurrentVersion.targets#L392)
* The target [`_CopyFilesMarkedCopyLocal`](https://github.com/dotnet/msbuild/blob/main/src/Tasks/Microsoft.Common.CurrentVersion.targets#L4795) touches `@(CopyUpToDateMarker)`, when:
  - `"'@(ReferencesCopiedInThisBuild)' != ''` and
  - `'$(WroteAtLeastOneFile)' == 'true'"`

* In out build output:
```
6>Target _CopyFilesMarkedCopyLocal:
6>  Using "Copy" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
6>  Task "Copy"
6>    Did not copy from file "C:\Users\migrie\dev\public\terminal\bin\x64\Debug\TerminalConnection\cpprest142_2_10d.dll" to file "C:\Users\migrie\dev\public\terminal\bin\x64\Debug\TerminalConnection\cpprest142_2_10d.dll" because the "SkipUnchangedFiles" parameter was set to "true" in the project and the files' sizes and timestamps match.
6>  Done executing task "Copy".
6>  Task "Touch" skipped, due to false condition; ('@(ReferencesCopiedInThisBuild)' != '' and '$(WroteAtLeastOneFile)' == 'true') was evaluated as ('C:\Users\migrie\dev\public\terminal\bin\x64\Debug\TerminalConnection\cpprest142_2_10d.dll' != '' and 'False' == 'true').
```
  - So `WroteAtLeastOneFile` should be true, when it's currently false. That _looks_ like it's set to true when the file does get copied, wheich did't happen because the copy was skipped.
  - WAIT LOOK AT THAT MESSAGE. "Did not copy from file "
    `"C:\Users\migrie\dev\public\terminal\bin\x64\Debug\TerminalConnection\cpprest142_2_10d.dll"`  to file
    `"C:\Users\migrie\dev\public\terminal\bin\x64\Debug\TerminalConnection\cpprest142_2_10d.dll"`
    THESE ARE THE SAME FILE.
    `@(ReferenceCopyLocalPaths)` is filled with the file already?!
- The Target `AppLocalFromInstalled` is the only other thing that references `cpprest142_2_10d.dll`.
- Even if you delete the `cpprest142_2_10d.dll`, then `_CopyFilesMarkedCopyLocal` still evaluates the Touch condition as false, and doesn't touch it.
- the `deployBinary()` function in `packages\vcpkg-cpprestsdk.2.10.14\scripts\buildsystems\msbuild\applocal.ps1` does the actual job of copying the file. It copies it outside of MsBuild, which prevents MsBuild from copying it, and now MsBuild thinks it shouldn't write the `.copycomplete` file itself.
2021-11-23 11:51:45 +00:00
Mike Griese 442432ea15
Fixes the wapproj fast-up-to-date check (#11806)
I'm working on making the FastUpToDate check in Vs work for the Terminal project. This is one of a few PRs in this area.

FastUpToDate lets vs check quickly determine that it doesn't need to do anything for a given project. 

However, a few of our projects don't produce all the right artifacts, or check too many things, and this eventually causes the `wapproj` to rebuild, EVERY TIME YOU F5 in VS. 

This third PR deals with the Actual fast up to date check for the CascadiaPackage.wapproj. When #11804, #11805 and this PR are all merged, you should be able to just F5 the Terminal in VS, and then change NOTHING, and F5 it again, without doing a build at all. 




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.

### teams chat where we figured this out

[3:38 PM] Dustin Howett
however, that's not the only thing that "GetTargetPath" checks.

[3:38 PM] Dustin Howett
oh yeah more info: wapproj calls GetTargetPath on all projects it references

[3:38 PM] Dustin Howett
when it calls GTP on WindowsTerminal.vcxproj it is getting back a winmd (!)


[3:39 PM] Dustin Howett
here's the magic

[3:39 PM] Dustin Howett
![image](https://user-images.githubusercontent.com/18356694/142945542-74734836-20d8-4f50-bf3a-be4e1170ae13.png)


[3:39 PM] Dustin Howett
it checks if any Link items specify GenerateWindowsMetadata

![image](https://user-images.githubusercontent.com/18356694/142945593-fd232243-0175-4653-8c34-cdc364a16031.png)
2021-11-23 11:22:56 +00:00
Leonard Hecker fc85bdf314
Upgrade to Windows SDK 22000 (#11728)
Upgrades our SDK from 19041 (Windows 10 20H1) to 22000 (Windows 11 RTM).
The newer SDK is  more compatible with /Zc:preprocessor
and will allow us to use newer Windows 11 APIs directly.

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

## Validation Steps Performed
* Compiles ✔️
* Runs ✔️
2021-11-18 18:08:26 +00:00
138 changed files with 1485 additions and 3104 deletions

View file

@ -43,14 +43,12 @@ fullkbd
futex
GETDESKWALLPAPER
GETHIGHCONTRAST
GETMOUSEHOVERTIME
Hashtable
HIGHCONTRASTON
HIGHCONTRASTW
hotkeys
href
hrgn
HTCLOSE
IActivation
IApp
IAppearance
@ -95,14 +93,11 @@ MENUINFO
MENUITEMINFOW
memicmp
mptt
MOUSELEAVE
mov
msappx
MULTIPLEUSE
NCHITTEST
NCLBUTTONDBLCLK
NCMOUSELEAVE
NCMOUSEMOVE
NCRBUTTONDBLCLK
NIF
NIN
@ -168,14 +163,13 @@ TASKBARCREATED
TBPF
THEMECHANGED
tlg
TME
tmp
tolower
toupper
TRACKMOUSEEVENT
TTask
TVal
UChar
UFIELD
ULARGE
UPDATEINIFILE
userenv

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.19041",
"Microsoft.VisualStudio.Component.Windows10SDK.22000",
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
"Microsoft.VisualStudio.Component.VC.CoreIde",
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",

View file

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

View file

@ -63,8 +63,14 @@
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
DependsOnTargets="_GenerateBranchAndBrandingCache">
<MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" />
<!-- This commandline is escaped like:
powershell -Command "&'$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1' -Path '%(FeatureFlagFile.FullPath)'' -Branding $(_WTBrandingName)"
which was the only way I could find to get it to obey spaces in the SolutionDir
-->
<Exec
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command &quot;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&quot; -Path &quot;%(FeatureFlagFile.FullPath)&quot; -Branding $(_WTBrandingName)"
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;"
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.19041.0\x86\MakeAppx.exe"
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86\MakeAppx.exe"
)
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {

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.19041.0"
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0"
)
$ErrorActionPreference = "Stop"

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

View file

@ -23,7 +23,7 @@
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>EchoCon</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.22000.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@ -163,4 +163,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

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

View file

@ -118,6 +118,23 @@
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />

View file

@ -128,22 +128,22 @@ bool TextAttribute::IsLegacy() const noexcept
// - Calculates rgb colors based off of current color table and active modification attributes.
// Arguments:
// - colorTable: the current color table rgb values.
// - defaultFgColor: the default foreground color rgb value.
// - defaultBgColor: the default background color rgb value.
// - defaultFgIndex: the color table index of the default foreground color.
// - defaultBgIndex: the color table index of the default background color.
// - reverseScreenMode: true if the screen mode is reversed.
// - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false)
// - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true)
// Return Value:
// - the foreground and background colors that should be displayed.
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
const COLORREF defaultFgColor,
const COLORREF defaultBgColor,
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
const size_t defaultFgIndex,
const size_t defaultBgIndex,
const bool reverseScreenMode,
const bool blinkingIsFaint,
const bool boldIsBright) const noexcept
{
auto fg = _foreground.GetColor(colorTable, defaultFgColor, boldIsBright && IsBold());
auto bg = _background.GetColor(colorTable, defaultBgColor);
auto fg = _foreground.GetColor(colorTable, defaultFgIndex, boldIsBright && IsBold());
auto bg = _background.GetColor(colorTable, defaultBgIndex);
if (IsFaint() || (IsBlinking() && blinkingIsFaint))
{
fg = (fg >> 1) & 0x7F7F7F; // Divide foreground color components by two.

View file

@ -64,9 +64,9 @@ public:
static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept;
WORD GetLegacyAttributes() const noexcept;
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
const COLORREF defaultFgColor,
const COLORREF defaultBgColor,
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable,
const size_t defaultFgIndex,
const size_t defaultBgIndex,
const bool reverseScreenMode = false,
const bool blinkingIsFaint = false,
const bool boldIsBright = true) const noexcept;

View file

@ -139,14 +139,16 @@ void TextColor::SetDefault() noexcept
// Arguments:
// - colorTable: The table of colors we should use to look up the value of
// an indexed attribute from.
// - defaultColor: The color value to use if we're a default attribute.
// - defaultIndex: The color table index to use if we're a default attribute.
// - brighten: if true, we'll brighten a dark color table index.
// Return Value:
// - a COLORREF containing the real value of this TextColor.
COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten) const noexcept
COLORREF TextColor::GetColor(const std::array<COLORREF, TextColor::TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten) const noexcept
{
if (IsDefault())
{
const auto defaultColor = til::at(colorTable, defaultIndex);
if (brighten)
{
// See MSFT:20266024 for context on this fix.

View file

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

View file

@ -27,9 +27,7 @@ Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
_fDeferCursorRedraw(false),
_fHaveDeferredCursorRedraw(false),
_ulSize(ulSize),
_cursorType(CursorType::Legacy),
_fUseColor(false),
_color(s_InvertCursorColor)
_cursorType(CursorType::Legacy)
{
}
@ -143,10 +141,9 @@ void Cursor::SetSize(const ULONG ulSize) noexcept
_RedrawCursor();
}
void Cursor::SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept
void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept
{
_ulSize = ulSize;
_color = color;
_cursorType = type;
_RedrawCursor();
@ -285,7 +282,6 @@ void Cursor::CopyProperties(const Cursor& OtherCursor) noexcept
// Size will be handled separately in the resize operation.
//_ulSize = OtherCursor._ulSize;
_cursorType = OtherCursor._cursorType;
_color = OtherCursor._color;
}
void Cursor::DelayEOLWrap(const COORD coordDelayedAt) noexcept
@ -335,21 +331,6 @@ const CursorType Cursor::GetType() const noexcept
return _cursorType;
}
const bool Cursor::IsUsingColor() const noexcept
{
return GetColor() != INVALID_COLOR;
}
const COLORREF Cursor::GetColor() const noexcept
{
return _color;
}
void Cursor::SetColor(const unsigned int color) noexcept
{
_color = gsl::narrow_cast<COLORREF>(color);
}
void Cursor::SetType(const CursorType type) noexcept
{
_cursorType = type;

View file

@ -24,7 +24,6 @@ class TextBuffer;
class Cursor final
{
public:
static const unsigned int s_InvertCursorColor = INVALID_COLOR;
// the following values are used to create the textmode cursor.
static constexpr unsigned int CURSOR_SMALL_SIZE = 25; // large enough to be one pixel on a six pixel font
@ -51,8 +50,6 @@ public:
COORD GetPosition() const noexcept;
const CursorType GetType() const noexcept;
const bool IsUsingColor() const noexcept;
const COLORREF GetColor() const noexcept;
void StartDeferDrawing() noexcept;
bool IsDeferDrawing() noexcept;
@ -67,7 +64,7 @@ public:
void SetIsPopupShown(const bool fIsPopupShown) noexcept;
void SetDelay(const bool fDelay) noexcept;
void SetSize(const ULONG ulSize) noexcept;
void SetStyle(const ULONG ulSize, const COLORREF color, const CursorType type) noexcept;
void SetStyle(const ULONG ulSize, const CursorType type) noexcept;
void SetPosition(const COORD cPosition) noexcept;
void SetXPosition(const int NewX) noexcept;
@ -84,7 +81,6 @@ public:
COORD GetDelayedAtPosition() const noexcept;
bool IsDelayedEOLWrap() const noexcept;
void SetColor(const unsigned int color) noexcept;
void SetType(const CursorType type) noexcept;
private:
@ -117,6 +113,4 @@ private:
void _RedrawCursorAlways() noexcept;
CursorType _cursorType;
bool _fUseColor;
COLORREF _color;
};

View file

@ -24,9 +24,11 @@ class TextAttributeTests
TEST_METHOD(TestRoundtripDefaultColors);
TEST_METHOD(TestBoldAsBright);
std::array<COLORREF, 256> _colorTable;
COLORREF _defaultFg = RGB(1, 2, 3);
COLORREF _defaultBg = RGB(4, 5, 6);
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
const COLORREF _defaultFg = RGB(1, 2, 3);
const COLORREF _defaultBg = RGB(4, 5, 6);
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
};
bool TextAttributeTests::ClassSetup()
@ -47,6 +49,8 @@ bool TextAttributeTests::ClassSetup()
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
_colorTable[15] = RGB(242, 242, 242); // White
_colorTable[_defaultFgIndex] = _defaultFg;
_colorTable[_defaultBgIndex] = _defaultBg;
return true;
}
@ -132,17 +136,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
// with reverse video set, calculated foreground/background values should be
// switched while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
// reset the reverse video
attr.SetReverseVideo(false);
@ -151,17 +155,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// while the background and getters stay the same
attr.SetFaint(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
// with reverse video set, calculated foreground/background values should be
// switched, and the background fainter, while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
// reset the reverse video and faint attributes
attr.SetReverseVideo(false);
@ -171,17 +175,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
// background, while getters stay the same
attr.SetInvisible(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
// with reverse video set, the calculated background value should match
// the foreground, while getters stay the same
attr.SetReverseVideo(true);
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
}
void TextAttributeTests::TestReverseDefaultColors()
@ -194,34 +198,34 @@ void TextAttributeTests::TestReverseDefaultColors()
// values when reverse video is not set
VERIFY_IS_FALSE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
// with reverse video set, calculated foreground/background values should be
// switched while getters stay the same
attr.SetReverseVideo(true);
VERIFY_IS_TRUE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
attr.SetForeground(red);
VERIFY_IS_TRUE(attr.IsReverseVideo());
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
attr.Invert();
VERIFY_IS_FALSE(attr.IsReverseVideo());
attr.SetDefaultForeground();
attr.SetBackground(green);
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex));
}
void TextAttributeTests::TestRoundtripDefaultColors()
@ -277,43 +281,43 @@ void TextAttributeTests::TestBoldAsBright()
// values when not bold
VERIFY_IS_FALSE(attr.IsBold());
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFgIndex));
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBgIndex));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
// with bold set, calculated foreground/background values shouldn't change for the default colors.
attr.SetBold(true);
VERIFY_IS_TRUE(attr.IsBold());
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
attr.SetIndexedForeground(TextColor::DARK_BLACK);
VERIFY_IS_TRUE(attr.IsBold());
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
Log::Comment(L"Foreground should be dark black when bold is bright is disabled");
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
attr.SetIndexedBackground(TextColor::DARK_GREEN);
VERIFY_IS_TRUE(attr.IsBold());
Log::Comment(L"background should be unaffected by 'bold is bright'");
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
attr.SetBold(false);
VERIFY_IS_FALSE(attr.IsBold());
Log::Comment(L"when not bold, 'bold is bright' changes nothing");
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
attr.SetBold(true);
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
VERIFY_IS_TRUE(attr.IsBold());
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFgIndex, _defaultBgIndex, false, false, false));
}

View file

@ -23,9 +23,11 @@ class TextColorTests
TEST_METHOD(TestRgbColor);
TEST_METHOD(TestChangeColor);
std::array<COLORREF, 256> _colorTable;
COLORREF _defaultFg = RGB(1, 2, 3);
COLORREF _defaultBg = RGB(4, 5, 6);
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
const COLORREF _defaultFg = RGB(1, 2, 3);
const COLORREF _defaultBg = RGB(4, 5, 6);
const size_t _defaultFgIndex = TextColor::DEFAULT_FOREGROUND;
const size_t _defaultBgIndex = TextColor::DEFAULT_BACKGROUND;
};
bool TextColorTests::ClassSetup()
@ -46,6 +48,8 @@ bool TextColorTests::ClassSetup()
_colorTable[13] = RGB(180, 0, 158); // Bright Magenta
_colorTable[14] = RGB(249, 241, 165); // Bright Yellow
_colorTable[15] = RGB(242, 242, 242); // White
_colorTable[_defaultFgIndex] = _defaultFg;
_colorTable[_defaultBgIndex] = _defaultBg;
return true;
}
@ -57,16 +61,16 @@ void TextColorTests::TestDefaultColor()
VERIFY_IS_FALSE(defaultColor.IsLegacy());
VERIFY_IS_FALSE(defaultColor.IsRgb());
auto color = defaultColor.GetColor(_colorTable, _defaultFg, false);
auto color = defaultColor.GetColor(_colorTable, _defaultFgIndex, false);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = defaultColor.GetColor(_colorTable, _defaultFg, true);
color = defaultColor.GetColor(_colorTable, _defaultFgIndex, true);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = defaultColor.GetColor(_colorTable, _defaultBg, false);
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, false);
VERIFY_ARE_EQUAL(_defaultBg, color);
color = defaultColor.GetColor(_colorTable, _defaultBg, true);
color = defaultColor.GetColor(_colorTable, _defaultBgIndex, true);
VERIFY_ARE_EQUAL(_defaultBg, color);
}
@ -78,16 +82,16 @@ void TextColorTests::TestDarkIndexColor()
VERIFY_IS_TRUE(indexColor.IsLegacy());
VERIFY_IS_FALSE(indexColor.IsRgb());
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = indexColor.GetColor(_colorTable, _defaultFg, true);
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBg, false);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = indexColor.GetColor(_colorTable, _defaultBg, true);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}
@ -99,16 +103,16 @@ void TextColorTests::TestBrightIndexColor()
VERIFY_IS_TRUE(indexColor.IsLegacy());
VERIFY_IS_FALSE(indexColor.IsRgb());
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
auto color = indexColor.GetColor(_colorTable, _defaultFgIndex, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultFg, true);
color = indexColor.GetColor(_colorTable, _defaultFgIndex, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBg, false);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = indexColor.GetColor(_colorTable, _defaultBg, true);
color = indexColor.GetColor(_colorTable, _defaultBgIndex, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}
@ -121,16 +125,16 @@ void TextColorTests::TestRgbColor()
VERIFY_IS_FALSE(rgbColor.IsLegacy());
VERIFY_IS_TRUE(rgbColor.IsRgb());
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
VERIFY_ARE_EQUAL(myColor, color);
}
@ -143,55 +147,55 @@ void TextColorTests::TestChangeColor()
VERIFY_IS_FALSE(rgbColor.IsLegacy());
VERIFY_IS_TRUE(rgbColor.IsRgb());
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
auto color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
VERIFY_ARE_EQUAL(myColor, color);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
VERIFY_ARE_EQUAL(myColor, color);
rgbColor.SetDefault();
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
VERIFY_ARE_EQUAL(_defaultFg, color);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
VERIFY_ARE_EQUAL(_defaultBg, color);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
VERIFY_ARE_EQUAL(_defaultBg, color);
rgbColor.SetIndex(7, false);
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
VERIFY_ARE_EQUAL(_colorTable[7], color);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
rgbColor.SetIndex(15, false);
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
color = rgbColor.GetColor(_colorTable, _defaultFgIndex, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, false);
VERIFY_ARE_EQUAL(_colorTable[15], color);
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
color = rgbColor.GetColor(_colorTable, _defaultBgIndex, true);
VERIFY_ARE_EQUAL(_colorTable[15], color);
}

View file

@ -61,13 +61,26 @@
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
<ItemGroup>
<ProjectReference Include="..\WindowsTerminal\WindowsTerminal.vcxproj" />
<ProjectReference Include="..\..\host\exe\Host.EXE.vcxproj" />
<ProjectReference Include="..\..\host\proxy\Host.Proxy.vcxproj" />
<ProjectReference Include="..\TerminalAzBridge\TerminalAzBridge.vcxproj" />
<ProjectReference Include="..\ShellExtension\WindowsTerminalShellExt.vcxproj" />
<ProjectReference Include="..\wt\wt.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj">
<Project>{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj">
<Project>{067F0A06-FCB7-472C-96E9-B03B54E8E18D}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj">
<Project>{f2ed628a-db22-446f-a081-4cc845b51a2b}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\wt\wt.vcxproj">
<Project>{506fd703-baa7-4f6e-9361-64f550ec8fca}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\host\exe\Host.EXE.vcxproj">
<Project>{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}</Project>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\host\proxy\Host.Proxy.vcxproj">
<Project>{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}</Project>
</ProjectReference>
</ItemGroup>
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">

View file

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

View file

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

View file

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

View file

@ -55,12 +55,8 @@ namespace SettingsModelLocalTests
TerminalSettings settings;
VERIFY_IS_NOT_NULL(settings);
auto oldFontSize = settings.FontSize();
auto selfSettings = winrt::make_self<implementation::TerminalSettings>();
VERIFY_ARE_EQUAL(oldFontSize, selfSettings->FontSize());
selfSettings->FontSize(oldFontSize + 5);
auto newFontSize = selfSettings->FontSize();
settings.FontSize(oldFontSize + 5);
auto newFontSize = settings.FontSize();
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
}

View file

@ -90,6 +90,7 @@ namespace TerminalAppLocalTests
TEST_METHOD(TestWindowRenameSuccessful);
TEST_METHOD(TestWindowRenameFailure);
TEST_METHOD(TestControlSettingsHasParent);
TEST_METHOD(TestPreviewCommitScheme);
TEST_METHOD(TestPreviewDismissScheme);
TEST_METHOD(TestPreviewSchemeWhilePreviewing);
@ -133,6 +134,10 @@ namespace TerminalAppLocalTests
// Just creating it is enough to know that everything is working.
TerminalSettings settings;
VERIFY_IS_NOT_NULL(settings);
auto oldFontSize = settings.FontSize();
settings.FontSize(oldFontSize + 5);
auto newFontSize = settings.FontSize();
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
}
void TabTests::TryCreateConnectionType()
@ -1292,6 +1297,25 @@ namespace TerminalAppLocalTests
});
}
void TabTests::TestControlSettingsHasParent()
{
Log::Comment(L"Ensure that when we create a control, it always has a parent TerminalSettings");
auto page = _commonSetup();
VERIFY_IS_NOT_NULL(page);
TestOnUIThread([&page]() {
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
});
}
void TabTests::TestPreviewCommitScheme()
{
Log::Comment(L"Preview a color scheme. Make sure it's applied, then committed accordingly");
@ -1303,9 +1327,12 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
@ -1319,12 +1346,17 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& previewSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(previewSettings);
const auto& originalSettings = previewSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
// And we should have stored a function to revert the change.
VERIFY_ARE_EQUAL(1u, page->_restorePreviewFuncs.size());
});
@ -1341,22 +1373,20 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
const auto& grandparentSettings = originalSettings.GetParent();
VERIFY_IS_NULL(grandparentSettings);
Log::Comment(L"Color should be changed");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
// After preview there should be no more restore functions to execute.
VERIFY_ARE_EQUAL(0u, page->_restorePreviewFuncs.size());
});
Log::Comment(L"Sleep to let events propagate");
// If you don't do this, we will _sometimes_ crash as we're tearing down
// the control from this test as we start the next one. We crash
// somewhere in the CursorPositionChanged handler. It's annoying, but
// this works.
Sleep(250);
}
void TabTests::TestPreviewDismissScheme()
@ -1370,9 +1400,12 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
@ -1386,9 +1419,15 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& previewSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(previewSettings);
const auto& originalSettings = previewSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
});
@ -1402,14 +1441,18 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
const auto& grandparentSettings = originalSettings.GetParent();
VERIFY_IS_NULL(grandparentSettings);
Log::Comment(L"Color should be the same as it originally was");
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
Log::Comment(L"Sleep to let events propagate");
Sleep(250);
}
void TabTests::TestPreviewSchemeWhilePreviewing()
@ -1425,9 +1468,12 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
@ -1441,9 +1487,15 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& previewSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(previewSettings);
const auto& originalSettings = previewSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
});
@ -1458,9 +1510,15 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& previewSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(previewSettings);
const auto& originalSettings = previewSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
});
@ -1477,14 +1535,18 @@ namespace TerminalAppLocalTests
const auto& activeControl{ page->_GetActiveControl() };
VERIFY_IS_NOT_NULL(activeControl);
const auto& controlSettings = activeControl.Settings();
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
VERIFY_IS_NOT_NULL(controlSettings);
const auto& originalSettings = controlSettings.GetParent();
VERIFY_IS_NOT_NULL(originalSettings);
const auto& grandparentSettings = originalSettings.GetParent();
VERIFY_IS_NULL(grandparentSettings);
Log::Comment(L"Color should be changed");
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
});
Log::Comment(L"Sleep to let events propagate");
Sleep(250);
}
void TabTests::TestClampSwitchToTab()

View file

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

View file

@ -43,8 +43,7 @@
<ClCompile Include="CommandlineTest.cpp" />
<ClCompile Include="SettingsTests.cpp" />
<ClCompile Include="TabTests.cpp" />
<ClCompile Include="TrustCommandlineTests.cpp" />
<ClCompile Include="FilteredCommandTests.cpp" />
<ClCompile Include="FilteredCommandTests.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>

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.19041.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />

View file

@ -1,123 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// A series of tests for the TerminalPage::_isTrustedCommandline function.
// That's a heuristic function for deciding if we should automatically trust
// certain commandlines by default. The logic in there is weird and there are
// lots of edge cases, so it's easier to just write a unit test.
#include "pch.h"
#include "../TerminalApp/TerminalPage.h"
using namespace Microsoft::Console;
using namespace TerminalApp;
using namespace winrt::TerminalApp;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Text;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
namespace WUX = Windows::UI::Xaml;
using IInspectable = Windows::Foundation::IInspectable;
}
namespace TerminalAppLocalTests
{
class TrustCommandlineTests
{
BEGIN_TEST_CLASS(TrustCommandlineTests)
END_TEST_CLASS()
TEST_METHOD(SimpleTests);
TEST_METHOD(TestCommandlineWithArgs);
TEST_METHOD(TestCommandlineWithSpaces);
TEST_METHOD(TestCommandlineWithEnvVars);
TEST_METHOD(WslTests);
TEST_METHOD(TestPwshLocation);
bool trust(std::wstring_view cmdline);
};
bool TrustCommandlineTests::trust(std::wstring_view cmdline)
{
return implementation::TerminalPage::_isTrustedCommandline(cmdline);
}
void TrustCommandlineTests::SimpleTests()
{
VERIFY_IS_TRUE(trust(L"C:\\Windows\\System32\\cmd.exe"));
VERIFY_IS_TRUE(trust(L"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"));
VERIFY_IS_FALSE(trust(L"C:\\Windows\\System32\\i-definitely-don't-exist.exe"));
Log::Comment(L"These are not fully qualified, and _shouldn't_ be trusted");
VERIFY_IS_FALSE(trust(L"cmd.exe"));
VERIFY_IS_FALSE(trust(L"powershell.exe"));
}
void TrustCommandlineTests::TestCommandlineWithArgs()
{
Log::Comment(L"These are sneaky things that _shouldn't_ be trusted");
VERIFY_IS_FALSE(trust(L"C:\\Windows\\System32\\cmd.exe /k echo Boo!"));
VERIFY_IS_FALSE(trust(L"C:\\Windows\\System32\\cmd.exe /k echo Boo! & cmd.exe"));
}
void TrustCommandlineTests::TestCommandlineWithSpaces()
{
Log::Comment(L"This is a valid place for powershell to live, and the space can be tricky");
VERIFY_IS_TRUE(trust(L"C:\\Program Files\\PowerShell\\7\\pwsh.exe"));
Log::Comment(L"These are sneaky things that _shouldn't_ be trusted");
VERIFY_IS_FALSE(trust(L"C:\\Windows\\System 32\\cmd.exe"));
VERIFY_IS_FALSE(trust(L"C:\\Windows\\System32\\ cmd.exe"));
VERIFY_IS_FALSE(trust(L"C:\\Windows\\System32\\cmd.exe /c cmd.exe"));
}
void TrustCommandlineTests::TestCommandlineWithEnvVars()
{
Log::Comment(L"Make sure we auto-expand environment variables");
VERIFY_IS_TRUE(trust(L"%WINDIR%\\system32\\cmd.exe"));
VERIFY_IS_TRUE(trust(L"%WINDIR%\\system32\\WindowsPowerShell\\v1.0\\powershell.exe"));
VERIFY_IS_TRUE(trust(L"%ProgramFiles%\\PowerShell\\7\\pwsh.exe"));
}
void TrustCommandlineTests::WslTests()
{
Log::Comment(L"We are explicitly deciding to not auto-approve "
L"`wsl.exe -d distro`-like commandlines. If we change this"
L" policy, remove this test.");
VERIFY_IS_FALSE(trust(L"C:\\Windows\\System32\\wsl"));
VERIFY_IS_TRUE(trust(L"C:\\Windows\\System32\\wsl.exe"), L"This we will trust though, since it's an exe in system32");
VERIFY_IS_FALSE(trust(L"C:\\Windows\\System32\\wsl.exe -d Ubuntu"));
VERIFY_IS_FALSE(trust(L"wsl.exe"));
}
void TrustCommandlineTests::TestPwshLocation()
{
Log::Comment(L"Test various locations that pwsh.exe can be in");
VERIFY_IS_TRUE(trust(L"%ProgramFiles%\\PowerShell\\7\\pwsh.exe"));
VERIFY_IS_TRUE(trust(L"%LOCALAPPDATA%\\Microsoft\\WindowsApps\\pwsh.exe"));
VERIFY_IS_TRUE(trust(L"%ProgramFiles%\\PowerShell\\10\\pwsh.exe"));
VERIFY_IS_TRUE(trust(L"%ProgramFiles%\\PowerShell\\7.1.5\\pwsh.exe"));
Log::Comment(L"These are sneaky things that _shouldn't_ be trusted");
VERIFY_IS_FALSE(trust(L"%ProgramFiles%\\PowerShell\\7\\pwsh.exe bad-stuff pwsh.exe"));
VERIFY_IS_FALSE(trust(L"%ProgramFiles%\\PowerShell\\7\\pwsh.exe bad-stuff c:\\pwsh.exe"));
VERIFY_IS_FALSE(trust(L"%ProgramFiles%\\PowerShell\\7\\pwsh.exe bad-stuff c:\\ %ProgramFiles%\\PowerShell\\7\\pwsh.exe"));
}
}

View file

@ -239,8 +239,8 @@ HRESULT HwndTerminal::Initialize()
_terminal->SetBackgroundCallback([](auto) {});
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
_terminal->SetDefaultBackground(RGB(12, 12, 12));
_terminal->SetDefaultForeground(RGB(204, 204, 204));
_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12));
_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204));
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
localPointerToThread->EnablePainting();
@ -781,8 +781,8 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
{
auto lock = publicTerminal->_terminal->LockForWriting();
publicTerminal->_terminal->SetDefaultForeground(theme.DefaultForeground);
publicTerminal->_terminal->SetDefaultBackground(theme.DefaultBackground);
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground);
publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground);
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha);
// Set the font colors

View file

@ -67,12 +67,8 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalPage::_EndPreviewColorScheme()
{
// Apply the reverts in reverse order - If we had multiple previews
// stacked on top of each other, then this will ensure the first one in
// is the last one out.
for (auto i{ _restorePreviewFuncs.rbegin() }; i < _restorePreviewFuncs.rend(); i++)
for (const auto& f : _restorePreviewFuncs)
{
auto f = *i;
f();
}
_restorePreviewFuncs.clear();
@ -94,18 +90,59 @@ namespace winrt::TerminalApp::implementation
{
if (const auto& scheme{ _settings.GlobalSettings().ColorSchemes().TryLookup(args.SchemeName()) })
{
// Clear the saved preview funcs because we don't need to add a restore each time
// the preview color changes, we only need to be able to restore the last one.
_restorePreviewFuncs.clear();
_ApplyToActiveControls([&](const auto& control) {
// Stash a copy of the current scheme.
auto originalScheme{ control.ColorScheme() };
// Get the settings of the focused control and stash them
const auto& controlSettings = control.Settings().as<TerminalSettings>();
// Make sure to recurse up to the root - if you're doing
// this while you're currently previewing a SetColorScheme
// action, then the parent of the control's settings is _the
// last preview TerminalSettings we inserted! We don't want
// to save that one!
auto originalSettings = controlSettings.GetParent();
while (originalSettings.GetParent() != nullptr)
{
originalSettings = originalSettings.GetParent();
}
// Create a new child for those settings
TerminalSettingsCreateResult fake{ originalSettings };
const auto& childStruct = TerminalSettings::CreateWithParent(fake);
// Modify the child to have the applied color scheme
childStruct.DefaultSettings().ApplyColorScheme(scheme);
// Apply the new scheme.
control.ColorScheme(scheme.ToCoreScheme());
// Insert that new child as the parent of the control's settings
controlSettings.SetParent(childStruct.DefaultSettings());
control.UpdateSettings();
// Each control will emplace a revert into the
// _restorePreviewFuncs for itself.
// Take a copy of the inputs, since they are pointers anyways.
_restorePreviewFuncs.emplace_back([=]() {
// On dismiss, restore the original scheme.
control.ColorScheme(originalScheme);
// Get the runtime settings of the focused control
const auto& controlSettings{ control.Settings().as<TerminalSettings>() };
// Get the control's root settings, the ones that we actually
// assigned to it.
auto parentSettings{ controlSettings.GetParent() };
while (parentSettings.GetParent() != nullptr)
{
parentSettings = parentSettings.GetParent();
}
// If the root settings are the same as the ones we stashed,
// then reset the parent of the runtime settings to the stashed
// settings. This condition might be false if the settings
// hot-reloaded while the palette was open. In that case, we
// don't want to reset the settings to what they were _before_
// the hot-reload.
if (originalSettings == parentSettings)
{
// Set the original settings as the parent of the control's settings
control.Settings().as<TerminalSettings>().SetParent(originalSettings);
}
control.UpdateSettings();
});
});
}

View file

@ -1,74 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "pch.h"
#include "AdminWarningPlaceholder.h"
#include "AdminWarningPlaceholder.g.cpp"
#include <LibraryResources.h>
using namespace winrt::Windows::UI::Xaml;
namespace winrt::TerminalApp::implementation
{
AdminWarningPlaceholder::AdminWarningPlaceholder(const winrt::Microsoft::Terminal::Control::TermControl& control, const winrt::hstring& cmdline) :
_control{ control },
_Commandline{ cmdline }
{
InitializeComponent();
// If the content we're hosting is a TermControl, then use the control's
// BG as our BG, to give the impression that it's there, under the
// dialog.
if (const auto termControl{ control.try_as<winrt::Microsoft::Terminal::Control::TermControl>() })
{
RootGrid().Background(termControl.BackgroundBrush());
}
}
void AdminWarningPlaceholder::_primaryButtonClick(winrt::Windows::Foundation::IInspectable const& /*sender*/,
RoutedEventArgs const& e)
{
_PrimaryButtonClickedHandlers(*this, e);
}
void AdminWarningPlaceholder::_cancelButtonClick(winrt::Windows::Foundation::IInspectable const& /*sender*/,
RoutedEventArgs const& e)
{
_CancelButtonClickedHandlers(*this, e);
}
winrt::Windows::UI::Xaml::Controls::UserControl AdminWarningPlaceholder::Control()
{
return _control;
}
// Method Description:
// - Move the focus to the cancel button by default. This has the LOAD
// BEARING side effect of also triggering Narrator to read out the
// contents of the dialog. It's unclear why doing this works, but it does.
// - Using a LayoutUpdated event to trigger the focus change when we're
// added to the UI tree did not seem to work.
// - Whoever is adding us to the UI tree is responsible for calling this!
// Arguments:
// - <none>
// Return Value:
// - <none>
void AdminWarningPlaceholder::FocusOnLaunch()
{
CancelButton().Focus(FocusState::Programmatic);
}
winrt::hstring AdminWarningPlaceholder::ControlName()
{
return RS_(L"AdminWarningPlaceholderName");
}
void AdminWarningPlaceholder::_keyUpHandler(IInspectable const& /*sender*/,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
// If the user presses escape, close the dialog (without confirming)
const auto key = e.OriginalKey();
if (key == winrt::Windows::System::VirtualKey::Escape)
{
_CancelButtonClickedHandlers(*this, e);
e.Handled(true);
}
}
}

View file

@ -1,51 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- AdminWarningPlaceholder
Abstract:
- The AdminWarningPlaceholder is a control used to fill space in a pane and
present a warning to the user. It holds on to a real control that it should be
replaced with. It looks just like a ContentDialog, except it exists per-pane,
whereas a ContentDialog can only be added to take up the whole window.
- The caller should make sure to bind our PrimaryButtonClicked and
CancelButtonClicked events, to be informed as to which was pressed.
Author(s):
- Mike Griese - September 2021
--*/
#pragma once
#include "AdminWarningPlaceholder.g.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
namespace winrt::TerminalApp::implementation
{
struct AdminWarningPlaceholder : AdminWarningPlaceholderT<AdminWarningPlaceholder>
{
AdminWarningPlaceholder(const winrt::Microsoft::Terminal::Control::TermControl& control, const winrt::hstring& cmdline);
void FocusOnLaunch();
winrt::Windows::UI::Xaml::Controls::UserControl Control();
winrt::hstring ControlName();
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Commandline, _PropertyChangedHandlers);
TYPED_EVENT(PrimaryButtonClicked, TerminalApp::AdminWarningPlaceholder, winrt::Windows::UI::Xaml::RoutedEventArgs);
TYPED_EVENT(CancelButtonClicked, TerminalApp::AdminWarningPlaceholder, winrt::Windows::UI::Xaml::RoutedEventArgs);
private:
friend struct AdminWarningPlaceholderT<AdminWarningPlaceholder>; // friend our parent so it can bind private event handlers
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
void _primaryButtonClick(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void _cancelButtonClick(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void _keyUpHandler(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
};
}

View file

@ -1,12 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace TerminalApp
{
[default_interface] runtimeclass AdminWarningPlaceholder : Windows.UI.Xaml.Controls.UserControl,
Windows.UI.Xaml.Data.INotifyPropertyChanged
{
String Commandline { get; };
String ControlName { get; };
}
}

View file

@ -1,97 +0,0 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<UserControl x:Class="TerminalApp.AdminWarningPlaceholder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
AutomationProperties.AccessibilityView="Content"
AutomationProperties.IsDialog="True"
AutomationProperties.Name="{x:Bind ControlName, Mode=OneWay}"
PreviewKeyUp="_keyUpHandler"
mc:Ignorable="d">
<!--
We have to use two grids to be tricky here:
- The outer grid will get its background from the control it hosts, and
expands to fit its container. This will make it look like the background
fills the space available.
- The inner grid is set to Center,Center, so that the "dialog" appears
centered
-->
<Grid x:Name="RootGrid"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid HorizontalAlignment="Center"
VerticalAlignment="Center">
<Border Margin="8,8,8,8"
Padding="16,8,16,8"
AllowFocusOnInteraction="True"
AutomationProperties.AccessibilityView="Raw"
AutomationProperties.IsDialog="True"
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
BorderBrush="{ThemeResource SystemAccentColor}"
BorderThickness="2,2,2,2"
CornerRadius="{ThemeResource OverlayCornerRadius}">
<StackPanel Orientation="Vertical">
<TextBlock x:Name="ApproveCommandlineWarningTitle"
x:Uid="ApproveCommandlineWarningTitle"
Padding="0,0,0,16"
HorizontalAlignment="Left"
FontSize="20"
FontWeight="Normal"
IsTextSelectionEnabled="True"
TextWrapping="WrapWholeWords" />
<TextBlock x:Name="PrefixTextBlock"
x:Uid="ApproveCommandlineWarningPrefixTextBlock"
HorizontalAlignment="Left"
IsTextSelectionEnabled="True"
TextWrapping="WrapWholeWords" />
<TextBlock x:Name="CommandlineText"
Margin="0,16,0,16"
HorizontalAlignment="Left"
FontFamily="Cascadia Mono"
IsTextSelectionEnabled="True"
Text="{x:Bind Commandline, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<TextBlock x:Name="SuffixTextBlock"
x:Uid="ApproveCommandlineWarningSuffixTextBlock"
HorizontalAlignment="Left"
IsTextSelectionEnabled="True"
TextWrapping="WrapWholeWords" />
<Grid Margin="0,8,0,8"
HorizontalAlignment="Stretch"
XYFocusKeyboardNavigation="Enabled">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="PrimaryButton"
x:Uid="ApproveCommandlineWarning_PrimaryButton"
Grid.Column="0"
Margin="0,0,8,0"
HorizontalAlignment="Stretch"
Click="_primaryButtonClick"
IsTabStop="True"
Style="{StaticResource AccentButtonStyle}" />
<Button x:Name="CancelButton"
x:Uid="ApproveCommandlineWarning_CancelButton"
Grid.Column="1"
HorizontalAlignment="Stretch"
Click="_cancelButtonClick"
IsTabStop="True" />
</Grid>
</StackPanel>
</Border>
</Grid>
</Grid>
</UserControl>

View file

@ -451,7 +451,28 @@ namespace winrt::TerminalApp::implementation
if (const auto scheme = _settings.GlobalSettings().ColorSchemes().TryLookup(realArgs.SchemeName()))
{
const auto res = _ApplyToActiveControls([&](auto& control) {
control.ColorScheme(scheme.ToCoreScheme());
// Start by getting the current settings of the control
auto controlSettings = control.Settings().as<TerminalSettings>();
auto parentSettings = controlSettings;
// Those are the _runtime_ settings however. What we
// need to do is:
//
// 1. Blow away any colors set in the runtime settings.
// 2. Apply the color scheme to the parent settings.
//
// 1 is important to make sure that the effects of
// something like `colortool` are cleared when setting
// the scheme.
if (controlSettings.GetParent() != nullptr)
{
parentSettings = controlSettings.GetParent();
}
// ApplyColorScheme(nullptr) will clear the old color scheme.
controlSettings.ApplyColorScheme(nullptr);
parentSettings.ApplyColorScheme(scheme);
control.UpdateSettings();
});
args.Handled(res);
}

View file

@ -1,67 +1,25 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// MinMaxCloseControl.xaml.cpp
// Implementation of the MinMaxCloseControl class
//
#include "pch.h"
#include "MinMaxCloseControl.h"
#include "MinMaxCloseControl.g.cpp"
#include <LibraryResources.h>
using namespace winrt::Windows::UI::Xaml;
namespace winrt::TerminalApp::implementation
{
static void closeToolTipForButton(const Controls::Button& button)
{
if (auto tt{ Controls::ToolTipService::GetToolTip(button) })
{
if (auto tooltip{ tt.try_as<Controls::ToolTip>() })
{
tooltip.IsOpen(false);
}
}
}
MinMaxCloseControl::MinMaxCloseControl()
{
// Get our dispatcher. This will get us the same dispatcher as
// Dispatcher(), but it's a DispatcherQueue, so we can use it with
// ThrottledFunc
auto dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
InitializeComponent();
// Get the tooltip hover time from the system, or default to 400ms
// (which should be the default, see:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-trackmouseevent#remarks)
unsigned int hoverTimeoutMillis{ 400 };
LOG_IF_WIN32_BOOL_FALSE(SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hoverTimeoutMillis, 0));
const auto toolTipInterval = std::chrono::milliseconds(hoverTimeoutMillis);
// Create a ThrottledFunc for opening the tooltip after the hover
// timeout. If we hover another button, we should make sure to call
// Run() with the new button. Calling `_displayToolTip.Run(nullptr)`,
// which will cause us to not display a tooltip, which is used when we
// leave the control entirely.
_displayToolTip = std::make_shared<ThrottledFuncTrailing<Controls::Button>>(
dispatcher,
toolTipInterval,
[weakThis = get_weak()](Controls::Button button) {
// If we provide a button, then open the tooltip on that button.
// We can "dismiss" this throttled func by calling it with null,
// which will cause us to do nothing at the end of the timeout
// instead.
if (button)
{
if (auto tt{ Controls::ToolTipService::GetToolTip(button) })
{
if (auto tooltip{ tt.try_as<Controls::ToolTip>() })
{
tooltip.IsOpen(true);
}
}
}
});
}
// These event handlers simply forward each buttons click events up to the
@ -137,104 +95,4 @@ namespace winrt::TerminalApp::implementation
break;
}
}
// Method Description:
// - Called when the mouse hovers a button.
// - Transition that button to `PointerOver`
// - run the throttled func with this button, to display the tooltip after
// a timeout
// - dismiss any open tooltips on other buttons.
// Arguments:
// - button: the button that was hovered
void MinMaxCloseControl::HoverButton(CaptionButton button)
{
// Keep track of the button that's been pressed. we get a mouse move
// message when we open the tooltip. If we move the mouse on top of this
// button, that we've already pressed, then no need to move to the
// "hovered" state, we should stay in the pressed state.
if (_lastPressedButton && _lastPressedButton.value() == button)
{
return;
}
switch (button)
{
// Make sure to use true for the useTransitions parameter, to
// animate the fade in/out transition between colors.
case CaptionButton::Minimize:
VisualStateManager::GoToState(MinimizeButton(), L"PointerOver", true);
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
_displayToolTip->Run(MinimizeButton());
closeToolTipForButton(MaximizeButton());
closeToolTipForButton(CloseButton());
break;
case CaptionButton::Maximize:
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
VisualStateManager::GoToState(MaximizeButton(), L"PointerOver", true);
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
closeToolTipForButton(MinimizeButton());
_displayToolTip->Run(MaximizeButton());
closeToolTipForButton(CloseButton());
break;
case CaptionButton::Close:
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
VisualStateManager::GoToState(CloseButton(), L"PointerOver", true);
closeToolTipForButton(MinimizeButton());
closeToolTipForButton(MaximizeButton());
_displayToolTip->Run(CloseButton());
break;
}
}
// Method Description:
// - Called when the mouse presses down on a button. NOT when it is
// released. That's handled one level above, in
// TitleBarControl::ReleaseButtons
// - Transition that button to `Pressed`
// Arguments:
// - button: the button that was pressed
void MinMaxCloseControl::PressButton(CaptionButton button)
{
switch (button)
{
case CaptionButton::Minimize:
VisualStateManager::GoToState(MinimizeButton(), L"Pressed", true);
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
break;
case CaptionButton::Maximize:
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
VisualStateManager::GoToState(MaximizeButton(), L"Pressed", true);
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
break;
case CaptionButton::Close:
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
VisualStateManager::GoToState(CloseButton(), L"Pressed", true);
break;
}
_lastPressedButton = button;
}
// Method Description:
// - Called when buttons are no longer hovered or pressed. Return them all
// to the normal state, and dismiss the tooltips.
void MinMaxCloseControl::ReleaseButtons()
{
_displayToolTip->Run(nullptr);
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
closeToolTipForButton(MinimizeButton());
closeToolTipForButton(MaximizeButton());
closeToolTipForButton(CloseButton());
_lastPressedButton = std::nullopt;
}
}

View file

@ -6,9 +6,11 @@
#pragma once
#include "winrt/Windows.UI.Xaml.h"
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.Xaml.Interop.h"
#include "MinMaxCloseControl.g.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
#include <ThrottledFunc.h>
namespace winrt::TerminalApp::implementation
{
@ -18,10 +20,6 @@ namespace winrt::TerminalApp::implementation
void SetWindowVisualState(WindowVisualState visualState);
void HoverButton(CaptionButton button);
void PressButton(CaptionButton button);
void ReleaseButtons();
void _MinimizeClick(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void _MaximizeClick(winrt::Windows::Foundation::IInspectable const& sender,
@ -32,9 +30,6 @@ namespace winrt::TerminalApp::implementation
TYPED_EVENT(MinimizeClick, TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs);
TYPED_EVENT(MaximizeClick, TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs);
TYPED_EVENT(CloseClick, TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs);
std::shared_ptr<ThrottledFuncTrailing<winrt::Windows::UI::Xaml::Controls::Button>> _displayToolTip{ nullptr };
std::optional<CaptionButton> _lastPressedButton{ std::nullopt };
};
}

View file

@ -11,10 +11,6 @@ namespace TerminalApp
void SetWindowVisualState(WindowVisualState visualState);
void HoverButton(CaptionButton button);
void PressButton(CaptionButton button);
void ReleaseButtons();
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> MinimizeClick;
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> MaximizeClick;
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> CloseClick;

View file

@ -220,7 +220,7 @@
</StackPanel.Resources>
<Button x:Name="MinimizeButton"
x:Uid="MinimizeButton"
x:Uid="WindowMinimizeButton"
Width="46.0"
Height="{StaticResource CaptionButtonHeightWindowed}"
MinWidth="46.0"
@ -232,14 +232,9 @@
<x:String x:Key="CaptionButtonPath">M 0 0 H 10</x:String>
</ResourceDictionary>
</Button.Resources>
<ToolTipService.ToolTip>
<ToolTip>
<TextBlock x:Uid="WindowMinimizeButtonToolTip" />
</ToolTip>
</ToolTipService.ToolTip>
</Button>
<Button x:Name="MaximizeButton"
x:Uid="MaximizeButton"
x:Uid="WindowMaximizeButton"
Width="46.0"
Height="{StaticResource CaptionButtonHeightWindowed}"
MinWidth="46.0"
@ -261,7 +256,7 @@
</ToolTipService.ToolTip>
</Button>
<Button x:Name="CloseButton"
x:Uid="CloseButton"
x:Uid="WindowCloseButton"
Width="46.0"
Height="{StaticResource CaptionButtonHeightWindowed}"
MinWidth="46.0"
@ -314,10 +309,5 @@
<x:String x:Key="CaptionButtonPath">M 0 0 L 10 10 M 10 0 L 0 10</x:String>
</ResourceDictionary>
</Button.Resources>
<ToolTipService.ToolTip>
<ToolTip>
<TextBlock x:Uid="WindowCloseButtonToolTip" />
</ToolTip>
</ToolTipService.ToolTip>
</Button>
</StackPanel>

View file

@ -34,7 +34,7 @@ static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Wi
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr };
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr };
Pane::Pane(const Profile& profile, const Controls::UserControl& control, const bool lastFocused) :
Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFocused) :
_control{ control },
_lastActive{ lastFocused },
_profile{ profile }
@ -42,11 +42,8 @@ Pane::Pane(const Profile& profile, const Controls::UserControl& control, const b
_root.Children().Append(_borderFirst);
_borderFirst.Child(_control);
if (const auto& termControl{ _control.try_as<TermControl>() })
{
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
_warningBellToken = termControl.WarningBell({ this, &Pane::_ControlWarningBellHandler });
}
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
_warningBellToken = _control.WarningBell({ this, &Pane::_ControlWarningBellHandler });
// On the first Pane's creation, lookup resources we'll use to theme the
// Pane, including the brushed to use for the focused/unfocused border
@ -128,23 +125,11 @@ NewTerminalArgs Pane::GetTerminalArgsForPane() const
assert(_IsLeaf());
NewTerminalArgs args{};
auto termControl{ _control.try_as<TermControl>() };
if (!termControl)
{
if (auto adminWarning{ _control.try_as<AdminWarningPlaceholder>() })
{
termControl = adminWarning.Content().try_as<TermControl>();
}
}
if (!termControl)
{
return nullptr;
}
auto controlSettings = termControl.Settings();
auto controlSettings = _control.Settings().as<TerminalSettings>();
args.Profile(controlSettings.ProfileName());
// If we know the user's working directory use it instead of the profile.
if (const auto dir = termControl.WorkingDirectory(); !dir.empty())
if (const auto dir = _control.WorkingDirectory(); !dir.empty())
{
args.StartingDirectory(dir);
}
@ -171,13 +156,16 @@ NewTerminalArgs Pane::GetTerminalArgsForPane() const
args.TabColor(winrt::Windows::Foundation::IReference<winrt::Windows::UI::Color>(c));
}
// TODO:GH#9800 - we used to be able to persist the color scheme that a
// TermControl was initialized with, by name. With the change to having the
// control own its own copy of its settings, this isn't possible anymore.
//
// We may be able to get around this by storing the Name in the Core::Scheme
// object. That would work for schemes set by the Terminal, but not ones set
// by VT, but that seems good enough.
if (controlSettings.AppliedColorScheme())
{
auto name = controlSettings.AppliedColorScheme().Name();
// Only save the color scheme if it is different than the profile color
// scheme to not override any other profile appearance choices.
if (_profile.DefaultAppearance().ColorSchemeName() != name)
{
args.ColorScheme(name);
}
}
return args;
}
@ -844,40 +832,6 @@ bool Pane::SwapPanes(std::shared_ptr<Pane> first, std::shared_ptr<Pane> second)
return false;
}
Controls::UserControl Pane::ReplaceControl(const Controls::UserControl& control)
{
if (!_IsLeaf())
{
return nullptr;
}
// Remove old control's event handlers
const auto& oldControl = _control;
_gotFocusRevoker.revoke();
_lostFocusRevoker.revoke();
if (const auto& oldTermControl{ _control.try_as<TermControl>() })
{
oldTermControl.ConnectionStateChanged(_connectionStateChangedToken);
oldTermControl.WarningBell(_warningBellToken);
}
_control = control;
_borderFirst.Child(_control);
// Register an event with the control to have it inform us when it gains focus.
_gotFocusRevoker = _control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
_lostFocusRevoker = _control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
if (const auto& termControl{ _control.try_as<TermControl>() })
{
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
_warningBellToken = termControl.WarningBell({ this, &Pane::_ControlWarningBellHandler });
}
return oldControl;
}
// Method Description:
// - Given two panes' offsets, test whether the `direction` side of first is adjacent to second.
// Arguments:
@ -1125,12 +1079,8 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
{
return;
}
const auto& termControl{ _control.try_as<TermControl>() };
if (!termControl)
{
return;
}
const auto newConnectionState = termControl.ConnectionState();
const auto newConnectionState = _control.ConnectionState();
const auto previousConnectionState = std::exchange(_connectionState, newConnectionState);
if (newConnectionState < ConnectionState::Closed)
@ -1173,9 +1123,7 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
{
return;
}
const auto& termControl{ _control.try_as<TermControl>() };
if (_profile && termControl)
if (_profile)
{
// We don't want to do anything if nothing is set, so check for that first
if (static_cast<int>(_profile.BellStyle()) != 0)
@ -1189,7 +1137,7 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
{
termControl.BellLightOn();
_control.BellLightOn();
}
// raise the event with the bool value corresponding to the taskbar flag
@ -1249,11 +1197,7 @@ void Pane::Shutdown()
std::unique_lock lock{ _createCloseLock };
if (_IsLeaf())
{
const auto& termControl{ _control.try_as<TermControl>() };
if (termControl)
{
termControl.Close();
}
_control.Close();
}
else
{
@ -1263,7 +1207,7 @@ void Pane::Shutdown()
}
// Method Description:
// - Get the root UIElement of this pane. There may be a single UserControl as a
// - Get the root UIElement of this pane. There may be a single TermControl as a
// child, or an entire tree of grids and panes as children of this element.
// Arguments:
// - <none>
@ -1322,7 +1266,7 @@ TermControl Pane::GetLastFocusedTerminalControl()
{
if (p->_IsLeaf())
{
return p->GetTerminalControl();
return p->_control;
}
pane = p;
}
@ -1330,7 +1274,7 @@ TermControl Pane::GetLastFocusedTerminalControl()
}
return _firstChild->GetLastFocusedTerminalControl();
}
return GetTerminalControl();
return _control;
}
// Method Description:
@ -1339,15 +1283,8 @@ TermControl Pane::GetLastFocusedTerminalControl()
// Arguments:
// - <none>
// Return Value:
// - nullptr if this Pane is a parent or isn't hosting a Terminal, otherwise the
// TermControl of this Pane.
TermControl Pane::GetTerminalControl() const
{
auto control{ GetUserControl() };
return control ? control.try_as<TermControl>() : nullptr;
}
Controls::UserControl Pane::GetUserControl() const
// - nullptr if this Pane is a parent, otherwise the TermControl of this Pane.
TermControl Pane::GetTerminalControl()
{
return _IsLeaf() ? _control : nullptr;
}
@ -1520,13 +1457,23 @@ void Pane::_FocusFirstChild()
void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
{
assert(_IsLeaf());
const auto& termControl{ _control.try_as<TermControl>() };
if (!termControl)
{
return;
}
_profile = profile;
termControl.UpdateControlSettings(settings.DefaultSettings(), settings.UnfocusedSettings());
auto controlSettings = _control.Settings().as<TerminalSettings>();
// Update the parent of the control's settings object (and not the object itself) so
// that any overrides made by the control don't get affected by the reload
controlSettings.SetParent(settings.DefaultSettings());
auto unfocusedSettings{ settings.UnfocusedSettings() };
if (unfocusedSettings)
{
// Note: the unfocused settings needs to be entirely unchanged _except_ we need to
// set its parent to the settings object that lives in the control. This is because
// the overrides made by the control live in that settings object, so we want to make
// sure the unfocused settings inherit from that.
unfocusedSettings.SetParent(controlSettings);
}
_control.UnfocusedAppearance(unfocusedSettings);
_control.UpdateSettings();
}
// Method Description:
@ -1667,12 +1614,8 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
_id = remainingChild->Id();
// Add our new event handler before revoking the old one.
const auto& termControl{ _control.try_as<TermControl>() };
if (termControl)
{
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
_warningBellToken = termControl.WarningBell({ this, &Pane::_ControlWarningBellHandler });
}
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
_warningBellToken = _control.WarningBell({ this, &Pane::_ControlWarningBellHandler });
// Revoke the old event handlers. Remove both the handlers for the panes
// themselves closing, and remove their handlers for their controls
@ -1686,11 +1629,8 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
closedChild->WalkTree([](auto p) {
if (p->_IsLeaf())
{
if (const auto& closedControl{ p->_control.try_as<TermControl>() })
{
closedControl.ConnectionStateChanged(p->_connectionStateChangedToken);
closedControl.WarningBell(p->_warningBellToken);
}
p->_control.ConnectionStateChanged(p->_connectionStateChangedToken);
p->_control.WarningBell(p->_warningBellToken);
}
return false;
});
@ -1698,19 +1638,15 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
closedChild->Closed(closedChildClosedToken);
remainingChild->Closed(remainingChildClosedToken);
if (const auto& remainingControl{ remainingChild->_control.try_as<TermControl>() })
{
remainingControl.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
remainingControl.WarningBell(remainingChild->_warningBellToken);
}
remainingChild->_control.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
remainingChild->_control.WarningBell(remainingChild->_warningBellToken);
// If we or either of our children was focused, we want to take that
// focus from them.
_lastActive = _lastActive || _firstChild->_lastActive || _secondChild->_lastActive;
// Remove all the ui elements of the remaining child. This'll make sure
// we can re-attach the UserControl to our Grid.
// we can re-attach the TermControl to our Grid.
remainingChild->_root.Children().Clear();
remainingChild->_borderFirst.Child(nullptr);
@ -1721,7 +1657,7 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
_root.ColumnDefinitions().Clear();
_root.RowDefinitions().Clear();
// Reattach the UserControl to our grid.
// Reattach the TermControl to our grid.
_root.Children().Append(_borderFirst);
_borderFirst.Child(_control);
@ -1783,11 +1719,8 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
closedChild->WalkTree([](auto p) {
if (p->_IsLeaf())
{
if (const auto& closedControl{ p->_control.try_as<TermControl>() })
{
closedControl.ConnectionStateChanged(p->_connectionStateChangedToken);
closedControl.WarningBell(p->_warningBellToken);
}
p->_control.ConnectionStateChanged(p->_connectionStateChangedToken);
p->_control.WarningBell(p->_warningBellToken);
}
return false;
});
@ -2535,14 +2468,11 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
if (_IsLeaf())
{
if (const auto& termControl{ _control.try_as<TermControl>() })
{
// revoke our handler - the child will take care of the control now.
termControl.ConnectionStateChanged(_connectionStateChangedToken);
termControl.WarningBell(_warningBellToken);
_connectionStateChangedToken.value = 0;
_warningBellToken.value = 0;
}
// revoke our handler - the child will take care of the control now.
_control.ConnectionStateChanged(_connectionStateChangedToken);
_connectionStateChangedToken.value = 0;
_control.WarningBell(_warningBellToken);
_warningBellToken.value = 0;
// Remove our old GotFocus handler from the control. We don't want the
// control telling us that it's now focused, we want it telling its new
@ -2552,7 +2482,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
}
// Remove any children we currently have. We can't add the existing
// UserControl to a new grid until we do this.
// TermControl to a new grid until we do this.
_root.Children().Clear();
_borderFirst.Child(nullptr);
_borderSecond.Child(nullptr);
@ -2930,13 +2860,8 @@ float Pane::CalcSnappedDimension(const bool widthOrHeight, const float dimension
// If requested size is already snapped, then both returned values equal this value.
Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
{
const auto& termControl{ _control.try_as<TermControl>() };
if (_IsLeaf())
{
if (!termControl)
{
return { dimension, dimension };
}
// If we're a leaf pane, align to the grid of controlling terminal
const auto minSize = _GetMinSize();
@ -2947,7 +2872,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
return { minDimension, minDimension };
}
float lower = termControl.SnapDimensionToGrid(widthOrHeight, dimension);
float lower = _control.SnapDimensionToGrid(widthOrHeight, dimension);
if (widthOrHeight)
{
lower += WI_IsFlagSet(_borders, Borders::Left) ? PaneBorderSize : 0;
@ -2967,7 +2892,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
}
else
{
const auto cellSize = termControl.CharacterDimensions();
const auto cellSize = _control.CharacterDimensions();
const auto higher = lower + (widthOrHeight ? cellSize.Width : cellSize.Height);
return { lower, higher };
}
@ -3012,39 +2937,26 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
// - <none>
void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& sizeNode) const
{
const auto& termControl{ _control.try_as<TermControl>() };
if (_IsLeaf())
{
if (termControl)
{
// We're a leaf pane, so just add one more row or column (unless isMinimumSize
// is true, see below).
// We're a leaf pane, so just add one more row or column (unless isMinimumSize
// is true, see below).
if (sizeNode.isMinimumSize)
{
// If the node is of its minimum size, this size might not be snapped (it might
// be, say, half a character, or fixed 10 pixels), so snap it upward. It might
// however be already snapped, so add 1 to make sure it really increases
// (not strictly necessary but to avoid surprises).
sizeNode.size = _CalcSnappedDimension(widthOrHeight, sizeNode.size + 1).higher;
}
else
{
const auto cellSize = termControl.CharacterDimensions();
sizeNode.size += widthOrHeight ? cellSize.Width : cellSize.Height;
}
if (sizeNode.isMinimumSize)
{
// If the node is of its minimum size, this size might not be snapped (it might
// be, say, half a character, or fixed 10 pixels), so snap it upward. It might
// however be already snapped, so add 1 to make sure it really increases
// (not strictly necessary but to avoid surprises).
sizeNode.size = _CalcSnappedDimension(widthOrHeight, sizeNode.size + 1).higher;
}
else
{
// If we're a leaf that didn't have a TermControl, then just increment
// by one. We have to increment by _some_ value, because this is used in
// a while() loop to find the next bigger size we can snap to. But since
// a non-terminal control doesn't really care what size it's snapped to,
// we can just say "one pixel larger is the next snap point"
sizeNode.size += 1;
const auto cellSize = _control.CharacterDimensions();
sizeNode.size += widthOrHeight ? cellSize.Width : cellSize.Height;
}
}
else // !_IsLeaf()
else
{
// We're a parent pane, so we have to advance dimension of our children panes. In
// fact, we advance only one child (chosen later) to keep the growth fine-grained.
@ -3146,8 +3058,7 @@ Size Pane::_GetMinSize() const
{
if (_IsLeaf())
{
const auto& termControl{ _control.try_as<TermControl>() };
auto controlSize = termControl ? termControl.MinimumSize() : Size{ 1, 1 };
auto controlSize = _control.MinimumSize();
auto newWidth = controlSize.Width;
auto newHeight = controlSize.Height;
@ -3333,10 +3244,7 @@ std::optional<SplitDirection> Pane::PreCalculateAutoSplit(const std::shared_ptr<
// - Returns true if the pane or one of its descendants is read-only
bool Pane::ContainsReadOnly() const
{
const auto& termControl{ GetTerminalControl() };
return termControl ?
termControl.ReadOnly() :
(_IsLeaf() ? false : (_firstChild->ContainsReadOnly() || _secondChild->ContainsReadOnly()));
return _IsLeaf() ? _control.ReadOnly() : (_firstChild->ContainsReadOnly() || _secondChild->ContainsReadOnly());
}
// Method Description:
@ -3349,14 +3257,13 @@ bool Pane::ContainsReadOnly() const
// - <none>
void Pane::CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states)
{
const auto& termControl{ GetTerminalControl() };
if (termControl)
if (_IsLeaf())
{
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(termControl.TaskbarState(),
termControl.TaskbarProgress()) };
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(_control.TaskbarState(),
_control.TaskbarProgress()) };
states.push_back(tbState);
}
else if (!_IsLeaf())
else
{
_firstChild->CollectTaskbarStates(states);
_secondChild->CollectTaskbarStates(states);

View file

@ -56,7 +56,7 @@ class Pane : public std::enable_shared_from_this<Pane>
{
public:
Pane(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
const winrt::Windows::UI::Xaml::Controls::UserControl& control,
const winrt::Microsoft::Terminal::Control::TermControl& control,
const bool lastFocused = false);
Pane(std::shared_ptr<Pane> first,
@ -66,9 +66,8 @@ public:
const bool lastFocused = false);
std::shared_ptr<Pane> GetActivePane();
winrt::Windows::UI::Xaml::Controls::UserControl GetUserControl() const;
winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl();
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl() const;
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl();
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
// Method Description:
@ -127,8 +126,6 @@ public:
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType);
std::shared_ptr<Pane> DetachPane(std::shared_ptr<Pane> pane);
winrt::Windows::UI::Xaml::Controls::UserControl ReplaceControl(const winrt::Windows::UI::Xaml::Controls::UserControl& control);
int GetLeafPaneCount() const noexcept;
void Maximize(std::shared_ptr<Pane> zoomedPane);
@ -203,8 +200,7 @@ private:
winrt::Windows::UI::Xaml::Controls::Grid _root{};
winrt::Windows::UI::Xaml::Controls::Border _borderFirst{};
winrt::Windows::UI::Xaml::Controls::Border _borderSecond{};
winrt::Windows::UI::Xaml::Controls::UserControl _control{ nullptr };
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_focusedBorderBrush;
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_unfocusedBorderBrush;

View file

@ -411,9 +411,6 @@
<data name="WindowCloseButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Close</value>
</data>
<data name="WindowCloseButtonToolTip.Text" xml:space="preserve">
<value>Close</value>
</data>
<data name="WindowMaximizeButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Maximize</value>
</data>
@ -423,9 +420,6 @@
<data name="WindowMinimizeButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Minimize</value>
</data>
<data name="WindowMinimizeButtonToolTip.Text" xml:space="preserve">
<value>Minimize</value>
</data>
<data name="AboutDialog.Title" xml:space="preserve">
<value>About</value>
</data>
@ -510,24 +504,6 @@
<data name="MultiLinePasteDialog.Title" xml:space="preserve">
<value>Warning</value>
</data>
<data name="ApproveCommandlineWarningPrefixTextBlock.Text" xml:space="preserve">
<value>You are about to execute the following command-line:</value>
</data>
<data name="ApproveCommandlineWarningSuffixTextBlock.Text" xml:space="preserve">
<value>Do you wish to continue?</value>
</data>
<data name="ApproveCommandlineWarning_PrimaryButton.Content" xml:space="preserve">
<value>Allow command-line</value>
</data>
<data name="ApproveCommandlineWarning_CancelButton.Content" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ApproveCommandlineWarningTitle.Text" xml:space="preserve">
<value>Warning</value>
</data>
<data name="AdminWarningPlaceholderName" xml:space="preserve">
<value>Elevated command-line warning</value>
</data>
<data name="CommandPalette_SearchBox.PlaceholderText" xml:space="preserve">
<value>Type a command name...</value>
</data>

View file

@ -16,7 +16,6 @@
#include <LibraryResources.h>
#include "TabRowControl.h"
#include "AdminWarningPlaceholder.h"
#include "ColorHelper.h"
#include "DebugTapConnection.h"
#include "SettingsTab.h"

View file

@ -63,9 +63,6 @@
<Page Include="CommandPalette.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="AdminWarningPlaceholder.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
@ -144,9 +141,6 @@
<ClInclude Include="AppLogic.h">
<DependentUpon>AppLogic.idl</DependentUpon>
</ClInclude>
<ClInclude Include="AdminWarningPlaceholder.h">
<DependentUpon>AdminWarningPlaceholder.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="Toast.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
@ -240,9 +234,6 @@
<ClCompile Include="AppLogic.cpp">
<DependentUpon>AppLogic.idl</DependentUpon>
</ClCompile>
<ClCompile Include="AdminWarningPlaceholder.cpp">
<DependentUpon>AdminWarningPlaceholder.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="Toast.cpp" />
</ItemGroup>
@ -304,10 +295,6 @@
<DependentUpon>CommandPalette.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="AdminWarningPlaceholder.idl">
<DependentUpon>AdminWarningPlaceholder.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="FilteredCommand.idl" />
<Midl Include="EmptyStringVisibilityConverter.idl" />
</ItemGroup>
@ -331,7 +318,29 @@
</ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below -->
manually include the winmds as References below
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
Up-to-date Check will look for the .xaml files from that project in our
output, which won't actually be there.
We do still need to separately reference the winmds manually below, which is annoying.
-->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. -->
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj">
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See

View file

@ -3,39 +3,38 @@
#include "pch.h"
#include "TerminalPage.h"
#include "Utils.h"
#include "../../types/inc/utils.hpp"
#include "TerminalPage.g.cpp"
#include "RenameWindowRequestedArgs.g.cpp"
#include <filesystem>
#include <inc/WindowingBehavior.h>
#include <LibraryResources.h>
#include <TerminalCore/ControlKeyStates.hpp>
#include <til/latch.h>
#include "TerminalPage.g.cpp"
#include <winrt/Windows.Storage.h>
#include "TabRowControl.h"
#include "../../types/inc/utils.hpp"
#include "ColorHelper.h"
#include "DebugTapConnection.h"
#include "SettingsTab.h"
#include "RenameWindowRequestedArgs.g.cpp"
#include "AdminWarningPlaceholder.h"
#include "../inc/WindowingBehavior.h"
#include <til/latch.h>
#include "TabRowControl.h"
using namespace winrt;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::System;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::UI::Text;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::System;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml;
using namespace ::TerminalApp;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Terminal::Core;
using namespace std::chrono_literals;
#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });
@ -1039,29 +1038,153 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
// Called when the users pressed keyBindings while CommandPalette is open.
// - Called when the users pressed keyBindings while CommandPalette is open.
// - This method is effectively an extract of TermControl::_KeyHandler and TermControl::_TryHandleKeyBinding.
// Arguments:
// - e: the KeyRoutedEventArgs containing info about the keystroke.
// Return Value:
// - <none>
void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
const auto key = e.OriginalKey();
const auto scanCode = e.KeyStatus().ScanCode;
const auto coreWindow = CoreWindow::GetForCurrentThread();
const auto ctrlDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
const auto altDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
const auto shiftDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
const auto keyStatus = e.KeyStatus();
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey());
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
const auto modifiers = _GetPressedModifierKeys();
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, false, static_cast<int32_t>(key), static_cast<int32_t>(scanCode) };
if (const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) })
// GH#11076:
// For some weird reason we sometimes receive a WM_KEYDOWN
// message without vkey or scanCode if a user drags a tab.
// The KeyChord constructor has a debug assertion ensuring that all KeyChord
// either have a valid vkey/scanCode. This is important, because this prevents
// accidential insertion of invalid KeyChords into classes like ActionMap.
if (!vkey && !scanCode)
{
if (CommandPalette().Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
return;
}
// Alt-Numpad# input will send us a character once the user releases
// Alt, so we should be ignoring the individual keydowns. The character
// will be sent through the TSFInputControl. See GH#1401 for more
// details
if (modifiers.IsAltPressed() && (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9))
{
return;
}
// GH#2235: Terminal::Settings hasn't been modified to differentiate
// between AltGr and Ctrl+Alt yet.
// -> Don't check for key bindings if this is an AltGr key combination.
if (modifiers.IsAltGrPressed())
{
return;
}
const auto actionMap = _settings.ActionMap();
if (!actionMap)
{
return;
}
const auto cmd = actionMap.GetActionByKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
modifiers.IsWinPressed(),
vkey,
scanCode,
});
if (!cmd)
{
return;
}
if (!_actionDispatch->DoAction(cmd.ActionAndArgs()))
{
return;
}
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
{
p.Visibility(Visibility::Collapsed);
}
// Let's assume the user has bound the dead key "^" to a sendInput command that sends "b".
// If the user presses the two keys "^a" it'll produce "bâ", despite us marking the key event as handled.
// The following is used to manually "consume" such dead keys and clear them from the keyboard state.
_ClearKeyboardState(vkey, scanCode);
e.Handled(true);
}
// Method Description:
// - Get the modifier keys that are currently pressed. This can be used to
// find out which modifiers (ctrl, alt, shift) are pressed in events that
// don't necessarily include that state.
// - This is a copy of TermControl::_GetPressedModifierKeys.
// Return Value:
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
ControlKeyStates TerminalPage::_GetPressedModifierKeys() noexcept
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
// DONT USE
// != CoreVirtualKeyStates::None
// OR
// == CoreVirtualKeyStates::Down
// Sometimes with the key down, the state is Down | Locked.
// Sometimes with the key up, the state is Locked.
// IsFlagSet(Down) is the only correct solution.
struct KeyModifier
{
VirtualKey vkey;
ControlKeyStates flags;
};
constexpr std::array<KeyModifier, 7> modifiers{ {
{ VirtualKey::RightMenu, ControlKeyStates::RightAltPressed },
{ VirtualKey::LeftMenu, ControlKeyStates::LeftAltPressed },
{ VirtualKey::RightControl, ControlKeyStates::RightCtrlPressed },
{ VirtualKey::LeftControl, ControlKeyStates::LeftCtrlPressed },
{ VirtualKey::Shift, ControlKeyStates::ShiftPressed },
{ VirtualKey::RightWindows, ControlKeyStates::RightWinPressed },
{ VirtualKey::LeftWindows, ControlKeyStates::LeftWinPressed },
} };
ControlKeyStates flags;
for (const auto& mod : modifiers)
{
const auto state = window.GetKeyState(mod.vkey);
const auto isDown = WI_IsFlagSet(state, CoreVirtualKeyStates::Down);
if (isDown)
{
CommandPalette().Visibility(Visibility::Collapsed);
flags |= mod.flags;
}
_actionDispatch->DoAction(cmd.ActionAndArgs());
e.Handled(true);
}
return flags;
}
// Method Description:
// - Discards currently pressed dead keys.
// - This is a copy of TermControl::_ClearKeyboardState.
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
void TerminalPage::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
{
std::array<BYTE, 256> keyState;
if (!GetKeyboardState(keyState.data()))
{
return;
}
// As described in "Sometimes you *want* to interfere with the keyboard's state buffer":
// http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
// > "The key here is to keep trying to pass stuff to ToUnicode until -1 is not returned."
std::array<wchar_t, 16> buffer;
while (ToUnicodeEx(vkey, scanCode, keyState.data(), buffer.data(), gsl::narrow_cast<int>(buffer.size()), 0b1, nullptr) < 0)
{
}
}
@ -1416,24 +1539,21 @@ namespace winrt::TerminalApp::implementation
{
if (const auto terminalTab{ _GetFocusedTabImpl() })
{
if (const auto& termControl{ terminalTab->GetActiveTerminalControl() })
uint32_t realRowsToScroll;
if (rowsToScroll == nullptr)
{
uint32_t realRowsToScroll;
if (rowsToScroll == nullptr)
{
// The magic value of WHEEL_PAGESCROLL indicates that we need to scroll the entire page
realRowsToScroll = _systemRowsToScroll == WHEEL_PAGESCROLL ?
termControl.ViewHeight() :
_systemRowsToScroll;
}
else
{
// use the custom value specified in the command
realRowsToScroll = rowsToScroll.Value();
}
auto scrollDelta = _ComputeScrollDelta(scrollDirection, realRowsToScroll);
terminalTab->Scroll(scrollDelta);
// The magic value of WHEEL_PAGESCROLL indicates that we need to scroll the entire page
realRowsToScroll = _systemRowsToScroll == WHEEL_PAGESCROLL ?
terminalTab->GetActiveTerminalControl().ViewHeight() :
_systemRowsToScroll;
}
else
{
// use the custom value specified in the command
realRowsToScroll = rowsToScroll.Value();
}
auto scrollDelta = _ComputeScrollDelta(scrollDirection, realRowsToScroll);
terminalTab->Scroll(scrollDelta);
}
}
@ -1487,246 +1607,6 @@ namespace winrt::TerminalApp::implementation
return true;
}
// Function Description:
// - Returns true if this commandline is a commandline that we know is safe.
// Generally, this is true for any executables in system32. We can use
// this to bypass the elevated state check, because we're confident that
// executables in that path won't have been hijacked.
// - TECHNICALLY a user can take ownership of a file in system32 and
// replace it as the system administrator. You could say it's OK though
// because you'd already have to have had admin rights to mess that
// folder up or something.
// - Will attempt to resolve environment strings.
// - Will also manually allow commandlines as generated for the default WSL
// distros.
// - Will also trust %ProgramFiles%\Powershell\...\pwsh.exe paths, for
// PowerShell Core.
// Arguments:
// - commandLine: the command to check.
// Return Value (example):
// - C:\windows\system32\cmd.exe -> returns true
// - cmd.exe -> returns false
// - C:\windows\system32\cmd.exe /k echo sneaky sneak -> returns false
// - %SystemRoot%\System32\cmd.exe -> returns true
// - %SystemRoot%\System32\wsl.exe -d <distro name> -> returns true
bool TerminalPage::_isTrustedCommandline(std::wstring_view commandLine)
{
// use C++11 magic statics to make sure we only do this once.
static std::wstring systemDirectory = []() -> std::wstring {
// *** THIS IS A SINGLETON ***
static std::wstring sys32{};
if (FAILED(wil::GetSystemDirectoryW(sys32)))
{
// we couldn't look up where system32 is?? Then it's definitely not
// in System32
return {};
}
return sys32;
}();
if (systemDirectory.empty())
{
return false;
}
const std::wstring fullCommandline{
wil::ExpandEnvironmentStringsW<std::wstring>(commandLine.data())
};
if (fullCommandline.size() > systemDirectory.size())
{
// Get the first part of the executable path
const auto start = fullCommandline.substr(0, systemDirectory.size());
// Doing this as an ASCII only check might be wrong, but I'm
// guessing if system32 isn't at X:\windows\system32... this isn't
// the only thing that is going to be sad in Windows.
const auto pathEquals = til::equals_insensitive_ascii(start, systemDirectory);
if (pathEquals && std::filesystem::exists(std::filesystem::path{ fullCommandline }))
{
return true;
}
}
// We're explicitly not auto-allowing wsl.exe -d <distro name>. It's
// trivial to insert some malicious stuff into WSL, via .bash_profile,
// so we're not giving them the (y)
// But we do want to allow `pwsh.exe` profiles in the expected place to
// work.
const std::vector<std::filesystem::path> powershellCoreRoots
{
// Always look in "%LOCALAPPDATA%\Microsoft\WindowsApps", which is
// where the pwsh.exe execution alias lives.
{ wil::ExpandEnvironmentStringsW<std::wstring>(L"%LOCALAPPDATA%\\Microsoft\\WindowsApps") },
// Always look in "%ProgramFiles%\PowerShell"
{ wil::ExpandEnvironmentStringsW<std::wstring>(L"%ProgramFiles%\\PowerShell") },
#if defined(_M_AMD64) || defined(_M_ARM64) // No point in looking for WOW if we're not somewhere it exists
{ wil::ExpandEnvironmentStringsW<std::wstring>(L"%ProgramFiles(x86)%\\PowerShell") },
#endif
#if defined(_M_ARM64) // same with ARM
{
wil::ExpandEnvironmentStringsW<std::wstring>(L"%ProgramFiles(Arm)%\\PowerShell")
}
#endif
};
// Is the filename for this commandline `pwsh.exe`?
const std::filesystem::path exePath{ fullCommandline };
const auto endsWithPwsh{ exePath.filename() == L"pwsh.exe" };
// We'll also need to check the parent path, so make sure it has one here.
if (endsWithPwsh && exePath.has_parent_path())
{
const auto parentPath{ exePath.parent_path() };
for (const auto& pwshRoot : powershellCoreRoots)
{
// Does the commandline start with this root, and end with pwsh.exe?
const auto startsWithRoot{ til::starts_with(fullCommandline, pwshRoot.c_str()) };
// Is either the immediate parent, or the grandparent, this root exactly?
//
// We need to check the grandparent for the
// `%ProgramFiles%\\PowerShell\\7\\pwsh.exe` case.
const auto parentIsCorrect = (parentPath == pwshRoot) ||
(parentPath.has_parent_path() && parentPath.parent_path() == pwshRoot);
if (startsWithRoot && parentIsCorrect)
{
return true;
}
}
}
return false;
}
// Method Description:
// - For a given commandline, determines if we should prompt the user for
// approval. We only do this check when elevated. This will check the
// AllowedCommandlines in `elevated-state.json`, to see if the commandline
// already exists in that list.
// Arguments:
// - cmdline: The commandline to check
// Return Value:
// - true if we should prompt the user for approval.
bool TerminalPage::_shouldPromptForCommandline(const winrt::hstring& cmdline) const
{
// NOTE: For debugging purposes, changing this to `true || IsElevated()`
// is a handy way of forcing the elevation logic, even when unelevated.
if (IsElevated())
{
// If the cmdline is EXACTLY an executable in
// `C:\WINDOWS\System32`, then ignore this check.
if (_isTrustedCommandline(cmdline))
{
return false;
}
if (const auto& allowedCommandlines{ ApplicationState::SharedInstance().AllowedCommandlines() })
{
for (const auto& approved : allowedCommandlines)
{
if (approved == cmdline)
{
return false;
}
}
}
return true;
}
return false;
}
void TerminalPage::_adminWarningPrimaryClicked(const TerminalApp::AdminWarningPlaceholder& sender,
const winrt::Windows::UI::Xaml::RoutedEventArgs& /*args*/)
{
auto warningControl{ winrt::get_self<AdminWarningPlaceholder>(sender) };
const auto& cmdline{ warningControl->Commandline() };
// Look through the tabs and panes to look for us. Whichever pane had us
// as content - replace their content with the TermControl we were
// holding on to.
for (const auto& tab : _tabs)
{
if (const auto& tabImpl{ _GetTerminalTabImpl(tab) })
{
tabImpl->GetRootPane()->WalkTree([warningControl, cmdline, tabImpl](std::shared_ptr<Pane> pane) -> bool {
const auto& projectedWarningControl{ pane->GetUserControl().try_as<TerminalApp::AdminWarningPlaceholder>() };
// If it was a warning control, then get our implementation
// type out of it.
if (const auto& otherWarning{ winrt::get_self<AdminWarningPlaceholder>(projectedWarningControl) })
{
// This pane had a warning in it.
// Was it a warning for the same commandline that we
// just approved?
if (otherWarning->Commandline() == cmdline)
{
// Go ahead and allow them. Swap the control into
// the pane, which will initialize and start it.
tabImpl->ReplaceControl(pane, otherWarning->Control());
}
// Don't return true here. We want to make sure to check
// all the panes for the same commandline we just
// approved.
}
// return false so we make sure to iterate on every leaf.
return false;
});
}
}
// Update the list of approved commandlines.
auto allowedCommandlines{ ApplicationState::SharedInstance().AllowedCommandlines() };
if (!allowedCommandlines)
{
allowedCommandlines = winrt::single_threaded_vector<winrt::hstring>();
}
// But of course, we don't need to add this commandline if it's already
// in the list of approved commandlines.
bool foundCopy = false;
for (const auto& approved : allowedCommandlines)
{
if (approved == cmdline)
{
foundCopy = true;
break;
}
}
if (!foundCopy)
{
allowedCommandlines.Append(cmdline);
}
ApplicationState::SharedInstance().AllowedCommandlines(allowedCommandlines);
}
void TerminalPage::_adminWarningCancelClicked(const TerminalApp::AdminWarningPlaceholder& sender,
const winrt::Windows::UI::Xaml::RoutedEventArgs& /*args*/)
{
auto warningControl{ winrt::get_self<AdminWarningPlaceholder>(sender) };
for (const auto& tab : _tabs)
{
if (const auto& tabImpl{ _GetTerminalTabImpl(tab) })
{
tabImpl->GetRootPane()->WalkTree([warningControl](std::shared_ptr<Pane> pane) -> bool {
if (pane->GetUserControl() == *warningControl)
{
pane->Close();
return true;
}
// We're not going to auto-close all the other panes with
// the same commandline warning, akin to what we're doing in
// the approve handler. If they want to reject one pane, but
// accept the next one, that's okay.
return false;
});
}
}
}
// Method Description:
// - Split the focused pane either horizontally or vertically, and place the
// given pane accordingly in the tree
@ -2096,10 +1976,8 @@ namespace winrt::TerminalApp::implementation
if (warnMultiLine)
{
const auto focusedTab = _GetFocusedTabImpl();
const auto& termControl{ focusedTab->GetActiveTerminalControl() };
// Do not warn about multi line pasting if the current tab has bracketed paste enabled.
warnMultiLine = warnMultiLine &&
(termControl && !termControl.BracketedPasteEnabled());
warnMultiLine = warnMultiLine && !focusedTab->GetActiveTerminalControl().BracketedPasteEnabled();
}
// We have to initialize the dialog here to be able to change the text of the text block within it
@ -2369,10 +2247,13 @@ namespace winrt::TerminalApp::implementation
TermControl TerminalPage::_InitControl(const TerminalSettingsCreateResult& settings, const ITerminalConnection& connection)
{
// Do any initialization that needs to apply to _every_ TermControl we
// create here.
// TermControl will copy the settings out of the settings passed to it.
TermControl term{ settings.DefaultSettings(), settings.UnfocusedSettings(), 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
const auto child = TerminalSettings::CreateWithParent(settings);
TermControl term{ child.DefaultSettings(), connection };
term.UnfocusedAppearance(child.UnfocusedSettings()); // It is okay for the unfocused settings to be null
return term;
}
@ -2404,14 +2285,11 @@ namespace winrt::TerminalApp::implementation
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
profile = GetClosestProfileForDuplicationOfProfile(profile);
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
if (const auto& control{ focusedTab->GetActiveTerminalControl() })
const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
const auto workingDirectory = control.WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
}
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
}
}
}
@ -2445,21 +2323,7 @@ namespace winrt::TerminalApp::implementation
const auto control = _InitControl(controlSettings, connection);
_RegisterTerminalEvents(control);
WUX::Controls::UserControl controlToAdd{ control };
// Check if we should warn the user about running a new unelevated
// commandline.
const auto& cmdline{ controlSettings.DefaultSettings().Commandline() };
const auto doAdminWarning{ _shouldPromptForCommandline(cmdline) };
if (doAdminWarning)
{
auto warningControl{ winrt::make_self<implementation::AdminWarningPlaceholder>(control, cmdline) };
warningControl->PrimaryButtonClicked({ get_weak(), &TerminalPage::_adminWarningPrimaryClicked });
warningControl->CancelButtonClicked({ get_weak(), &TerminalPage::_adminWarningCancelClicked });
controlToAdd = *warningControl;
}
auto resultPane = std::make_shared<Pane>(profile, controlToAdd);
auto resultPane = std::make_shared<Pane>(profile, control);
if (debugConnection) // this will only be set if global debugging is on and tap is active
{
@ -2480,17 +2344,6 @@ namespace winrt::TerminalApp::implementation
original->SetActive();
}
if (doAdminWarning)
{
// We know this is safe - we literally just added the
// AdminWarningPlaceholder as the controlToAdd like 20 lines up.
//
// Focus the warning here. The LayoutUpdated within the dialog
// itself isn't good enough. That, for some reason, fires _before_
// the dialog is in the UI tree, which is useless for us.
controlToAdd.try_as<implementation::AdminWarningPlaceholder>()->FocusOnLaunch();
}
return resultPane;
}

View file

@ -14,13 +14,17 @@
static constexpr uint32_t DefaultRowsToScroll{ 3 };
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
// fwdecl unittest classes
namespace TerminalAppLocalTests
{
class TabTests;
class SettingsTests;
class TrustCommandlineTests;
};
}
namespace Microsoft::Terminal::Core
{
class ControlKeyStates;
}
namespace winrt::TerminalApp::implementation
{
@ -208,7 +212,6 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowCloseReadOnlyDialog();
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowMultiLinePasteWarningDialog();
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowLargePasteWarningDialog();
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowCommandlineApproveWarning();
void _CreateNewTabFlyout();
void _OpenNewTabDropdown();
@ -227,6 +230,8 @@ namespace winrt::TerminalApp::implementation
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) noexcept;
void _RegisterActionCallbacks();
@ -405,12 +410,6 @@ namespace winrt::TerminalApp::implementation
winrt::Microsoft::Terminal::Settings::Model::Profile GetClosestProfileForDuplicationOfProfile(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile) const noexcept;
bool _shouldPromptForCommandline(const winrt::hstring& cmdline) const;
void _adminWarningPrimaryClicked(const winrt::TerminalApp::AdminWarningPlaceholder& sender,
const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
void _adminWarningCancelClicked(const winrt::TerminalApp::AdminWarningPlaceholder& sender,
const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
winrt::fire_and_forget _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
@ -418,7 +417,6 @@ namespace winrt::TerminalApp::implementation
void _SetAsDefaultOpenSettingsHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
static bool _isTrustedCommandline(std::wstring_view commandLine);
#pragma region ActionHandlers
// These are all defined in AppActionHandlers.cpp
@ -429,7 +427,6 @@ namespace winrt::TerminalApp::implementation
friend class TerminalAppLocalTests::TabTests;
friend class TerminalAppLocalTests::SettingsTests;
friend class TerminalAppLocalTests::TrustCommandlineTests;
};
}

View file

@ -426,10 +426,7 @@ namespace winrt::TerminalApp::implementation
winrt::fire_and_forget TerminalTab::Scroll(const int delta)
{
auto control = GetActiveTerminalControl();
if (!control)
{
co_return;
}
co_await winrt::resume_foreground(control.Dispatcher());
const auto currentOffset = control.ScrollOffset();
@ -514,11 +511,7 @@ namespace winrt::TerminalApp::implementation
if (p->_IsLeaf())
{
p->Id(_nextPaneId);
if (auto termControl{ p->_control.try_as<TermControl>() })
{
_AttachEventHandlersToControl(p->Id().value(), termControl);
}
_AttachEventHandlersToControl(p->Id().value(), p->_control);
_nextPaneId++;
}
return false;
@ -863,10 +856,6 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalTab::_AttachEventHandlersToControl(const uint32_t paneId, const TermControl& control)
{
if (!control)
{
return;
}
auto weakThis{ get_weak() };
auto dispatcher = TabViewItem().Dispatcher();
ControlEventTokens events{};
@ -1755,19 +1744,6 @@ namespace winrt::TerminalApp::implementation
return Title();
}
void TerminalTab::ReplaceControl(std::shared_ptr<Pane> pane, const Controls::UserControl& control)
{
pane->ReplaceControl(control);
if (auto termControl{ pane->_control.try_as<TermControl>() })
{
_AttachEventHandlersToControl(pane->Id().value(), termControl);
}
// Update the title manually.
UpdateTitle();
}
DEFINE_EVENT(TerminalTab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
DEFINE_EVENT(TerminalTab, ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
DEFINE_EVENT(TerminalTab, ColorCleared, _colorCleared, winrt::delegate<>);

View file

@ -93,9 +93,6 @@ namespace winrt::TerminalApp::implementation
std::shared_ptr<Pane> GetRootPane() const { return _rootPane; }
void ReplaceControl(std::shared_ptr<Pane> pane,
const winrt::Windows::UI::Xaml::Controls::UserControl& control);
winrt::TerminalApp::TerminalTabStatus TabStatus()
{
return _tabStatus;

View file

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// TitlebarControl.xaml.cpp
// Implementation of the TitlebarControl class
//
@ -23,14 +24,6 @@ namespace winrt::TerminalApp::implementation
MinMaxCloseControl().CloseClick({ this, &TitlebarControl::Close_Click });
}
double TitlebarControl::CaptionButtonWidth()
{
// Divide by three, since we know there are only three buttons. When
// Windows 12 comes along and adds another, we can update this /s
static double width{ MinMaxCloseControl().ActualWidth() / 3.0 };
return width;
}
IInspectable TitlebarControl::Content()
{
return ContentRoot().Content();
@ -100,48 +93,4 @@ namespace winrt::TerminalApp::implementation
{
MinMaxCloseControl().SetWindowVisualState(visualState);
}
// GH#9443: HoverButton, PressButton, ClickButton and ReleaseButtons are all
// used to manually interact with the buttons, in the same way that XAML
// would normally send events.
void TitlebarControl::HoverButton(CaptionButton button)
{
MinMaxCloseControl().HoverButton(button);
}
void TitlebarControl::PressButton(CaptionButton button)
{
MinMaxCloseControl().PressButton(button);
}
winrt::fire_and_forget TitlebarControl::ClickButton(CaptionButton button)
{
// GH#8587: Handle this on the _next_ pass of the UI thread. If we
// handle this immediately, then we'll accidentally leave the button in
// the "Hovered" state when we minimize. This will leave the button
// visibly hovered in the taskbar preview for our window.
auto weakThis{ get_weak() };
co_await MinMaxCloseControl().Dispatcher();
if (auto self{ weakThis.get() })
{
// Just handle this in the same way we would if the button were
// clicked normally.
switch (button)
{
case CaptionButton::Minimize:
Minimize_Click(nullptr, nullptr);
break;
case CaptionButton::Maximize:
Maximize_Click(nullptr, nullptr);
break;
case CaptionButton::Close:
Close_Click(nullptr, nullptr);
break;
}
}
}
void TitlebarControl::ReleaseButtons()
{
MinMaxCloseControl().ReleaseButtons();
}
}

View file

@ -1,8 +1,14 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// Declaration of the MainUserControl class.
//
#pragma once
#include "winrt/Windows.UI.Xaml.h"
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.Xaml.Interop.h"
#include "TitlebarControl.g.h"
namespace winrt::TerminalApp::implementation
@ -11,12 +17,6 @@ namespace winrt::TerminalApp::implementation
{
TitlebarControl(uint64_t handle);
void HoverButton(CaptionButton button);
void PressButton(CaptionButton button);
winrt::fire_and_forget ClickButton(CaptionButton button);
void ReleaseButtons();
double CaptionButtonWidth();
IInspectable Content();
void Content(IInspectable content);

View file

@ -10,25 +10,11 @@ namespace TerminalApp
WindowVisualStateIconified
};
// For simplicity, make sure that these are the same values as the ones used
// by messages like WM_NCHITTEST
enum CaptionButton {
Minimize = 8, // HTMINBUTTON
Maximize = 9, // HTMAXBUTTON
Close = 20 // HTCLOSE
};
[default_interface] runtimeclass TitlebarControl : Windows.UI.Xaml.Controls.Grid
{
TitlebarControl(UInt64 parentWindowHandle);
void SetWindowVisualState(WindowVisualState visualState);
void HoverButton(CaptionButton button);
void PressButton(CaptionButton button);
void ClickButton(CaptionButton button);
void ReleaseButtons();
Double CaptionButtonWidth { get; };
IInspectable Content;
Windows.UI.Xaml.Controls.Border DragBar { get; };
}

View file

@ -68,5 +68,22 @@
</Link>
</ItemDefinitionGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
</Project>

View file

@ -97,4 +97,39 @@
</Link>
</ItemDefinitionGroup>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>
<!--
BODGY:
We depend on `cpprest142*.dll`, which comes from our vcpkg dependency. As a
part of the vcpkg dependency restore, msbuild will call the `deployBinary()`
function in
`packages\vcpkg-cpprestsdk.2.10.14\scripts\BuildSystems\msbuild\AppLocal.ps1`.
That function does the actual job of copying the file. It copies it outside of
MsBuild. MsBuild then, in the `_CopyFilesMarkedCopyLocal` target, determines
that it needs to copy `cpprest142*.dll`, because that dll is a member of
`@(ReferencesCopiedInThisBuild)`. However, the file's already been copied, so
MsBuild never copies it. But that also prevents MsBuild from setting
`WroteAtLeastOneFile`, which then means that MsBuild will never create the
.CopyComplete file for this project.
Because that file is missing, MsBuild will never think the project is up to
date, and the FastUpToDate check in VS will always force MsBuild to run a pass
on this project.
To mitigate this, we're adding this other target here, which runs after
_CopyFilesMarkedCopyLocal, and always creates the CopyUpToDateMarker. This
makes the FastUpToDate check succeed.
-->
<Target
Name="_Post_CopyFilesMarkedCopyLocal"
AfterTargets="_CopyFilesMarkedCopyLocal"
Condition="'@(ReferenceCopyLocalPaths)' != ''">
<Touch Files="@(CopyUpToDateMarker)"
AlwaysCreate="true" />
</Target>
</Project>

View file

@ -1,49 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
--*/
#pragma once
#include "../../inc/cppwinrt_utils.h"
#include "../../inc/ControlProperties.h"
#include <DefaultSettings.h>
#include <conattrs.hpp>
namespace winrt::Microsoft::Terminal::Control::implementation
{
struct ControlAppearance : public winrt::implements<ControlAppearance, Microsoft::Terminal::Core::ICoreAppearance, Microsoft::Terminal::Control::IControlAppearance>
{
#define SETTINGS_GEN(type, name, ...) WINRT_PROPERTY(type, name, __VA_ARGS__);
CORE_APPEARANCE_SETTINGS(SETTINGS_GEN)
CONTROL_APPEARANCE_SETTINGS(SETTINGS_GEN)
#undef SETTINGS_GEN
private:
// Color Table is special because it's an array
std::array<winrt::Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE> _ColorTable;
public:
winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept
{
return _ColorTable.at(index);
}
void SetColorTableEntry(int32_t index,
winrt::Microsoft::Terminal::Core::Color color) noexcept
{
_ColorTable.at(index) = color;
}
ControlAppearance(Control::IControlAppearance appearance)
{
#define COPY_SETTING(type, name, ...) _##name = appearance.name();
CORE_APPEARANCE_SETTINGS(COPY_SETTING)
CONTROL_APPEARANCE_SETTINGS(COPY_SETTING)
#undef COPY_SETTING
for (size_t i = 0; i < _ColorTable.size(); i++)
{
_ColorTable[i] = appearance.GetColorTableEntry(static_cast<int32_t>(i));
}
}
};
}

View file

@ -56,17 +56,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return initialized;
}
ControlCore::ControlCore(Control::IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
ControlCore::ControlCore(IControlSettings settings,
TerminalConnection::ITerminalConnection connection) :
_connection{ connection },
_settings{ settings },
_desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false }
{
_EnsureStaticInitialization();
_settings = winrt::make_self<implementation::ControlSettings>(settings, unfocusedAppearance);
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
// Subscribe to the connection's disconnected event and call our connection closed handlers.
@ -82,7 +80,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
});
// GH#8969: pre-seed working directory to prevent potential races
_terminal->SetWorkingDirectory(_settings->StartingDirectory());
_terminal->SetWorkingDirectory(_settings.StartingDirectory());
auto pfnCopyToClipboard = std::bind(&ControlCore::_terminalCopyToClipboard, this, std::placeholders::_1);
_terminal->SetCopyToClipboardCallback(pfnCopyToClipboard);
@ -189,7 +187,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
});
UpdateSettings(settings, unfocusedAppearance);
UpdateSettings(settings);
}
ControlCore::~ControlCore()
@ -228,7 +226,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return false;
}
if (Feature_AtlasEngine::IsEnabled() && _settings->UseAtlasEngine())
if (Feature_AtlasEngine::IsEnabled() && _settings.UseAtlasEngine())
{
_renderEngine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
}
@ -254,7 +252,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
LOG_IF_FAILED(_renderEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
// Update DxEngine's SelectionBackground
_renderEngine->SetSelectionBackground(til::color{ _settings->SelectionBackground() });
_renderEngine->SetSelectionBackground(til::color{ _settings.SelectionBackground() });
const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels);
const auto width = vp.Width();
@ -262,10 +260,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_connection.Resize(height, width);
// Override the default width and height to match the size of the swapChainPanel
_settings->InitialCols(width);
_settings->InitialRows(height);
_settings.InitialCols(width);
_settings.InitialRows(height);
_terminal->CreateFromSettings(*_settings, *_renderer);
_terminal->CreateFromSettings(_settings, *_renderer);
// IMPORTANT! Set this callback up sooner than later. If we do it
// after Enable, then it'll be possible to paint the frame once
@ -277,17 +275,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems)
_renderEngine->SetCallback(std::bind(&ControlCore::_renderEngineSwapChainChanged, this));
_renderEngine->SetRetroTerminalEffect(_settings->RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(_settings->PixelShaderPath());
_renderEngine->SetForceFullRepaintRendering(_settings->ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings->SoftwareRendering());
_renderEngine->SetIntenseIsBold(_settings->IntenseIsBold());
_renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(_settings.PixelShaderPath());
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
_updateAntiAliasingMode();
// GH#5098: Inform the engine of the opacity of the default text background.
// GH#11315: Always do this, even if they don't have acrylic on.
_renderEngine->EnableTransparentBackground(_isBackgroundTransparent());
const auto backgroundIsOpaque = _settings.Opacity() == 1.0 && _settings.BackgroundImage().empty();
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
THROW_IF_FAILED(_renderEngine->Enable());
@ -445,13 +444,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
auto newOpacity = std::clamp(Opacity() + adjustment,
auto newOpacity = std::clamp(_settings.Opacity() + adjustment,
0.0,
1.0);
auto lock = _terminal->LockForWriting();
// Update our runtime opacity value
Opacity(newOpacity);
// GH#5098: Inform the engine of the new opacity of the default text background.
SetBackgroundOpacity(::base::saturated_cast<float>(newOpacity));
_settings.Opacity(newOpacity);
// GH#11285 - If the user is on Windows 10, and they changed the
// transparency of the control s.t. it should be partially opaque, then
@ -461,14 +461,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// is what the Terminal did prior to 1.12.
if (!IsVintageOpacityAvailable())
{
_runtimeUseAcrylic = newOpacity < 1.0;
}
// Update the renderer as well. It might need to fall back from
// cleartype -> grayscale if the BG is transparent / acrylic.
if (_renderEngine)
{
_renderEngine->EnableTransparentBackground(_isBackgroundTransparent());
_settings.UseAcrylic(newOpacity < 1.0);
}
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
@ -483,7 +476,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// specify a custom pixel shader, manually enable the legacy retro
// effect first. This will ensure that a toggle off->on will still work,
// even if they currently have retro effect off.
if (_settings->PixelShaderPath().empty() && !_renderEngine->GetRetroTerminalEffect())
if (_settings.PixelShaderPath().empty() && !_renderEngine->GetRetroTerminalEffect())
{
// SetRetroTerminalEffect to true will enable the effect. In this
// case, the shader effect will already be disabled (because neither
@ -593,27 +586,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Method Description:
// - Updates the settings of the current terminal.
// - INVARIANT: This method can only be called if the caller DOES NOT HAVE writing lock on the terminal.
void ControlCore::UpdateSettings(const IControlSettings& settings, const IControlAppearance& newAppearance)
void ControlCore::UpdateSettings(const IControlSettings& settings)
{
_settings = winrt::make_self<implementation::ControlSettings>(settings, newAppearance);
auto lock = _terminal->LockForWriting();
_runtimeOpacity = std::nullopt;
_runtimeUseAcrylic = std::nullopt;
_settings = settings;
// GH#11285 - If the user is on Windows 10, and they wanted opacity, but
// didn't explicitly request acrylic, then opt them in to acrylic.
// On Windows 11+, this isn't needed, because we can have vintage opacity.
if (!IsVintageOpacityAvailable() && _settings->Opacity() < 1.0 && !_settings->UseAcrylic())
if (!IsVintageOpacityAvailable() && _settings.Opacity() < 1.0 && !_settings.UseAcrylic())
{
_runtimeUseAcrylic = true;
_settings.UseAcrylic(true);
}
// Initialize our font information.
const auto fontFace = _settings->FontFace();
const short fontHeight = ::base::saturated_cast<short>(_settings->FontSize());
const auto fontWeight = _settings->FontWeight();
const auto fontFace = _settings.FontFace();
const short fontHeight = ::base::saturated_cast<short>(_settings.FontSize());
const auto fontWeight = _settings.FontWeight();
// The font width doesn't terribly matter, we'll only be using the
// height to look it up
// The other params here also largely don't matter.
@ -625,7 +615,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_desiredFont = { _actualFont };
// Update the terminal core with its new Core settings
_terminal->UpdateSettings(*_settings);
_terminal->UpdateSettings(_settings);
if (!_initializedTerminal)
{
@ -634,10 +624,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
_renderEngine->SetForceFullRepaintRendering(_settings->ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings->SoftwareRendering());
// Inform the renderer of our opacity
_renderEngine->EnableTransparentBackground(_isBackgroundTransparent());
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
_updateAntiAliasingMode();
@ -654,21 +642,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Method Description:
// - Updates the appearance of the current terminal.
// - INVARIANT: This method can only be called if the caller DOES NOT HAVE writing lock on the terminal.
void ControlCore::ApplyAppearance(const bool& focused)
void ControlCore::UpdateAppearance(const IControlAppearance& newAppearance)
{
auto lock = _terminal->LockForWriting();
const auto& newAppearance{ focused ? _settings->FocusedAppearance() : _settings->UnfocusedAppearance() };
// Update the terminal core with its new Core settings
_terminal->UpdateAppearance(*newAppearance);
_terminal->UpdateAppearance(newAppearance);
// Update DxEngine settings under the lock
if (_renderEngine)
{
// Update DxEngine settings under the lock
_renderEngine->SetSelectionBackground(til::color{ newAppearance->SelectionBackground() });
_renderEngine->SetRetroTerminalEffect(newAppearance->RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(newAppearance->PixelShaderPath());
_renderEngine->SetIntenseIsBold(_settings->IntenseIsBold());
_renderEngine->SetSelectionBackground(til::color{ newAppearance.SelectionBackground() });
_renderEngine->SetRetroTerminalEffect(newAppearance.RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(newAppearance.PixelShaderPath());
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
_renderer->TriggerRedrawAll();
}
}
@ -676,8 +664,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlCore::_updateAntiAliasingMode()
{
D2D1_TEXT_ANTIALIAS_MODE mode;
// Update DxEngine's AntialiasingMode
switch (_settings->AntialiasingMode())
switch (_settings.AntialiasingMode())
{
case TextAntialiasingMode::Cleartype:
mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
@ -713,7 +701,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_renderEngine)
{
std::unordered_map<std::wstring_view, uint32_t> featureMap;
if (const auto fontFeatures = _settings->FontFeatures())
if (const auto fontFeatures = _settings.FontFeatures())
{
featureMap.reserve(fontFeatures.Size());
@ -723,7 +711,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
std::unordered_map<std::wstring_view, float> axesMap;
if (const auto fontAxes = _settings->FontAxes())
if (const auto fontAxes = _settings.FontAxes())
{
axesMap.reserve(fontAxes.Size());
@ -765,8 +753,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// Make sure we have a non-zero font size
const auto newSize = std::max<short>(gsl::narrow_cast<short>(fontSize), 1);
const auto fontFace = _settings->FontFace();
const auto fontWeight = _settings->FontWeight();
const auto fontFace = _settings.FontFace();
const auto fontWeight = _settings.FontWeight();
_actualFont = { fontFace, 0, fontWeight.Weight, { 0, newSize }, CP_UTF8, false };
_actualFontFaceName = { fontFace };
_desiredFont = { _actualFont };
@ -791,7 +779,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - none
void ControlCore::ResetFontSize()
{
_setFontSize(_settings->FontSize());
_setFontSize(_settings.FontSize());
}
// Method Description:
@ -1003,7 +991,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TextBuffer::GenHTML(bufferData,
_actualFont.GetUnscaledSize().Y,
_actualFont.GetFaceName(),
til::color{ _settings->DefaultBackground() }) :
til::color{ _settings.DefaultBackground() }) :
"";
// convert to RTF format
@ -1011,10 +999,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TextBuffer::GenRTF(bufferData,
_actualFont.GetUnscaledSize().Y,
_actualFont.GetFaceName(),
til::color{ _settings->DefaultBackground() }) :
til::color{ _settings.DefaultBackground() }) :
"";
if (!_settings->CopyOnSelect())
if (!_settings.CopyOnSelect())
{
_terminal->ClearSelection();
_renderer->TriggerSelection();
@ -1101,10 +1089,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::color ControlCore::BackgroundColor() const
{
// The Terminal internally stores it's BG with 0 opacity, so as to allow
// DX to paint the BG color transparently. We however don't want to leak
// that implementation detail.
return _terminal->GetDefaultBackground().with_alpha(0xff);
return _terminal->GetColorTableEntry(TextColor::DEFAULT_BACKGROUND);
}
// Method Description:
@ -1261,7 +1246,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool ControlCore::CopyOnSelect() const
{
return _settings->CopyOnSelect();
return _settings.CopyOnSelect();
}
Windows::Foundation::Collections::IVector<winrt::hstring> ControlCore::SelectedText(bool trimTrailingWhitespace) const
@ -1319,6 +1304,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void ControlCore::SetBackgroundOpacity(const double opacity)
{
if (_renderEngine)
{
auto lock = _terminal->LockForWriting();
const auto backgroundIsOpaque = opacity == 1.0 && _settings.BackgroundImage().empty();
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
}
}
// Method Description:
// - Asynchronously close our connection. The Connection will likely wait
// until the attached process terminates before Close returns. If that's
@ -1604,125 +1599,4 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE;
}
Core::Scheme ControlCore::ColorScheme() const noexcept
{
Core::Scheme s;
// This part is definitely a hack.
//
// This function is usually used by the "Preview Color Scheme"
// functionality in TerminalPage. If we've got an unfocused appearance,
// then we've applied that appearance before this is even getting called
// (because the command palette is open with focus on top of us). If we
// return the _current_ colors now, we'll return out the _unfocused_
// colors. If we do that, and the user dismisses the command palette,
// then the scheme that will get restored is the _unfocused_ one, which
// is not what we want.
//
// So if that's the case, then let's grab the colors from the focused
// appearance as the scheme instead. We'll lose any current runtime
// changes to the color table, but those were already blown away when we
// switched to an unfocused appearance.
//
// IF WE DON'T HAVE AN UNFOCUSED APPEARANCE: then just ask the Terminal
// for it's current color table. That way, we can restore those colors
// back.
if (HasUnfocusedAppearance())
{
s.Foreground = _settings->FocusedAppearance()->DefaultForeground();
s.Background = _settings->FocusedAppearance()->DefaultBackground();
s.CursorColor = _settings->FocusedAppearance()->CursorColor();
s.Black = _settings->FocusedAppearance()->GetColorTableEntry(0);
s.Red = _settings->FocusedAppearance()->GetColorTableEntry(1);
s.Green = _settings->FocusedAppearance()->GetColorTableEntry(2);
s.Yellow = _settings->FocusedAppearance()->GetColorTableEntry(3);
s.Blue = _settings->FocusedAppearance()->GetColorTableEntry(4);
s.Purple = _settings->FocusedAppearance()->GetColorTableEntry(5);
s.Cyan = _settings->FocusedAppearance()->GetColorTableEntry(6);
s.White = _settings->FocusedAppearance()->GetColorTableEntry(7);
s.BrightBlack = _settings->FocusedAppearance()->GetColorTableEntry(8);
s.BrightRed = _settings->FocusedAppearance()->GetColorTableEntry(9);
s.BrightGreen = _settings->FocusedAppearance()->GetColorTableEntry(10);
s.BrightYellow = _settings->FocusedAppearance()->GetColorTableEntry(11);
s.BrightBlue = _settings->FocusedAppearance()->GetColorTableEntry(12);
s.BrightPurple = _settings->FocusedAppearance()->GetColorTableEntry(13);
s.BrightCyan = _settings->FocusedAppearance()->GetColorTableEntry(14);
s.BrightWhite = _settings->FocusedAppearance()->GetColorTableEntry(15);
}
else
{
s = _terminal->GetColorScheme();
}
// This might be a tad bit of a hack. This event only gets called by set
// color scheme / preview color scheme, and in that case, we know the
// control _is_ focused.
s.SelectionBackground = _settings->FocusedAppearance()->SelectionBackground();
return s;
}
// Method Description:
// - Apply the given color scheme to this control. We'll take the colors out
// of it and apply them to our focused appearance, and update the terminal
// buffer with the new color table.
// - This is here to support the Set Color Scheme action, and the ability to
// preview schemes in the control.
// Arguments:
// - scheme: the collection of colors to apply.
// Return Value:
// - <none>
void ControlCore::ColorScheme(const Core::Scheme& scheme)
{
auto l{ _terminal->LockForWriting() };
_settings->FocusedAppearance()->DefaultForeground(scheme.Foreground);
_settings->FocusedAppearance()->DefaultBackground(scheme.Background);
_settings->FocusedAppearance()->CursorColor(scheme.CursorColor);
_settings->FocusedAppearance()->SelectionBackground(scheme.SelectionBackground);
_settings->FocusedAppearance()->SetColorTableEntry(0, scheme.Black);
_settings->FocusedAppearance()->SetColorTableEntry(1, scheme.Red);
_settings->FocusedAppearance()->SetColorTableEntry(2, scheme.Green);
_settings->FocusedAppearance()->SetColorTableEntry(3, scheme.Yellow);
_settings->FocusedAppearance()->SetColorTableEntry(4, scheme.Blue);
_settings->FocusedAppearance()->SetColorTableEntry(5, scheme.Purple);
_settings->FocusedAppearance()->SetColorTableEntry(6, scheme.Cyan);
_settings->FocusedAppearance()->SetColorTableEntry(7, scheme.White);
_settings->FocusedAppearance()->SetColorTableEntry(8, scheme.BrightBlack);
_settings->FocusedAppearance()->SetColorTableEntry(9, scheme.BrightRed);
_settings->FocusedAppearance()->SetColorTableEntry(10, scheme.BrightGreen);
_settings->FocusedAppearance()->SetColorTableEntry(11, scheme.BrightYellow);
_settings->FocusedAppearance()->SetColorTableEntry(12, scheme.BrightBlue);
_settings->FocusedAppearance()->SetColorTableEntry(13, scheme.BrightPurple);
_settings->FocusedAppearance()->SetColorTableEntry(14, scheme.BrightCyan);
_settings->FocusedAppearance()->SetColorTableEntry(15, scheme.BrightWhite);
_terminal->ApplyScheme(scheme);
_renderEngine->SetSelectionBackground(til::color{ _settings->SelectionBackground() });
_renderer->TriggerRedrawAll();
_BackgroundColorChangedHandlers(*this, nullptr);
}
bool ControlCore::HasUnfocusedAppearance() const
{
return _settings->HasUnfocusedAppearance();
}
bool ControlCore::_isBackgroundTransparent()
{
// If we're:
// * Not fully opaque
// * On an acrylic background (of any opacity)
// * rendering on top of an image
//
// then the renderer should not render "default background" text with a
// fully opaque background. Doing that would cover up our nice
// transparency, or our acrylic, or our image.
return Opacity() < 1.0f || UseAcrylic() || !_settings->BackgroundImage().empty();
}
}

View file

@ -16,35 +16,23 @@
#pragma once
#include "ControlCore.g.h"
#include "ControlSettings.h"
#include "../../renderer/base/Renderer.hpp"
#include "../../cascadia/TerminalCore/Terminal.hpp"
#include "../buffer/out/search.h"
#include "cppwinrt_utils.h"
#include <til/ticket_lock.h>
namespace ControlUnitTests
{
class ControlCoreTests;
class ControlInteractivityTests;
};
#define RUNTIME_SETTING(type, name, setting) \
private: \
std::optional<type> _runtime##name{ std::nullopt }; \
void name(const type newValue) { _runtime##name = newValue; } \
\
public: \
type name() const { return til::coalesce_value(_runtime##name, setting); }
namespace winrt::Microsoft::Terminal::Control::implementation
{
struct ControlCore : ControlCoreT<ControlCore>
{
public:
ControlCore(Control::IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
ControlCore(IControlSettings settings,
TerminalConnection::ITerminalConnection connection);
~ControlCore();
@ -53,16 +41,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const double compositionScale);
void EnablePainting();
void UpdateSettings(const Control::IControlSettings& settings, const IControlAppearance& newAppearance);
void ApplyAppearance(const bool& focused);
Control::IControlSettings Settings() { return *_settings; };
Control::IControlAppearance FocusedAppearance() const { return *_settings->FocusedAppearance(); };
Control::IControlAppearance UnfocusedAppearance() const { return *_settings->UnfocusedAppearance(); };
bool HasUnfocusedAppearance() const;
winrt::Microsoft::Terminal::Core::Scheme ColorScheme() const noexcept;
void ColorScheme(const winrt::Microsoft::Terminal::Core::Scheme& scheme);
void UpdateSettings(const IControlSettings& settings);
void UpdateAppearance(const IControlAppearance& newAppearance);
void SizeChanged(const double width, const double height);
void ScaleChanged(const double scale);
uint64_t SwapChainHandle() const;
@ -77,6 +57,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
uint16_t FontWeight() const noexcept;
til::color BackgroundColor() const;
void SetBackgroundOpacity(const double opacity);
void SendInput(const winrt::hstring& wstr);
void PasteText(const winrt::hstring& hstr);
@ -167,9 +148,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
static bool IsVintageOpacityAvailable() noexcept;
RUNTIME_SETTING(double, Opacity, _settings->Opacity());
RUNTIME_SETTING(bool, UseAcrylic, _settings->UseAcrylic());
// -------------------------------- WinRT Events ---------------------------------
// clang-format off
WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs);
@ -200,8 +178,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
event_token _connectionOutputEventToken;
TerminalConnection::ITerminalConnection::StateChanged_revoker _connectionStateChangedRevoker;
winrt::com_ptr<ControlSettings> _settings{ nullptr };
std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal{ nullptr };
// NOTE: _renderEngine must be ordered before _renderer.
@ -212,6 +188,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
std::unique_ptr<::Microsoft::Console::Render::IRenderEngine> _renderEngine{ nullptr };
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr };
IControlSettings _settings{ nullptr };
FontInfoDesired _desiredFont;
FontInfo _actualFont;
winrt::hstring _actualFontFaceName;
@ -271,8 +249,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _connectionOutputHandler(const hstring& hstr);
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
bool _isBackgroundTransparent();
inline bool _IsClosing() const noexcept
{
#ifndef NDEBUG

View file

@ -33,27 +33,20 @@ namespace Microsoft.Terminal.Control
[default_interface] runtimeclass ControlCore : ICoreState
{
ControlCore(IControlSettings settings,
IControlAppearance unfocusedAppearance,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
Boolean Initialize(Double actualWidth,
Double actualHeight,
Double compositionScale);
void UpdateSettings(IControlSettings settings, IControlAppearance appearance);
void ApplyAppearance(Boolean focused);
IControlSettings Settings { get; };
IControlAppearance FocusedAppearance { get; };
IControlAppearance UnfocusedAppearance { get; };
Boolean HasUnfocusedAppearance();
void UpdateSettings(IControlSettings settings);
void UpdateAppearance(IControlAppearance appearance);
UInt64 SwapChainHandle { get; };
Windows.Foundation.Size FontSize { get; };
String FontFaceName { get; };
UInt16 FontWeight { get; };
Double Opacity { get; };
Boolean TrySendKeyEvent(Int16 vkey,
Int16 scanCode,
@ -82,6 +75,7 @@ namespace Microsoft.Terminal.Control
void BlinkAttributeTick();
void UpdatePatternLocations();
void Search(String text, Boolean goForward, Boolean caseSensitive);
void SetBackgroundOpacity(Double opacity);
Microsoft.Terminal.Core.Color BackgroundColor { get; };
Boolean HasSelection { get; };

View file

@ -39,14 +39,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
ControlInteractivity::ControlInteractivity(IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection) :
_touchAnchor{ std::nullopt },
_lastMouseClickTimestamp{},
_lastMouseClickPos{},
_selectionNeedsToBeCopied{ false }
{
_core = winrt::make_self<ControlCore>(settings, unfocusedAppearance, connection);
_core = winrt::make_self<ControlCore>(settings, connection);
}
// Method Description:
@ -642,15 +641,4 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _core->GetUiaData();
}
// Method Description:
// - Used by the TermControl to know if it should translate drag-dropped
// paths into WSL-friendly paths.
// Arguments:
// - <none>
// Return Value:
// - true if the connection we were created with was a WSL profile.
bool ControlInteractivity::ManglePathsForWsl()
{
return _core->Settings().ProfileSource() == L"Windows.Terminal.Wsl";
}
}

View file

@ -36,7 +36,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
public:
ControlInteractivity(IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection);
void GotFocus();
@ -84,7 +83,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const Windows::Foundation::IReference<CopyFormat>& formats);
void RequestPasteTextFromClipboard();
void SetEndSelectionPoint(const til::point pixelPosition);
bool ManglePathsForWsl();
TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);

View file

@ -14,7 +14,6 @@ namespace Microsoft.Terminal.Control
[default_interface] runtimeclass ControlInteractivity
{
ControlInteractivity(IControlSettings settings,
IControlAppearance unfocusedAppearance,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
ControlCore Core { get; };
@ -59,8 +58,6 @@ namespace Microsoft.Terminal.Control
void UpdateScrollbar(Double newValue);
Boolean ManglePathsForWsl { get; };
event Windows.Foundation.TypedEventHandler<Object, OpenHyperlinkEventArgs> OpenHyperlink;
event Windows.Foundation.TypedEventHandler<Object, ScrollPositionChangedArgs> ScrollPositionChanged;
event Windows.Foundation.TypedEventHandler<Object, PasteFromClipboardEventArgs> PasteFromClipboard;

View file

@ -1,81 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
--*/
#pragma once
#include "../../inc/cppwinrt_utils.h"
#include "../../inc/ControlProperties.h"
#include <DefaultSettings.h>
#include <conattrs.hpp>
#include "ControlAppearance.h"
using IFontFeatureMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, uint32_t>;
using IFontAxesMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, float>;
namespace winrt::Microsoft::Terminal::Control::implementation
{
struct ControlSettings : public winrt::implements<ControlSettings, Microsoft::Terminal::Control::IControlSettings, Microsoft::Terminal::Control::IControlAppearance, Microsoft::Terminal::Core::ICoreSettings, Microsoft::Terminal::Core::ICoreAppearance>
{
// Getters and setters for each *Setting member. We're not using
// WINRT_PROPERTY for these, because they actually exist inside the
// _focusedAppearance member. We don't need to reserve another member to
// hold them.
#define SETTINGS_GEN(type, name, ...) WINRT_PROPERTY(type, name, __VA_ARGS__);
CORE_SETTINGS(SETTINGS_GEN)
CONTROL_SETTINGS(SETTINGS_GEN)
#undef SETTINGS_GEN
private:
winrt::com_ptr<ControlAppearance> _unfocusedAppearance{ nullptr };
winrt::com_ptr<ControlAppearance> _focusedAppearance{ nullptr };
bool _hasUnfocusedAppearance{ false };
public:
ControlSettings(const Control::IControlSettings& settings,
const Control::IControlAppearance& unfocusedAppearance)
{
_hasUnfocusedAppearance = unfocusedAppearance != nullptr;
_focusedAppearance = winrt::make_self<implementation::ControlAppearance>(settings);
_unfocusedAppearance = unfocusedAppearance ?
winrt::make_self<implementation::ControlAppearance>(unfocusedAppearance) :
_focusedAppearance;
// Copy every value from the passed in settings, into us.
#define COPY_SETTING(type, name, ...) _##name = settings.name();
CORE_SETTINGS(COPY_SETTING)
CONTROL_SETTINGS(COPY_SETTING)
#undef COPY_SETTING
}
winrt::com_ptr<ControlAppearance> UnfocusedAppearance() { return _unfocusedAppearance; }
winrt::com_ptr<ControlAppearance> FocusedAppearance() { return _focusedAppearance; }
bool HasUnfocusedAppearance() { return _hasUnfocusedAppearance; }
// Getters and setters for each Appearance member. We're not using
// WINRT_PROPERTY for these, because they actually exist inside the
// _focusedAppearance member. We don't need to reserve another member to
// hold them.
//
// The Appearance members (including GetColorTableEntry below) are used
// when this ControlSettings is cast to a IControlAppearance or
// ICoreAppearance. In those cases, we'll always return the Focused
// appearance's version of the member. Callers who care about which
// appearance is being used should be more careful. Fortunately, this
// situation is generally only used when a control is first created, or
// when calling UpdateSettings.
#define APPEARANCE_GEN(type, name, ...) \
type name() const noexcept { return _focusedAppearance->name(); } \
void name(const type& value) noexcept { _focusedAppearance->name(value); }
CORE_APPEARANCE_SETTINGS(APPEARANCE_GEN)
CONTROL_APPEARANCE_SETTINGS(APPEARANCE_GEN)
#undef APPEARANCE_GEN
winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept
{
return _focusedAppearance->GetColorTableEntry(index);
}
};
}

View file

@ -5,18 +5,18 @@ namespace Microsoft.Terminal.Control
{
interface IControlAppearance requires Microsoft.Terminal.Core.ICoreAppearance
{
Microsoft.Terminal.Core.Color SelectionBackground { get; };
String BackgroundImage { get; };
Double BackgroundImageOpacity { get; };
Windows.UI.Xaml.Media.Stretch BackgroundImageStretchMode { get; };
Windows.UI.Xaml.HorizontalAlignment BackgroundImageHorizontalAlignment { get; };
Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment { get; };
Boolean IntenseIsBold { get; };
Microsoft.Terminal.Core.Color SelectionBackground;
String BackgroundImage;
Double BackgroundImageOpacity;
Windows.UI.Xaml.Media.Stretch BackgroundImageStretchMode;
Windows.UI.Xaml.HorizontalAlignment BackgroundImageHorizontalAlignment;
Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment;
Boolean IntenseIsBold;
// IntenseIsBright is in Core Appearance
Double Opacity { get; };
Double Opacity;
// Experimental settings
Boolean RetroTerminalEffect { get; };
String PixelShaderPath { get; };
Boolean RetroTerminalEffect;
String PixelShaderPath;
};
}

View file

@ -24,37 +24,34 @@ namespace Microsoft.Terminal.Control
// TermControl's behavior. In these settings there is both the entirety
// of the Core ITerminalSettings interface, and any additional settings
// for specifically the control.
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings,
Microsoft.Terminal.Control.IControlAppearance
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings, Microsoft.Terminal.Control.IControlAppearance
{
String ProfileName;
String ProfileSource;
Boolean UseAcrylic { get; };
ScrollbarState ScrollState { get; };
Boolean UseAcrylic;
ScrollbarState ScrollState;
Boolean UseAtlasEngine;
String FontFace;
Int32 FontSize;
Windows.UI.Text.FontWeight FontWeight;
String Padding;
Windows.Foundation.Collections.IMap<String, UInt32> FontFeatures;
Windows.Foundation.Collections.IMap<String, Single> FontAxes;
Boolean UseAtlasEngine { get; };
Microsoft.Terminal.Control.IKeyBindings KeyBindings;
String FontFace { get; };
Int32 FontSize { get; };
Windows.UI.Text.FontWeight FontWeight { get; };
String Padding { get; };
Windows.Foundation.Collections.IMap<String, UInt32> FontFeatures { get; };
Windows.Foundation.Collections.IMap<String, Single> FontAxes { get; };
Boolean CopyOnSelect;
Boolean FocusFollowMouse;
Microsoft.Terminal.Control.IKeyBindings KeyBindings { get; };
String Commandline;
String StartingDirectory;
String EnvironmentVariables;
Boolean CopyOnSelect { get; };
Boolean FocusFollowMouse { get; };
String Commandline { get; };
String StartingDirectory { get; };
String EnvironmentVariables { get; };
TextAntialiasingMode AntialiasingMode { get; };
TextAntialiasingMode AntialiasingMode;
// Experimental Settings
Boolean ForceFullRepaintRendering { get; };
Boolean SoftwareRendering { get; };
Boolean ForceFullRepaintRendering;
Boolean SoftwareRendering;
};
}

View file

@ -22,7 +22,5 @@ namespace Microsoft.Terminal.Control
Boolean BracketedPasteEnabled { get; };
Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; };
Microsoft.Terminal.Core.Scheme ColorScheme { get; set; };
};
}

View file

@ -48,8 +48,8 @@ DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::MouseButtonState
namespace winrt::Microsoft::Terminal::Control::implementation
{
TermControl::TermControl(IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection) :
_settings{ settings },
_isInternalScrollBarUpdate{ false },
_autoScrollVelocity{ 0 },
_autoScrollingPointerPoint{ std::nullopt },
@ -61,7 +61,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
InitializeComponent();
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, unfocusedAppearance, connection);
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
_core = _interactivity.Core();
// These events might all be triggered by the connection, but that
@ -77,7 +77,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// These callbacks can only really be triggered by UI interactions. So
// they don't need weak refs - they can't be triggered unless we're
// alive.
_core.BackgroundColorChanged({ this, &TermControl::_coreBackgroundColorChanged });
_core.BackgroundColorChanged({ this, &TermControl::_BackgroundColorChangedHandler });
_core.FontSizeChanged({ this, &TermControl::_coreFontSizeChanged });
_core.TransparencyChanged({ this, &TermControl::_coreTransparencyChanged });
_core.RaiseNotice({ this, &TermControl::_coreRaisedNotice });
@ -144,7 +144,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
_autoScrollTimer.Tick({ this, &TermControl::_UpdateAutoScroll });
_ApplyUISettings();
_ApplyUISettings(_settings);
}
// Method Description:
@ -229,15 +229,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
this->Focus(FocusState::Programmatic);
}
winrt::fire_and_forget TermControl::UpdateControlSettings(IControlSettings settings)
{
return UpdateControlSettings(settings, _core.UnfocusedAppearance());
}
// Method Description:
// - Given Settings having been updated, applies the settings to the current terminal.
// Return Value:
// - <none>
winrt::fire_and_forget TermControl::UpdateControlSettings(IControlSettings settings, IControlAppearance unfocusedAppearance)
winrt::fire_and_forget TermControl::UpdateSettings()
{
auto weakThis{ get_weak() };
@ -245,18 +241,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// terminal.
co_await winrt::resume_foreground(Dispatcher());
_core.UpdateSettings(settings, unfocusedAppearance);
_UpdateSettingsFromUIThread(_settings);
_UpdateSettingsFromUIThread();
_UpdateAppearanceFromUIThread(_focused ? _core.FocusedAppearance() : _core.UnfocusedAppearance());
auto appearance = _settings.try_as<IControlAppearance>();
if (!_focused && _UnfocusedAppearance)
{
appearance = _UnfocusedAppearance;
}
_UpdateAppearanceFromUIThread(appearance);
}
// Method Description:
// - Dispatches a call to the UI thread and updates the appearance
// Arguments:
// - newAppearance: the new appearance to set
winrt::fire_and_forget TermControl::UpdateAppearance(IControlAppearance newAppearance)
winrt::fire_and_forget TermControl::UpdateAppearance(const IControlAppearance newAppearance)
{
// Dispatch a call to the UI thread
co_await winrt::resume_foreground(Dispatcher());
@ -272,15 +271,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - INVARIANT: This method must be called from the UI thread.
// Arguments:
// - newSettings: the new settings to set
void TermControl::_UpdateSettingsFromUIThread()
void TermControl::_UpdateSettingsFromUIThread(IControlSettings newSettings)
{
if (_IsClosing())
{
return;
}
_core.UpdateSettings(_settings);
// Update our control settings
_ApplyUISettings();
_ApplyUISettings(_settings);
}
// Method Description:
@ -288,7 +289,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - INVARIANT: This method must be called from the UI thread.
// Arguments:
// - newAppearance: the new appearance to set
void TermControl::_UpdateAppearanceFromUIThread(Control::IControlAppearance newAppearance)
void TermControl::_UpdateAppearanceFromUIThread(IControlAppearance newAppearance)
{
if (_IsClosing())
{
@ -299,10 +300,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Update our control settings
const auto bg = newAppearance.DefaultBackground();
// In the future, this might need to be changed to a
// _InitializeBackgroundBrush call instead, because we may need to
// switch from a solid color brush to an acrylic one.
_changeBackgroundColor(bg);
// Set TSF Foreground
@ -310,7 +307,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
foregroundBrush.Color(static_cast<til::color>(newAppearance.DefaultForeground()));
TSFInputControl().Foreground(foregroundBrush);
_core.ApplyAppearance(_focused);
_core.UpdateAppearance(newAppearance);
}
// Method Description:
@ -334,7 +331,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// Method Description:
// - Style our UI elements based on the values in our settings, and set up
// - Style our UI elements based on the values in our _settings, and set up
// other control-specific settings. This method will be called whenever
// the settings are reloaded.
// * Calls _InitializeBackgroundBrush to set up the Xaml brush responsible
@ -345,21 +342,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <none>
// Return Value:
// - <none>
void TermControl::_ApplyUISettings()
void TermControl::_ApplyUISettings(const IControlSettings& newSettings)
{
_InitializeBackgroundBrush();
// settings might be out-of-proc in the future
auto settings{ _core.Settings() };
const auto bg = newSettings.DefaultBackground();
_changeBackgroundColor(bg);
// Apply padding as swapChainPanel's margin
const auto newMargin = ParseThicknessFromPadding(settings.Padding());
const auto newMargin = ParseThicknessFromPadding(newSettings.Padding());
SwapChainPanel().Margin(newMargin);
TSFInputControl().Margin(newMargin);
// Apply settings for scrollbar
if (settings.ScrollState() == ScrollbarState::Hidden)
if (newSettings.ScrollState() == ScrollbarState::Hidden)
{
// In the scenario where the user has turned off the OS setting to automatically hide scrollbars, the
// Terminal scrollbar would still be visible; so, we need to set the control's visibility accordingly to
@ -443,15 +440,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// use bgcolor as acrylic's tint
// - Avoids image flickering and acrylic brush redraw if settings are changed
// but the appropriate brush is still in place.
// - Does not apply background color outside of acrylic mode;
// _BackgroundColorChanged must be called to do so.
// Arguments:
// - <none>
// Return Value:
// - <none>
void TermControl::_InitializeBackgroundBrush()
{
auto settings{ _core.Settings() };
auto bgColor = til::color{ _core.FocusedAppearance().DefaultBackground() }.with_alpha(0xff);
if (settings.UseAcrylic())
auto appearance = _settings.try_as<IControlAppearance>();
if (_settings.UseAcrylic())
{
// See if we've already got an acrylic background brush
// to avoid the flicker when setting up a new one
@ -466,83 +464,65 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// see GH#1082: Initialize background color so we don't get a
// fade/flash when _BackgroundColorChanged is called
auto bgColor = til::color{ _settings.DefaultBackground() }.with_alpha(0xff);
acrylic.FallbackColor(bgColor);
acrylic.TintColor(bgColor);
// Apply brush settings
acrylic.TintOpacity(_core.Opacity());
acrylic.TintOpacity(appearance.Opacity());
// Apply brush to control if it's not already there
if (RootGrid().Background() != acrylic)
{
RootGrid().Background(acrylic);
}
// GH#5098: Inform the engine of the new opacity of the default text background.
_core.SetBackgroundOpacity(appearance.Opacity());
}
else
{
Media::SolidColorBrush solidColor{};
solidColor.Opacity(_core.Opacity());
solidColor.Color(bgColor);
solidColor.Opacity(_settings.Opacity());
RootGrid().Background(solidColor);
// GH#5098: Inform the engine of the new opacity of the default text background.
_core.SetBackgroundOpacity(appearance.Opacity());
}
}
// Method Description:
// - Handler for the core's BackgroundColorChanged event. Updates the color
// of our background brush to match.
// - Hops over to the UI thread to do this work.
// - Style the background of the control with the provided background color
// Arguments:
// <unused>
// - color: The background color to use as a uint32 (aka DWORD COLORREF)
// Return Value:
// - <none>
winrt::fire_and_forget TermControl::_coreBackgroundColorChanged(const IInspectable& /*sender*/,
const IInspectable& /*args*/)
void TermControl::_BackgroundColorChangedHandler(const IInspectable& /*sender*/,
const IInspectable& /*args*/)
{
til::color newBgColor{ _core.BackgroundColor() };
_changeBackgroundColor(newBgColor);
}
winrt::fire_and_forget TermControl::_changeBackgroundColor(const til::color bg)
{
auto weakThis{ get_weak() };
co_await winrt::resume_foreground(Dispatcher());
if (auto control{ weakThis.get() })
{
til::color newBgColor{ _core.BackgroundColor() };
_changeBackgroundColor(newBgColor);
}
}
// Method Description:
// - Update the color of the background brush we're using. This does _not_
// update the opacity, or what type of brush it is.
// - INVARIANT: This needs to be called on the UI thread.
// Arguments:
// - bg: the new color to use as the background color.
void TermControl::_changeBackgroundColor(const til::color bg)
{
if (auto acrylic = RootGrid().Background().try_as<Media::AcrylicBrush>())
{
acrylic.FallbackColor(bg);
acrylic.TintColor(bg);
}
else if (auto solidColor = RootGrid().Background().try_as<Media::SolidColorBrush>())
{
const auto originalOpacity = solidColor.Opacity();
solidColor.Color(bg);
solidColor.Opacity(originalOpacity);
}
}
// Method Description:
// - Update the opacity of the background brush we're using. This does _not_
// update the color, or what type of brush it is.
// - INVARIANT: This needs to be called on the UI thread.
void TermControl::_changeBackgroundOpacity()
{
const auto opacity{ _core.Opacity() };
if (auto acrylic = RootGrid().Background().try_as<Media::AcrylicBrush>())
{
acrylic.TintOpacity(opacity);
}
else if (auto solidColor = RootGrid().Background().try_as<Media::SolidColorBrush>())
{
solidColor.Opacity(opacity);
if (auto acrylic = RootGrid().Background().try_as<Media::AcrylicBrush>())
{
acrylic.FallbackColor(bg);
acrylic.TintColor(bg);
}
else if (auto solidColor = RootGrid().Background().try_as<Media::SolidColorBrush>())
{
const auto originalOpacity = solidColor.Opacity();
solidColor.Color(bg);
solidColor.Opacity(originalOpacity);
}
}
}
@ -638,7 +618,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
{
message = { fmt::format(std::wstring_view{ RS_(L"PixelShaderNotFound") },
(_focused ? _core.FocusedAppearance() : _core.UnfocusedAppearance()).PixelShaderPath()) };
_settings.PixelShaderPath()) };
}
else if (D2DERR_SHADER_COMPILE_FAILED == hr)
{
@ -760,7 +740,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// Now that the renderer is set up, update the appearance for initialization
_UpdateAppearanceFromUIThread(_core.FocusedAppearance());
_UpdateAppearanceFromUIThread(_settings);
_initializedTerminal = true;
@ -793,12 +773,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_HidePointerCursorHandlers(*this, nullptr);
const auto ch = e.Character();
const auto scanCode = gsl::narrow_cast<WORD>(e.KeyStatus().ScanCode);
const auto keyStatus = e.KeyStatus();
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
auto modifiers = _GetPressedModifierKeys();
if (e.KeyStatus().IsExtendedKey)
if (keyStatus.IsExtendedKey)
{
modifiers |= ControlKeyStates::EnhancedKey;
}
const bool handled = _core.SendCharEvent(ch, scanCode, modifiers);
e.Handled(handled);
}
@ -832,7 +815,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// This is required as part of GH#638.
// Or do so for alt+space; only send to terminal when explicitly unbound
// That is part of #GH7125
auto bindings{ _core.Settings().KeyBindings() };
auto bindings{ _settings.KeyBindings() };
bool isUnbound = false;
const KeyChord kc = {
modifiers.IsCtrlPressed(),
@ -893,6 +876,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
auto modifiers = _GetPressedModifierKeys();
if (keyStatus.IsExtendedKey)
{
modifiers |= ControlKeyStates::EnhancedKey;
}
// GH#11076:
// For some weird reason we sometimes receive a WM_KEYDOWN
// message without vkey or scanCode if a user drags a tab.
@ -926,11 +914,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
if (keyStatus.IsExtendedKey)
{
modifiers |= ControlKeyStates::EnhancedKey;
}
// Alt-Numpad# input will send us a character once the user releases
// Alt, so we should be ignoring the individual keydowns. The character
// will be sent through the TSFInputControl. See GH#1401 for more
@ -977,13 +960,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - modifiers: The ControlKeyStates representing the modifier key states.
bool TermControl::_TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const
{
// TODO: GH#5000
// The Core owning the keybindings is weird. That's for sure. In the
// future, we may want to pass the keybindings into the control
// separately, so the control can have a pointer to an in-proc
// Keybindings object, rather than routing through the ControlCore.
// (see GH#5000)
auto bindings = _core.Settings().KeyBindings();
auto bindings = _settings.KeyBindings();
if (!bindings)
{
return false;
@ -1014,7 +991,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
{
std::array<BYTE, 256> keyState;
if (!GetKeyboardState(keyState.data()))
@ -1162,7 +1139,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto pixelPosition = _toTerminalOrigin(cursorPosition);
const auto type = ptr.PointerDeviceType();
if (!_focused && _core.Settings().FocusFollowMouse())
if (!_focused && _settings.FocusFollowMouse())
{
_FocusFollowMouseRequestedHandlers(*this, nullptr);
}
@ -1330,7 +1307,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Called in response to the core's TransparencyChanged event. We'll use
// this to update our background brush.
// - The Core should have already updated the TintOpacity and UseAcrylic
// properties in the _settings->
// properties in the _settings.
// Arguments:
// - <unused>
// Return Value:
@ -1341,7 +1318,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
co_await resume_foreground(Dispatcher());
try
{
_changeBackgroundOpacity();
_InitializeBackgroundBrush();
const auto bg = _settings.DefaultBackground();
_changeBackgroundColor(bg);
}
CATCH_LOG();
}
@ -1548,13 +1527,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_blinkTimer->Start();
}
// Only update the appearance here if an unfocused config exists - if an
// unfocused config does not exist then we never would have switched
// appearances anyway so there's no need to switch back upon gaining
// focus
if (_core.HasUnfocusedAppearance())
// Only update the appearance here if an unfocused config exists -
// if an unfocused config does not exist then we never would have switched
// appearances anyway so there's no need to switch back upon gaining focus
if (_UnfocusedAppearance)
{
UpdateAppearance(_core.FocusedAppearance());
UpdateAppearance(_settings);
}
}
@ -1596,9 +1574,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Check if there is an unfocused config we should set the appearance to
// upon losing focus
if (_core.HasUnfocusedAppearance())
if (_UnfocusedAppearance)
{
UpdateAppearance(_core.UnfocusedAppearance());
UpdateAppearance(_UnfocusedAppearance);
}
}
@ -1747,7 +1725,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
hstring TermControl::GetProfileName() const
{
return _core.Settings().ProfileName();
return _settings.ProfileName();
}
hstring TermControl::WorkingDirectory() const
@ -1969,7 +1947,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
double width = fontSize.Width;
double height = fontSize.Height;
// Reserve additional space if scrollbar is intended to be visible
if (_core.Settings().ScrollState() == ScrollbarState::Visible)
if (_settings.ScrollState() == ScrollbarState::Visible)
{
width += ScrollBar().ActualWidth();
}
@ -1990,8 +1968,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
return GetProposedDimensions(_core.Settings(), dpi, minSize);
return GetProposedDimensions(_settings, dpi, minSize);
}
}
@ -2013,7 +1990,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
padding.Left + padding.Right :
padding.Top + padding.Bottom);
if (widthOrHeight && _core.Settings().ScrollState() == ScrollbarState::Visible)
if (widthOrHeight && _settings.ScrollState() == ScrollbarState::Visible)
{
nonTerminalArea += gsl::narrow_cast<float>(ScrollBar().ActualWidth());
}
@ -2086,7 +2063,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// don't necessarily include that state.
// Return Value:
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
ControlKeyStates TermControl::_GetPressedModifierKeys() const
ControlKeyStates TermControl::_GetPressedModifierKeys() noexcept
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
// DONT USE
@ -2296,16 +2273,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
std::wstring fullPath{ item.Path() };
// Fix path for WSL
// In the fullness of time, we should likely plumb this up
// to the TerminalApp layer, and have it make the decision
// if this control should have it's path mangled (and do the
// mangling), rather than exposing the source concept to the
// Control layer.
//
// However, it's likely that the control layer may need to
// know about the source anyways in the future, to support
// GH#3158
if (_interactivity.ManglePathsForWsl())
if (_settings.ProfileSource() == L"Windows.Terminal.Wsl")
{
std::replace(fullPath.begin(), fullPath.end(), L'\\', L'/');
@ -2452,19 +2420,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
IControlSettings TermControl::Settings() const
{
// TODO: GH#5000
// We still need this in a couple places:
// - Pane.cpp uses this for parsing out the StartingTitle, Commandline,
// etc for Pane::GetTerminalArgsForPane.
// - TerminalTab::_CreateToolTipTitle uses the ProfileName for the
// tooltip for the tab.
//
// These both happen on the UI thread right now. In the future, when we
// have to hop across the process boundary to get at the core settings,
// it may make sense to cache these values inside the TermControl
// itself, so it can do the hop once when it's first setup, rather than
// when it's needed by the UI thread.
return _core.Settings();
return _settings;
}
void TermControl::Settings(IControlSettings newSettings)
{
_settings = newSettings;
}
Windows::Foundation::IReference<winrt::Windows::UI::Color> TermControl::TabColor() noexcept
@ -2687,19 +2648,4 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
return _core.ReadEntireBuffer();
}
Core::Scheme TermControl::ColorScheme() const noexcept
{
return _core.ColorScheme();
}
void TermControl::ColorScheme(const Core::Scheme& scheme) const noexcept
{
_core.ColorScheme(scheme);
}
Media::Brush TermControl::BackgroundBrush()
{
return RootGrid().Background();
}
}

View file

@ -25,13 +25,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
struct TermControl : TermControlT<TermControl>
{
TermControl(IControlSettings settings,
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection);
TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection);
winrt::fire_and_forget UpdateControlSettings(Control::IControlSettings settings);
winrt::fire_and_forget UpdateControlSettings(Control::IControlSettings settings, Control::IControlAppearance unfocusedAppearance);
IControlSettings Settings() const;
winrt::fire_and_forget UpdateSettings();
winrt::fire_and_forget UpdateAppearance(const IControlAppearance newAppearance);
hstring GetProfileName() const;
@ -91,6 +88,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer();
const Windows::UI::Xaml::Thickness GetPadding();
IControlSettings Settings() const;
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);
@ -105,10 +105,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
hstring ReadEntireBuffer() const;
winrt::Microsoft::Terminal::Core::Scheme ColorScheme() const noexcept;
void ColorScheme(const winrt::Microsoft::Terminal::Core::Scheme& scheme) const noexcept;
Windows::UI::Xaml::Media::Brush BackgroundBrush();
// -------------------------------- WinRT Events ---------------------------------
// clang-format off
WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs);
@ -131,6 +127,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TYPED_EVENT(WarningBell, IInspectable, IInspectable);
// clang-format on
WINRT_PROPERTY(IControlAppearance, UnfocusedAppearance);
private:
friend struct TermControlT<TermControl>; // friend our parent so it can bind private event handlers
@ -148,6 +146,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::com_ptr<SearchBoxControl> _searchBox;
IControlSettings _settings;
bool _closing{ false };
bool _focused{ false };
bool _initializedTerminal{ false };
@ -194,16 +193,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _closing;
}
void _UpdateSettingsFromUIThread();
void _UpdateAppearanceFromUIThread(Control::IControlAppearance newAppearance);
void _ApplyUISettings();
winrt::fire_and_forget UpdateAppearance(Control::IControlAppearance newAppearance);
void _UpdateSettingsFromUIThread(IControlSettings newSettings);
void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance);
void _ApplyUISettings(const IControlSettings&);
void _SetBackgroundImage(const IControlAppearance& newAppearance);
void _InitializeBackgroundBrush();
winrt::fire_and_forget _coreBackgroundColorChanged(const IInspectable& sender, const IInspectable& args);
void _changeBackgroundColor(const til::color bg);
void _changeBackgroundOpacity();
void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args);
winrt::fire_and_forget _changeBackgroundColor(const til::color bg);
bool _InitializeTerminal();
void _SetFontSize(int fontSize);
@ -248,9 +245,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown);
::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
static ::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() noexcept;
bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const;
void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept;
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition);

View file

@ -17,15 +17,14 @@ namespace Microsoft.Terminal.Control
ICoreState
{
TermControl(IControlSettings settings,
IControlAppearance unfocusedAppearance,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
static Windows.Foundation.Size GetProposedDimensions(IControlSettings settings, UInt32 dpi);
void UpdateControlSettings(IControlSettings settings);
void UpdateControlSettings(IControlSettings settings, IControlAppearance unfocusedAppearance);
void UpdateSettings();
Microsoft.Terminal.Control.IControlSettings Settings { get; };
Microsoft.Terminal.Control.IControlSettings Settings;
Microsoft.Terminal.Control.IControlAppearance UnfocusedAppearance;
event FontSizeChangedEventArgs FontSizeChanged;
event Windows.Foundation.TypedEventHandler<Object, TitleChangedEventArgs> TitleChanged;
@ -72,7 +71,5 @@ namespace Microsoft.Terminal.Control
void ToggleReadOnly();
String ReadEntireBuffer();
Windows.UI.Xaml.Media.Brush BackgroundBrush { get; };
}
}

View file

@ -50,37 +50,6 @@ namespace Microsoft.Terminal.Core
UInt32 Value;
};
struct Scheme
{
Microsoft.Terminal.Core.Color Foreground;
Microsoft.Terminal.Core.Color Background;
Microsoft.Terminal.Core.Color SelectionBackground;
Microsoft.Terminal.Core.Color CursorColor;
// Table: A WinRT struct doesn't allow pointers (READ: doesn't allow
// array members) in structs, but we very much would like this object to
// be a struct. So we'll call out each color individually. There's only
// 16, it's not that bad.
Microsoft.Terminal.Core.Color Black;
Microsoft.Terminal.Core.Color Red;
Microsoft.Terminal.Core.Color Green;
Microsoft.Terminal.Core.Color Yellow;
Microsoft.Terminal.Core.Color Blue;
Microsoft.Terminal.Core.Color Purple;
Microsoft.Terminal.Core.Color Cyan;
Microsoft.Terminal.Core.Color White;
Microsoft.Terminal.Core.Color BrightBlack;
Microsoft.Terminal.Core.Color BrightRed;
Microsoft.Terminal.Core.Color BrightGreen;
Microsoft.Terminal.Core.Color BrightYellow;
Microsoft.Terminal.Core.Color BrightBlue;
Microsoft.Terminal.Core.Color BrightPurple;
Microsoft.Terminal.Core.Color BrightCyan;
Microsoft.Terminal.Core.Color BrightWhite;
};
declare
{
// Forward declare this parameterized specialization so that it lives

View file

@ -40,13 +40,10 @@ namespace Microsoft::Terminal::Core
virtual bool WarningBell() noexcept = 0;
virtual bool SetWindowTitle(std::wstring_view title) noexcept = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept = 0;
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept = 0;
virtual bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept = 0;
virtual bool SetCursorColor(const DWORD color) noexcept = 0;
virtual bool SetDefaultForeground(const DWORD color) noexcept = 0;
virtual bool SetDefaultBackground(const DWORD color) noexcept = 0;
virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;

View file

@ -41,8 +41,6 @@ Terminal::Terminal() :
_mutableViewport{ Viewport::Empty() },
_title{},
_colorTable{},
_defaultFg{ RGB(255, 255, 255) },
_defaultBg{ ARGB(0, 0, 0, 0) },
_screenReversed{ false },
_pfnWriteInput{ nullptr },
_scrollOffset{ 0 },
@ -81,6 +79,10 @@ Terminal::Terminal() :
_terminalInput = std::make_unique<TerminalInput>(passAlongInput);
_InitializeColorTable();
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = RGB(255, 255, 255);
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = ARGB(0, 0, 0, 0);
_colorTable.at(TextColor::CURSOR_COLOR) = INVALID_COLOR;
}
void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, IRenderTarget& renderTarget)
@ -178,14 +180,17 @@ void Terminal::UpdateSettings(ICoreSettings settings)
// - appearance: an ICoreAppearance with new settings values for us to use.
void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
{
_intenseIsBright = appearance.IntenseIsBright();
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
// Set the default background as transparent to prevent the
// DX layer from overwriting the background image or acrylic effect
til::color newBackgroundColor{ appearance.DefaultBackground() };
_defaultBg = newBackgroundColor.with_alpha(0);
_defaultFg = appearance.DefaultForeground();
const til::color newBackgroundColor{ appearance.DefaultBackground() };
_colorTable.at(TextColor::DEFAULT_BACKGROUND) = newBackgroundColor.with_alpha(0);
const til::color newForegroundColor{ appearance.DefaultForeground() };
_colorTable.at(TextColor::DEFAULT_FOREGROUND) = newForegroundColor;
const til::color newCursorColor{ appearance.CursorColor() };
_colorTable.at(TextColor::CURSOR_COLOR) = newCursorColor;
_intenseIsBright = appearance.IntenseIsBright();
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
for (int i = 0; i < 16; i++)
{
@ -222,9 +227,7 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
if (_buffer)
{
_buffer->GetCursor().SetStyle(appearance.CursorHeight(),
til::color{ appearance.CursorColor() },
cursorShape);
_buffer->GetCursor().SetStyle(appearance.CursorHeight(), cursorShape);
}
_defaultCursorShape = cursorShape;
@ -1299,67 +1302,3 @@ const size_t Microsoft::Terminal::Core::Terminal::GetTaskbarProgress() const noe
{
return _taskbarProgress;
}
Scheme Terminal::GetColorScheme() const noexcept
{
Scheme s;
s.Foreground = til::color{ _defaultFg };
// Don't leak the implementation detail that our _defaultBg is stored
// internally without alpha.
s.Background = til::color{ _defaultBg.with_alpha(0xff) };
// SelectionBackground is stored in the ControlAppearance
s.CursorColor = til::color{ _buffer->GetCursor().GetColor() };
s.Black = til::color{ _colorTable[0] };
s.Red = til::color{ _colorTable[1] };
s.Green = til::color{ _colorTable[2] };
s.Yellow = til::color{ _colorTable[3] };
s.Blue = til::color{ _colorTable[4] };
s.Purple = til::color{ _colorTable[5] };
s.Cyan = til::color{ _colorTable[6] };
s.White = til::color{ _colorTable[7] };
s.BrightBlack = til::color{ _colorTable[8] };
s.BrightRed = til::color{ _colorTable[9] };
s.BrightGreen = til::color{ _colorTable[10] };
s.BrightYellow = til::color{ _colorTable[11] };
s.BrightBlue = til::color{ _colorTable[12] };
s.BrightPurple = til::color{ _colorTable[13] };
s.BrightCyan = til::color{ _colorTable[14] };
s.BrightWhite = til::color{ _colorTable[15] };
return s;
}
void Terminal::ApplyScheme(const Scheme& colorScheme)
{
_defaultFg = colorScheme.Foreground;
// Set the default background as transparent to prevent the
// DX layer from overwriting the background image or acrylic effect
til::color newBackgroundColor{ colorScheme.Background };
_defaultBg = newBackgroundColor.with_alpha(0);
_colorTable[0] = til::color{ colorScheme.Black };
_colorTable[1] = til::color{ colorScheme.Red };
_colorTable[2] = til::color{ colorScheme.Green };
_colorTable[3] = til::color{ colorScheme.Yellow };
_colorTable[4] = til::color{ colorScheme.Blue };
_colorTable[5] = til::color{ colorScheme.Purple };
_colorTable[6] = til::color{ colorScheme.Cyan };
_colorTable[7] = til::color{ colorScheme.White };
_colorTable[8] = til::color{ colorScheme.BrightBlack };
_colorTable[9] = til::color{ colorScheme.BrightRed };
_colorTable[10] = til::color{ colorScheme.BrightGreen };
_colorTable[11] = til::color{ colorScheme.BrightYellow };
_colorTable[12] = til::color{ colorScheme.BrightBlue };
_colorTable[13] = til::color{ colorScheme.BrightPurple };
_colorTable[14] = til::color{ colorScheme.BrightCyan };
_colorTable[15] = til::color{ colorScheme.BrightWhite };
_buffer->GetCursor().SetColor(til::color{ colorScheme.CursorColor });
if (_adjustIndistinguishableColors)
{
_MakeAdjustedColorArray();
}
}

View file

@ -30,7 +30,6 @@ namespace winrt::Microsoft::Terminal::Core
{
struct ICoreSettings;
struct ICoreAppearance;
struct Scheme;
}
namespace Microsoft::Terminal::Core
@ -107,11 +106,9 @@ public:
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
bool WarningBell() noexcept override;
bool SetWindowTitle(std::wstring_view title) noexcept override;
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
bool SetCursorColor(const COLORREF color) noexcept override;
bool SetDefaultForeground(const COLORREF color) noexcept override;
bool SetDefaultBackground(const COLORREF color) noexcept override;
bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
@ -213,10 +210,6 @@ public:
void ClearPatternTree() noexcept;
const std::optional<til::color> GetTabColor() const noexcept;
til::color GetDefaultBackground() const noexcept;
winrt::Microsoft::Terminal::Core::Scheme GetColorScheme() const noexcept;
void ApplyScheme(const winrt::Microsoft::Terminal::Core::Scheme& scheme);
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
@ -285,9 +278,7 @@ private:
std::optional<til::color> _startingTabColor;
// This is still stored as a COLORREF because it interacts with some code in ConTypes
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
til::color _defaultFg;
til::color _defaultBg;
std::array<COLORREF, TextColor::TABLE_SIZE> _colorTable;
CursorType _defaultCursorShape;
bool _screenReversed;
mutable Microsoft::Console::Render::BlinkingState _blinkingState;

View file

@ -69,14 +69,6 @@ COORD Terminal::GetCursorPosition() noexcept
return newPos;
}
bool Terminal::SetCursorColor(const COLORREF color) noexcept
try
{
_buffer->GetCursor().SetColor(color);
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Moves the cursor down one line, and possibly also to the leftmost column.
// Arguments:
@ -370,6 +362,22 @@ try
}
CATCH_RETURN_FALSE()
// Method Description:
// - Retrieves the value in the colortable at the specified index.
// Arguments:
// - tableIndex: the index of the color table to retrieve.
// Return Value:
// - the COLORREF value for the color at that index in the table.
COLORREF Terminal::GetColorTableEntry(const size_t tableIndex) const noexcept
try
{
return _colorTable.at(tableIndex);
}
catch (...)
{
return INVALID_COLOR;
}
// Method Description:
// - Updates the value in the colortable at index tableIndex to the new color
// color. color is a COLORREF, format 0x00BBGGRR.
@ -383,6 +391,11 @@ try
{
_colorTable.at(tableIndex) = color;
if (tableIndex == TextColor::DEFAULT_BACKGROUND)
{
_pfnBackgroundColorChanged(color);
}
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
@ -442,46 +455,6 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
return true;
}
// Method Description:
// - Updates the default foreground color from a COLORREF, format 0x00BBGGRR.
// Arguments:
// - color: the new COLORREF to use as the default foreground color
// Return Value:
// - true
bool Terminal::SetDefaultForeground(const COLORREF color) noexcept
try
{
_defaultFg = color;
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Updates the default background color from a COLORREF, format 0x00BBGGRR.
// Arguments:
// - color: the new COLORREF to use as the default background color
// Return Value:
// - true
bool Terminal::SetDefaultBackground(const COLORREF color) noexcept
try
{
_defaultBg = color;
_pfnBackgroundColorChanged(color);
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
}
CATCH_RETURN_FALSE()
til::color Terminal::GetDefaultBackground() const noexcept
{
return _defaultBg;
}
bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
try
{

View file

@ -227,7 +227,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
try
{
return _terminalApi.SetCursorColor(color);
return _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color);
}
CATCH_LOG_RETURN_FALSE()
@ -247,7 +247,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
try
{
return _terminalApi.SetDefaultForeground(color);
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color);
}
CATCH_LOG_RETURN_FALSE()
@ -260,7 +260,7 @@ CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
try
{
return _terminalApi.SetDefaultBackground(color);
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color);
}
CATCH_LOG_RETURN_FALSE()

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, _defaultFg);
colors.second = fgTextColor.GetColor(_colorTable, TextColor::DEFAULT_FOREGROUND);
}
else
{
colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
colors.second = bgTextColor.GetColor(_colorTable, _defaultBg);
colors.second = bgTextColor.GetColor(_colorTable, TextColor::DEFAULT_BACKGROUND);
}
}
else
{
colors = attr.CalculateRgbColors(_colorTable,
_defaultFg,
_defaultBg,
TextColor::DEFAULT_FOREGROUND,
TextColor::DEFAULT_BACKGROUND,
_screenReversed,
_blinkingState.IsBlinkingFaint(),
_intenseIsBright);
@ -135,7 +135,7 @@ CursorType Terminal::GetCursorStyle() const noexcept
COLORREF Terminal::GetCursorColor() const noexcept
{
return _buffer->GetCursor().GetColor();
return _colorTable.at(TextColor::CURSOR_COLOR);
}
bool Terminal::IsCursorDoubleWidth() const
@ -312,8 +312,8 @@ void Terminal::_MakeAdjustedColorArray()
// to include the default background and default foreground colors
std::array<COLORREF, 18> colorTableWithDefaults;
std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults));
colorTableWithDefaults[DefaultBgIndex] = _defaultBg;
colorTableWithDefaults[DefaultFgIndex] = _defaultFg;
colorTableWithDefaults[DefaultBgIndex] = _colorTable.at(TextColor::DEFAULT_BACKGROUND);
colorTableWithDefaults[DefaultFgIndex] = _colorTable.at(TextColor::DEFAULT_FOREGROUND);
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
{
const auto fg = til::at(colorTableWithDefaults, fgIndex);

View file

@ -398,7 +398,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
Profiles::Profiles() :
_previewControl{ Control::TermControl(Model::TerminalSettings{}, nullptr, make<PreviewConnection>()) }
_previewControl{ Control::TermControl(Model::TerminalSettings{}, make<PreviewConnection>()) }
{
InitializeComponent();
@ -453,23 +453,26 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
_PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentScrollState" });
}
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
_previewControl.Settings(_State.Profile().TermSettings());
_previewControl.UpdateSettings();
});
// The Appearances object handles updating the values in the settings UI, but
// we still need to listen to the changes here just to update the preview control
_AppearanceViewModelChangedRevoker = _State.Profile().DefaultAppearance().PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& /*args*/) {
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
_previewControl.Settings(_State.Profile().TermSettings());
_previewControl.UpdateSettings();
});
// Navigate to the pivot in the provided navigation state
ProfilesPivot().SelectedIndex(static_cast<int>(_State.LastActivePivot()));
_previewControl.Settings(_State.Profile().TermSettings());
// There is a possibility that the control has not fully initialized yet,
// so wait for it to initialize before updating the settings (so we know
// that the renderer is set up)
_previewControl.Initialized([&](auto&& /*s*/, auto&& /*e*/) {
_previewControl.UpdateControlSettings(_State.Profile().TermSettings());
_previewControl.UpdateSettings();
});
}

View file

@ -147,30 +147,3 @@ void ColorScheme::SetColorTableEntry(uint8_t index, const Core::Color& value) no
THROW_HR_IF(E_INVALIDARG, index >= _table.size());
_table[index] = value;
}
winrt::Microsoft::Terminal::Core::Scheme ColorScheme::ToCoreScheme() const noexcept
{
winrt::Microsoft::Terminal::Core::Scheme coreScheme{};
coreScheme.Foreground = Foreground();
coreScheme.Background = Background();
coreScheme.CursorColor = CursorColor();
coreScheme.SelectionBackground = SelectionBackground();
coreScheme.Black = Table()[0];
coreScheme.Red = Table()[1];
coreScheme.Green = Table()[2];
coreScheme.Yellow = Table()[3];
coreScheme.Blue = Table()[4];
coreScheme.Purple = Table()[5];
coreScheme.Cyan = Table()[6];
coreScheme.White = Table()[7];
coreScheme.BrightBlack = Table()[8];
coreScheme.BrightRed = Table()[9];
coreScheme.BrightGreen = Table()[10];
coreScheme.BrightYellow = Table()[11];
coreScheme.BrightBlue = Table()[12];
coreScheme.BrightPurple = Table()[13];
coreScheme.BrightCyan = Table()[14];
coreScheme.BrightWhite = Table()[15];
return coreScheme;
}

View file

@ -47,8 +47,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static com_ptr<ColorScheme> FromJson(const Json::Value& json);
Json::Value ToJson() const;
winrt::Microsoft::Terminal::Core::Scheme ToCoreScheme() const noexcept;
com_array<Core::Color> Table() const noexcept;
void SetColorTableEntry(uint8_t index, const Core::Color& value) noexcept;

View file

@ -19,7 +19,5 @@ namespace Microsoft.Terminal.Settings.Model
// we expose the getter as a function.
Microsoft.Terminal.Core.Color[] Table();
void SetColorTableEntry(UInt8 index, Microsoft.Terminal.Core.Color value);
Microsoft.Terminal.Core.Scheme ToCoreScheme();
}
}

View file

@ -197,9 +197,29 @@
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below -->
manually include the winmds as References below
BODGY: we do need to add a ProjectReference to TerminalControl.vcxproj,
with Private=true, ReferenceOutputAssembly=false, so that Visual Studio's
"Fast Up-to-date Check" will work with this project. If we don't, the Fast
Up-to-date Check will look for the .xaml files from that project in our
output, which won't actually be there.
We do still need to separately reference the winmds manually below, which is annoying.
-->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. -->
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<!-- Manually add references to each of our dependent winmds. Mark them as
@ -266,4 +286,5 @@
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
<Import Project="..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets" Condition="Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" />
</Project>

View file

@ -206,6 +206,59 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_Opacity = appearance.Opacity();
}
// Method Description:
// - Creates a TerminalSettingsCreateResult from a parent TerminalSettingsCreateResult
// - The returned defaultSettings inherits from the parent's defaultSettings, and the
// returned unfocusedSettings inherits from the returned defaultSettings
// - Note that the unfocused settings needs to be entirely unchanged _except_ we need to
// set its parent to the other settings object that we return. This is because the overrides
// made by the control will live in that other settings object, so we want to make
// sure the unfocused settings inherit from that.
// - Another way to think about this is that initially we have UnfocusedSettings inherit
// from DefaultSettings. This function simply adds another TerminalSettings object
// in the middle of these two, so UnfocusedSettings now inherits from the new object
// and the new object inherits from the DefaultSettings. And this new object is what
// the control can put overrides in.
// Arguments:
// - parent: the TerminalSettingsCreateResult that we create a new one from
// Return Value:
// - A TerminalSettingsCreateResult object that contains a defaultSettings that inherits
// from parent's defaultSettings, and contains an unfocusedSettings that inherits from
// its defaultSettings
Model::TerminalSettingsCreateResult TerminalSettings::CreateWithParent(const Model::TerminalSettingsCreateResult& parent)
{
THROW_HR_IF_NULL(E_INVALIDARG, parent);
auto defaultImpl{ get_self<TerminalSettings>(parent.DefaultSettings()) };
auto defaultChild = defaultImpl->CreateChild();
if (parent.UnfocusedSettings())
{
parent.UnfocusedSettings().SetParent(*defaultChild);
}
return winrt::make<TerminalSettingsCreateResult>(*defaultChild, parent.UnfocusedSettings());
}
// Method Description:
// - Sets our parent to the provided TerminalSettings
// Arguments:
// - parent: our new parent
void TerminalSettings::SetParent(const Model::TerminalSettings& parent)
{
ClearParents();
com_ptr<TerminalSettings> parentImpl;
parentImpl.copy_from(get_self<TerminalSettings>(parent));
InsertParent(parentImpl);
}
Model::TerminalSettings TerminalSettings::GetParent()
{
if (_parents.size() > 0)
{
return *_parents.at(0);
}
return nullptr;
}
// Method Description:
// - Apply Profile settings, as well as any colors from our color scheme, if we have one.
// Arguments:

View file

@ -64,6 +64,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
const Model::NewTerminalArgs& newTerminalArgs,
const Control::IKeyBindings& keybindings);
static Model::TerminalSettingsCreateResult CreateWithParent(const Model::TerminalSettingsCreateResult& parent);
Model::TerminalSettings GetParent();
void SetParent(const Model::TerminalSettings& parent);
void ApplyColorScheme(const Model::ColorScheme& scheme);
// --------------------------- Core Settings ---------------------------
@ -89,6 +95,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
INHERITABLE_SETTING(Model::TerminalSettings, hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
INHERITABLE_SETTING(Model::TerminalSettings, bool, CopyOnSelect, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, InputServiceWarning, true);
INHERITABLE_SETTING(Model::TerminalSettings, bool, FocusFollowMouse, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, TrimBlockSelection, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, DetectURLs, true);

View file

@ -28,16 +28,12 @@ namespace Microsoft.Terminal.Settings.Model
static TerminalSettingsCreateResult CreateWithProfile(CascadiaSettings appSettings, Profile profile, Microsoft.Terminal.Control.IKeyBindings keybindings);
static TerminalSettingsCreateResult CreateWithNewTerminalArgs(CascadiaSettings appSettings, NewTerminalArgs newTerminalArgs, Microsoft.Terminal.Control.IKeyBindings keybindings);
static TerminalSettingsCreateResult CreateWithParent(TerminalSettingsCreateResult parent);
void SetParent(TerminalSettings parent);
TerminalSettings GetParent();
void ApplyColorScheme(ColorScheme scheme);
ColorScheme AppliedColorScheme;
// The getters for these are already defined in IControlSettings. So
// we're just adding the setters here, because TerminalApp likes to be
// able to change these at runtime (e.g. when duplicating a pane).
String Commandline { set; };
String StartingDirectory { set; };
String EnvironmentVariables { set; };
};
}

View file

@ -65,7 +65,7 @@
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj">
<!-- Private:false and ReferenceOutputAssembly:false, in combination with
<!-- Private:true and ReferenceOutputAssembly:false, in combination with
the manual reference to TerminalControl.winmd below make sure that this
project will compile correct, and that we won't roll up the TermControl
xbf's into the packaging project twice. -->

View file

@ -67,7 +67,7 @@ namespace ControlUnitTests
{
Log::Comment(L"Create ControlCore object");
auto core = winrt::make_self<Control::implementation::ControlCore>(settings, settings, conn);
auto core = winrt::make_self<Control::implementation::ControlCore>(settings, conn);
core->_inUnitTests = true;
return core;
}
@ -128,14 +128,13 @@ namespace ControlUnitTests
double expectedOpacity = 0.5;
auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable {
VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->Opacity());
// The Settings object's opacity shouldn't be changed
VERIFY_ARE_EQUAL(0.5, settings->Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, settings->Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.Opacity());
if (expectedOpacity < 1.0)
{
VERIFY_IS_TRUE(settings->UseAcrylic());
VERIFY_IS_TRUE(core->_settings->UseAcrylic());
VERIFY_IS_TRUE(core->_settings.UseAcrylic());
}
// GH#603: Adjusting opacity shouldn't change whether or not we
@ -143,8 +142,8 @@ namespace ControlUnitTests
auto expectedUseAcrylic = winrt::Microsoft::Terminal::Control::implementation::ControlCore::IsVintageOpacityAvailable() ? true :
(expectedOpacity < 1.0 ? true : false);
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->UseAcrylic());
VERIFY_ARE_EQUAL(true, core->_settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->_settings.UseAcrylic());
};
core->TransparencyChanged(opacityCallback);

View file

@ -71,7 +71,7 @@ namespace ControlUnitTests
TerminalConnection::ITerminalConnection conn)
{
Log::Comment(L"Create ControlInteractivity object");
auto interactivity = winrt::make_self<Control::implementation::ControlInteractivity>(settings, settings, conn);
auto interactivity = winrt::make_self<Control::implementation::ControlInteractivity>(settings, conn);
VERIFY_IS_NOT_NULL(interactivity);
auto core = interactivity->_core;
core->_inUnitTests = true;
@ -116,14 +116,13 @@ namespace ControlUnitTests
double expectedOpacity = 0.5;
auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable {
VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->Opacity());
// The Settings object's opacity shouldn't be changed
VERIFY_ARE_EQUAL(0.5, settings->Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, settings->Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.Opacity());
auto expectedUseAcrylic = winrt::Microsoft::Terminal::Control::implementation::ControlCore::IsVintageOpacityAvailable() ? useAcrylic :
(expectedOpacity < 1.0 ? true : false);
VERIFY_ARE_EQUAL(useAcrylic, settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->_settings.UseAcrylic());
};
core->TransparencyChanged(opacityCallback);

View file

@ -35,6 +35,7 @@ namespace ControlUnitTests
WINRT_PROPERTY(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
WINRT_PROPERTY(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
WINRT_PROPERTY(bool, CopyOnSelect, false);
WINRT_PROPERTY(bool, InputServiceWarning, true);
WINRT_PROPERTY(bool, FocusFollowMouse, false);
WINRT_PROPERTY(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, TabColor, nullptr);

View file

@ -96,9 +96,10 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final
auto& g = ServiceLocator::LocateGlobals();
auto& gci = g.getConsoleInformation();
gci.SetDefaultForegroundColor(INVALID_COLOR);
gci.SetDefaultBackgroundColor(INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, INVALID_COLOR);
gci.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, INVALID_COLOR);
gci.SetFillAttribute(0x07); // DARK_WHITE on DARK_BLACK
gci.CalculateDefaultColorIndices();
m_state->PrepareNewTextBufferInfo(true, TerminalViewWidth, TerminalViewHeight);
auto& currentBuffer = gci.GetActiveOutputBuffer();

View file

@ -59,7 +59,6 @@ void TerminalApiTest::SetColorTableEntry()
VERIFY_IS_TRUE(term.SetColorTableEntry(128, 100));
VERIFY_IS_TRUE(term.SetColorTableEntry(255, 100));
VERIFY_IS_FALSE(term.SetColorTableEntry(256, 100));
VERIFY_IS_FALSE(term.SetColorTableEntry(512, 100));
}

View file

@ -87,203 +87,51 @@ void NonClientIslandWindow::MakeWindow() noexcept
THROW_HR_IF_NULL(E_UNEXPECTED, _dragBarWindow);
}
LRESULT NonClientIslandWindow::_dragBarNcHitTest(const til::point& pointer)
{
RECT rcParent = GetWindowRect();
// The size of the buttons doesn't change over the life of the application.
const auto buttonWidthInDips{ _titlebar.CaptionButtonWidth() };
// However, the DPI scaling might, so get the updated size of the buttons in pixels
const auto buttonWidthInPixels{ buttonWidthInDips * GetCurrentDpiScale() };
// make sure to account for the width of the window frame!
const til::rectangle nonClientFrame{ GetNonClientFrame(_currentDpi) };
const auto rightBorder{ rcParent.right - nonClientFrame.right<int>() };
// From the right to the left,
// * are we in the close button?
// * the maximize button?
// * the minimize button?
// If we're not, then we're in either the top resize border, or just
// generally in the titlebar.
if ((rightBorder - pointer.x()) < (buttonWidthInPixels))
{
return HTCLOSE;
}
else if ((rightBorder - pointer.x()) < (buttonWidthInPixels * 2))
{
return HTMAXBUTTON;
}
else if ((rightBorder - pointer.x()) < (buttonWidthInPixels * 3))
{
return HTMINBUTTON;
}
else
{
// If we're not on a caption button, then check if we're on the top
// border. If we're not on the top border, then we're just generally in
// the caption area.
const auto resizeBorderHeight = _GetResizeHandleHeight();
const auto isOnResizeBorder = pointer.y() < rcParent.top + resizeBorderHeight;
return isOnResizeBorder ? HTTOP : HTCAPTION;
}
}
// Function Description:
// - The window procedure for the drag bar forwards clicks on its client area to
// its parent as non-client clicks.
// - BODGY: It also _manually_ handles the caption buttons. They exist in the
// titlebar, and work reasonably well with just XAML, if the drag bar isn't
// covering them.
// - However, to get snap layout support (GH#9443), we need to actually return
// HTMAXBUTTON where the maximize button is. If the drag bar doesn't cover the
// caption buttons, then the core input site (which takes up the entirety of
// the XAML island) will steal the WM_NCHITTEST before we get a chance to
// handle it.
// - So, the drag bar covers the caption buttons, and manually handles hovering
// and pressing them when needed. This gives the impression that they're
// getting input as they normally would, even if they're not _really_ getting
// input via XAML.
LRESULT NonClientIslandWindow::_InputSinkMessageHandler(UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept
// - The window procedure for the drag bar forwards clicks on its client area to its parent as non-client clicks.
LRESULT NonClientIslandWindow::_InputSinkMessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
{
std::optional<UINT> nonClientMessage{ std::nullopt };
// translate WM_ messages on the window to WM_NC* on the top level window
switch (message)
{
case WM_NCHITTEST:
{
// Try to determine what part of the window is being hovered here. This
// is absolutely critical to making sure Snap Layouts (GH#9443) works!
return _dragBarNcHitTest(til::point{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) });
case WM_LBUTTONDOWN:
nonClientMessage = WM_NCLBUTTONDOWN;
break;
case WM_LBUTTONDBLCLK:
nonClientMessage = WM_NCLBUTTONDBLCLK;
break;
case WM_LBUTTONUP:
nonClientMessage = WM_NCLBUTTONUP;
break;
case WM_RBUTTONDOWN:
nonClientMessage = WM_NCRBUTTONDOWN;
break;
case WM_RBUTTONDBLCLK:
nonClientMessage = WM_NCRBUTTONDBLCLK;
break;
case WM_RBUTTONUP:
nonClientMessage = WM_NCRBUTTONUP;
break;
}
break;
case WM_NCMOUSEMOVE:
// When we get this message, it's because the mouse moved when it was
// over somewhere we said was the non-client area.
//
// We'll use this to communicate state to the title bar control, so that
// it can update its visuals.
// - If we're over a button, hover it.
// - If we're over _anything else_, stop hovering the buttons.
switch (wparam)
if (nonClientMessage.has_value())
{
const POINT clientPt{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) };
POINT screenPt{ clientPt };
if (ClientToScreen(_dragBarWindow.get(), &screenPt))
{
case HTTOP:
case HTCAPTION:
{
_titlebar.ReleaseButtons();
// Pass caption-related nonclient messages to the parent window.
// Make sure to do this for the HTTOP, which is the top resize
// border, so we can resize the window on the top.
auto parentWindow{ GetHandle() };
return SendMessage(parentWindow, message, wparam, lparam);
}
case HTMINBUTTON:
case HTMAXBUTTON:
case HTCLOSE:
_titlebar.HoverButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
break;
default:
_titlebar.ReleaseButtons();
}
// If we haven't previously asked for mouse tracking, request mouse
// tracking. We need to do this so we can get the WM_NCMOUSELEAVE
// message when the mouse leave the titlebar. Otherwise, we won't always
// get that message (especially if the user moves the mouse _real
// fast_).
if (!_trackingMouse &&
(wparam == HTMINBUTTON || wparam == HTMAXBUTTON || wparam == HTCLOSE))
{
TRACKMOUSEEVENT ev{};
ev.cbSize = sizeof(TRACKMOUSEEVENT);
// TME_NONCLIENT is absolutely critical here. In my experimentation,
// we'd get WM_MOUSELEAVE messages after just a HOVER_DEFAULT
// timeout even though we're not requesting TME_HOVER, which kinda
// ruined the whole point of this.
ev.dwFlags = TME_LEAVE | TME_NONCLIENT;
ev.hwndTrack = _dragBarWindow.get();
ev.dwHoverTime = HOVER_DEFAULT; // we don't _really_ care about this.
LOG_IF_WIN32_BOOL_FALSE(TrackMouseEvent(&ev));
_trackingMouse = true;
}
break;
const LPARAM newLparam = MAKELPARAM(screenPt.x, screenPt.y);
// Hit test the parent window at the screen coordinates the user clicked in the drag input sink window,
// then pass that click through as an NC click in that location.
const LRESULT hitTest{ SendMessage(parentWindow, WM_NCHITTEST, 0, newLparam) };
SendMessage(parentWindow, nonClientMessage.value(), hitTest, newLparam);
case WM_NCMOUSELEAVE:
case WM_MOUSELEAVE:
// When the mouse leaves the drag rect, make sure to dismiss any hover.
_titlebar.ReleaseButtons();
_trackingMouse = false;
break;
// NB: *Shouldn't be forwarding these* when they're not over the caption
// because they can inadvertently take action using the system's default
// metrics instead of our own.
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONDBLCLK:
// Manual handling for mouse clicks in the drag bar. If it's in a
// caption button, then tell the titlebar to "press" the button, which
// should change its visual state.
//
// If it's not in a caption button, then just forward the message along
// to the root HWND. Make sure to do this for the HTTOP, which is the
// top resize border.
switch (wparam)
{
case HTTOP:
case HTCAPTION:
{
// Pass caption-related nonclient messages to the parent window.
auto parentWindow{ GetHandle() };
return SendMessage(parentWindow, message, wparam, lparam);
return 0;
}
// The buttons won't work as you'd expect; we need to handle those
// ourselves.
case HTMINBUTTON:
case HTMAXBUTTON:
case HTCLOSE:
_titlebar.PressButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
break;
}
return 0;
case WM_NCLBUTTONUP:
// Manual handling for mouse RELEASES in the drag bar. If it's in a
// caption button, then manually handle what we'd expect for that button.
//
// If it's not in a caption button, then just forward the message along
// to the root HWND.
switch (wparam)
{
case HTTOP:
case HTCAPTION:
{
// Pass caption-related nonclient messages to the parent window.
// The buttons won't work as you'd expect; we need to handle those ourselves.
auto parentWindow{ GetHandle() };
return SendMessage(parentWindow, message, wparam, lparam);
}
break;
// If we do find a button, then tell the titlebar to raise the same
// event that would be raised if it were "tapped"
case HTMINBUTTON:
case HTMAXBUTTON:
case HTCLOSE:
_titlebar.ReleaseButtons();
_titlebar.ClickButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
break;
}
return 0;
// Make sure to pass along right-clicks in this region to our parent window
// - we don't need to handle these.
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONDBLCLK:
case WM_NCRBUTTONUP:
auto parentWindow{ GetHandle() };
return SendMessage(parentWindow, message, wparam, lparam);
}
return DefWindowProc(_dragBarWindow.get(), message, wparam, lparam);
@ -431,17 +279,10 @@ RECT NonClientIslandWindow::_GetDragAreaRect() const noexcept
{
const auto scale = GetCurrentDpiScale();
const auto transform = _dragBar.TransformToVisual(_rootGrid);
// GH#9443: Previously, we'd only extend the drag bar from the left of
// the tabs to the right of the caption buttons. Now, we're extending it
// all the way to the right side of the window, covering the caption
// buttons. We'll manually handle input to those buttons, to make it
// seem like they're still getting XAML input. We do this so we can get
// snap layout support for the maximize button.
const auto logicalDragBarRect = winrt::Windows::Foundation::Rect{
0.0f,
0.0f,
static_cast<float>(_rootGrid.ActualWidth()),
static_cast<float>(_dragBar.ActualWidth()),
static_cast<float>(_dragBar.ActualHeight())
};
const auto clientDragBarRect = transform.TransformBounds(logicalDragBarRect);
@ -709,7 +550,6 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept
// we didn't change them.
LPARAM lParam = MAKELONG(ptMouse.x, ptMouse.y);
const auto originalRet = DefWindowProc(_window.get(), WM_NCHITTEST, 0, lParam);
if (originalRet != HTCLIENT)
{
// If we're the quake window, suppress resizing on any side except the

View file

@ -62,7 +62,6 @@ private:
winrt::Windows::UI::Xaml::ElementTheme _theme;
bool _isMaximized;
bool _trackingMouse{ false };
[[nodiscard]] static LRESULT __stdcall _StaticInputSinkWndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept;
[[nodiscard]] LRESULT _InputSinkMessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept;
@ -72,7 +71,6 @@ private:
int _GetResizeHandleHeight() const noexcept;
RECT _GetDragAreaRect() const noexcept;
int _GetTopBorderHeight() const noexcept;
LRESULT _dragBarNcHitTest(const til::point& pointer);
[[nodiscard]] LRESULT _OnNcCreate(WPARAM wParam, LPARAM lParam) noexcept override;
[[nodiscard]] LRESULT _OnNcCalcSize(const WPARAM wParam, const LPARAM lParam) noexcept;

View file

@ -115,6 +115,23 @@
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<!--
BODGY
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
executable we put in the package. But we DON'T produce a winmd. This makes the
FastUpToDate check fail every time, and leads to the whole wapproj build
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
Setting GenerateWindowsMetadata=false is enough to tell the build system that
we don't produce one, and get it off our backs.
-->
<ItemDefinitionGroup>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />

View file

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

View file

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

View file

@ -1,70 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
// --------------------------- Core Appearance ---------------------------
// All of these settings are defined in ICoreAppearance.
#define CORE_APPEARANCE_SETTINGS(X) \
X(til::color, DefaultForeground, DEFAULT_FOREGROUND) \
X(til::color, DefaultBackground, DEFAULT_BACKGROUND) \
X(til::color, CursorColor, DEFAULT_CURSOR_COLOR) \
X(winrt::Microsoft::Terminal::Core::CursorStyle, CursorShape, winrt::Microsoft::Terminal::Core::CursorStyle::Vintage) \
X(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT) \
X(bool, IntenseIsBright, true) \
X(bool, AdjustIndistinguishableColors, true)
// --------------------------- Control Appearance ---------------------------
// All of these settings are defined in IControlSettings.
#define CONTROL_APPEARANCE_SETTINGS(X) \
X(til::color, SelectionBackground, DEFAULT_FOREGROUND) \
X(double, Opacity, 1.0) \
X(winrt::hstring, BackgroundImage) \
X(double, BackgroundImageOpacity, 1.0) \
X(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill) \
X(winrt::Windows::UI::Xaml::HorizontalAlignment, BackgroundImageHorizontalAlignment, winrt::Windows::UI::Xaml::HorizontalAlignment::Center) \
X(winrt::Windows::UI::Xaml::VerticalAlignment, BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center) \
X(bool, IntenseIsBold) \
X(bool, RetroTerminalEffect, false) \
X(winrt::hstring, PixelShaderPath)
// --------------------------- Core Settings ---------------------------
// All of these settings are defined in ICoreSettings.
#define CORE_SETTINGS(X) \
X(int32_t, HistorySize, DEFAULT_HISTORY_SIZE) \
X(int32_t, InitialRows, 30) \
X(int32_t, InitialCols, 80) \
X(bool, SnapOnInput, true) \
X(bool, AltGrAliasing, true) \
X(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS) \
X(bool, CopyOnSelect, false) \
X(bool, FocusFollowMouse, false) \
X(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, TabColor, nullptr) \
X(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, StartingTabColor, nullptr) \
X(bool, TrimBlockSelection, false) \
X(bool, DetectURLs, true)
// --------------------------- Control Settings ---------------------------
// All of these settings are defined in IControlSettings.
#define CONTROL_SETTINGS(X) \
X(winrt::hstring, ProfileName) \
X(winrt::hstring, ProfileSource) \
X(bool, UseAcrylic, false) \
X(winrt::hstring, Padding, DEFAULT_PADDING) \
X(winrt::hstring, FontFace, L"Consolas") \
X(int32_t, FontSize, DEFAULT_FONT_SIZE) \
X(winrt::Windows::UI::Text::FontWeight, FontWeight) \
X(IFontFeatureMap, FontFeatures) \
X(IFontAxesMap, FontAxes) \
X(winrt::Microsoft::Terminal::Control::IKeyBindings, KeyBindings, nullptr) \
X(winrt::hstring, Commandline) \
X(winrt::hstring, StartingDirectory) \
X(winrt::hstring, StartingTitle) \
X(bool, SuppressApplicationTitle) \
X(winrt::hstring, EnvironmentVariables) \
X(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible) \
X(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
X(bool, ForceFullRepaintRendering, false) \
X(bool, SoftwareRendering, false) \
X(bool, ForceVTInput, false) \
X(bool, UseAtlasEngine, false)

View file

@ -29,7 +29,7 @@
<Description>TAEF Packaged Cwa FullTrust Application Host Process</Description>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.22000.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>

View file

@ -75,7 +75,7 @@
</ItemGroup>
<PropertyGroup Label="Globals">
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.22000.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion Condition="'$(WindowsTargetPlatformMinVersion)' == ''">10.0.18362.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>

View file

@ -219,36 +219,6 @@ InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
return pInputBuffer;
}
// Method Description:
// - Return the default foreground color of the console. If the settings are
// configured to have a default foreground color (separate from the color
// table), this will return that value. Otherwise it will return the value
// from the colortable corresponding to our default attributes.
// Arguments:
// - <none>
// Return Value:
// - the default foreground color of the console.
COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
{
const auto fg = GetDefaultForegroundColor();
return fg != INVALID_COLOR ? fg : GetLegacyColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS);
}
// Method Description:
// - Return the default background color of the console. If the settings are
// configured to have a default background color (separate from the color
// table), this will return that value. Otherwise it will return the value
// from the colortable corresponding to our default attributes.
// Arguments:
// - <none>
// Return Value:
// - the default background color of the console.
COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
{
const auto bg = GetDefaultBackgroundColor();
return bg != INVALID_COLOR ? bg : GetLegacyColorTableEntry((LOBYTE(GetFillAttribute()) & BG_ATTRS) >> 4);
}
// Method Description:
// - Get the colors of a particular text attribute, using our color table,
// and our configured default attributes.
@ -257,26 +227,12 @@ COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
// Return Value:
// - The color values of the attribute's foreground and background.
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr) const noexcept
{
return LookupAttributeColors(attr, GetDefaultForeground(), GetDefaultBackground());
}
// Method Description:
// - Get the colors of a particular text attribute, using our color table,
// and the given default color values.
// Arguments:
// - attr: the TextAttribute to retrieve the foreground and background color of.
// - defaultFg: the COLORREF to use for a default foreground color.
// - defaultBg: the COLORREF to use for a default background color.
// Return Value:
// - The color values of the attribute's foreground and background.
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr, const COLORREF defaultFg, const COLORREF defaultBg) const noexcept
{
_blinkingState.RecordBlinkingUsage(attr);
return attr.CalculateRgbColors(
GetColorTable(),
defaultFg,
defaultBg,
GetDefaultForegroundIndex(),
GetDefaultBackgroundIndex(),
IsScreenReversed(),
_blinkingState.IsBlinkingFaint());
}

View file

@ -143,7 +143,7 @@
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy $(SolutionDir)\dep\WinAppDriver\* $(OutDir)\</PostBuildEvent>
<PostBuildEvent>copy &quot;$(SolutionDir)\dep\WinAppDriver\*&quot; &quot;$(OutDir)\&quot;</PostBuildEvent>
</PropertyGroup>
<Import Project="..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets" Condition="Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
@ -152,4 +152,4 @@
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Taef.10.60.210621002\build\Microsoft.Taef.targets'))" />
</Target>
</Project>
</Project>

View file

@ -1499,12 +1499,6 @@ void DoSrvSetCursorStyle(SCREEN_INFORMATION& screenInfo,
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetType(cursorType);
}
void DoSrvSetCursorColor(SCREEN_INFORMATION& screenInfo,
const COLORREF cursorColor)
{
screenInfo.GetActiveBuffer().GetTextBuffer().GetCursor().SetColor(cursorColor);
}
void DoSrvAddHyperlink(SCREEN_INFORMATION& screenInfo,
const std::wstring_view uri,
const std::wstring_view params)
@ -1963,115 +1957,6 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
screenInfo.GetActiveBuffer().MoveToBottom();
}
// Method Description:
// - Retrieve the color table value at the specified index.
// Arguments:
// - index: the index in the table to retrieve.
// - value: receives the RGB value for the color at that index in the table.
// Return Value:
// - E_INVALIDARG if index is >= 256, else S_OK
[[nodiscard]] HRESULT DoSrvPrivateGetColorTableEntry(const size_t index, COLORREF& value) noexcept
{
RETURN_HR_IF(E_INVALIDARG, index >= 256);
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
value = gci.GetColorTableEntry(index);
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the color table value in index to the color specified in value.
// Can be used to set the 256-color table as well as the 16-color table.
// Arguments:
// - index: the index in the table to change.
// - value: the new RGB value to use for that index in the color table.
// Return Value:
// - E_INVALIDARG if index is >= 256, else S_OK
// Notes:
// Does not take a buffer parameter. The color table for a console and for
// terminals as well is global, not per-screen-buffer.
[[nodiscard]] HRESULT DoSrvPrivateSetColorTableEntry(const size_t index, const COLORREF value) noexcept
{
RETURN_HR_IF(E_INVALIDARG, index >= 256);
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetColorTableEntry(index, value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the default foreground color to the color specified in value.
// Arguments:
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// - S_OK
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept
{
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetDefaultForegroundColor(value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Method Description:
// - Sets the default background color to the color specified in value.
// Arguments:
// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR.
// Return Value:
// - S_OK
[[nodiscard]] HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept
{
try
{
Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
gci.SetDefaultBackgroundColor(value);
// Update the screen colors if we're not a pty
// No need to force a redraw in pty mode.
if (g.pRender && !gci.IsInVtIoMode())
{
g.pRender->TriggerRedrawAll();
}
return S_OK;
}
CATCH_RETURN();
}
// Routine Description:
// - A private API call for filling a region of the screen buffer.
// Arguments:

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