Compare commits

..

64 Commits

Author SHA1 Message Date
Dustin L. Howett
4562dd5ffa Migrate spelling-0.0.21 changes from main 2022-02-04 01:51:47 +01:00
Leonard Hecker
49ab008b35 wip 2022-02-04 01:51:47 +01:00
Dustin L. Howett
25e67fee59 appx: Use a different resource for the Properties DisplayName (#12337)
We have to do this so that the store sees us as one thing ("Windows
Terminal") and the Start menu sees us as another ("Terminal").

The store will reject our package if the value we use for "DisplayName"
here doesn't match the store's "reserved names".

This value is *not used* by the start menu.

(cherry picked from commit e064c15675)
2022-02-02 21:00:03 -06:00
Carlos Zamora
c4826198dc Update accessible names for 'add profile' page buttons (#12324)
## Summary of the Pull Request
When using a screen reader, the buttons on the "add a new profile" page were being read weirdly:
- "New empty profile" button read as "create new button button"
- "duplicate" button read as "duplicate button button"

It's generally standard to read out the text inside the button, so I did just that by reusing the existing localized resources. This also removes the redundant "button" that is said by the screen reader.

I also removed the unused `AutomationId` and unnecessary `Button.Content` tags.

#11156 can be closed upon validation by the accessibility team.

## Validation Steps Performed
 navigate to both buttons using Narrator; make sure it sounds right

(cherry picked from commit 24c5f7bba4)
2022-02-02 15:45:13 -06:00
Mike Griese
4b9dc5ba84 Research how often folks disable the KB warning (#12322)
(cherry picked from commit bf32f45616)
2022-02-02 13:00:30 -06:00
Dustin L. Howett
093ab06272 Make sure Terminal Stable shows up as default on 22544+ (#12320)
Since we turned this feature on in windows, and it relies on _lying
about the contents of the registry_, Terminal needs to be in on the
joke.

This will need to be reverted and serviced if we choose not to ship like
this.

Fixes #12308

(cherry picked from commit 457738e388)
2022-02-02 13:00:30 -06:00
Dustin L. Howett
d3d68ac874 Set the default WSL starting directory to ~ (#12315)
The update that enables this on 20H1+, [KB5007253], went out in November
2021.

[KB5007253]: https://support.microsoft.com/en-us/topic/november-22-2021-kb5007253-os-builds-19041-1387-19042-1387-19043-1387-and-19044-1387-preview-d1847be9-46c1-49fc-bf56-1d469fc1b3af

(cherry picked from commit 70d8b2a2ef)
2022-02-02 13:00:30 -06:00
Dustin Howett
a84d988473 Remove a test that doesn't compile without /permissive- 2022-02-01 09:57:10 -06:00
Mike Griese
9ec2667ae3 This actually fixes the FI. I obviously forgot to build the tests.
(cherry picked from commit a2e93284ee)
2022-01-31 19:41:37 -06:00
Mike Griese
89f9a55258 Uh oh someone broke main on an FI
Fixes FI bugs introduced in 33c2cd458a

(cherry picked from commit d4ebcc27eb)
2022-01-31 19:39:20 -06:00
Michael Niksa
7438669930 Add PGOBuildMode to PGD merge step (#12306)
I added a condition to exclude some of the NuGet PGO stuff when there was no build mode, but appear to not have propagated any of it in the PGD merge job. This sets it to Optimize here so it'll go through.

## PR Checklist
* [x] Closes #12300
* [x] I work here.
* [x] It blends.

## Validation Steps Performed
* [x] Ran the PGO Instrument Phase
* [x] Ran the PGO Optimize Phase

(cherry picked from commit 469202f462)
2022-01-31 19:14:02 -06:00
Mike Griese
e103a7364b Make the SearchBox announce if it found results or not (#12301)
Basically, this is the same as #12266, but for the `SearchBoxControl`. Trickily, the ControlCore is the one that knows if there were search results, but the TermControl has to be the one to announce it.

* [x] Will take care of #11973 once a11y team confirms
* [x] Tested manually with Narrator
* [x] Resolves a part of #6319, which I'm repurposing just to displaying the number of results in general.
* See also #3920

(cherry picked from commit fbe0416305)
2022-01-31 18:52:01 -06:00
Mike Griese
5664cf84e5 Add a11y names to more controls (#12299)
This adds names to more of our focusable elements. This should be the rest of them that I missed in #11364

* #9990: a11y megathread
* #11155: original version of this

* [x] Should take care of #11996 once confirmed
* [x] I work here

Used Accessibility Insights to verify.

There is one other weird bit. All the expanders that have content below the expander (not inline), show up as focusable, but don't have names. Even when I add names to them. I believe this is due to https://github.com/microsoft/microsoft-ui-xaml/issues/5820, which is fixed in https://github.com/microsoft/microsoft-ui-xaml/pull/6032, in https://github.com/microsoft/microsoft-ui-xaml/releases/tag/v2.8.0-prerelease.220118001. Unfortunately, we're on a 2.7 prerelease, so we don't have that fix yet. I may see how painful moving to that is, because we're gonna get another a11y ping as soon as 1.13 ships.

I pre-emptively added names to these guys in f7ba158dc, so that the new MUX should just fix this without any thinking on our part.

(cherry picked from commit cf4d47c54d)
2022-01-31 18:48:57 -06:00
Mike Griese
b53a902b55 Change where the NotificationIcon looks up our resources (#12282)
I didn't have the tray icon enabled before I suppose, so this never got hit? Anyhow, we need to change where we look for the AppName. Otherwise we crash on launch 😨

* [x] fixes `main`
* [x] I work here
* regressed in #12264
* [x] Tested by: actually running the Terminal with this, it launched

(cherry picked from commit 7150fd8f97)
2022-01-31 11:02:19 -06:00
Carlos Zamora
99dd8549f3 Fix SizeOfSet and PositionInSet for 'Open JSON File' nav item (#12286)
## Summary of the Pull Request
According to https://github.com/microsoft/microsoft-ui-xaml/issues/1971, `PaneFooter` does not set the `SizeOfSet` or `PositionInSet` properties. However, `FooterMenuItems` does and works for our scenario. So we just replaced `PaneFooter` with `FooterMenuItems`.

Will handle #11154 upon verification from the accessibility team.

## Validation Steps Performed
 Verified using Accessibility Insights
 "Open Json File" button can still be invoked and keyboard navigated to as expected

(cherry picked from commit 2861b41fd0)
2022-01-31 10:59:03 -06:00
Dustin L. Howett
0837b186cb Move to the 21H1 Helix pool (#12285)
The 19H1 pool is being decommissioned.

(cherry picked from commit eb7559733d)
2022-01-31 10:59:03 -06:00
Mike Griese
38b4a858c9 Rename "Windows Terminal" -> "Terminal" (#12264)
This should be most of the surfaces that we really care about for displaying "Windows Terminal". There's a pile of other references in code, but I couldn't find any other resources that mention it.

I left a lot of the references to Windows Terminal throughout. Seemed like it was fine to keep calling it that in most places, just these localized strings that are going to be displayed in the Shell that should be changed.

Rough compare:
![image](https://user-images.githubusercontent.com/18356694/151248506-edf9a6ab-d93f-438f-8755-cdf6ae643736.png)

The strings were also moved to the Context Menu resources file, because that's localized into more languages.

@DHowett we may want to spin a full build to make sure this works and I didn't miss anything

* [x] Closes #12091

(cherry picked from commit a66a1c0cf5)
2022-01-31 10:58:13 -06:00
Carlos Zamora
a03fde9cac [Command Palette] Announce if suggestions were found to screen readers (#12266)
## Summary of the Pull Request
Expands on #9582. If the command palette finds results, the screen reader says "Suggestions available".

Makes the scenario mentioned in #7907 work.

This is sufficient for various reasons:
1. According to the bug report, saying that suggestions are available is sufficient
> Screen reader should provide the results info on searching commands like 10 results found or suggestions available when there are any search results (Source: #7907)

2. This is common practice. Settings app and XAML Controls Gallery do this for their search box.

Also, the user should be able to know how many results were found by tabbing/selecting a result item. When this is done, the screen reader will use `SizeOfSet` and `PositionInSet` to announce how many results were found and which one we're currently on.

## Validation Steps Performed
Verified this behavior using Narrator.
Verified it matches the behavior of the Settings app and the XAML Controls Gallery.

(cherry picked from commit 1e47d7aca7)
2022-01-31 10:58:13 -06:00
Mike Griese
8baf3af5e1 Add a keyboard shortcut handler to the TabRowControl (#12260)
This makes the scenario mentioned in #8480 work. It's maybe not as holistic a solution as we'd like, but it definitely works.

Tested both with Narrator, and using the TabView scroll handles to get tab focus into the tab row manually

* [x] Closing the _active_ tab with <kbd>Ctrl+Shift+w</kbd> works (not the `TabViewItem` that has focus, but that's how Edgium works so that seems fine)
* [x] Opening a tab with <kbd>Ctrl+Shift+t</kbd> works
* [x] Opening the cmdpal with <kbd>Ctrl+Shift+p</kbd> works
* [x] Will take care of #8480 once we get the a11y team to validate
* [x] I work here

#### Notes:

None of

```xaml
PreviewKeyDown="_KeyDownHandler"
KeyDown="_KeyDownHandler"
KeyUp="_KeyDownHandler"
```

On the TerminalPage directly seem to fire when the focus is in the `TabViewItem` or the New Tab flyout. But they fire just fine when focus is in the `TermControl`. Interesting, because you'd think that the `TermControl` would have already handled the key...

(cherry picked from commit 6f69487829)
2022-01-31 10:58:13 -06:00
Carlos Zamora
adbf2fa7e2 Expose Defterm info to ComboBoxItem properly (#12259)
## Summary of the Pull Request
Makes `Model::DefaultTerminal` an `IStringable`, which presents it as a string, when possible. This enables text search for defterm's setting. This also enables screen readers to identify the combo box items by their text content (app name, author, and version) as opposed to being treated as an item containing more text. As a part of that, I cleaned up the UIA tree to treat the item's name as "\<name\>, \<author\>, \<version\>". This is consistent with how the Settings App presents installed apps in Apps > Installed apps.

#11251 will be resolved upon verification by the accessibility team.

## Validation Steps Performed
Verified using Narrator and Accessibility Insights.

(cherry picked from commit d89c241dac)
2022-01-31 10:58:13 -06:00
Michael Niksa
0655dfd354 Update PGO helpers to mitigate Y2K22 bug (#12262)
The PGO helpers NuGet had the Y2K22 bug. This receives and integrates the updated package in our project to restore NuGet functionality.

## PR Checklist
* [x] Closes #12261
* [x] I work here
* [x] If it builds it sits.

## Validation Steps Performed
* [x] Build new PGO instrument data with this pipeline update: https://dev.azure.com/microsoft/Dart/_build/results?buildId=44304850&view=results

(cherry picked from commit fe52368f9b)
2022-01-31 10:58:13 -06:00
Mike Griese
c4398bac5d Send an updated cursor position at the end of writing a run (#12210)
I can find the commit where this regressed tomorrow if needed. In #10685 we stopped emitting these notifications while we were deferring cursor drawing. We however forgot to send the notification at the end of the defer.

This likely has a small perf impact. We however do need these cursor position events for IMEs to be able to track the cursor position (and low key for #10821)

* [x] regressed in #10685
* [x] Closes #11170
* [x] I work here
* [x] Tests added

(cherry picked from commit 01fd7141ed)
2022-01-31 10:58:13 -06:00
James Holderness
0d1e4d3461 Make sure titles always sanitized before passing over conpty (#12211)
When title updates are forwarded from the host to the client terminal,
they're passed over conpty in an `OSC 0` sequence. If there are any
control characters embedded in that title text it's essential they be
filtered out, otherwise they are likely to be misinterpreted by the VT
parser on the other side. This PR fixes a case where that sanitization
step was missed for titles initialized at startup.

Originally the sanitization step was handled in `DoSrvSetConsoleTitleW`,
which catches title changes made via VT escape sequences, or through the
console API, but missed the title initialization at startup. I've now
moved that sanitization code into the `CONSOLE_INFORMATION::SetTitle`
method, which should cover all cases.

This sanitization is only meant to occur when in "pty mode", though,
which we were originally establishing with an `IsInVtIoMode` call.
However, `IsInVtIoMode` does not return the correct result when the
title is set at startup, since the VT I/O thread is not initialized at
that point. So I've instead had to change that to an `InConptyMode`
call, which determines the conpty state from the launch args.

## Validation Steps Performed

I've manually confirmed the test case described in issue #12206 is now
working correctly.

However, the change to using `InConptyMode` caused some of the unit
tests to fail, because there isn't a real conpty connection when
testing. Fortunately there are some `EnableConptyModeForTests` methods
used by the unit tests to fake the appearance of a conpty connection,
and I just needed to add some additional state in one of those methods
to trigger the correct `InConptyMode` response.

Closes #12206

(cherry picked from commit 3804f2672e)
2022-01-31 10:58:13 -06:00
Leon Liang
2c3bf1880d PR 6616045: Hand off to Windows Terminal Stable by default (!)
This commit also introduces a check that we are in an interactive
session before we perform handoff, so as to not break service accounts.

It also adds some tracing.

Merged PR 6882227: [Git2Git] Merged PR 6881763: Change to hardcoded system GUIDs to appease manifest validation

Manifest validation won't accept migration/initialization of HKCU-based registry keys anymore. The enforcement scripts says that they should be defined in code instead. So here it is: defined in code insteead.

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 67c720b628de4acefbc381891b7e7d29d387038e

Related work items: MSFT-37867666
2022-01-31 10:50:35 -06:00
Dustin L. Howett
42e5671a79 [build] Fix the release build after we removed WTU (#12188)
(cherry picked from commit 4e46c855e9)
2022-01-21 15:01:59 -06:00
Mike Griese
fffcb63877 Manually replace unqualified cmd, powershell paths for the default profiles (#12149)
In previous releases, we had the commandlines for the Command Prompt and PowerShell profiles unqualified, as `cmd.exe` and `powershell.exe`. This was bad - theoretically, that would have preferred the cmd that was in the CWD over the one in System32. Or, something could insert itself into the path, and you'd end up with a malicious `cmd.exe` before the real one.

In #11437, we made sure that the `userDefaults` are initiated with the fully qualified paths. However, that didn't fix the issue for folks who already had settings files.

In an effort to better prevent this kind of badness, if we see a profile _with a default profile guid_, AND the unqualified version of the path, then we'll stealth replace it with the fully qualified one.

* Related to #11437
* [x] fixes #12126
* [x] Tests added

(cherry picked from commit f1baa319fc)
2022-01-21 15:01:59 -06:00
Mike Griese
75745df774 Make sure to copy connectionType for the azure shell (#12147)
This was a simple oversight. No user profile ever has `connectionType` set, because why would they. So even for the Azure Shell, which needed this, the check would fail and we'd forget to duplicate the connectionType to the new profile.

* [x] I work here
* [x] Closes #12120
* [x] Tested manually

(cherry picked from commit eb83469874)
2022-01-21 15:01:59 -06:00
Mike Griese
d91b4ca899 Fix //wsl$ paths not working in MangleStartingDirectoryForWSL (#12102)
This PR does two things, which are best viewed as atomic commits:
* e64ae7d: Move the `MangleStartingDirectoryForWSL` to `types/utils`. It doesn't _really_ make sense in `types`, since it's only really being used in a single place in TerminalConnection. However, TerminalConnection doesn't have tests, and types does. So this commit move the function there, and adds tests from #9223 to the types tests.
* 42036c5: This actually fixes the bug in #11994. Unfortunately, `wsl --cd` will try to treat paths starting with `//wsl$` as a linux-relative path, when the user almost certainly wanted a windows-relative one. So we'll mangle that back into a path that looks like `\\wsl$\foo\bar`.
* [x] closes #11994
* [x] I work here
* [x] tests added 🎉

(cherry picked from commit b87b809fa0)
2022-01-21 15:01:55 -06:00
Michael Niksa
b512e7d5a4 Pass additional parameters when making PGO package (#12131)
(cherry picked from commit d0c4cf744c)
2022-01-21 15:00:46 -06:00
Mike Griese
6d86429522 Initialize cursorOn to match focus state (#12094)
I'm not 100% sure that this is the right solution, but it does seem to work well enough. This is unfortunately a classic heisenbug. It was already hard enough to repro originally, but attaching a debugger made it totally impossible to hit.

My theory is that it's possible for the GotFocus event to fire before the LayoutUpdated event does. If that were to occur, then we'd try to turn on the cursor timer before it exists, gracefully do nothing, then create the timer. In that case, we'd never get a subsequent message to start the blinking.

I tested that theory by just initializing the cursor blinker to our `_focused` state. In that case, if the control has already been focused at the time of the LayoutUpdated event, then we can init the cursor to the correct state. Testing that out, I couldn't once get this to repro, which makes me think this works. I've opened some 900 (<sup>hyperbole</sup>) tabs now, so I'm pretty confident I'd have seen it by now.

* Regressed in #10978
* [x] fixes #11411
* [x] I made sure I didn't regress #6586
* [x] I work here

(cherry picked from commit 55aea08d15)
2022-01-21 15:00:46 -06:00
Michael Niksa
d8170bcbb6 Remove deprecated Windows Terminal Universal project (#12119)
Remove deprecated Windows Terminal Universal project

* [x] Closes #12118
* [x] I work here

(cherry picked from commit 591b949b3c)
2022-01-21 15:00:44 -06:00
Dustin L. Howett
503e27e475 Move the context menu strings to a separate resw compartment (#12090)
This is so that they can be localized separately, and into more
languages.

References MSFT-33615189

(cherry picked from commit 63a3517871)
2022-01-21 15:00:24 -06:00
Davide Giacometti
b30137b94f Disable duplicate button without selected profile (#12096)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request

- Settings > Add a new profile
- Disable "Duplicate" button until a profile is selected

![Duplicate](https://user-images.githubusercontent.com/25966642/148303450-a084cd5f-7f1c-4de3-86bd-602b9336649e.gif)

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Should take care of #12056, once we can get a build to the a11y team (MAINTAINER EDIT: we unfortunately can't just say "closes #foo" for issues like this one, we need another team to validate the following build.)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

(cherry picked from commit a766798fb8)
2022-01-21 15:00:24 -06:00
Luan Vitor Simião Oliveira
c197ca5f5d fix ~ not work as startingDirectory for WSL (#12050)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
fix #11432
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #11432
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
compiled and verified that "\~"  ,  "/usr/bin"  ,  "~/.config" and "/" as stating directory didn't get relative path resolve
verified that '.' did

(cherry picked from commit c98ec15144)
2022-01-21 15:00:24 -06:00
Ian O'Neill
717d9b77c3 Ensure PowerShell Core profile commandline is quoted (#12086)
Ensures the PowerShell Core profile's commandline is quoted. This allows
the profile to work correctly if there are files in place on the machine
(e.g. one called `C:\Program`) that prevent `CreateProcess()` from
invoking the un-quoted commandline.

## Validation Steps Performed
Created a file called `C:\Program` and opened the PowerShell profile in
terminal.

Closes #11717

(cherry picked from commit 4930508b8c)
2022-01-21 15:00:24 -06:00
James Holderness
48cb5f0bfa Use the correct background color when copying to clipboard (#11991)
When copying content from the terminal to the clipboard (with
formatting), a default background color needs to be set to fill the
unused area of the pasted block. Prior to this PR, that color was not
correctly set, so the pasted content did not match what was seen on
screen.

Windows Terminal previously used the default background from the initial
color scheme, so it didn't take palette changes into account.
OpenConsole did use the active default color, but didn't take the
reverse screen mode into account, so could end up using the foreground
rather than the background color.

In both case I've changed the code to lookup the runtime colors in the
same way that renderer does, so they should now match what is seen on
screen.

I've manually confirmed that the background color is now correctly set
when copying from both Windows Terminal and OpenConsole.

Closes #11988

(cherry picked from commit b61b24ecd1)
2022-01-21 15:00:22 -06:00
PankajBhojwani
df2d9fc542 Revert delta E change for release 1.12 (#12163)
Co-authored-by: Pankaj Bhojwani <pabhojwa@microsoft.com>
2022-01-14 08:20:24 -08:00
Michael Niksa
789d22ef2b Enable Security and Compliance tasks in our Release pipeline (#11849)
Enables a series of tasks run against our release pipeline that validate the security and compliance status of our code in an automated fashion. These checks include:
- Component Governance - (we had this one, it was moved to here) - Inventories open-source components used in our build
- PREfast - C/C++ static analysis for common code errors and exploits
- Policheck - Searches source code, comments, and text for words that could be sensitive legally, culturally, or geopolitically
- Credscan - Looks for credentials left behind in the code/documents and build output files
- BinSkim - Searches for common vulnerabilities in binaries
- CheckCFlags - Validates that compile/link flags match the policies recommended by Windows engineering for inclusion into the OS product image
- CFGCheck/XFGCheck - Validates that the CFG and/or XFG settings were enabled at compile and link time to guard against control flow attacks.

We're also required to run the SBOM one, but that was done in a separate PR and we're still pending the detectors being updated.

- #11948 - Move from CFG to XFG once XFG task folks get back to me on it
- #11949 - Enable bug filing for SecComp tasks
- #11950 - Bulk process bugs filed by SecComp tasks
- #11947 - Validate SBOM when checkers come online

- [x] - Fixes #10735
- [x] - Fixes #908
- [x] - I work here
- [x] - If it fits, it sits.
2022-01-10 14:47:51 -08:00
Michael Niksa
db5ddccc17 Only look for PGO package if build mode targeted; add packages.config dependency to ease restoration (#11981)
Only look for PGO package if build mode targeted; add packages.config dependency to ease restoration

## PR Checklist
* [x] Closes #11978 
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Test of restore and build on fresh repo copy passed.
2022-01-10 14:47:06 -08:00
Michael Niksa
3f385f11a1 Move to PGO Nuget (#11819)
To unify with WinUI, we're going to share an engineering component of this particular NuGet package full of scripts and utilities to make PGOing things easier.

This basically removes all of the scripts that I ~blatantly stole~ copied from https://github.com/microsoft/microsoft-ui-xaml and moves to the NuGet package that the team generates instead. A bunch of build things had to be massaged to make it work in our pipeline.
2022-01-10 14:46:51 -08:00
Michael Niksa
a3b9cd2369 Enable SBOM generation for Windows Terminal (#11908)
Microsoft will be providing a Software Bill of Materials for our products. This onboards the Windows Terminal product to the common engineering system task that can scavenge for this information within our build project (already recorded for internal compliance reasons) and present it in a machine-readable interchange format.

See also: https://devblogs.microsoft.com/engineering-at-microsoft/generating-software-bills-of-materials-sboms-with-spdx-at-microsoft/

This does not yet include packaging and distributing the SBOM with our final packages. We are waiting for that tooling to come online for MSIX. Guidance is "Coming Soon™️."

## References
- https://github.com/microsoft/dropvalidator/issues/216 - `cgmanifest.json` are not being pulled in yet, but I've been told internally this will fix it. I will double-check when I hear back on this issue.

## PR Checklist
* [x] Closes #11810 
* [x] I work here
* [x] I ran it and I see the manifest generated.
2022-01-10 14:45:25 -08:00
Dustin Howett
5f7c66bc0c [STABLE ONLY] Combined revert of Environment Block Changes
Revert "Fix environment block creation (#7401)"

This reverts commit 7886f16714.

(cherry picked from commit e46ba65665)

Revert "Always create a new environment block before we spawn a process (#7243)"

This reverts commit 849243af99.

References #7418

(cherry picked from commit 4204d2535c)
(cherry picked from commit f8e8572c23)
(cherry picked from commit cb4c4f7b73)
(cherry picked from commit afb0cac3e3)
(cherry picked from commit b25dc74a1d)
2022-01-10 14:20:59 -08:00
Mike Griese
757399650d Fix the cmdpal moving the infobar down (#11670)
Just read the code, it's immediately obvious what I messed up

Closes #11645

@DHowett turns out I was wrong, I could get this one done before 5 😜

(cherry picked from commit 3667678df1)
2021-12-13 20:50:46 -06:00
Comzyh
1ce8424ab7 Parse UTF-16 surrogates pairs for calculating pattern's position (#11915)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request

Properly handle UTF-16 surrogates when calculating the position of matched pattern.

Fix #8709

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
b88ffb21b0/src/buffer/out/search.cpp (L335-L339)

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #8709
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
use `Utf16Parser::Parse` to handle code points from U+010000 to U+10FFFF in UTF-16.

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

![image](https://user-images.githubusercontent.com/1068203/145421736-c842c7d4-0136-42d0-ad72-f004f58d9e3b.png)

also the case by @mas90  https://github.com/microsoft/terminal/issues/8709#issuecomment-884915485:

![image](https://user-images.githubusercontent.com/1068203/145420264-3fe220b4-42c5-44ac-aa94-4e604b164ed3.png)

(cherry picked from commit a2d96d6b1f)
2021-12-13 16:56:00 -06:00
Leonard Hecker
e0c4277777 Fix length calculation of GetConsoleCommandHistoryLengthA (#11897)
This is a primitive bug fix for GetConsoleCommandHistoryLengthA.

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

(cherry picked from commit ca20bbde1e)
2021-12-13 16:56:00 -06:00
Schuyler Rosefield
3a51afc375 Make sure we dont access an invalid optional on close (#11857)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Clean up an invalid access that I introduced in #11440

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #11684
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

(cherry picked from commit 29e6235151)
2021-12-13 16:56:00 -06:00
Michael Niksa
a303c63b07 Tell PublishSymbols task about binaries as well as the PDB files (#11852)
We have been advised to give not only the PDB paths, but paths to the EXE and DLL files we produce, to the PublishSymbols build task. We are assured by our engineering systems teams that enlightening the task to all of this information helps it hook things up better somewhere between our build machine and the symbol server such that debugging is more robust, especially around thrown exception stacks.

## PR Checklist
* [x] Closes #11737 - main fix for feeding EXEs and DLLs into the symbol publisher
* [x] Closes #11860 - bonus fix because I noticed the PDB source linking wasn't working
* [x] I work here.
* [x] If it fits, it sits.

(cherry picked from commit 52235b0fb6)
2021-12-13 16:56:00 -06:00
Mike Griese
ccc74686a2 Add snap-layouts support to the Terminal (#11680)
Adds snap layout support to the Terminal's maximize button. This PR is
full of BODGY, so brace yourselves.

Big thanks to Chris Swan in #11134 for building the prototype.
I don't believe this solves #8795, because XAML islands can't get
nchittest messages

- 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, 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.
- We also need to manually display the button tooltips now, because XAML
  doesn't know when they've been hovered for long enough. Hence, the
  `_displayToolTip` `ThrottledFuncTrailing`

## Validation
Minimized, maximized, restored down, hovered the buttons slowly, moved
the mouse over them quickly, they feel the same as before. But now with
snap layouts appearing.

## TODO!
* [x] I'm working on getting the ToolTips on the caption buttons back. Alas, I needed a demo of this _today_, so I'll fix that tomorrow morning.
* [x] mild concern: I should probably test Win 10 to make sure there wasn't weird changes to the message loop in win11 that means this is broken on win10.
* [x] I think I used the wrong issue number for tons of my comments throughout this PR. Double check that. Should be #9443, not #9447.

Closes #9443
I thought this took care of #8587 ~as a bonus, because I was here, and the fix is _now_ trivial~, but looking at the latest commit that regressed.

Co-authored-by: Chris Swan <chswan@microsoft.com>
(cherry picked from commit f2ebb21bd1)
2021-12-13 16:56:00 -06:00
Mike Griese
0c022811e6 Don't crash if we fail to BeginBufferedPaint (#11674)
Fixes MSFT:34673647, at least I'm pretty sure. That's only ever hit a few
times externally, and internally it's hitting a lot on 1.9.1942 builds, which
doesn't really make any sense.

(cherry picked from commit a74c37bbcd)
2021-12-13 16:56:00 -06:00
Sergey
83b482a05f Fix missing window border when use "win+arrow down" in fullscreen mode in Terminal (#11653)
Window sends an event that requests exit from fullscreen then SC_RESTORE messages is sent and it is in fullscreen mode.
Closes #10607

## Validation Steps Performed
Border and tabbar now appear after exiting fullscreen via "win+arrow down".

(cherry picked from commit 7aae2e9100)
2021-12-13 16:55:26 -06:00
Mike Griese
217196e592 Make sure to format the error message with an UNSIGNED int (#11667)
Closes #11556
![image](https://user-images.githubusercontent.com/18356694/139715591-b18ef7c1-2967-42a5-9528-2522220aa177.png)

(cherry picked from commit 8826cc028b)
2021-12-13 16:55:26 -06:00
James Holderness
ab683c00cc Default all G-sets to ASCII unless ISO-2022 is requested (#11658)
## Summary of the Pull Request

There is a non-zero subset of applications that randomly output _Locking Shift_ escape sequences which will invoke a character set from G2 or G3 into the left half of the code table. If those G-sets are mapped to Latin1, that can result in the terminal producing output that appears to be broken. This PR now defaults all G-sets to ASCII, to prevent an unintentional _Locking Shift_ from having any effect.

## PR Checklist
* [x] Closes #10408
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #10408

## Detailed Description of the Pull Request / Additional comments

Most other modern terminals also default to ASCII in all G-sets, so this shouldn't break any modern applications. Legacy 8-bit applications may still expect the G2 and G3 sets mapped to Latin1, but they would also need to have the ISO-2022 encoding enabled, so we can keep them happy by setting G2 and G3 correctly when the ISO-2022 encoding is requested.

## Validation Steps Performed

I've manually confirmed that `echo -e "\en"` and `echo -e "\eo"` no longer have any visible effect on the output (at least without first invoking another character set into G2 or G3). I've also confirmed that they do still work as expected (i.e. selecting Latin1) after enabling the ISO-2022 encoding.

(cherry picked from commit 27e042b784)
2021-12-13 16:55:26 -06:00
PankajBhojwani
4ad3156f42 Check that the control exists before we try to focus it (#11635)
## Summary of the Pull Request
When we are on a settings UI tab, `_GetActiveControl` returns a `nullptr`, make sure not to try and focus it in that case

## PR Checklist
* [x] Closes #11633
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here

## Validation Steps Performed
No longer crashes

(cherry picked from commit a7ce93a357)
2021-12-13 16:55:26 -06:00
Mike Griese
bf27a79ace Fix the wt action in defterm windows (#11646)
This is a pretty obvious typo in retrospect. Never hit it before, because in all non-defterm windows, the `_startupActions` always has one action.

* [x] Closes #11463

(cherry picked from commit b90f3605a2)
2021-12-13 16:55:26 -06:00
Ian O'Neill
3a615149da Ensure the background image path is displayed in the settings UI (#11580)
## Summary of the Pull Request
Ensures that the background image path is displayed in the settings UI.

## References
One of the items on #11353

## PR Checklist
* [x] Closes #11541
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA

## Validation Steps Performed
Set the background image path and saw that it was displayed in the settings UI.

(cherry picked from commit 9662bc6910)
2021-12-13 16:55:26 -06:00
Dustin L. Howett
dadee5bdaf Update Cascadia Code to 2111.01 (#11937)
This update fixes the bracket ligatures in italic.

See microsoft/cascadia-code#595 for more details.

(cherry picked from commit 246e57f1b2)
2021-12-13 16:41:24 -06:00
Leonard Hecker
4c364e9342 Use nearby fonts for font fallback (#11764)
This commit is a minimal fix in order to pass the
`IDWriteFontCollection` we create out of .ttf files residing next to our
binaries to the `IDWriteFontFallback::MapCharacters` call. The
`IDWriteTextFormat` is used in order to carry the font collection over
into `CustomTextLayout`.

## Validation
* Put `JetBrainsMono-Regular.ttf` into the binary output directory
* Modify `HKCU:\Console\*\FaceName`  to `JetBrains Mono`
* Launch OpenConsole.exe
* OpenConsole uses JetBrains Mono ✔️

Closes #11032
Closes #11648

(cherry picked from commit 131f5d2b32)
2021-12-13 14:19:52 -06:00
Mike Griese
aaabce77c7 Fix the opacity slider (#11643)
I can't even write a description for this. Just read the code change, you'll see what I goofed.

Regressed in #11372

Closes #11555

(cherry picked from commit 1cedac6a33)
2021-12-13 14:19:52 -06:00
Leonard Hecker
c9cde49716 Fix loading of fragments that update multiple profiles (#11598)
The "updates" key is an alternative "guid" key for fragment profiles.
But SettingsLoader::_appendProfile stores and deduplicates profiles according
to their "guid" only. We need to modify the function to optionally store
profiles by their "updates" key as well, otherwise multiple fragment
profiles without "guid" might collide as they produce the same default GUID.

## PR Checklist
* [x] Closes #11597
* [x] I work here
* [ ] Tests added/passed
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

## Validation Steps Performed
* Unit tests pass ✔️
* Issue #11597 doesn't reproduce anymore ✔️

(cherry picked from commit fe26a6efc0)
2021-12-13 14:19:52 -06:00
Mike Griese
5198c8e2e4 Make sure the infobar is inserted before the tab content, not on top of (#11609)
Fixes #11606

This is weird, but the infobars would appear totally on top of the
TerminalPage when `showTabsInTitlebar:false`. This would result in the infobar
obscuring the tabs.

Now, the infobars are strictly inserted after the tabs, before the content. So
when they appear, they will reduce the amount of space usable for the control.
That is a little annoying, but preferable to the tabs totally not existing.

Relevant conversation notes from #10798:

> > If the info bar is not local to the tab, then its location between the tab
> > bar (when the title bar is hidden) and the terminal panes feels
> > misleading. Should it instead be above the tab bar or below the terminal
> > panes?
>
> You're... not wrong here. It's maybe not the best place for it, but _on top_
> of the tabs would look insane, and probably wouldn't even work easily, given
> the way we reparent the tab row into the titlebar.
>
> In the pane itself would make more sense, but that runs abreast of all sorts
> of things like #9024, #4998, which might make more sense.

I'm just gonna go with this now, because it's _better_ than before, while we
work out what's _best_.

![gh-11606-fix](https://user-images.githubusercontent.com/18356694/138729178-b96b7003-0dd2-4521-8fff-0fd2a5989f22.gif)

(cherry picked from commit a916a5d9de)
2021-12-13 14:19:52 -06:00
Leonard Hecker
2aa2458b22 Compile OpenConsoleProxy without CRT (#11610)
After this commit OpenConsoleProxy will be built without a CRT.
This cuts down its binary size and DLL dependency bloat.
We hope that this fixes a COM server activation bug if the
user doesn't have a CRT installed globally on their system.

Fixes #11529

(cherry picked from commit def1bdd693)
2021-12-13 14:19:52 -06:00
Leonard Hecker
aacfc2a424 Fix AltGr not working in the settings UI (#11808) (#11814)
Since the settings UI's input fields behave similarly to the terminal's input,
`TerminalPage::_KeyDownHandler` also needs to behave similarly to
`TermControl::_KeyHandler`. This commit copies all relevant code
over from the latter into the former, including the suppression
of AltGr keys for keychord/action handling.

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

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

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

View File

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

View File

@@ -276,43 +276,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## ConEmu
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
### License
```
BSD 3-Clause License
Copyright (c) 2009-2017, Maximus5 <ConEmu.Maximus5@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
# Microsoft Open Source
This product also incorporates source code from other Microsoft open source projects, all licensed under the MIT license.

View File

@@ -10,6 +10,8 @@
<clear />
</disabledPackageSources>
<config>
<!-- TODO: TEMPORARY UNTIL PGO-Helpers is updated to search both. We shouldn't need to keep the globals path here. -->
<add key="globalPackagesFolder" value=".\packages" />
<add key="repositorypath" value=".\packages" />
</config>
</configuration>

View File

@@ -268,8 +268,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererUia", "src\renderer
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinRTUtils", "src\cascadia\WinRTUtils\WinRTUtils.vcxproj", "{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminalUniversal", "src\cascadia\WindowsTerminalUniversal\WindowsTerminalUniversal.vcxproj", "{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winconpty.LIB", "src\winconpty\lib\winconptylib.vcxproj", "{58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winconpty.DLL", "src\winconpty\dll\winconptydll.vcxproj", "{A22EC5F6-7851-4B88-AC52-47249D437A52}"
@@ -400,8 +398,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererAtlas", "src\renderer\atlas\atlas.vcxproj", "{8222900C-8B6C-452A-91AC-BE95DB04B95F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|Any CPU = AuditMode|Any CPU
@@ -2354,50 +2350,6 @@ Global
{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Release|x64.Build.0 = Release|x64
{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Release|x86.ActiveCfg = Release|Win32
{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Release|x86.Build.0 = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|Any CPU.ActiveCfg = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|Any CPU.Build.0 = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|Any CPU.Deploy.0 = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|ARM64.ActiveCfg = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|ARM64.Build.0 = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|ARM64.Deploy.0 = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|DotNet_x64Test.ActiveCfg = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|DotNet_x86Test.ActiveCfg = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|x64.ActiveCfg = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|x86.ActiveCfg = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|x86.Build.0 = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.AuditMode|x86.Deploy.0 = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|Any CPU.ActiveCfg = Debug|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|ARM.ActiveCfg = Debug|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|ARM64.ActiveCfg = Debug|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x64.ActiveCfg = Debug|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x64.Build.0 = Debug|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x64.Deploy.0 = Debug|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x86.ActiveCfg = Debug|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x86.Build.0 = Debug|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x86.Deploy.0 = Debug|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|Any CPU.ActiveCfg = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|ARM.ActiveCfg = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|ARM64.ActiveCfg = Release|ARM64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|ARM64.Build.0 = Release|ARM64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|ARM64.Deploy.0 = Release|ARM64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|x64.ActiveCfg = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|x64.Build.0 = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|x64.Deploy.0 = Release|x64
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|x86.ActiveCfg = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|x86.Build.0 = Release|Win32
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|x86.Deploy.0 = Release|Win32
{58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
@@ -3341,46 +3293,6 @@ Global
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.ActiveCfg = AuditMode|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.Build.0 = AuditMode|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.Build.0 = AuditMode|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|Any CPU.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.ActiveCfg = Debug|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.Build.0 = Debug|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.ActiveCfg = Debug|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.Build.0 = Debug|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.Build.0 = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.Build.0 = Fuzzing|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|Any CPU.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.ActiveCfg = Release|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.Build.0 = Release|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.ActiveCfg = Release|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.Build.0 = Release|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3446,7 +3358,6 @@ Global
{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{48D21369-3D7B-4431-9967-24E81292CF63} = {05500DEF-2294-41E3-AF9A-24E580B82836}
{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE} = {59840756-302F-44DF-AA47-441A9D673202}
{B0AC39D6-7B40-49A9-8202-58549BAE1FB1} = {59840756-302F-44DF-AA47-441A9D673202}
{58A03BB2-DF5A-4B66-91A0-7EF3BA01269A} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{A22EC5F6-7851-4B88-AC52-47249D437A52} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
@@ -3480,7 +3391,6 @@ Global
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}

View File

@@ -214,7 +214,7 @@ resources useful and interesting:
* Windows Terminal Launch: [Build 2019
Session](https://www.youtube.com/watch?v=KMudkRcwjCw)
* Run As Radio: [Show 645 - Windows Terminal with Richard
Turner](https://www.runasradio.com/Shows/Show/645)
Turner](http://www.runasradio.com/Shows/Show/645)
* Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps
on the Windows
Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54)

View File

@@ -31,7 +31,7 @@ $totalTestsExecutedCount = 0
# We assume that we only have one testRun with a given name that we care about
# We only process the last testRun with a given name (based on completedDate)
# The name of a testRun is set to the Helix queue that it was run on (e.g. windows.10.amd64.client19h1.xaml)
# The name of a testRun is set to the Helix queue that it was run on (e.g. windows.10.amd64.client21h1.xaml)
# If we have multiple test runs on the same queue that we care about, we will need to re-visit this logic
foreach ($testRun in ($testRuns.value | Sort-Object -Property "completedDate" -Descending))
{

View File

@@ -0,0 +1,11 @@
<PoliCheckExclusions>
<!-- All strings must be UPPER CASE -->
<!--Each of these exclusions is a folder name -if \[name]\exists in the file path, it will be skipped -->
<Exclusion Type="FolderPathFull">winrt|.git|oss|packages</Exclusion>
<!--Each of these exclusions is a folder name -if any folder or file starts with "\[name]", it will be skipped -->
<!--<Exclusion Type="FolderPathStart">ABC|XYZ</Exclusion>-->
<!--Each of these file types will be completely skipped for the entire scan -->
<Exclusion Type="FileType">.PNG|.SVG|.BMP|.ICO</Exclusion>
<!--The specified file names will be skipped during the scan regardless which folder they are in -->
<!--<Exclusion Type="FileName">ABC.TXT|XYZ.CS</Exclusion>-->
</PoliCheckExclusions>

View File

@@ -2,4 +2,5 @@
<packages>
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
</packages>

4
build/pgo/PGO.DB.proj Normal file
View File

@@ -0,0 +1,4 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="Terminal.PGO.props" />
<Import Project="$(PkgMicrosoft_PGO_Helpers_Cpp)\build\Microsoft.PGO-Helpers.Cpp.targets" />
</Project>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Microsoft.Internal.Windows.Terminal.PGODatabase</id>
<version>0</version>
<title>Windows Terminal PGO Database</title>
<authors>Microsoft</authors>
<owners>Microsoft</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Windows Terminal PGO Database</description>
</metadata>
<files>
<!-- The target directories for pgd files need to remain as is. PGO optimization pass will rely on this exact directory layout. -->
<file src="x64\*.pgd" target="tools\x64"/>
</files>
</package>

View File

@@ -0,0 +1,51 @@
<Project>
<PropertyGroup>
<NuGetPackageDirectory>$(MSBuildThisFileDirectory)..\..\packages</NuGetPackageDirectory>
<PkgMicrosoft_PGO_Helpers_Cpp>$(NuGetPackageDirectory)\Microsoft.Internal.PGO-Helpers.Cpp.0.2.34</PkgMicrosoft_PGO_Helpers_Cpp>
</PropertyGroup>
<!-- Get version information -->
<Import Project="$(MSBuildThisFileDirectory)..\..\custom.props" />
<PropertyGroup>
<!-- Optional, defaults to main. Name of the branch which will be used for calculating branch point. -->
<PGOBranch>release-1.12</PGOBranch>
<!-- Mandatory. Name of the NuGet package which will contain PGO databases for consumption by build system. -->
<PGOPackageName>Microsoft.Internal.Windows.Terminal.PGODatabase</PGOPackageName>
<!-- Mandatory. Major version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<PGOPackageVersionMajor>$(VersionMajor)</PGOPackageVersionMajor>
<!-- Mandatory. Minor version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<PGOPackageVersionMinor>$(VersionMinor)</PGOPackageVersionMinor>
<!-- Mandatory, defaults to 0. Patch version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<PGOPackageVersionPatch>0</PGOPackageVersionPatch>
<!-- Optional, defaults to empty. Prerelease version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<PGOPackageVersionPrerelease></PGOPackageVersionPrerelease>
<!-- Mandatory. Path to nuget.config file for the project. Path is relative to where the props file will be. -->
<PGONuGetConfigPath>$(MSBuildThisFileDirectory)..\..\nuget.config</PGONuGetConfigPath>
<!-- Mandatory. Path to PGO database NuSpec, see section below. -->
<PGONuspecPath>$(MSBuildThisFileDirectory)Terminal.PGO.DB.nuspec</PGONuspecPath>
<!-- Optional, defaults to true. Should verification result in build failure or error? -->
<PGOVerifyFailureTreatedAsError>true</PGOVerifyFailureTreatedAsError>
<!-- Optional, defaults to $(IntDir)\Nuspec. Temporary path where PGD files are copied to. -->
<PGONuspecBasePath>$(PGDPathForAllArch)</PGONuspecBasePath>
<!-- Optional, defaults to true. Specifies whether to use default information for PGD files. -->
<PGOUseDefaultPGDFileInfo>true</PGOUseDefaultPGDFileInfo>
<!-- Copying the PGO runtime brings along a CRT. If we do that under normal circumstances, WAPPROJ will get its grubby hands on it and mess up all the CRT shenanigans we have to pull to make MSIX packages happy. So only pull it in for Instrument builds.-->
<PGOCopyRuntime>false</PGOCopyRuntime>
<PGOCopyRuntime Condition="'$(PGOBuildMode)' == 'Instrument'">true</PGOCopyRuntime>
</PropertyGroup>
<!-- Import PGO-Helpers -->
<Import Project="$(PkgMicrosoft_PGO_Helpers_Cpp)\build\Microsoft.PGO-Helpers.Cpp.props" />
</Project>

View File

@@ -2,9 +2,11 @@
trigger: none
pr: none
pool:
pool:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
demands:
- ImageOverride -equals WinDevVS16-latest
- ImageVersionOverride -equals 6.0.0
parameters:
- name: branding
@@ -18,6 +20,10 @@ parameters:
displayName: "Build Windows Terminal MSIX"
type: boolean
default: true
- name: runCompliance
displayName: "Run Compliance and Security Build"
type: boolean
default: true
- name: buildTerminalVPack
displayName: "Build Windows Terminal VPack"
type: boolean
@@ -34,7 +40,6 @@ parameters:
- Optimize
- Instrument
- None
- name: buildConfigurations
type: object
default:
@@ -65,6 +70,7 @@ jobs:
BuildConfiguration: ${{ config }}
BuildPlatform: ${{ platform }}
displayName: Build
timeoutInMinutes: 240
cancelTimeoutInMinutes: 1
steps:
- checkout: self
@@ -89,6 +95,17 @@ jobs:
displayName: Use NuGet 5.10
inputs:
versionSpec: 5.10
- task: NuGetAuthenticate@0
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for extraneous build actions
inputs:
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: build/packages.config
restoreDirectory: '$(Build.SourcesDirectory)\packages'
- task: NuGetCommand@2
displayName: NuGet custom
inputs:
@@ -96,6 +113,8 @@ jobs:
selectOrConfig: config
nugetConfigPath: NuGet.Config
arguments: restore OpenConsole.sln -SolutionDirectory $(Build.SourcesDirectory)
# Pull the Windows SDK for the developer tools like the debuggers so we can index sources later
- template: .\templates\install-winsdk-steps.yml
- task: UniversalPackages@0
displayName: Download terminal-internal Universal Package
inputs:
@@ -111,6 +130,8 @@ jobs:
resourceFilePath: >-
src\cascadia\TerminalApp\Resources\en-US\Resources.resw
src\cascadia\TerminalApp\Resources\en-US\ContextMenu.resw
src\cascadia\TerminalControl\Resources\en-US\Resources.resw
src\cascadia\TerminalConnection\Resources\en-US\Resources.resw
@@ -119,8 +140,6 @@ jobs:
src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw
src\cascadia\WindowsTerminalUniversal\Resources\en-US\Resources.resw
src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw
appendRelativeDir: true
localizationTarget: false
@@ -140,19 +159,14 @@ jobs:
filePath: .\build\scripts\Generate-ThirdPartyNotices.ps1
arguments: -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
pwsh: true
- ${{ if eq(parameters.pgoBuildMode, 'Optimize') }}:
- task: PowerShell@2
displayName: Restore PGO Database
inputs:
filePath: tools/PGODatabase/restore-pgodb.ps1
workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase
- ${{ if eq(parameters.buildTerminal, true) }}:
- task: VSBuild@1
displayName: Build solution **\OpenConsole.sln
condition: true
inputs:
solution: '**\OpenConsole.sln'
vsVersion: 16.0
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /t:Terminal\CascadiaPackage;Terminal\WindowsTerminalUniversal /p:WindowsTerminalReleaseBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /t:Terminal\CascadiaPackage /p:WindowsTerminalReleaseBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
clean: true
@@ -164,20 +178,6 @@ jobs:
inputs:
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
ArtifactName: binlog-$(BuildPlatform)
- ${{ if eq(parameters.pgoBuildMode, 'Optimize') }}:
- task: PowerShell@2
displayName: Validate binaries are optimized
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
inputs:
targetType: inline
script: >-
$Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll'
foreach ($BinFile in $Binaries) {
& "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/src/cascadia/CascadiaPackage/bin/$(BuildPlatform)/$(BuildConfiguration)/$BinFile"
}
- task: PowerShell@2
displayName: Check MSIX for common regressions
inputs:
@@ -203,8 +203,6 @@ jobs:
filePath: build\scripts\Index-Pdbs.ps1
arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
errorActionPreference: silentlyContinue
- task: ComponentGovernanceComponentDetection@0
displayName: Component Detection
- task: PowerShell@2
displayName: Run Unit Tests
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
@@ -234,6 +232,10 @@ jobs:
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
OverWrite: true
flattenFolders: true
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'Generate SBOM manifest'
inputs:
BuildDropPath: '$(System.ArtifactsDirectory)/appx'
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (appx)
inputs:
@@ -257,14 +259,21 @@ jobs:
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/wpf
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)
- task: PublishSymbols@2
displayName: Publish symbols path
continueOnError: True
inputs:
SearchPattern: '**/*.pdb'
SearchPattern: |
$(Build.SourcesDirectory)/bin/**/*.pdb
$(Build.SourcesDirectory)/bin/**/*.exe
$(Build.SourcesDirectory)/bin/**/*.dll
IndexSources: false
SymbolServerType: TeamServices
- ${{ if eq(parameters.runCompliance, true) }}:
- template: ./templates/build-console-compliance-job.yml
- ${{ if eq(parameters.buildTerminal, true) }}:
- job: BundleAndSign
displayName: Create and sign AppX/MSIX bundles
@@ -292,11 +301,6 @@ jobs:
inputs:
filePath: build\scripts\Create-AppxBundle.ps1
arguments: -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion 0.0.0.0 -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminal_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
- task: PowerShell@2
displayName: Create WindowsTerminalUniversal*.msixbundle
inputs:
filePath: build\scripts\Create-AppxBundle.ps1
arguments: -InputPath "$(System.ArtifactsDirectory)" -ProjectName WindowsTerminalUniversal -BundleVersion $(XES_APPXMANIFESTVERSION) -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminalUniversal_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
- task: EsrpCodeSigning@1
displayName: Submit *.msixbundle to ESRP for code signing
inputs:
@@ -402,7 +406,10 @@ jobs:
displayName: Publish symbols path
continueOnError: True
inputs:
SearchPattern: '**/*.pdb'
SearchPattern: |
$(Build.SourcesDirectory)/bin/**/*.pdb
$(Build.SourcesDirectory)/bin/**/*.exe
$(Build.SourcesDirectory)/bin/**/*.dll
IndexSources: false
SymbolServerType: TeamServices
SymbolsArtifactName: Symbols_WPF_$(BuildConfiguration)

View File

@@ -8,12 +8,14 @@ jobs:
variables:
BuildConfiguration: AuditMode
BuildPlatform: ${{ parameters.platform }}
pool:
pool:
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPoolOSS-L
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
demands:
- ImageOverride -equals WinDevVS16-latest
- ImageVersionOverride -equals 6.0.0
steps:
- checkout: self
@@ -25,6 +27,17 @@ jobs:
inputs:
versionSpec: 4.8.1
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for extraneous build actions
inputs:
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: build/packages.config
restoreDirectory: '$(Build.SourcesDirectory)\packages'
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2

View File

@@ -11,12 +11,14 @@ jobs:
variables:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
pool:
pool:
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPoolOSS-L
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
demands:
- ImageOverride -equals WinDevVS16-latest
- ImageVersionOverride -equals 6.0.0
steps:
- template: build-console-steps.yml
@@ -33,16 +35,16 @@ jobs:
parameters:
name: 'RunTestsInHelix'
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
condition: and(succeeded(), and(eq('${{ parameters.platform }}', 'x64'), not(eq(variables['Build.Reason'], 'PullRequest'))))
condition: and(succeeded(), and(eq('${{ parameters.platform }}', 'x64'), not(eq(variables['Build.Reason'], 'PullRequest'))))
testSuite: 'DevTestSuite'
platform: ${{ parameters.platform }}
configuration: ${{ parameters.configuration }}
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
- template: helix-processtestresults-job.yml
parameters:
dependsOn:
- RunTestsInHelix
condition: and(succeededOrFailed(), and(eq('${{ parameters.platform }}', 'x64'), not(eq(variables['Build.Reason'], 'PullRequest'))))
condition: and(succeededOrFailed(), and(eq('${{ parameters.platform }}', 'x64'), not(eq(variables['Build.Reason'], 'PullRequest'))))
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}

View File

@@ -0,0 +1,222 @@
jobs:
- job: Compliance
# We don't *need* a matrix but there's no other way to set parameters on a "job"
# in the AzDO YAML syntax. It would have to be a "stage" or a "template".
# Doesn't matter. We're going to do compliance on Release x64 because
# that's the one all the tooling works against for sure.
strategy:
matrix:
Release_x64:
BuildConfiguration: Release
BuildPlatform: x64
displayName: Validate Security and Compliance
timeoutInMinutes: 240
steps:
- checkout: self
clean: true
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: PowerShell@2
displayName: Rationalize Build Platform
inputs:
targetType: inline
script: >-
$Arch = "$(BuildPlatform)"
If ($Arch -Eq "x86") { $Arch = "Win32" }
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
- task: NuGetToolInstaller@1
displayName: Use NuGet 5.10
inputs:
versionSpec: 5.10
- task: NuGetAuthenticate@0
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for extraneous build actions
inputs:
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: build/packages.config
restoreDirectory: '$(Build.SourcesDirectory)\packages'
- task: NuGetCommand@2
displayName: NuGet custom
inputs:
command: custom
selectOrConfig: config
nugetConfigPath: NuGet.Config
arguments: restore OpenConsole.sln -SolutionDirectory $(Build.SourcesDirectory)
- task: UniversalPackages@0
displayName: Download terminal-internal Universal Package
inputs:
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
versionListDownload: $(TerminalInternalPackageVersion)
- task: TouchdownBuildTask@1
displayName: Download Localization Files
inputs:
teamId: 7105
authId: $(TouchdownAppId)
authKey: $(TouchdownAppKey)
resourceFilePath: >-
src\cascadia\TerminalApp\Resources\en-US\Resources.resw
src\cascadia\TerminalControl\Resources\en-US\Resources.resw
src\cascadia\TerminalConnection\Resources\en-US\Resources.resw
src\cascadia\TerminalSettingsModel\Resources\en-US\Resources.resw
src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw
src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw
appendRelativeDir: true
localizationTarget: false
pseudoSetting: Included
- task: PowerShell@2
displayName: Move Loc files one level up
inputs:
targetType: inline
script: >-
$Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw'
$Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore }
pwsh: true
# 1ES Component Governance onboarding (Detects open source components). See https://docs.opensource.microsoft.com/tools/cg.html
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: Component Detection
# # PREfast and PoliCheck need Node. Install that first.
- task: NodeTool@0
# !!! NOTE !!! Run PREfast first. Some of the other tasks are going to run on a completed build.
# PREfast is going to build the code as a part of its analysis and the generated sources
# and output binaries will be sufficient for the rest of the analysis.
# If you disable this, the other tasks won't likely work. You would have to add a build
# step instead that builds the code normally before calling them.
# Also... PREfast will rebuild anyway so that's why we're not running a normal build first.
# Waste of time to build twice.
# PREfast. See https://www.1eswiki.com/wiki/SDL_Native_Rules_Build_Task
# The following 1ES tasks all operate completely differently and have a different syntax for usage.
# Most notable is every one of them has a different way of excluding things.
# Go see their 1eswiki.com pages to figure out how to exclude things.
# When writing exclusions, try to make them narrow so when new projects/binaries are added, they
# cause an error here and have to be explicitly pulled out. Don't write an exclusion so broad
# that it will catch other new stuff.
# https://www.1eswiki.com/wiki/PREfast_Build_Task
# Builds the project with C/C++ static analysis tools to find coding flaws and vulnerabilities
# !!! WARNING !!! It doesn't work with WAPPROJ packaging projects. Build the sub-projects instead.
- task: securedevelopmentteam.vss-secure-development-tools.build-task-prefast.SDLNativeRules@3
displayName: 'Run the PREfast SDL Native Rules for MSBuild'
condition: succeededOrFailed()
inputs:
msBuildCommandline: msbuild.exe /nologo /m /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /p:WindowsTerminalReleaseBuild=true /p:platform=$(BuildPlatform) /p:configuration=$(BuildConfiguration) /t:Terminal\Window\WindowsTerminal /p:VisualStudioVersion=16.0 $(Build.SourcesDirectory)\OpenConsole.sln
# Copies output from PREfast SDL Native Rules task to expected location for consumption by PkgESSecComp
- task: CopyFiles@1
displayName: 'Copy PREfast xml files to SDLNativeRulesDir'
inputs:
SourceFolder: '$(Agent.BuildDirectory)'
Contents: |
**\*.nativecodeanalysis.xml
TargetFolder: '$(Agent.BuildDirectory)\_sdt\logs\SDLNativeRules'
# https://www.1eswiki.com/index.php?title=PoliCheck_Build_Task
# Scans the text of source code, comments, and content for terminology that could be sensitive for legal, cultural, or geopolitical reasons.
# (Also finds vulgarities... takes all the fun out of everything.)
- task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@2
displayName: 'Run PoliCheck'
inputs:
targetType: F
targetArgument: $(Build.SourcesDirectory)
result: PoliCheck.xml
optionsFC: 1
optionsXS: 1
optionsUEPath: $(Build.SourcesDirectory)\build\config\PolicheckExclusions.xml
optionsHMENABLE: 0
continueOnError: true
# https://www.1eswiki.com/wiki/CredScan_Azure_DevOps_Build_Task
# Searches through source code and build outputs for a credential left behind in the open
- task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3
displayName: 'Run CredScan'
inputs:
outputFormat: pre
# suppressionsFile: LocalSuppressions.json
batchSize: 20
debugMode: false
continueOnError: true
# https://www.1eswiki.com/wiki/BinSkim_Build_Task
# Searches managed and unmanaged binaries for known security vulnerabilities.
- task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@4
displayName: 'Run BinSkim'
inputs:
TargetPattern: guardianGlob
# See https://aka.ms/gdn-globs for how to do match patterns
AnalyzeTargetGlob: $(Build.SourcesDirectory)\bin\**\*.dll;$(Build.SourcesDirectory)\bin\**\*.exe;-:file|**\Microsoft.UI.Xaml.dll;-:file|**\Microsoft.Toolkit.Win32.UI.XamlHost.dll;-:file|**\vcruntime*.dll;-:file|**\vcomp*.dll;-:file|**\vccorlib*.dll;-:file|**\vcamp*.dll;-:file|**\msvcp*.dll;-:file|**\concrt*.dll;-:file|**\TerminalThemeHelpers*.dll;-:file|**\cpprest*.dll
continueOnError: true
# Set XES_SERIALPOSTBUILDREADY to run Security and Compliance task once per build
- powershell: Write-Host “##vso[task.setvariable variable=XES_SERIALPOSTBUILDREADY;]true”
displayName: 'Set XES_SERIALPOSTBUILDREADY Vars'
# https://www.osgwiki.com/wiki/Package_ES_Security_and_Compliance
# Does a few things:
# - Ensures that Windows-required compliance tasks are run either inside this task
# or were run as a previous step prior to this one
# (PREfast, PoliCheck, Credscan)
# - Runs Windows-specific compliance tasks inside the task
# + CheckCFlags - ensures that compiler and linker flags meet Windows standards
# + CFGCheck/XFGCheck - ensures that Control Flow Guard (CFG) or
# eXtended Flow Guard (XFG) are enabled on binaries
# NOTE: CFG is deprecated and XFG isn't fully ready yet.
# NOTE2: CFG fails on an XFG'd binary
# - Brokers all security/compliance task logs to "Trust Services Automation (TSA)" (https://aka.ms/tsa)
# which is a system that maps all errors into the appropriate bug database
# template for each organization since they all vary. It should also suppress
# new bugs when one already exists for the product.
# This one is set up to go to the OS repository and use the given parameters
# to file bugs to our AzDO product path.
# If we don't use PkgESSecComp to do this for us, we need to install the TSA task
# ourselves in this pipeline to finalize data upload and bug creation.
# !!! NOTE !!! This task goes *LAST* after any other compliance tasks so it catches their logs
- task: PkgESSecComp@10
displayName: 'Security and Compliance tasks'
inputs:
fileNewBugs: false
areaPath: 'OS\WDX\DXP\WinDev\Terminal'
teamProject: 'OS'
iterationPath: 'OS\Future'
bugTags: 'TerminalReleaseCompliance'
scanAll: true
errOnBugs: false
failOnStdErr: true
taskLogVerbosity: Diagnostic
secCompConfigFromTask: |
# Overrides default build sources directory
sourceTargetOverrideAll: $(Build.SourcesDirectory)
# Overrides default build binaries directory when "Scan all" option is specified
binariesTargetOverrideAll: $(Build.SourcesDirectory)\bin
# Set the tools to false if they should not run in the build
tools:
- toolName: CheckCFlags
enable: true
- toolName: CFGCheck
enable: true
- toolName: Policheck
enable: false
- toolName: CredScan
enable: false
- toolName: XFGCheck
enable: false

View File

@@ -12,17 +12,19 @@ jobs:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
PGOBuildMode: 'Instrument'
pool:
pool:
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPoolOSS-L
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
demands:
- ImageOverride -equals WinDevVS16-latest
- ImageVersionOverride -equals 6.0.0
steps:
- template: build-console-steps.yml
parameters:
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
additionalBuildArguments: '${{ parameters.additionalBuildArguments }}'
- template: helix-runtests-job.yml
parameters:
@@ -34,7 +36,7 @@ jobs:
configuration: ${{ parameters.configuration }}
platform: ${{ parameters.platform }}
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
- template: helix-processtestresults-job.yml
parameters:
name: 'ProcessTestResults'
@@ -52,3 +54,4 @@ jobs:
- ProcessTestResults
pgoArtifact: 'PGO'
platform: ${{ parameters.platform }}
configuration: ${{ parameters.configuration }}

View File

@@ -12,17 +12,10 @@ steps:
inputs:
versionSpec: 5.2.0
- task: NuGetAuthenticate@0
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for solution
inputs:
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: OpenConsole.sln
restoreDirectory: '$(Build.SourcesDirectory)\packages'
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for extraneous build actions
inputs:
@@ -32,6 +25,15 @@ steps:
restoreSolution: build/packages.config
restoreDirectory: '$(Build.SourcesDirectory)\packages'
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for solution
inputs:
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: OpenConsole.sln
restoreDirectory: '$(Build.SourcesDirectory)\packages'
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
- script: |
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
@@ -47,14 +49,6 @@ steps:
inputs:
filename: 'set'
- task: powershell@2
displayName: 'Restore PGO database'
condition: eq(variables['PGOBuildMode'], 'Optimize')
inputs:
targetType: filePath
workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase
filePath: $(Build.SourcesDirectory)\tools\PGODatabase\restore-pgodb.ps1
- task: VSBuild@1
displayName: 'Build solution **\OpenConsole.sln'
inputs:
@@ -62,7 +56,7 @@ steps:
vsVersion: 16.0
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
msbuildArgs: "${{ parameters.additionalBuildArguments }}"
msbuildArgs: "${{ parameters.additionalBuildArguments }} /p:PGOBuildMode=$(PGOBuildMode) /bl:$(Build.SourcesDirectory)\\msbuild.binlog"
clean: true
maximumCpuCount: true
@@ -95,18 +89,6 @@ steps:
If ($Arch -Eq "x86") { $Arch = "Win32" }
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
- task: PowerShell@2
displayName: 'Validate binaries are optimized'
condition: eq(variables['pgoBuildMode'], 'Optimize')
inputs:
targetType: inline
script: |
$Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll'
foreach ($BinFile in $Binaries)
{
& "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/$BinFile"
}
- task: PowerShell@2
displayName: 'Run Unit Tests'
inputs:
@@ -211,3 +193,11 @@ steps:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO'
ArtifactName: 'PGO'
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: binlog'
condition: failed()
continueOnError: True
inputs:
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
ArtifactName: binlog-$(BuildPlatform)

View File

@@ -14,8 +14,8 @@ parameters:
platform: ''
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
useBuildOutputFromPipeline: $(System.DefinitionId)
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
openHelixTargetQueues: 'windows.10.amd64.client21h1.open.xaml'
closedHelixTargetQueues: 'windows.10.amd64.client21h1.xaml'
jobs:
- job: ${{ parameters.name }}

View File

@@ -0,0 +1,9 @@
parameters:
sdkVersion: 18362
steps:
- task: powershell@2
inputs:
targetType: filePath
filePath: build\scripts\Install-WindowsSdkISO.ps1
arguments: ${{ parameters.sdkVersion }}
displayName: 'Install Windows SDK (${{ parameters.sdkVersion }})'

View File

@@ -11,7 +11,7 @@ jobs:
vmImage: 'windows-2019'
variables:
artifactsPath: $(Build.SourcesDirectory)\Artifacts
pgoToolsPath: $(Build.SourcesDirectory)\tools\PGODatabase
pgoToolsPath: $(Build.SourcesDirectory)\build\PGO
nuspecPath: $(pgoToolsPath)\NuSpecs
nuspecFilename: PGO.nuspec
@@ -30,28 +30,22 @@ jobs:
inputs:
versionSpec: 5.8.0
- task: CopyFiles@2
displayName: 'Copy pgd files to NuGet build directory'
inputs:
sourceFolder: $(artifactsPath)\${{ parameters.pgoArtifact }}
contents: '**\*.pgd'
targetFolder: $(nuspecPath)\tools
- task: powershell@2
displayName: 'Generate NuSpec file'
inputs:
targetType: filePath
filePath: $(pgoToolsPath)\generate-nuspec.ps1
workingDirectory: $(pgoToolsPath)
arguments: $(nuspecPath)\$(nuspecFilename).template $(nuspecPath)\$(nuspecFilename)
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet pack'
displayName: Restore NuGet packages for extraneous build actions
inputs:
command: pack
packagesToPack: '$(nuspecPath)\$(nuspecFilename)'
basePath: '$(nuspecPath)'
packDestination: '$(Build.ArtifactStagingDirectory)'
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: build/packages.config
restoreDirectory: '$(Build.SourcesDirectory)\packages'
- task: MSBuild@1
displayName: 'Create PGO Nuget'
inputs:
solution: $(pgoToolsPath)\PGO.DB.proj
msbuildArguments: '/t:CreatePGONuGet /p:PGOBuildMode=Instrument /p:PGDPathForAllArch=$(artifactsPath)\${{ parameters.pgoArtifact }} /p:PGOOutputPath=$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
inputs:
@@ -69,4 +63,4 @@ jobs:
# This is the name of that connection
publishFeedCredentials: 'Terminal Public Artifact Feed'
feedsToUse: config
nugetConfigPath: '$(Build.SourcesDirectory)/NuGet.config'
nugetConfigPath: '$(Build.SourcesDirectory)/NuGet.config'

View File

@@ -2,6 +2,7 @@ parameters:
dependsOn: ''
pgoArtifact: PGO
platform: ''
configuration: ''
jobs:
- job: MergePGD
@@ -12,6 +13,7 @@ jobs:
artifactsPath: $(Build.SourcesDirectory)\Artifacts
pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }}
buildPlatform: ${{ parameters.platform }}
buildConfiguration: ${{ parameters.configuration }}
steps:
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
@@ -24,58 +26,36 @@ jobs:
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
displayName: 'Retrieve VC tools directory'
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 5.2.0'
inputs:
versionSpec: 5.2.0
- task: NuGetAuthenticate@0
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
# This should be `task: NuGetCommand@2`
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for extraneous build actions
inputs:
command: restore
feedsToUse: config
configPath: NuGet.config
restoreSolution: build/packages.config
restoreDirectory: '$(Build.SourcesDirectory)\packages'
- task: DownloadBuildArtifacts@0
inputs:
artifactName: ${{ parameters.pgoArtifact }}
downloadPath: $(artifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge WindowsTerminal*.pgc WindowsTerminal.pgd
displayName: 'Merge Terminal pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge OpenConsole*.pgc OpenConsole.pgd
displayName: 'Merge OpenConsole pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Control*.pgc Microsoft.Terminal.Control.pgd
displayName: 'Merge Microsoft.Terminal.Control pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Remoting*.pgc Microsoft.Terminal.Remoting.pgd
displayName: 'Merge Microsoft.Terminal.Remoting pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Editor*.pgc Microsoft.Terminal.Settings.Editor.pgd
displayName: 'Merge Microsoft.Terminal.Settings.Editor pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Model*.pgc Microsoft.Terminal.Settings.Model.pgd
displayName: 'Merge Microsoft.Terminal.Settings.Model pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalApp*.pgc TerminalApp.pgd
displayName: 'Merge TerminalApp pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalConnection*.pgc TerminalConnection.pgd
displayName: 'Merge TerminalConnection pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- task: MSBuild@1
displayName: Merge counts into PGD
inputs:
solution: $(Build.SourcesDirectory)\OpenConsole.sln
platform: $(buildPlatform)
configuration: $(buildConfiguration)
msbuildArguments: '/t:MergePGOCounts /p:PGOBuildMode=Instrument /p:PGDPath=$(pgoArtifactsPath)\$(buildPlatform) /p:PGCRootPath=$(pgoArtifactsPath)\$(buildPlatform)'
- task: CopyFiles@2
displayName: 'Copy merged pgd to artifact staging'
@@ -87,4 +67,4 @@ jobs:
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: $(Build.ArtifactStagingDirectory)
artifactName: ${{ parameters.pgoArtifact }}
artifactName: ${{ parameters.pgoArtifact }}

View File

@@ -23,6 +23,7 @@ $mappedFiles = New-Object System.Collections.ArrayList
foreach ($file in (Get-ChildItem -r:$recursive "$SearchDir\*.pdb"))
{
$mappedFiles = New-Object System.Collections.ArrayList
Write-Verbose "Found $file"
$ErrorActionPreference = "Continue" # Azure Pipelines defaults to "Stop", continue past errors in this script.
@@ -50,7 +51,7 @@ foreach ($file in (Get-ChildItem -r:$recursive "$SearchDir\*.pdb"))
if ($relative)
{
$mapping = $allFiles[$i] + "*$relative"
$mappedFiles.Add($mapping)
$ignore = $mappedFiles.Add($mapping)
Write-Verbose "Mapped path $($i): $mapping"
}
@@ -78,7 +79,26 @@ $($mappedFiles -join "`r`n")
SRCSRV: end ------------------------------------------------
"@ | Set-Content $pdbstrFile
Write-Host
Write-Host
Write-Host (Get-Content $pdbstrFile)
Write-Host
Write-Host
Write-Host "$pdbstrExe -p:""$file"" -w -s:srcsrv -i:$pdbstrFile"
& $pdbstrExe -p:"$file" -w -s:srcsrv -i:$pdbstrFile
Write-Host
Write-Host
Write-Host "$pdbstrExe -p:""$file"" -r -s:srcsrv"
& $pdbstrExe -p:"$file" -r -s:srcsrv
Write-Host
Write-Host
Write-Host "$srctoolExe $file"
& $srctoolExe "$file"
Write-Host
Write-Host
}
# Return with exit 0 to override any weird error code from other tools

View File

@@ -0,0 +1,346 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true, Position=0)]
[string]$buildNumber)
# Ensure the error action preference is set to the default for PowerShell3, 'Stop'
$ErrorActionPreference = 'Stop'
# Constants
$WindowsSDKOptions = @("OptionId.UWPCpp", "OptionId.DesktopCPPx64", "OptionId.DesktopCPPx86", "OptionId.DesktopCPPARM64", "OptionId.DesktopCPPARM", "OptionId.WindowsDesktopDebuggers")
$WindowsSDKRegPath = "HKLM:\Software\WOW6432Node\Microsoft\Windows Kits\Installed Roots"
$WindowsSDKRegRootKey = "KitsRoot10"
$WindowsSDKVersion = "10.0.$buildNumber.0"
$WindowsSDKInstalledRegPath = "$WindowsSDKRegPath\$WindowsSDKVersion\Installed Options"
$StrongNameRegPath = "HKLM:\SOFTWARE\Microsoft\StrongName\Verification"
$PublicKeyTokens = @("31bf3856ad364e35")
if ($buildNumber -notmatch "^\d{5,}$")
{
Write-Host "ERROR: '$buildNumber' doesn't look like a windows build number"
Write-Host
Exit 1
}
function Download-File
{
param ([string] $outDir,
[string] $downloadUrl,
[string] $downloadName)
$downloadPath = Join-Path $outDir "$downloadName.download"
$downloadDest = Join-Path $outDir $downloadName
$downloadDestTemp = Join-Path $outDir "$downloadName.tmp"
Write-Host -NoNewline "Downloading $downloadName..."
$retries = 10
$downloaded = $false
while (-not $downloaded)
{
try
{
$webclient = new-object System.Net.WebClient
$webclient.DownloadFile($downloadUrl, $downloadPath)
$downloaded = $true
}
catch [System.Net.WebException]
{
Write-Host
Write-Warning "Failed to fetch updated file from $downloadUrl : $($error[0])"
if (!(Test-Path $downloadDest))
{
if ($retries -gt 0)
{
Write-Host "$retries retries left, trying download again"
$retries--
start-sleep -Seconds 10
}
else
{
throw "$downloadName was not found at $downloadDest"
}
}
else
{
Write-Warning "$downloadName may be out of date"
}
}
}
Unblock-File $downloadPath
$downloadDestTemp = $downloadPath;
# Delete and rename to final dest
Write-Host "testing $downloadDest"
if (Test-Path $downloadDest)
{
Write-Host "Deleting: $downloadDest"
Remove-Item $downloadDest -Force
}
Move-Item -Force $downloadDestTemp $downloadDest
Write-Host "Done"
return $downloadDest
}
function Get-ISODriveLetter
{
param ([string] $isoPath)
$diskImage = Get-DiskImage -ImagePath $isoPath
if ($diskImage)
{
$volume = Get-Volume -DiskImage $diskImage
if ($volume)
{
$driveLetter = $volume.DriveLetter
if ($driveLetter)
{
$driveLetter += ":"
return $driveLetter
}
}
}
return $null
}
function Mount-ISO
{
param ([string] $isoPath)
# Check if image is already mounted
$isoDrive = Get-ISODriveLetter $isoPath
if (!$isoDrive)
{
Mount-DiskImage -ImagePath $isoPath -StorageType ISO | Out-Null
}
$isoDrive = Get-ISODriveLetter $isoPath
Write-Verbose "$isoPath mounted to ${isoDrive}:"
}
function Dismount-ISO
{
param ([string] $isoPath)
$isoDrive = (Get-DiskImage -ImagePath $isoPath | Get-Volume).DriveLetter
if ($isoDrive)
{
Write-Verbose "$isoPath dismounted"
Dismount-DiskImage -ImagePath $isoPath | Out-Null
}
}
function Disable-StrongName
{
param ([string] $publicKeyToken = "*")
reg ADD "HKLM\SOFTWARE\Microsoft\StrongName\Verification\*,$publicKeyToken" /f | Out-Null
if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64")
{
reg ADD "HKLM\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\*,$publicKeyToken" /f | Out-Null
}
}
function Test-Admin
{
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal $identity
$principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Test-RegistryPathAndValue
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $path,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $value)
try
{
if (Test-Path $path)
{
Get-ItemProperty -Path $path | Select-Object -ExpandProperty $value -ErrorAction Stop | Out-Null
return $true
}
}
catch
{
}
return $false
}
function Test-InstallWindowsSDK
{
$retval = $true
if (Test-RegistryPathAndValue -Path $WindowsSDKRegPath -Value $WindowsSDKRegRootKey)
{
# A Windows SDK is installed
# Is an SDK of our version installed with the options we need?
$allRequiredSdkOptionsInstalled = $true
foreach($sdkOption in $WindowsSDKOptions)
{
if (!(Test-RegistryPathAndValue -Path $WindowsSDKInstalledRegPath -Value $sdkOption))
{
$allRequiredSdkOptionsInstalled = $false
}
}
if($allRequiredSdkOptionsInstalled)
{
# It appears we have what we need. Double check the disk
$sdkRoot = Get-ItemProperty -Path $WindowsSDKRegPath | Select-Object -ExpandProperty $WindowsSDKRegRootKey
if ($sdkRoot)
{
if (Test-Path $sdkRoot)
{
$refPath = Join-Path $sdkRoot "References\$WindowsSDKVersion"
if (Test-Path $refPath)
{
$umdPath = Join-Path $sdkRoot "UnionMetadata\$WindowsSDKVersion"
if (Test-Path $umdPath)
{
# Pretty sure we have what we need
$retval = $false
}
}
}
}
}
}
return $retval
}
function Test-InstallStrongNameHijack
{
foreach($publicKeyToken in $PublicKeyTokens)
{
$key = "$StrongNameRegPath\*,$publicKeyToken"
if (!(Test-Path $key))
{
return $true
}
}
return $false
}
Write-Host -NoNewline "Checking for installed Windows SDK $WindowsSDKVersion..."
$InstallWindowsSDK = Test-InstallWindowsSDK
if ($InstallWindowsSDK)
{
Write-Host "Installation required"
}
else
{
Write-Host "INSTALLED"
}
$StrongNameHijack = Test-InstallStrongNameHijack
Write-Host -NoNewline "Checking if StrongName bypass required..."
if ($StrongNameHijack)
{
Write-Host "REQUIRED"
}
else
{
Write-Host "Done"
}
if ($StrongNameHijack -or $InstallWindowsSDK)
{
if (!(Test-Admin))
{
Write-Host
throw "ERROR: Elevation required"
}
}
if ($InstallWindowsSDK)
{
# Static(ish) link for Windows SDK
# Note: there is a delay from Windows SDK announcements to availability via the static link
$uri = "https://software-download.microsoft.com/download/sg/Windows_InsiderPreview_SDK_en-us_$($buildNumber)_1.iso";
if ($env:TEMP -eq $null)
{
$env:TEMP = Join-Path $env:SystemDrive 'temp'
}
$winsdkTempDir = Join-Path (Join-Path $env:TEMP ([System.IO.Path]::GetRandomFileName())) "WindowsSDK"
if (![System.IO.Directory]::Exists($winsdkTempDir))
{
[void][System.IO.Directory]::CreateDirectory($winsdkTempDir)
}
$file = "winsdk_$buildNumber.iso"
Write-Verbose "Getting WinSDK from $uri"
$downloadFile = Download-File $winsdkTempDir $uri $file
Write-Verbose "File is at $downloadFile"
$downloadFileItem = Get-Item $downloadFile
# Check to make sure the file is at least 10 MB.
if ($downloadFileItem.Length -lt 10*1024*1024)
{
Write-Host
Write-Host "ERROR: Downloaded file doesn't look large enough to be an ISO. The requested version may not be on microsoft.com yet."
Write-Host
Exit 1
}
# TODO Check if zip, exe, iso, etc.
try
{
Write-Host -NoNewline "Mounting ISO $file..."
Mount-ISO $downloadFile
Write-Host "Done"
$isoDrive = Get-ISODriveLetter $downloadFile
if (Test-Path $isoDrive)
{
Write-Host -NoNewLine "Installing WinSDK..."
$setupPath = Join-Path "$isoDrive" "WinSDKSetup.exe"
Start-Process -Wait $setupPath "/features $WindowsSDKOptions /q"
Write-Host "Done"
}
else
{
throw "Could not find mounted ISO at ${isoDrive}"
}
}
finally
{
Write-Host -NoNewline "Dismounting ISO $file..."
Dismount-ISO $downloadFile
Write-Host "Done"
}
}
if ($StrongNameHijack)
{
Write-Host -NoNewline "Disabling StrongName for Windows SDK..."
foreach($key in $PublicKeyTokens)
{
Disable-StrongName $key
}
Write-Host "Done"
}

View File

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

View File

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

View File

@@ -188,10 +188,6 @@
],
"type": "string"
},
"adjustIndistinguishableColors": {
"description": "When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color.",
"type": "boolean"
},
"experimental.retroTerminalEffect": {
"description": "When set to true, enable retro terminal effects when unfocused. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "boolean"
@@ -1478,11 +1474,6 @@
"description": "When set to true, trailing white-spaces will be removed from text in rectangular (block) selection while copied to your clipboard. When set to false, the white-spaces will be preserved.",
"type": "boolean"
},
"trimPaste": {
"default": true,
"description": "When enabled, the Terminal will automatically trim trailing whitespace characters when pasting text",
"type": "boolean"
},
"experimental.detectURLs": {
"default": true,
"description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.",
@@ -1550,7 +1541,7 @@
},
"startOnUserLogin": {
"default": false,
"description": "When set to true, this enables the launch of Windows Terminal at startup. Setting this to false will disable the startup task entry. If the Windows Terminal startup task entry is disabled either by org policy or by user action this setting will have no effect.",
"description": "When set to true, this enables the launch of Terminal at startup. Setting this to false will disable the startup task entry. If the Terminal startup task entry is disabled either by org policy or by user action this setting will have no effect.",
"type": "boolean"
},
"firstWindowPreference": {
@@ -1988,10 +1979,6 @@
}
]
},
"adjustIndistinguishableColors": {
"description": "When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color.",
"type": "boolean"
},
"scrollbarState": {
"default": "visible",
"description": "Defines the visibility of the scrollbar.",

View File

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

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -8,5 +8,5 @@ Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadi
### Fonts Included
* Cascadia Code, Cascadia Mono (2108.26)
* from microsoft/cascadia-code@f91d08f703ee61cf4ae936b9700ca974de2748fe
* Cascadia Code, Cascadia Mono (2111.01)
* from microsoft/cascadia-code@de36d62e777d34d3bed92a7e23988e5d61e0ba02

View File

@@ -12,30 +12,8 @@ static_assert(alignof(TextAttribute) == 2);
// Ensure that we can memcpy() and memmove() the struct for performance.
static_assert(std::is_trivially_copyable_v<TextAttribute>);
namespace
{
constexpr std::array<TextColor, 16> s_initLegacyColorMap(const BYTE defaultIndex)
{
std::array<TextColor, 16> legacyColorMap;
for (auto i = 0u; i < legacyColorMap.size(); i++)
{
const auto legacyIndex = TextColor::TransposeLegacyIndex(i);
gsl::at(legacyColorMap, i) = i == defaultIndex ? TextColor{} : TextColor{ legacyIndex, true };
}
return legacyColorMap;
}
BYTE s_legacyDefaultForeground = 7;
BYTE s_legacyDefaultBackground = 0;
BYTE s_ansiDefaultForeground = 7;
BYTE s_ansiDefaultBackground = 0;
}
// These maps allow for an efficient conversion from a legacy attribute index
// to a TextColor with the corresponding ANSI index, also taking into account
// the legacy index values that need to be converted to a default TextColor.
std::array<TextColor, 16> TextAttribute::s_legacyForegroundColorMap = s_initLegacyColorMap(7);
std::array<TextColor, 16> TextAttribute::s_legacyBackgroundColorMap = s_initLegacyColorMap(0);
BYTE TextAttribute::s_legacyDefaultForeground = 7;
BYTE TextAttribute::s_legacyDefaultBackground = 0;
// Routine Description:
// - Sets the legacy attributes which map to and from the default colors.
@@ -45,22 +23,8 @@ std::array<TextColor, 16> TextAttribute::s_legacyBackgroundColorMap = s_initLega
// - None
void TextAttribute::SetLegacyDefaultAttributes(const WORD defaultAttributes) noexcept
{
// First we reset the current default color map entries to what they should
// be for a regular translation from a legacy index to an ANSI TextColor.
gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{ s_ansiDefaultForeground, true };
gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{ s_ansiDefaultBackground, true };
// Then we save the new default attribute values and their corresponding
// ANSI translations. We use the latter values to more efficiently handle
// the "VT Quirk" conversion below.
s_legacyDefaultForeground = defaultAttributes & FG_ATTRS;
s_legacyDefaultBackground = (defaultAttributes & BG_ATTRS) >> 4;
s_ansiDefaultForeground = TextColor::TransposeLegacyIndex(s_legacyDefaultForeground);
s_ansiDefaultBackground = TextColor::TransposeLegacyIndex(s_legacyDefaultBackground);
// Finally we set the new default color map entries.
gsl::at(s_legacyForegroundColorMap, s_legacyDefaultForeground) = TextColor{};
gsl::at(s_legacyBackgroundColorMap, s_legacyDefaultBackground) = TextColor{};
}
// Routine Description:
@@ -91,13 +55,13 @@ TextAttribute TextAttribute::StripErroneousVT16VersionsOfLegacyDefaults(const Te
const auto bg{ attribute.GetBackground() };
auto copy{ attribute };
if (fg.IsIndex16() &&
attribute.IsBold() == WI_IsFlagSet(s_ansiDefaultForeground, FOREGROUND_INTENSITY) &&
fg.GetIndex() == (s_ansiDefaultForeground & ~FOREGROUND_INTENSITY))
attribute.IsBold() == WI_IsFlagSet(s_legacyDefaultForeground, FOREGROUND_INTENSITY) &&
fg.GetIndex() == (s_legacyDefaultForeground & ~FOREGROUND_INTENSITY))
{
// We don't want to turn 1;37m into 39m (or even 1;39m), as this was meant to mimic a legacy color.
copy.SetDefaultForeground();
}
if (bg.IsIndex16() && bg.GetIndex() == s_ansiDefaultBackground)
if (bg.IsIndex16() && bg.GetIndex() == s_legacyDefaultBackground)
{
copy.SetDefaultBackground();
}

View File

@@ -41,8 +41,8 @@ public:
explicit constexpr TextAttribute(const WORD wLegacyAttr) noexcept :
_wAttrLegacy{ gsl::narrow_cast<WORD>(wLegacyAttr & META_ATTRS) },
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
_foreground{ s_LegacyIndexOrDefault(wLegacyAttr & FG_ATTRS, s_legacyDefaultForeground) },
_background{ s_LegacyIndexOrDefault((wLegacyAttr & BG_ATTRS) >> 4, s_legacyDefaultBackground) },
_extendedAttrs{ ExtendedAttributes::Normal },
_hyperlinkId{ 0 }
{
@@ -167,8 +167,13 @@ public:
}
private:
static std::array<TextColor, 16> s_legacyForegroundColorMap;
static std::array<TextColor, 16> s_legacyBackgroundColorMap;
static constexpr TextColor s_LegacyIndexOrDefault(const BYTE requestedIndex, const BYTE defaultIndex)
{
return requestedIndex == defaultIndex ? TextColor{} : TextColor{ requestedIndex, true };
}
static BYTE s_legacyDefaultForeground;
static BYTE s_legacyDefaultBackground;
uint16_t _wAttrLegacy; // sizeof: 2, alignof: 2
uint16_t _hyperlinkId; // sizeof: 2, alignof: 2

View File

@@ -32,7 +32,7 @@ constexpr std::array<BYTE, 256> CompressedRgbToIndex16 = {
// A table mapping indexed colors from the 256-color palette,
// down to one of the 16 colors in the legacy palette.
constexpr std::array<BYTE, 256> Index256ToIndex16 = {
0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 1, 1, 9, 9, 2, 1, 1, 1, 1, 1, 2, 2, 3, 3,
3, 3, 2, 2, 11, 11, 3, 3, 10, 10, 11, 11, 11, 11, 10, 10,
10, 10, 11, 11, 5, 5, 5, 5, 1, 1, 8, 8, 1, 1, 9, 9,
@@ -252,7 +252,11 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept
{
return defaultIndex;
}
else if (IsIndex16() || IsIndex256())
else if (IsIndex16())
{
return GetIndex();
}
else if (IsIndex256())
{
return til::at(Index256ToIndex16, GetIndex());
}

View File

@@ -48,23 +48,6 @@ enum class ColorType : BYTE
struct TextColor
{
public:
static constexpr BYTE DARK_BLACK = 0;
static constexpr BYTE DARK_RED = 1;
static constexpr BYTE DARK_GREEN = 2;
static constexpr BYTE DARK_YELLOW = 3;
static constexpr BYTE DARK_BLUE = 4;
static constexpr BYTE DARK_MAGENTA = 5;
static constexpr BYTE DARK_CYAN = 6;
static constexpr BYTE DARK_WHITE = 7;
static constexpr BYTE BRIGHT_BLACK = 8;
static constexpr BYTE BRIGHT_RED = 9;
static constexpr BYTE BRIGHT_GREEN = 10;
static constexpr BYTE BRIGHT_YELLOW = 11;
static constexpr BYTE BRIGHT_BLUE = 12;
static constexpr BYTE BRIGHT_MAGENTA = 13;
static constexpr BYTE BRIGHT_CYAN = 14;
static constexpr BYTE BRIGHT_WHITE = 15;
constexpr TextColor() noexcept :
_meta{ ColorType::IsDefault },
_red{ 0 },
@@ -113,16 +96,6 @@ public:
COLORREF GetRGB() const noexcept;
static constexpr BYTE TransposeLegacyIndex(const size_t index)
{
// When converting a 16-color index in the legacy Windows order to or
// from an ANSI-compatible order, we need to swap the bits in positions
// 0 and 2. We do this by XORing the index with 00000101, but only if
// one (but not both) of those bit positions is set.
const auto oneBitSet = (index ^ (index >> 2)) & 1;
return gsl::narrow_cast<BYTE>(index ^ oneBitSet ^ (oneBitSet << 2));
}
private:
union
{

View File

@@ -8,6 +8,7 @@
#include "../types/inc/utils.hpp"
#include "../types/inc/convert.hpp"
#include "../../types/inc/Utf16Parser.hpp"
#include "../../types/inc/GlyphWidth.hpp"
#pragma hdrstop
@@ -2585,16 +2586,17 @@ PointTree TextBuffer::GetPatterns(const size_t firstRow, const size_t lastRow) c
// match and the previous match, so we use the size of the prefix
// along with the size of the match to determine the locations
size_t prefixSize = 0;
for (const auto ch : i->prefix().str())
for (const std::vector<wchar_t> parsedGlyph : Utf16Parser::Parse(i->prefix().str()))
{
prefixSize += IsGlyphFullWidth(ch) ? 2 : 1;
const std::wstring_view glyph{ parsedGlyph.data(), parsedGlyph.size() };
prefixSize += IsGlyphFullWidth(glyph) ? 2 : 1;
}
const auto start = lenUpToThis + prefixSize;
size_t matchSize = 0;
for (const auto ch : i->str())
for (const std::vector<wchar_t> parsedGlyph : Utf16Parser::Parse(i->str()))
{
matchSize += IsGlyphFullWidth(ch) ? 2 : 1;
const std::wstring_view glyph{ parsedGlyph.data(), parsedGlyph.size() };
matchSize += IsGlyphFullWidth(glyph) ? 2 : 1;
}
const auto end = start + matchSize;
lenUpToThis = end;

View File

@@ -237,7 +237,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
Log::Comment(L"Foreground legacy default index should map to default text color.");
legacyAttribute = fgLegacyDefault | BACKGROUND_GREEN;
textAttribute.SetDefaultForeground();
textAttribute.SetIndexedBackground256(TextColor::DARK_GREEN);
textAttribute.SetIndexedBackground256(BACKGROUND_GREEN >> 4);
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
Log::Comment(L"Default foreground text color should map back to legacy default index.");
@@ -245,7 +245,7 @@ void TextAttributeTests::TestRoundtripDefaultColors()
Log::Comment(L"Background legacy default index should map to default text color.");
legacyAttribute = FOREGROUND_GREEN | bgLegacyDefault;
textAttribute.SetIndexedForeground256(TextColor::DARK_GREEN);
textAttribute.SetIndexedForeground256(FOREGROUND_GREEN);
textAttribute.SetDefaultBackground();
VERIFY_ARE_EQUAL(textAttribute, TextAttribute{ legacyAttribute });
@@ -288,7 +288,7 @@ void TextAttributeTests::TestBoldAsBright()
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
attr.SetIndexedForeground(TextColor::DARK_BLACK);
attr.SetIndexedForeground(0);
VERIFY_IS_TRUE(attr.IsBold());
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
@@ -297,7 +297,7 @@ void TextAttributeTests::TestBoldAsBright()
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));
attr.SetIndexedBackground(TextColor::DARK_GREEN);
attr.SetIndexedBackground(2);
VERIFY_IS_TRUE(attr.IsBold());
Log::Comment(L"background should be unaffected by 'bold is bright'");
@@ -312,7 +312,7 @@ void TextAttributeTests::TestBoldAsBright()
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
attr.SetBold(true);
attr.SetIndexedForeground(TextColor::BRIGHT_BLACK);
attr.SetIndexedForeground(8);
VERIFY_IS_TRUE(attr.IsBold());
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));

View File

@@ -20,7 +20,7 @@
Version="0.0.1.0" />
<Properties>
<DisplayName>Windows Terminal Dev</DisplayName>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppStoreNameDev</DisplayName>
<PublisherDisplayName>A Lone Developer</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
@@ -38,8 +38,8 @@
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="ms-resource:AppNameDev"
Description="ms-resource:AppDescriptionDev"
DisplayName="ms-resource:TerminalApp/ContextMenu/AppNameDev"
Description="ms-resource:TerminalApp/ContextMenu/AppDescriptionDev"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
@@ -47,7 +47,7 @@
Wide310x150Logo="Images\Wide310x150Logo.png"
Square71x71Logo="Images\SmallTile.png"
Square310x310Logo="Images\LargeTile.png"
ShortName="ms-resource:AppShortNameDev">
ShortName="ms-resource:TerminalApp/ContextMenu/AppShortNameDev">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo"/>
<uap:ShowOn Tile="wide310x150Logo"/>
@@ -66,7 +66,7 @@
<uap5:StartupTask
TaskId="StartTerminalOnLoginTask"
Enabled="false"
DisplayName="ms-resource:AppNameDev" />
DisplayName="ms-resource:TerminalApp/ContextMenu/AppNameDev" />
</uap5:Extension>
<uap3:Extension Category="windows.appExtensionHost">
<uap3:AppExtensionHost>
@@ -87,7 +87,7 @@
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.terminal.host"
Id="Terminal-Dev"
DisplayName="Windows Terminal Dev"
DisplayName="Terminal Dev"
Description="Terminal host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>

View File

@@ -21,7 +21,7 @@
Version="0.5.0.0" />
<Properties>
<DisplayName>Windows Terminal Preview</DisplayName>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppStoreNamePre</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
@@ -39,8 +39,8 @@
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="ms-resource:AppNamePre"
Description="ms-resource:AppDescriptionPre"
DisplayName="ms-resource:TerminalApp/ContextMenu/AppNamePre"
Description="ms-resource:TerminalApp/ContextMenu/AppDescriptionPre"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
@@ -48,7 +48,7 @@
Wide310x150Logo="Images\Wide310x150Logo.png"
Square71x71Logo="Images\SmallTile.png"
Square310x310Logo="Images\LargeTile.png"
ShortName="ms-resource:AppShortNamePre">
ShortName="ms-resource:TerminalApp/ContextMenu/AppShortNamePre">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo"/>
<uap:ShowOn Tile="wide310x150Logo"/>
@@ -72,7 +72,7 @@
<uap5:StartupTask
TaskId="StartTerminalOnLoginTask"
Enabled="false"
DisplayName="ms-resource:AppNamePre" />
DisplayName="ms-resource:TerminalApp/ContextMenu/AppNamePre" />
</uap5:Extension>
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.console.host"
@@ -88,7 +88,7 @@
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.terminal.host"
Id="Terminal-Pre"
DisplayName="Windows Terminal Preview"
DisplayName="Terminal Preview"
Description="Terminal host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>

View File

@@ -21,7 +21,7 @@
Version="1.0.0.0" />
<Properties>
<DisplayName>Windows Terminal</DisplayName>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppStoreName</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
@@ -39,8 +39,8 @@
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="ms-resource:AppName"
Description="ms-resource:AppDescription"
DisplayName="ms-resource:TerminalApp/ContextMenu/AppName"
Description="ms-resource:TerminalApp/ContextMenu/AppDescription"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
@@ -48,7 +48,7 @@
Wide310x150Logo="Images\Wide310x150Logo.png"
Square71x71Logo="Images\SmallTile.png"
Square310x310Logo="Images\LargeTile.png"
ShortName="ms-resource:AppShortName">
ShortName="ms-resource:TerminalApp/ContextMenu/AppShortName">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo"/>
<uap:ShowOn Tile="wide310x150Logo"/>
@@ -72,7 +72,7 @@
<uap5:StartupTask
TaskId="StartTerminalOnLoginTask"
Enabled="false"
DisplayName="ms-resource:AppName" />
DisplayName="ms-resource:TerminalApp/ContextMenu/AppName" />
</uap5:Extension>
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.console.host"
@@ -88,7 +88,7 @@
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.terminal.host"
Id="Terminal"
DisplayName="Windows Terminal"
DisplayName="Terminal"
Description="Terminal host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>

View File

@@ -117,22 +117,4 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppName" xml:space="preserve">
<value>Windows Terminal</value>
</data>
<data name="AppNameDev" xml:space="preserve">
<value>Windows Terminal Dev</value>
</data>
<data name="AppNamePre" xml:space="preserve">
<value>Windows Terminal Preview</value>
</data>
<data name="AppShortName" xml:space="preserve">
<value>Terminal</value>
</data>
<data name="AppShortNameDev" xml:space="preserve">
<value>Terminal Dev</value>
</data>
<data name="AppShortNamePre" xml:space="preserve">
<value>Terminal Preview</value>
</data>
</root>
</root>

View File

@@ -117,13 +117,4 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDescription" xml:space="preserve">
<value>The New Windows Terminal</value>
</data>
<data name="AppDescriptionDev" xml:space="preserve">
<value>The Windows Terminal, but Unofficial</value>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Windows Terminal with a preview of upcoming features</value>
</data>
</root>
</root>

View File

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

View File

@@ -40,6 +40,8 @@ namespace SettingsModelLocalTests
TEST_METHOD(LayerProfilesOnArray);
TEST_METHOD(DuplicateProfileTest);
TEST_METHOD(TestGenGuidsForProfiles);
TEST_METHOD(TestCorrectOldDefaultShellPaths);
};
void ProfileTests::ProfileGeneratesGuid()
@@ -347,4 +349,59 @@ namespace SettingsModelLocalTests
VERIFY_ARE_NOT_EQUAL(settings->AllProfiles().GetAt(0).Guid(), settings->AllProfiles().GetAt(1).Guid());
}
void ProfileTests::TestCorrectOldDefaultShellPaths()
{
static constexpr std::string_view inboxProfiles{ R"({
"profiles": [
{
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
"name": "Windows PowerShell",
"commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
},
{
"guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
"name": "Command Prompt",
"commandline": "%SystemRoot%\\System32\\cmd.exe",
}
]
})" };
static constexpr std::string_view userProfiles{ R"({
"profiles": [
{
"name" : "powershell 1",
"commandline": "powershell.exe",
"guid" : "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}"
},
{
"name" : "powershell 2",
"commandline": "powershell.exe",
"guid" : "{61c54bbd-0000-5271-96e7-009a87ff44bf}"
},
{
"name" : "cmd 1",
"commandline": "cmd.exe",
"guid" : "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}"
},
{
"name" : "cmd 2",
"commandline": "cmd.exe",
"guid" : "{0caa0dad-0000-5f56-a8ff-afceeeaa6101}"
}
]
})" };
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userProfiles, inboxProfiles);
const auto allProfiles = settings->AllProfiles();
VERIFY_ARE_EQUAL(4u, allProfiles.Size());
VERIFY_ARE_EQUAL(L"powershell 1", allProfiles.GetAt(0).Name());
VERIFY_ARE_EQUAL(L"powershell 2", allProfiles.GetAt(1).Name());
VERIFY_ARE_EQUAL(L"cmd 1", allProfiles.GetAt(2).Name());
VERIFY_ARE_EQUAL(L"cmd 2", allProfiles.GetAt(3).Name());
VERIFY_ARE_EQUAL(L"%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", allProfiles.GetAt(0).Commandline());
VERIFY_ARE_EQUAL(L"powershell.exe", allProfiles.GetAt(1).Commandline());
VERIFY_ARE_EQUAL(L"%SystemRoot%\\System32\\cmd.exe", allProfiles.GetAt(2).Commandline());
VERIFY_ARE_EQUAL(L"cmd.exe", allProfiles.GetAt(3).Commandline());
}
}

View File

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

View File

@@ -508,7 +508,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
result = RunOnUIThread([&page]() {
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
@@ -526,7 +526,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
result = RunOnUIThread([&page]() {
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Automatic, SplitType::Duplicate, 0.5f, nullptr);
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
@@ -844,7 +844,7 @@ namespace TerminalAppLocalTests
// | 1 | 2 |
// | | |
// -------------------
page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Right, SplitType::Duplicate, 0.5f, nullptr);
secondId = tab->_activePane->Id().value();
});
Sleep(250);
@@ -862,7 +862,7 @@ namespace TerminalAppLocalTests
// | 3 | |
// | | |
// -------------------
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
// Split again to make the 3rd tab
thirdId = tab->_activePane->Id().value();
@@ -882,7 +882,7 @@ namespace TerminalAppLocalTests
// | 3 | 4 |
// | | |
// -------------------
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Down, SplitType::Duplicate, 0.5f, nullptr);
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
fourthId = tab->_activePane->Id().value();
});

View File

@@ -977,7 +977,7 @@ void HwndTerminal::_StringPaste(const wchar_t* const pData) noexcept
CATCH_LOG();
}
COORD HwndTerminal::GetFontSize() const noexcept
COORD HwndTerminal::GetFontSize() const
{
return _actualFont.GetSize();
}

View File

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

View File

@@ -29,9 +29,6 @@
<ProjectReference Include="$(SolutionDir)src\types\lib\types.vcxproj">
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)src\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)src\renderer\base\lib\base.vcxproj">
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
</ProjectReference>

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
</packages>

View File

@@ -33,5 +33,5 @@ DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*)
return TRUE;
}
// Usurp the TerminalApp's resource group.
UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"TerminalApp/Resources")
// Usurp the TerminalApp's Context Menu specific resource group.
UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"TerminalApp/ContextMenu")

View File

@@ -174,9 +174,10 @@ namespace winrt::TerminalApp::implementation
else if (const auto& realArgs = args.ActionArgs().try_as<SplitPaneArgs>())
{
_SplitPane(realArgs.SplitDirection(),
realArgs.SplitMode(),
// This is safe, we're already filtering so the value is (0, 1)
::base::saturated_cast<float>(realArgs.SplitSize()),
_MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
realArgs.TerminalArgs());
args.Handled(true);
}
}

View File

@@ -12,8 +12,6 @@
#include <WtExeUtils.h>
#include <wil/token_helpers.h >
#include "../../types/inc/utils.hpp"
using namespace winrt::Windows::ApplicationModel;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::UI::Xaml;
@@ -133,6 +131,38 @@ static Documents::Run _BuildErrorRun(const winrt::hstring& text, const ResourceD
return textRun;
}
// Method Description:
// - Returns whether the user is either a member of the Administrators group or
// is currently elevated.
// - This will return **FALSE** if the user has UAC disabled entirely, because
// there's no separation of power between the user and an admin in that case.
// Return Value:
// - true if the user is an administrator
static bool _isUserAdmin() noexcept
try
{
wil::unique_handle processToken{ GetCurrentProcessToken() };
const auto elevationType = wil::get_token_information<TOKEN_ELEVATION_TYPE>(processToken.get());
const auto elevationState = wil::get_token_information<TOKEN_ELEVATION>(processToken.get());
if (elevationType == TokenElevationTypeDefault && elevationState.TokenIsElevated)
{
// In this case, the user has UAC entirely disabled. This is sort of
// weird, we treat this like the user isn't an admin at all. There's no
// separation of powers, so the things we normally want to gate on
// "having special powers" doesn't apply.
//
// See GH#7754, GH#11096
return false;
}
return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return false;
}
namespace winrt::TerminalApp::implementation
{
// Function Description:
@@ -184,7 +214,7 @@ namespace winrt::TerminalApp::implementation
// The TerminalPage has to be constructed during our construction, to
// make sure that there's a terminal page for callers of
// SetTitleBarContent
_isElevated = ::Microsoft::Console::Utils::IsElevated();
_isElevated = _isUserAdmin();
_root = winrt::make_self<TerminalPage>();
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
@@ -304,9 +334,6 @@ namespace winrt::TerminalApp::implementation
_RefreshThemeRoutine();
_ApplyStartupTaskStateChange();
auto args = winrt::make_self<SystemMenuChangeArgs>(RS_(L"SettingsMenuItem"), SystemMenuChangeAction::Add, SystemMenuItemHandler(this, &AppLogic::_OpenSettingsUI));
_SystemMenuChangeRequestedHandlers(*this, *args);
TraceLoggingWrite(
g_hTerminalAppProvider,
"AppCreated",
@@ -505,8 +532,26 @@ namespace winrt::TerminalApp::implementation
if (keyboardServiceIsDisabled)
{
_root->ShowKeyboardServiceWarning();
TraceLoggingWrite(
g_hTerminalAppProvider,
"KeyboardServiceWasDisabled",
TraceLoggingDescription("Event emitted when the keyboard service is disabled, and we warned them about it"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
}
}
else
{
// For when the warning was disabled in the settings
TraceLoggingWrite(
g_hTerminalAppProvider,
"KeyboardServiceWarningWasDisabledBySetting",
TraceLoggingDescription("Event emitted when the user has disabled the KB service warning"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
}
if (FAILED(_settingsLoadedResult))
{
@@ -880,6 +925,8 @@ namespace winrt::TerminalApp::implementation
void AppLogic::_RegisterSettingsChange()
{
const std::filesystem::path settingsPath{ std::wstring_view{ CascadiaSettings::SettingsPath() } };
const std::filesystem::path statePath{ std::wstring_view{ ApplicationState::SharedInstance().FilePath() } };
_reader.create(
settingsPath.parent_path().c_str(),
false,
@@ -888,29 +935,14 @@ namespace winrt::TerminalApp::implementation
// editors, who will write a temp file, then rename it to be the
// actual file you wrote. So listen for that too.
wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime,
[this, settingsBasename = settingsPath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
// DO NOT create a static reference to ApplicationState::SharedInstance here.
//
// ApplicationState::SharedInstance already caches its own
// static ref. If _we_ keep a static ref to the member in
// AppState, then our reference will keep ApplicationState alive
// after the `ActionToStringMap` gets cleaned up. Then, when we
// try to persist the actions in the window state, we won't be
// able to. We'll try to look up the action and the map just
// won't exist. We'll explode, even though the Terminal is
// tearing down anyways. So we'll just die, but still invoke
// WinDBG's post-mortem debugger, who won't be able to attach to
// the process that's already exiting.
//
// So DON'T ~give a mouse a cookie~ take a static ref here.
const winrt::hstring modifiedBasename{ std::filesystem::path{ fileModified }.filename().c_str() };
[this, settingsBasename = settingsPath.filename(), stateBasename = statePath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) {
const auto modifiedBasename = std::filesystem::path{ fileModified }.filename();
if (modifiedBasename == settingsBasename)
{
_reloadSettings->Run();
}
else if (ApplicationState::SharedInstance().IsStatePath(modifiedBasename))
else if (modifiedBasename == stateBasename)
{
_reloadState();
}
@@ -1037,11 +1069,6 @@ namespace winrt::TerminalApp::implementation
_SettingsChangedHandlers(*this, nullptr);
}
void AppLogic::_OpenSettingsUI()
{
_root->OpenSettingsUI();
}
// Method Description:
// - Returns a pointer to the global shared settings.
[[nodiscard]] CascadiaSettings AppLogic::GetSettings() const noexcept
@@ -1068,18 +1095,18 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Gets the title of the currently focused terminal control. If there
// isn't a control selected for any reason, returns "Windows Terminal"
// isn't a control selected for any reason, returns "Terminal"
// Arguments:
// - <none>
// Return Value:
// - the title of the focused control if there is one, else "Windows Terminal"
// - the title of the focused control if there is one, else "Terminal"
hstring AppLogic::Title()
{
if (_root)
{
return _root->Title();
}
return { L"Windows Terminal" };
return { L"Terminal" };
}
// Method Description:

View File

@@ -5,7 +5,6 @@
#include "AppLogic.g.h"
#include "FindTargetWindowResult.g.h"
#include "SystemMenuChangeArgs.g.h"
#include "Jumplist.h"
#include "LanguageProfileNotifier.h"
#include "TerminalPage.h"
@@ -36,17 +35,6 @@ namespace winrt::TerminalApp::implementation
FindTargetWindowResult(id, L""){};
};
struct SystemMenuChangeArgs : SystemMenuChangeArgsT<SystemMenuChangeArgs>
{
WINRT_PROPERTY(winrt::hstring, Name, L"");
WINRT_PROPERTY(SystemMenuChangeAction, Action, SystemMenuChangeAction::Add);
WINRT_PROPERTY(SystemMenuItemHandler, Handler, nullptr);
public:
SystemMenuChangeArgs(const winrt::hstring& name, SystemMenuChangeAction action, SystemMenuItemHandler handler = nullptr) :
_Name{ name }, _Action{ action }, _Handler{ handler } {};
};
struct AppLogic : AppLogicT<AppLogic, IInitializeWithWindow>
{
public:
@@ -126,7 +114,6 @@ namespace winrt::TerminalApp::implementation
// -------------------------------- WinRT Events ---------------------------------
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs);
private:
bool _isUwp{ false };
@@ -177,7 +164,6 @@ namespace winrt::TerminalApp::implementation
void _RegisterSettingsChange();
fire_and_forget _DispatchReloadSettings();
void _ReloadSettings();
void _OpenSettingsUI();
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);

View File

@@ -19,20 +19,6 @@ namespace TerminalApp
String WindowName { get; };
};
delegate void SystemMenuItemHandler();
enum SystemMenuChangeAction
{
Add = 0,
Remove = 1
};
[default_interface] runtimeclass SystemMenuChangeArgs {
String Name { get; };
SystemMenuChangeAction Action { get; };
SystemMenuItemHandler Handler { get; };
};
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter
{
AppLogic();
@@ -125,6 +111,5 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
}
}

View File

@@ -822,16 +822,13 @@ namespace winrt::TerminalApp::implementation
{
const auto currentNeedleHasResults{ _filteredActions.Size() > 0 };
_noMatchesText().Visibility(currentNeedleHasResults ? Visibility::Collapsed : Visibility::Visible);
if (!currentNeedleHasResults)
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(_searchBox()) })
{
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(_searchBox()) })
{
automationPeer.RaiseNotificationEvent(
Automation::Peers::AutomationNotificationKind::ActionCompleted,
Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent,
NoMatchesText(), // NoMatchesText contains the right text for the current mode
L"CommandPaletteResultAnnouncement" /* unique name for this notification */);
}
automationPeer.RaiseNotificationEvent(
Automation::Peers::AutomationNotificationKind::ActionCompleted,
Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent,
currentNeedleHasResults ? RS_(L"CommandPalette_MatchesAvailable") : NoMatchesText(), // what to announce if results were found
L"CommandPaletteResultAnnouncement" /* unique name for this group of notifications */);
}
}
else

View File

@@ -1,25 +1,67 @@
// 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
@@ -95,4 +137,104 @@ 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,11 +6,9 @@
#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
{
@@ -20,6 +18,10 @@ 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,
@@ -30,6 +32,9 @@ 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,6 +11,10 @@ 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="WindowMinimizeButton"
x:Uid="MinimizeButton"
Width="46.0"
Height="{StaticResource CaptionButtonHeightWindowed}"
MinWidth="46.0"
@@ -232,9 +232,14 @@
<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="WindowMaximizeButton"
x:Uid="MaximizeButton"
Width="46.0"
Height="{StaticResource CaptionButtonHeightWindowed}"
MinWidth="46.0"
@@ -256,7 +261,7 @@
</ToolTipService.ToolTip>
</Button>
<Button x:Name="CloseButton"
x:Uid="WindowCloseButton"
x:Uid="CloseButton"
Width="46.0"
Height="{StaticResource CaptionButtonHeightWindowed}"
MinWidth="46.0"
@@ -309,5 +314,10 @@
<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

@@ -2351,32 +2351,35 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
}
// Method Description:
// - The same as above, except this takes in the pane directly instead of a
// profile and control to make a pane with
// - Split the focused pane in our tree of panes, and place the given
// TermControl into the newly created pane. If we're the focused pane, then
// we'll create two new children, and place them side-by-side in our Grid.
// Arguments:
// - splitType: what type of split we want to create.
// - splitSize: the desired size of the split
// - newPane: the new pane
// - profile: The profile to associate with the newly created pane.
// - control: A TermControl to use in the new pane.
// Return Value:
// - The two newly created Panes, with the original pane first
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> newPane)
const Profile& profile,
const TermControl& control)
{
if (!_lastActive)
{
if (_firstChild && _firstChild->_HasFocusedChild())
{
return _firstChild->Split(splitType, splitSize, newPane);
return _firstChild->Split(splitType, splitSize, profile, control);
}
else if (_secondChild && _secondChild->_HasFocusedChild())
{
return _secondChild->Split(splitType, splitSize, newPane);
return _secondChild->Split(splitType, splitSize, profile, control);
}
return { nullptr, nullptr };
}
auto newPane = std::make_shared<Pane>(profile, control);
return _Split(splitType, splitSize, newPane);
}

View File

@@ -110,7 +110,8 @@ public:
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> pane);
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
const winrt::Microsoft::Terminal::Control::TermControl& control);
bool ToggleSplitOrientation();
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,

View File

@@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppName" xml:space="preserve">
<value>Terminal</value>
</data>
<data name="AppNameDev" xml:space="preserve">
<value>Terminal Dev</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppNamePre" xml:space="preserve">
<value>Terminal Preview</value>
</data>
<data name="AppStoreName" xml:space="preserve">
<value>Windows Terminal</value>
</data>
<data name="AppStoreNameDev" xml:space="preserve">
<value>Windows Terminal Dev</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppStoreNamePre" xml:space="preserve">
<value>Windows Terminal Preview</value>
</data>
<data name="AppShortName" xml:space="preserve">
<value>Terminal</value>
</data>
<data name="AppShortNameDev" xml:space="preserve">
<value>Terminal Dev</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppShortNamePre" xml:space="preserve">
<value>Terminal Preview</value>
</data>
<data name="AppDescription" xml:space="preserve">
<value>The New Windows Terminal</value>
</data>
<data name="AppDescriptionDev" xml:space="preserve">
<value>The Windows Terminal, but Unofficial</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Windows Terminal with a preview of upcoming features</value>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Dev" xml:space="preserve">
<value>Open in Terminal (Dev)</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Preview" xml:space="preserve">
<value>Open in Terminal Preview</value>
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem" xml:space="preserve">
<value>Open in Terminal</value>
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the non-preview version of Windows Terminal</comment>
</data>
</root>

View File

@@ -411,6 +411,9 @@
<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>
@@ -420,6 +423,9 @@
<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>
@@ -679,18 +685,6 @@
<value>Windows</value>
<comment>This is displayed as a label for the context menu item that holds the submenu of available windows.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Dev" xml:space="preserve">
<value>Open in Windows Terminal (Dev)</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Preview" xml:space="preserve">
<value>Open in Windows Terminal Preview</value>
<comment>{Locked="Windows"} This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem" xml:space="preserve">
<value>Open in Windows Terminal</value>
<comment>{Locked="Windows"} This is a menu item that will be displayed in the Windows File Explorer that launches the non-preview version of Windows Terminal</comment>
</data>
<data name="DropPathTabRun.Text" xml:space="preserve">
<value>Open a new tab in given starting directory</value>
</data>
@@ -731,4 +725,7 @@
<value>Open Settings</value>
<comment>This is a call-to-action hyperlink; it will open the settings.</comment>
</data>
</root>
<data name="CommandPalette_MatchesAvailable" xml:space="preserve">
<value>Suggestions available</value>
</data>
</root>

View File

@@ -251,4 +251,5 @@ namespace winrt::TerminalApp::implementation
}
});
}
}

View File

@@ -68,7 +68,7 @@ namespace winrt::TerminalApp::implementation
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection));
_CreateNewTabWithProfileAndSettings(profile, settings, existingConnection);
const uint32_t tabCount = _tabs.Size();
const bool usedManualProfile = (newTerminalArgs != nullptr) &&
@@ -244,6 +244,58 @@ namespace winrt::TerminalApp::implementation
_InitializeTab(newTabImpl);
}
// Method Description:
// - Creates a new tab with the given settings. If the tab bar is not being
// currently displayed, it will be shown.
// Arguments:
// - profile: profile settings for this connection
// - settings: the TerminalSettings object to use to create the TerminalControl with.
// - existingConnection: optionally receives a connection from the outside world instead of attempting to create one
void TerminalPage::_CreateNewTabWithProfileAndSettings(const Profile& profile, const TerminalSettingsCreateResult& settings, TerminalConnection::ITerminalConnection existingConnection)
{
// Initialize the new tab
// Create a connection based on the values in our settings object if we weren't given one.
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, settings.DefaultSettings());
// If we had an `existingConnection`, then this is an inbound handoff from somewhere else.
// We need to tell it about our size information so it can match the dimensions of what
// we are about to present.
if (existingConnection)
{
connection.Resize(settings.DefaultSettings().InitialRows(), settings.DefaultSettings().InitialCols());
}
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
if (_settings.GlobalSettings().DebugFeaturesEnabled())
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
if (bothAltsPressed)
{
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
}
}
// Give term control a child of the settings so that any overrides go in the child
// This way, when we do a settings reload we just update the parent and the overrides remain
auto term = _InitControl(settings, connection);
auto newTabImpl = winrt::make_self<TerminalTab>(profile, term);
_RegisterTerminalEvents(term);
_InitializeTab(newTabImpl);
if (debugConnection) // this will only be set if global debugging is on and tap is active
{
auto newControl = _InitControl(settings, debugConnection);
_RegisterTerminalEvents(newControl);
// Split (auto) with the debug tap.
newTabImpl->SplitPane(SplitDirection::Automatic, 0.5f, profile, newControl);
}
}
// Method Description:
// - Get the icon of the currently focused terminal control, and set its
// tab's icon to that icon.
@@ -313,14 +365,28 @@ namespace winrt::TerminalApp::implementation
// In the future, it may be preferable to just duplicate the
// current control's live settings (which will include changes
// made through VT).
_CreateNewTabFromPane(_MakePane(nullptr, true, nullptr));
const auto runtimeTabText{ tab.GetTabText() };
if (!runtimeTabText.empty())
if (auto profile = tab.GetFocusedProfile())
{
if (auto newTab{ _GetFocusedTabImpl() })
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
profile = GetClosestProfileForDuplicationOfProfile(profile);
const auto settingsCreateResult{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
newTab->SetTabText(runtimeTabText);
settingsCreateResult.DefaultSettings().StartingDirectory(workingDirectory);
}
_CreateNewTabWithProfileAndSettings(profile, settingsCreateResult);
const auto runtimeTabText{ tab.GetTabText() };
if (!runtimeTabText.empty())
{
if (auto newTab{ _GetFocusedTabImpl() })
{
newTab->SetTabText(runtimeTabText);
}
}
}
}
@@ -336,7 +402,7 @@ namespace winrt::TerminalApp::implementation
try
{
_SetFocusedTab(tab);
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
_SplitPane(tab, SplitDirection::Automatic, SplitType::Duplicate);
}
CATCH_LOG();
}

View File

@@ -301,6 +301,7 @@
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<PRIResource Include="Resources\en-US\Resources.resw" />
<PRIResource Include="Resources\en-US\ContextMenu.resw" />
<OCResourceDirectory Include="Resources" />
<None Include="packages.config" />
</ItemGroup>

View File

@@ -20,6 +20,7 @@
#include "../inc/WindowingBehavior.h"
#include <til/latch.h>
#include <TerminalCore/ControlKeyStates.hpp>
using namespace winrt;
using namespace winrt::Windows::Foundation::Collections;
@@ -35,6 +36,7 @@ using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace ::TerminalApp;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Terminal::Core;
using namespace std::chrono_literals;
#define HOOKUP_ACTION(action) _actionDispatch->action({ this, &TerminalPage::_Handle##action });
@@ -300,7 +302,10 @@ namespace winrt::TerminalApp::implementation
// - true if the ApplicationState should be used.
bool TerminalPage::ShouldUsePersistedLayout(CascadiaSettings& settings) const
{
// GH#5000 Until there is a separate state file for elevated sessions we should just not
// save at all while in an elevated window.
return Feature_PersistedWindowLayout::IsEnabled() &&
!IsElevated() &&
settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout;
}
@@ -847,7 +852,14 @@ namespace winrt::TerminalApp::implementation
WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
if (shiftPressed && !debugTap)
if (altPressed && !debugTap)
{
this->_SplitPane(SplitDirection::Automatic,
SplitType::Manual,
0.5f,
newTerminalArgs);
}
else if (shiftPressed && !debugTap)
{
// Manually fill in the evaluated profile.
if (newTerminalArgs.ProfileIndex() != nullptr)
@@ -863,17 +875,7 @@ namespace winrt::TerminalApp::implementation
}
else
{
const auto newPane = _MakePane(newTerminalArgs);
if (altPressed && !debugTap)
{
this->_SplitPane(SplitDirection::Automatic,
0.5f,
newPane);
}
else
{
_CreateNewTabFromPane(newPane);
}
LOG_IF_FAILED(this->_OpenNewTab(newTerminalArgs));
}
}
@@ -943,8 +945,8 @@ namespace winrt::TerminalApp::implementation
// process until later, on another thread, after we've already
// restored the CWD to it's original value.
winrt::hstring newWorkingDirectory{ settings.StartingDirectory() };
if (newWorkingDirectory.size() <= 1 ||
!(newWorkingDirectory[0] == L'~' || newWorkingDirectory[0] == L'/'))
if (newWorkingDirectory.size() == 0 || newWorkingDirectory.size() == 1 &&
!(newWorkingDirectory[0] == L'~' || newWorkingDirectory[0] == L'/'))
{ // We only want to resolve the new WD against the CWD if it doesn't look like a Linux path (see GH#592)
std::wstring cwdString{ wil::GetCurrentDirectoryW<std::wstring>() };
std::filesystem::path cwd{ cwdString };
@@ -1038,29 +1040,159 @@ 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.
// - As of GH#8480, this is also bound to the TabRowControl's KeyUp event.
// That should only fire when focus is in the tab row, which is hard to
// do. Notably, that's possible:
// - When you have enough tabs to make the little scroll arrows appear,
// click one, then hit tab
// - When Narrator is in Scan mode (which is the a11y bug we're fixing here)
// - This method is effectively an extract of TermControl::_KeyHandler and TermControl::_TryHandleKeyBinding.
// Arguments:
// - e: the KeyRoutedEventArgs containing info about the keystroke.
// Return Value:
// - <none>
void TerminalPage::_KeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
const auto key = e.OriginalKey();
const auto scanCode = e.KeyStatus().ScanCode;
const auto coreWindow = CoreWindow::GetForCurrentThread();
const auto ctrlDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
const auto altDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
const auto shiftDown = WI_IsFlagSet(coreWindow.GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
const auto keyStatus = e.KeyStatus();
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey());
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
const auto modifiers = _GetPressedModifierKeys();
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, false, static_cast<int32_t>(key), static_cast<int32_t>(scanCode) };
if (const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) })
// GH#11076:
// For some weird reason we sometimes receive a WM_KEYDOWN
// message without vkey or scanCode if a user drags a tab.
// The KeyChord constructor has a debug assertion ensuring that all KeyChord
// either have a valid vkey/scanCode. This is important, because this prevents
// accidential insertion of invalid KeyChords into classes like ActionMap.
if (!vkey && !scanCode)
{
if (CommandPalette().Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
return;
}
// Alt-Numpad# input will send us a character once the user releases
// Alt, so we should be ignoring the individual keydowns. The character
// will be sent through the TSFInputControl. See GH#1401 for more
// details
if (modifiers.IsAltPressed() && (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9))
{
return;
}
// GH#2235: Terminal::Settings hasn't been modified to differentiate
// between AltGr and Ctrl+Alt yet.
// -> Don't check for key bindings if this is an AltGr key combination.
if (modifiers.IsAltGrPressed())
{
return;
}
const auto actionMap = _settings.ActionMap();
if (!actionMap)
{
return;
}
const auto cmd = actionMap.GetActionByKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
modifiers.IsWinPressed(),
vkey,
scanCode,
});
if (!cmd)
{
return;
}
if (!_actionDispatch->DoAction(cmd.ActionAndArgs()))
{
return;
}
if (const auto p = CommandPalette(); p.Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
{
p.Visibility(Visibility::Collapsed);
}
// Let's assume the user has bound the dead key "^" to a sendInput command that sends "b".
// If the user presses the two keys "^a" it'll produce "bâ", despite us marking the key event as handled.
// The following is used to manually "consume" such dead keys and clear them from the keyboard state.
_ClearKeyboardState(vkey, scanCode);
e.Handled(true);
}
// Method Description:
// - Get the modifier keys that are currently pressed. This can be used to
// find out which modifiers (ctrl, alt, shift) are pressed in events that
// don't necessarily include that state.
// - This is a copy of TermControl::_GetPressedModifierKeys.
// Return Value:
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
ControlKeyStates TerminalPage::_GetPressedModifierKeys() noexcept
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
// DONT USE
// != CoreVirtualKeyStates::None
// OR
// == CoreVirtualKeyStates::Down
// Sometimes with the key down, the state is Down | Locked.
// Sometimes with the key up, the state is Locked.
// IsFlagSet(Down) is the only correct solution.
struct KeyModifier
{
VirtualKey vkey;
ControlKeyStates flags;
};
constexpr std::array<KeyModifier, 7> modifiers{ {
{ VirtualKey::RightMenu, ControlKeyStates::RightAltPressed },
{ VirtualKey::LeftMenu, ControlKeyStates::LeftAltPressed },
{ VirtualKey::RightControl, ControlKeyStates::RightCtrlPressed },
{ VirtualKey::LeftControl, ControlKeyStates::LeftCtrlPressed },
{ VirtualKey::Shift, ControlKeyStates::ShiftPressed },
{ VirtualKey::RightWindows, ControlKeyStates::RightWinPressed },
{ VirtualKey::LeftWindows, ControlKeyStates::LeftWinPressed },
} };
ControlKeyStates flags;
for (const auto& mod : modifiers)
{
const auto state = window.GetKeyState(mod.vkey);
const auto isDown = WI_IsFlagSet(state, CoreVirtualKeyStates::Down);
if (isDown)
{
CommandPalette().Visibility(Visibility::Collapsed);
flags |= mod.flags;
}
_actionDispatch->DoAction(cmd.ActionAndArgs());
e.Handled(true);
}
return flags;
}
// Method Description:
// - Discards currently pressed dead keys.
// - This is a copy of TermControl::_ClearKeyboardState.
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
void TerminalPage::_ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept
{
std::array<BYTE, 256> keyState;
if (!GetKeyboardState(keyState.data()))
{
return;
}
// As described in "Sometimes you *want* to interfere with the keyboard's state buffer":
// http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
// > "The key here is to keep trying to pass stuff to ToUnicode until -1 is not returned."
std::array<wchar_t, 16> buffer;
while (ToUnicodeEx(vkey, scanCode, keyState.data(), buffer.data(), gsl::narrow_cast<int>(buffer.size()), 0b1, nullptr) < 0)
{
}
}
@@ -1485,15 +1617,18 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Split the focused pane either horizontally or vertically, and place the
// given pane accordingly in the tree
// given TermControl into the newly created pane.
// Arguments:
// - newPane: the pane to add to our tree of panes
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
// new pane should be split from its parent.
// - splitSize: the size of the split
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
// - newTerminalArgs: An object that may contain a blob of parameters to
// control which profile is created and with possible other
// configurations. See CascadiaSettings::BuildSettings for more details.
void TerminalPage::_SplitPane(const SplitDirection splitDirection,
const SplitType splitMode,
const float splitSize,
std::shared_ptr<Pane> newPane)
const NewTerminalArgs& newTerminalArgs)
{
const auto focusedTab{ _GetFocusedTabImpl() };
@@ -1503,52 +1638,104 @@ namespace winrt::TerminalApp::implementation
return;
}
_SplitPane(*focusedTab, splitDirection, splitSize, newPane);
_SplitPane(*focusedTab, splitDirection, splitMode, splitSize, newTerminalArgs);
}
// Method Description:
// - Split the focused pane of the given tab, either horizontally or vertically, and place the
// given pane accordingly
// given TermControl into the newly created pane.
// Arguments:
// - tab: The tab that is going to be split.
// - newPane: the pane to add to our tree of panes
// - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the
// new pane should be split from its parent.
// - splitSize: the size of the split
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
// - newTerminalArgs: An object that may contain a blob of parameters to
// control which profile is created and with possible other
// configurations. See CascadiaSettings::BuildSettings for more details.
void TerminalPage::_SplitPane(TerminalTab& tab,
const SplitDirection splitDirection,
const SplitType splitMode,
const float splitSize,
std::shared_ptr<Pane> newPane)
const NewTerminalArgs& newTerminalArgs)
{
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
auto realSplitType = splitDirection;
if (realSplitType == SplitDirection::Automatic)
try
{
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
}
TerminalSettingsCreateResult controlSettings{ nullptr };
Profile profile{ nullptr };
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
if (!canSplit)
{
return;
}
_UnZoomIfNeeded();
tab.SplitPane(realSplitType, splitSize, newPane);
// After GH#6586, the control will no longer focus itself
// automatically when it's finished being laid out. Manually focus
// the control here instead.
if (_startupState == StartupState::Initialized)
{
if (const auto control = _GetActiveControl())
if (splitMode == SplitType::Duplicate)
{
control.Focus(FocusState::Programmatic);
profile = tab.GetFocusedProfile();
if (profile)
{
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
profile = GetClosestProfileForDuplicationOfProfile(profile);
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
}
}
// TODO: GH#5047 - In the future, we should get the Profile of
// the focused pane, and use that to build a new instance of the
// settings so we can duplicate this tab/pane.
//
// Currently, if the profile doesn't exist anymore in our
// settings, we'll silently do nothing.
//
// In the future, it will be preferable to just duplicate the
// current control's settings, but we can't do that currently,
// because we won't be able to create a new instance of the
// connection without keeping an instance of the original Profile
// object around.
}
if (!profile)
{
profile = _settings.GetProfileForArgs(newTerminalArgs);
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
}
const auto controlConnection = _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
const winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
auto realSplitType = splitDirection;
if (realSplitType == SplitDirection::Automatic)
{
realSplitType = tab.PreCalculateAutoSplit(availableSpace);
}
const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
if (!canSplit)
{
return;
}
auto newControl = _InitControl(controlSettings, controlConnection);
// Hookup our event handlers to the new terminal
_RegisterTerminalEvents(newControl);
_UnZoomIfNeeded();
tab.SplitPane(realSplitType, splitSize, profile, newControl);
// After GH#6586, the control will no longer focus itself
// automatically when it's finished being laid out. Manually focus
// the control here instead.
if (_startupState == StartupState::Initialized)
{
if (const auto control = _GetActiveControl())
{
control.Focus(FocusState::Programmatic);
}
}
}
CATCH_LOG();
}
// Method Description:
@@ -1613,11 +1800,11 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Gets the title of the currently focused terminal control. If there
// isn't a control selected for any reason, returns "Windows Terminal"
// isn't a control selected for any reason, returns "Terminal"
// Arguments:
// - <none>
// Return Value:
// - the title of the focused control if there is one, else "Windows Terminal"
// - the title of the focused control if there is one, else "Terminal"
hstring TerminalPage::Title()
{
if (_settings.GlobalSettings().ShowTitleInTitlebar())
@@ -1635,7 +1822,7 @@ namespace winrt::TerminalApp::implementation
CATCH_LOG();
}
}
return { L"Windows Terminal" };
return { L"Terminal" };
}
// Method Description:
@@ -1817,22 +2004,6 @@ namespace winrt::TerminalApp::implementation
}
}
if (_settings.GlobalSettings().TrimPaste())
{
std::wstring_view textView{ text };
const auto pos = textView.find_last_not_of(L"\t\n\v\f\r ");
if (pos == textView.npos)
{
// Text is all white space, nothing to paste
co_return;
}
else if (const auto toRemove = textView.size() - 1 - pos; toRemove > 0)
{
textView.remove_suffix(toRemove);
text = { textView };
}
}
bool warnMultiLine = _settings.GlobalSettings().WarnAboutMultiLinePaste();
if (warnMultiLine)
{
@@ -2056,7 +2227,7 @@ namespace winrt::TerminalApp::implementation
{
if (target == SettingsTarget::SettingsUI)
{
OpenSettingsUI();
_OpenSettingsUI();
}
else
{
@@ -2133,96 +2304,6 @@ namespace winrt::TerminalApp::implementation
return term;
}
// Method Description:
// - Creates a pane and returns a shared_ptr to it
// - The caller should handle where the pane goes after creation,
// either to split an already existing pane or to create a new tab with it
// Arguments:
// - newTerminalArgs: an object that may contain a blob of parameters to
// control which profile is created and with possible other
// configurations. See CascadiaSettings::BuildSettings for more details.
// - duplicate: a boolean to indicate whether the pane we create should be
// a duplicate of the currently focused pane
// - existingConnection: optionally receives a connection from the outside
// world instead of attempting to create one
std::shared_ptr<Pane> TerminalPage::_MakePane(const NewTerminalArgs& newTerminalArgs, const bool duplicate, TerminalConnection::ITerminalConnection existingConnection)
{
TerminalSettingsCreateResult controlSettings{ nullptr };
Profile profile{ nullptr };
if (duplicate)
{
const auto focusedTab{ _GetFocusedTabImpl() };
if (focusedTab)
{
profile = focusedTab->GetFocusedProfile();
if (profile)
{
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
profile = GetClosestProfileForDuplicationOfProfile(profile);
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
}
}
}
}
if (!profile)
{
profile = _settings.GetProfileForArgs(newTerminalArgs);
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
}
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
if (existingConnection)
{
connection.Resize(controlSettings.DefaultSettings().InitialRows(), controlSettings.DefaultSettings().InitialCols());
}
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
if (_settings.GlobalSettings().DebugFeaturesEnabled())
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
if (bothAltsPressed)
{
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
}
}
const auto control = _InitControl(controlSettings, connection);
_RegisterTerminalEvents(control);
auto resultPane = std::make_shared<Pane>(profile, control);
if (debugConnection) // this will only be set if global debugging is on and tap is active
{
auto newControl = _InitControl(controlSettings, debugConnection);
_RegisterTerminalEvents(newControl);
// Split (auto) with the debug tap.
auto debugPane = std::make_shared<Pane>(profile, newControl);
// Since we're doing this split directly on the pane (instead of going through TerminalTab,
// we need to handle the panes 'active' states
// Set the pane we're splitting to active (otherwise Split will not do anything)
resultPane->SetActive();
auto [original, _] = resultPane->Split(SplitDirection::Automatic, 0.5f, debugPane);
// Set the non-debug pane as active
resultPane->ClearActive();
original->SetActive();
}
return resultPane;
}
// Method Description:
// - Hook up keybindings, and refresh the UI of the terminal.
// This includes update the settings of all the tabs according
@@ -2787,7 +2868,7 @@ namespace winrt::TerminalApp::implementation
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, connection));
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
// Request a summon of this window to the foreground
_SummonWindowRequestedHandlers(*this, nullptr);
@@ -2803,7 +2884,7 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Return Value:
// - <none>
void TerminalPage::OpenSettingsUI()
void TerminalPage::_OpenSettingsUI()
{
// If we're holding the settings tab's switch command, don't create a new one, switch to the existing one.
if (!_settingsTab)
@@ -3421,7 +3502,7 @@ namespace winrt::TerminalApp::implementation
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
OpenSettingsUI();
_OpenSettingsUI();
}
// Method Description:

View File

@@ -14,12 +14,17 @@
static constexpr uint32_t DefaultRowsToScroll{ 3 };
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
// fwdecl unittest classes
namespace TerminalAppLocalTests
{
class TabTests;
class SettingsTests;
};
}
namespace Microsoft::Terminal::Core
{
class ControlKeyStates;
}
namespace winrt::TerminalApp::implementation
{
@@ -122,8 +127,6 @@ namespace winrt::TerminalApp::implementation
bool IsQuakeWindow() const noexcept;
bool IsElevated() const noexcept;
void OpenSettingsUI();
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
// -------------------------------- WinRT Events ---------------------------------
@@ -212,6 +215,7 @@ namespace winrt::TerminalApp::implementation
void _OpenNewTabDropdown();
HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
void _CreateNewTabFromPane(std::shared_ptr<Pane> pane);
void _CreateNewTabWithProfileAndSettings(const Microsoft::Terminal::Settings::Model::Profile& profile, const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettings settings);
winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);
@@ -225,6 +229,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();
@@ -299,12 +305,14 @@ namespace winrt::TerminalApp::implementation
void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference<uint32_t>& rowsToScroll);
void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> newPane);
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
const float splitSize = 0.5f,
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
void _SplitPane(TerminalTab& tab,
const Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> newPane);
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
const float splitSize = 0.5f,
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
void _ToggleSplitOrientation();
@@ -351,10 +359,6 @@ namespace winrt::TerminalApp::implementation
winrt::Microsoft::Terminal::Control::TermControl _InitControl(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection);
std::shared_ptr<Pane> _MakePane(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr,
const bool duplicate = false,
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
void _RefreshUIForSettingsReload();
void _SetNonClientAreaColors(const Windows::UI::Color& selectedTabColor);
@@ -370,6 +374,8 @@ namespace winrt::TerminalApp::implementation
void _UnZoomIfNeeded();
void _OpenSettingsUI();
static int _ComputeScrollDelta(ScrollDirection scrollDirection, const uint32_t rowsToScroll);
static uint32_t _ReadSystemRowsToScroll();

View File

@@ -21,7 +21,8 @@
</Grid.RowDefinitions>
<local:TabRowControl x:Name="TabRow"
Grid.Row="0" />
Grid.Row="0"
KeyUp="_KeyDownHandler" />
<StackPanel Grid.Row="1">
<mux:InfoBar x:Name="KeyboardServiceWarningInfoBar"

View File

@@ -25,6 +25,18 @@ namespace winrt
namespace winrt::TerminalApp::implementation
{
TerminalTab::TerminalTab(const Profile& profile, const TermControl& control)
{
_rootPane = std::make_shared<Pane>(profile, control, true);
_rootPane->Id(_nextPaneId);
_activePane = _rootPane;
_mruPanes.insert(_mruPanes.begin(), _nextPaneId);
++_nextPaneId;
_Setup();
}
TerminalTab::TerminalTab(std::shared_ptr<Pane> rootPane)
{
_rootPane = rootPane;
@@ -52,9 +64,8 @@ namespace winrt::TerminalApp::implementation
// focus the first one.
if (_activePane == nullptr)
{
const auto firstPane = _rootPane->FindPane(firstId);
firstPane->SetActive();
_activePane = firstPane;
_rootPane->FocusPane(firstId);
_activePane = _rootPane->GetActivePane();
}
// If the focused pane is a leaf, add it to the MRU panes
if (const auto id = _activePane->Id())
@@ -492,48 +503,39 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Split the focused pane in our tree of panes, and place the
// given pane into the tree of panes according to the split
// given TermControl into the newly created pane.
// Arguments:
// - splitType: The type of split we want to create
// - splitSize: The size of the split we want to create
// - pane: The new pane to add to the tree of panes; note that this pane
// could itself be a parent pane/the root node of a tree of panes
// - splitType: The type of split we want to create.
// - profile: The profile GUID to associate with the newly created pane.
// - control: A TermControl to use in the new pane.
// Return Value:
// - <none>
void TerminalTab::SplitPane(SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> pane)
const Profile& profile,
TermControl& control)
{
// Add the new event handlers to the new pane(s)
// and update their ids.
pane->WalkTree([&](auto p) {
_AttachEventHandlersToPane(p);
if (p->_IsLeaf())
{
p->Id(_nextPaneId);
_AttachEventHandlersToControl(p->Id().value(), p->_control);
_nextPaneId++;
}
return false;
});
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
const auto activePaneId = _activePane->Id();
// Depending on which direction will be split, the new pane can be
// either the first or second child, but this will always return the
// original pane first.
auto [original, newPane] = _activePane->Split(splitType, splitSize, pane);
auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control);
// The active pane has an id if it is a leaf
if (activePaneId)
{
original->Id(activePaneId.value());
}
newPane->Id(_nextPaneId);
++_nextPaneId;
_activePane = original;
// Add a event handlers to the new panes' GotFocus event. When the pane
// gains focus, we'll mark it as the new active pane.
_AttachEventHandlersToControl(newPane->Id().value(), control);
_AttachEventHandlersToPane(original);
_AttachEventHandlersToPane(newPane);
// Immediately update our tracker of the focused pane now. If we're
// splitting panes during startup (from a commandline), then it's

View File

@@ -21,6 +21,7 @@ namespace winrt::TerminalApp::implementation
struct TerminalTab : TerminalTabT<TerminalTab, TabBase>
{
public:
TerminalTab(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile, const winrt::Microsoft::Terminal::Control::TermControl& control);
TerminalTab(std::shared_ptr<Pane> rootPane);
// Called after construction to perform the necessary setup, which relies on weak_ptr
@@ -39,7 +40,8 @@ namespace winrt::TerminalApp::implementation
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize,
std::shared_ptr<Pane> newPane);
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
winrt::Microsoft::Terminal::Control::TermControl& control);
void ToggleSplitOrientation();
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);

View File

@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// TitlebarControl.xaml.cpp
// Implementation of the TitlebarControl class
//
@@ -24,6 +23,14 @@ 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();
@@ -93,4 +100,48 @@ 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,14 +1,8 @@
// 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
@@ -17,6 +11,12 @@ 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,11 +10,25 @@ 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

@@ -3,4 +3,5 @@
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.0-prerelease.210913003" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
</packages>

View File

@@ -5,7 +5,6 @@
#include "ConptyConnection.h"
#include <UserEnv.h>
#include <winternl.h>
#include "ConptyConnection.g.cpp"
@@ -61,72 +60,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
return S_OK;
}
// Function Description:
// - Promotes a starting directory provided to a WSL invocation to a commandline argument.
// This is necessary because WSL has some modicum of support for linux-side directories (!) which
// CreateProcess never will.
static std::tuple<std::wstring, std::wstring> _tryMangleStartingDirectoryForWSL(std::wstring_view commandLine, std::wstring_view startingDirectory)
{
do
{
if (startingDirectory.size() > 0 && commandLine.size() >= 3)
{ // "wsl" is three characters; this is a safe bet. no point in doing it if there's no starting directory though!
// Find the first space, quote or the end of the string -- we'll look for wsl before that.
const auto terminator{ commandLine.find_first_of(LR"(" )", 1) }; // look past the first character in case it starts with "
const auto start{ til::at(commandLine, 0) == L'"' ? 1 : 0 };
const std::filesystem::path executablePath{ commandLine.substr(start, terminator - start) };
const auto executableFilename{ executablePath.filename().wstring() };
if (executableFilename == L"wsl" || executableFilename == L"wsl.exe")
{
// We've got a WSL -- let's just make sure it's the right one.
if (executablePath.has_parent_path())
{
std::wstring systemDirectory{};
if (FAILED(wil::GetSystemDirectoryW(systemDirectory)))
{
break; // just bail out.
}
if (executablePath.parent_path().wstring() != systemDirectory)
{
break; // it wasn't in system32!
}
}
else
{
// assume that unqualified WSL is the one in system32 (minor danger)
}
const auto arguments{ terminator == std::wstring_view::npos ? std::wstring_view{} : commandLine.substr(terminator + 1) };
if (arguments.find(L"--cd") != std::wstring_view::npos)
{
break; // they've already got a --cd!
}
const auto tilde{ arguments.find_first_of(L'~') };
if (tilde != std::wstring_view::npos)
{
if (tilde + 1 == arguments.size() || til::at(arguments, tilde + 1) == L' ')
{
// We want to suppress --cd if they have added a bare ~ to their commandline (they conflict).
break;
}
// Tilde followed by non-space should be okay (like, wsl -d Debian ~/blah.sh)
}
return {
fmt::format(LR"("{}" --cd "{}" {})", executablePath.wstring(), startingDirectory, arguments),
std::wstring{}
};
}
}
} while (false);
return {
std::wstring{ commandLine },
std::wstring{ startingDirectory }
};
}
// Function Description:
// - launches the client application attached to the new pseudoconsole
HRESULT ConptyConnection::_LaunchAttachedClient() noexcept
@@ -165,11 +98,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
environment.clear();
});
{
const auto newEnvironmentBlock{ Utils::CreateEnvironmentBlock() };
// Populate the environment map with the current environment.
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment, newEnvironmentBlock.get()));
}
// Populate the environment map with the current environment.
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment));
{
// Convert connection Guid to string and ignore the enclosing '{}'.
@@ -233,7 +163,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
siEx.StartupInfo.lpTitle = mutableTitle.data();
}
auto [newCommandLine, newStartingDirectory] = _tryMangleStartingDirectoryForWSL(cmdline, _startingDirectory);
auto [newCommandLine, newStartingDirectory] = Utils::MangleStartingDirectoryForWSL(cmdline, _startingDirectory);
const wchar_t* const startingDirectory = newStartingDirectory.size() > 0 ? newStartingDirectory.c_str() : nullptr;
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(

View File

@@ -2,4 +2,5 @@
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="vcpkg-cpprestsdk" version="2.10.14" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
</packages>

View File

@@ -3,18 +3,16 @@
#include "pch.h"
#include "ControlCore.h"
#include <argb.h>
#include <DefaultSettings.h>
#include <unicode.hpp>
#include <Utf16Parser.hpp>
#include <Utils.h>
#include <WinUser.h>
#include <LibraryResources.h>
#include "EventArgs.h"
#include "../../types/inc/GlyphWidth.hpp"
#include "../../types/inc/Utils.hpp"
#include "../../buffer/out/search.h"
#include "../../renderer/atlas/AtlasEngine.h"
#include "../../renderer/dx/DxRenderer.hpp"
#include "ControlCore.g.cpp"
@@ -204,8 +202,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const double actualHeight,
const double compositionScale)
{
assert(_settings);
_panelWidth = actualWidth;
_panelHeight = actualHeight;
_compositionScale = compositionScale;
@@ -226,16 +222,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return false;
}
if (Feature_AtlasEngine::IsEnabled() && _settings.UseAtlasEngine())
{
_renderEngine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
}
else
{
_renderEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
}
_renderer->AddRenderEngine(_renderEngine.get());
// Set up the DX Engine
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
_renderer->AddRenderEngine(dxEngine.get());
_renderEngine = std::move(dxEngine);
// Initialize our font with the renderer
// We don't have to care about DPI. We'll get a change message immediately if it's not 96
@@ -281,12 +271,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
_renderEngine->SetIntenseIsBold(_settings.IntenseIsBold());
_updateAntiAliasingMode();
_updateAntiAliasingMode(_renderEngine.get());
// GH#5098: Inform the engine of the opacity of the default text background.
// GH#11315: Always do this, even if they don't have acrylic on.
const auto backgroundIsOpaque = _settings.Opacity() == 1.0 && _settings.BackgroundImage().empty();
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.Opacity()));
THROW_IF_FAILED(_renderEngine->Enable());
@@ -627,7 +616,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
_updateAntiAliasingMode();
_updateAntiAliasingMode(_renderEngine.get());
// Refresh our font with the renderer
const auto actualFontOldSize = _actualFont.GetSize();
@@ -661,24 +650,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void ControlCore::_updateAntiAliasingMode()
void ControlCore::_updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine)
{
D2D1_TEXT_ANTIALIAS_MODE mode;
// Update DxEngine's AntialiasingMode
switch (_settings.AntialiasingMode())
{
case TextAntialiasingMode::Cleartype:
mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
break;
case TextAntialiasingMode::Aliased:
mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
break;
case TextAntialiasingMode::Grayscale:
default:
mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
break;
}
_renderEngine->SetAntialiasingMode(mode);
}
// Method Description:
@@ -983,6 +970,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
textData += text;
}
const auto bgColor = _terminal->GetAttributeColors({}).second;
// convert text to HTML format
// GH#5347 - Don't provide a title for the generated HTML, as many
// web applications will paste the title first, followed by the HTML
@@ -991,7 +980,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TextBuffer::GenHTML(bufferData,
_actualFont.GetUnscaledSize().Y,
_actualFont.GetFaceName(),
til::color{ _settings.DefaultBackground() }) :
bgColor) :
"";
// convert to RTF format
@@ -999,7 +988,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TextBuffer::GenRTF(bufferData,
_actualFont.GetUnscaledSize().Y,
_actualFont.GetFaceName(),
til::color{ _settings.DefaultBackground() }) :
bgColor) :
"";
if (!_settings.CopyOnSelect())
@@ -1296,12 +1285,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
::Search search(*GetUiaData(), text.c_str(), direction, sensitivity);
auto lock = _terminal->LockForWriting();
if (search.FindNext())
const bool foundMatch{ search.FindNext() };
if (foundMatch)
{
_terminal->SetBlockSelection(false);
search.Select();
_renderer->TriggerSelection();
}
// Raise a FoundMatch event, which the control will use to notify
// narrator if there was any results in the buffer
auto foundResults = winrt::make_self<implementation::FoundResultsArgs>(foundMatch);
_FoundMatchHandlers(*this, *foundResults);
}
void ControlCore::SetBackgroundOpacity(const double opacity)
@@ -1309,8 +1304,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_renderEngine)
{
auto lock = _terminal->LockForWriting();
const auto backgroundIsOpaque = opacity == 1.0 && _settings.BackgroundImage().empty();
_renderEngine->SetDefaultTextBackgroundOpacity(static_cast<float>(backgroundIsOpaque));
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(opacity));
}
}

View File

@@ -15,8 +15,11 @@
#pragma once
#include "EventArgs.h"
#include "ControlCore.g.h"
#include "../../renderer/base/Renderer.hpp"
#include "../../renderer/dx/DxRenderer.hpp"
#include "../../renderer/uia/UiaRenderer.hpp"
#include "../../cascadia/TerminalCore/Terminal.hpp"
#include "../buffer/out/search.h"
#include "cppwinrt_utils.h"
@@ -168,6 +171,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TYPED_EVENT(RaiseNotice, IInspectable, Control::NoticeEventArgs);
TYPED_EVENT(TransparencyChanged, IInspectable, Control::TransparencyChangedEventArgs);
TYPED_EVENT(ReceivedOutput, IInspectable, IInspectable);
TYPED_EVENT(FoundMatch, IInspectable, Control::FoundResultsArgs);
// clang-format on
private:
@@ -185,7 +189,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// As _renderer has a dependency on _renderEngine (through a raw pointer)
// we must ensure the _renderer is deallocated first.
// (C++ class members are destroyed in reverse order.)
std::unique_ptr<::Microsoft::Console::Render::IRenderEngine> _renderEngine{ nullptr };
std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr };
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr };
IControlSettings _settings{ nullptr };
@@ -245,7 +249,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
#pragma endregion
void _raiseReadOnlyWarning();
void _updateAntiAliasingMode();
void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine);
void _connectionOutputHandler(const hstring& hstr);
void _updateHoveredCell(const std::optional<til::point> terminalPosition);

View File

@@ -110,6 +110,7 @@ namespace Microsoft.Terminal.Control
event Windows.Foundation.TypedEventHandler<Object, NoticeEventArgs> RaiseNotice;
event Windows.Foundation.TypedEventHandler<Object, TransparencyChangedEventArgs> TransparencyChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> ReceivedOutput;
event Windows.Foundation.TypedEventHandler<Object, FoundResultsArgs> FoundMatch;
};
}

View File

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

View File

@@ -11,3 +11,4 @@
#include "ScrollPositionChangedArgs.g.cpp"
#include "RendererWarningArgs.g.cpp"
#include "TransparencyChangedEventArgs.g.cpp"
#include "FoundResultsArgs.g.cpp"

View File

@@ -11,6 +11,7 @@
#include "ScrollPositionChangedArgs.g.h"
#include "RendererWarningArgs.g.h"
#include "TransparencyChangedEventArgs.g.h"
#include "FoundResultsArgs.g.h"
#include "cppwinrt_utils.h"
namespace winrt::Microsoft::Terminal::Control::implementation
@@ -131,4 +132,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
WINRT_PROPERTY(double, Opacity);
};
struct FoundResultsArgs : public FoundResultsArgsT<FoundResultsArgs>
{
public:
FoundResultsArgs(const bool foundMatch) :
_FoundMatch(foundMatch)
{
}
WINRT_PROPERTY(bool, FoundMatch);
};
}

View File

@@ -67,4 +67,10 @@ namespace Microsoft.Terminal.Control
{
Double Opacity { get; };
}
runtimeclass FoundResultsArgs
{
Boolean FoundMatch { get; };
}
}

View File

@@ -27,11 +27,10 @@ namespace Microsoft.Terminal.Control
interface IControlSettings requires Microsoft.Terminal.Core.ICoreSettings, Microsoft.Terminal.Control.IControlAppearance
{
String ProfileName;
String ProfileSource;
Boolean UseAcrylic;
ScrollbarState ScrollState;
Boolean UseAtlasEngine;
String FontFace;
Int32 FontSize;
Windows.UI.Text.FontWeight FontWeight;

View File

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

View File

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

View File

@@ -200,4 +200,12 @@ Please either install the missing font or choose another one.</value>
<data name="TermControlReadOnly" xml:space="preserve">
<value>Read-only mode is enabled.</value>
</data>
<data name="SearchBox_MatchesAvailable" xml:space="preserve">
<value>Results found</value>
<comment>Announced to a screen reader when the user searches for some text and there are matches for that text in the terminal.</comment>
</data>
<data name="SearchBox_NoMatches" xml:space="preserve">
<value>No results found</value>
<comment>Announced to a screen reader when the user searches for some text and there are no matches for that text in the terminal.</comment>
</data>
</root>

View File

@@ -3,16 +3,17 @@
#include "pch.h"
#include "TermControl.h"
#include <argb.h>
#include <DefaultSettings.h>
#include <unicode.hpp>
#include <Utf16Parser.hpp>
#include <Utils.h>
#include <LibraryResources.h>
#include "TermControlAutomationPeer.h"
#include "../../types/inc/GlyphWidth.hpp"
#include "../../renderer/atlas/AtlasEngine.h"
#include "../../types/inc/Utils.hpp"
#include "TermControl.g.cpp"
#include "TermControlAutomationPeer.h"
using namespace ::Microsoft::Console::Types;
using namespace ::Microsoft::Console::VirtualTerminal;
@@ -82,6 +83,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_core.TransparencyChanged({ this, &TermControl::_coreTransparencyChanged });
_core.RaiseNotice({ this, &TermControl::_coreRaisedNotice });
_core.HoveredHyperlinkChanged({ this, &TermControl::_hoveredHyperlinkChanged });
_core.FoundMatch({ this, &TermControl::_coreFoundMatch });
_interactivity.OpenHyperlink({ this, &TermControl::_HyperlinkHandler });
_interactivity.ScrollPositionChanged({ this, &TermControl::_ScrollPositionChanged });
@@ -296,7 +298,37 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
_SetBackgroundImage(newAppearance);
if (!newAppearance.BackgroundImage().empty())
{
Windows::Foundation::Uri imageUri{ newAppearance.BackgroundImage() };
// Check if the image brush is already pointing to the image
// in the modified settings; if it isn't (or isn't there),
// set a new image source for the brush
auto imageSource = BackgroundImage().Source().try_as<Media::Imaging::BitmapImage>();
if (imageSource == nullptr ||
imageSource.UriSource() == nullptr ||
imageSource.UriSource().RawUri() != imageUri.RawUri())
{
// Note that BitmapImage handles the image load asynchronously,
// which is especially important since the image
// may well be both large and somewhere out on the
// internet.
Media::Imaging::BitmapImage image(imageUri);
BackgroundImage().Source(image);
}
// Apply stretch, opacity and alignment settings
BackgroundImage().Stretch(newAppearance.BackgroundImageStretchMode());
BackgroundImage().Opacity(newAppearance.BackgroundImageOpacity());
BackgroundImage().HorizontalAlignment(newAppearance.BackgroundImageHorizontalAlignment());
BackgroundImage().VerticalAlignment(newAppearance.BackgroundImageVerticalAlignment());
}
else
{
BackgroundImage().Source(nullptr);
}
// Update our control settings
const auto bg = newAppearance.DefaultBackground();
@@ -381,57 +413,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
// Method Description:
// - Sets background image and applies its settings (stretch, opacity and alignment)
// - Checks path validity
// Arguments:
// - newAppearance
// Return Value:
// - <none>
void TermControl::_SetBackgroundImage(const IControlAppearance& newAppearance)
{
if (newAppearance.BackgroundImage().empty())
{
BackgroundImage().Source(nullptr);
return;
}
Windows::Foundation::Uri imageUri{ nullptr };
try
{
imageUri = Windows::Foundation::Uri{ newAppearance.BackgroundImage() };
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
BackgroundImage().Source(nullptr);
return;
}
// Check if the image brush is already pointing to the image
// in the modified settings; if it isn't (or isn't there),
// set a new image source for the brush
auto imageSource = BackgroundImage().Source().try_as<Media::Imaging::BitmapImage>();
if (imageSource == nullptr ||
imageSource.UriSource() == nullptr ||
imageSource.UriSource().RawUri() != imageUri.RawUri())
{
// Note that BitmapImage handles the image load asynchronously,
// which is especially important since the image
// may well be both large and somewhere out on the
// internet.
Media::Imaging::BitmapImage image(imageUri);
BackgroundImage().Source(image);
}
// Apply stretch, opacity and alignment settings
BackgroundImage().Stretch(newAppearance.BackgroundImageStretchMode());
BackgroundImage().Opacity(newAppearance.BackgroundImageOpacity());
BackgroundImage().HorizontalAlignment(newAppearance.BackgroundImageHorizontalAlignment());
BackgroundImage().VerticalAlignment(newAppearance.BackgroundImageVerticalAlignment());
}
// Method Description:
// - Set up each layer's brush used to display the control's background.
// - Respects the settings for acrylic, background image and opacity from
@@ -712,8 +693,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_cursorTimer.emplace(std::move(cursorTimer));
// As of GH#6586, don't start the cursor timer immediately, and
// don't show the cursor initially. We'll show the cursor and start
// the timer when the control is first focused. cursorTimer.Start();
_core.CursorOn(false);
// the timer when the control is first focused.
//
// As of GH#11411, turn on the cursor if we've already been marked
// as focused. We suspect that it's possible for the Focused event
// to fire before the LayoutUpdated. In that case, the
// _GotFocusHandler would mark us _focused, but find that a
// _cursorTimer doesn't exist, and it would never turn on the
// cursor. To mitigate, we'll initialize the cursor's 'on' state
// with `_focused` here.
_core.CursorOn(_focused);
}
else
{
@@ -773,12 +762,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);
}
@@ -873,6 +865,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.
@@ -906,11 +903,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
@@ -988,7 +980,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()))
@@ -1827,7 +1819,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const winrt::Windows::Foundation::Size initialSize{ cols, rows };
return GetProposedDimensions(settings, dpi, initialSize);
return GetProposedDimensions(initialSize,
settings.FontSize(),
settings.FontWeight(),
settings.FontFace(),
settings.ScrollState(),
settings.Padding(),
dpi);
}
// Function Description:
@@ -1848,15 +1846,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// caller knows what monitor the control is about to appear on.
// Return Value:
// - a size containing the requested dimensions in pixels.
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars)
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
const int32_t& fontHeight,
const winrt::Windows::UI::Text::FontWeight& fontWeight,
const winrt::hstring& fontFace,
const ScrollbarState& scrollState,
const winrt::hstring& padding,
const uint32_t dpi)
{
const auto cols = ::base::saturated_cast<int>(initialSizeInChars.Width);
const auto rows = ::base::saturated_cast<int>(initialSizeInChars.Height);
const auto fontSize = settings.FontSize();
const auto fontWeight = settings.FontWeight();
const auto fontFace = settings.FontFace();
const auto scrollState = settings.ScrollState();
const auto padding = settings.Padding();
// Initialize our font information.
// The font width doesn't terribly matter, we'll only be using the
@@ -1865,39 +1864,28 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// The family is only used to determine if the font is truetype or
// not, but DX doesn't use that info at all.
// The Codepage is additionally not actually used by the DX engine at all.
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast<short>(fontSize) }, CP_UTF8, false };
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast<short>(fontHeight) }, CP_UTF8, false };
FontInfoDesired desiredFont = { actualFont };
// Create a DX engine and initialize it with our font and DPI. We'll
// then use it to measure how much space the requested rows and columns
// will take up.
// TODO: MSFT:21254947 - use a static function to do this instead of
// instantiating a DxEngine/AtlasEngine.
// instantiating a DxEngine
// GH#10211 - UNDER NO CIRCUMSTANCE should this fail. If it does, the
// whole app will crash instantaneously on launch, which is no good.
double scale;
if (Feature_AtlasEngine::IsEnabled() && settings.UseAtlasEngine())
{
auto engine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>();
LOG_IF_FAILED(engine->UpdateDpi(dpi));
LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont));
scale = engine->GetScaling();
}
else
{
auto engine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
LOG_IF_FAILED(engine->UpdateDpi(dpi));
LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont));
scale = engine->GetScaling();
}
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
LOG_IF_FAILED(dxEngine->UpdateDpi(dpi));
LOG_IF_FAILED(dxEngine->UpdateFont(desiredFont, actualFont));
const auto actualFontSize = actualFont.GetSize();
const auto scale = dxEngine->GetScaling();
const auto fontSize = actualFont.GetSize();
// UWP XAML scrollbars aren't guaranteed to be the same size as the
// ComCtl scrollbars, but it's certainly close enough.
const auto scrollbarSize = GetSystemMetricsForDpi(SM_CXVSCROLL, dpi);
double width = cols * actualFontSize.X;
double width = cols * fontSize.X;
// Reserve additional space if scrollbar is intended to be visible
if (scrollState == ScrollbarState::Visible)
@@ -1905,7 +1893,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
width += scrollbarSize;
}
double height = rows * actualFontSize.Y;
double height = rows * fontSize.Y;
const auto thickness = ParseThicknessFromPadding(padding);
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
width += scale * (thickness.Left + thickness.Right);
@@ -1965,7 +1953,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
return GetProposedDimensions(_settings, dpi, minSize);
return GetProposedDimensions(minSize,
_settings.FontSize(),
_settings.FontWeight(),
_settings.FontFace(),
_settings.ScrollState(),
_settings.Padding(),
dpi);
}
}
@@ -2060,7 +2054,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
@@ -2268,42 +2262,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
std::wstring fullPath{ item.Path() };
// Fix path for WSL
if (_settings.ProfileSource() == L"Windows.Terminal.Wsl")
{
std::replace(fullPath.begin(), fullPath.end(), L'\\', L'/');
if (fullPath.size() >= 2 && fullPath.at(1) == L':')
{
// C:/foo/bar -> Cc/foo/bar
fullPath.at(1) = til::tolower_ascii(fullPath.at(0));
// Cc/foo/bar -> /mnt/c/foo/bar
fullPath.replace(0, 1, L"/mnt/");
}
else
{
static constexpr std::wstring_view wslPathPrefixes[] = { L"//wsl.localhost/", L"//wsl$/" };
for (auto prefix : wslPathPrefixes)
{
if (til::starts_with(fullPath, prefix))
{
if (const auto idx = fullPath.find(L'/', prefix.size()); idx != std::wstring::npos)
{
// //wsl.localhost/Ubuntu-18.04/foo/bar -> /foo/bar
fullPath.erase(0, idx);
}
else
{
// //wsl.localhost/Ubuntu-18.04 -> /
fullPath = L"/";
}
break;
}
}
}
}
const auto containsSpaces = std::find(fullPath.begin(),
fullPath.end(),
L' ') != fullPath.end();
@@ -2316,7 +2274,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
allPaths += fullPath;
}
_core.PasteText(winrt::hstring{ allPaths });
}
}
@@ -2645,4 +2602,28 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
return _core.ReadEntireBuffer();
}
// Method Description:
// - Called when the core raises a FoundMatch event. That's done in response
// to us starting a search query with ControlCore::Search.
// - The args will tell us if there were or were not any results for that
// particular search. We'll use that to control what to announce to
// Narrator. When we have more elaborate search information to report, we
// may want to report that here. (see GH #3920)
// Arguments:
// - args: contains information about the results that were or were not found.
// Return Value:
// - <none>
void TermControl::_coreFoundMatch(const IInspectable& /*sender*/, const Control::FoundResultsArgs& args)
{
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this) })
{
automationPeer.RaiseNotificationEvent(
Automation::Peers::AutomationNotificationKind::ActionCompleted,
Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent,
args.FoundMatch() ? RS_(L"SearchBox_MatchesAvailable") : RS_(L"SearchBox_NoMatches"), // what to announce if results were found
L"SearchBoxResultAnnouncement" /* unique name for this group of notifications */);
}
}
}

View File

@@ -92,7 +92,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void Settings(IControlSettings newSettings);
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi);
static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars);
static Windows::Foundation::Size GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
const int32_t& fontSize,
const winrt::Windows::UI::Text::FontWeight& fontWeight,
const winrt::hstring& fontFace,
const ScrollbarState& scrollState,
const winrt::hstring& padding,
const uint32_t dpi);
void BellLightOn();
@@ -196,7 +202,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _UpdateSettingsFromUIThread(IControlSettings newSettings);
void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance);
void _ApplyUISettings(const IControlSettings&);
void _SetBackgroundImage(const IControlAppearance& newAppearance);
void _InitializeBackgroundBrush();
void _BackgroundColorChangedHandler(const IInspectable& sender, const IInspectable& args);
@@ -245,9 +250,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);
@@ -269,6 +274,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::fire_and_forget _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args);
void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args);
void _coreWarningBell(const IInspectable& sender, const IInspectable& args);
void _coreFoundMatch(const IInspectable& sender, const Control::FoundResultsArgs& args);
};
}

View File

@@ -147,7 +147,6 @@
<ProjectReference Include="..\..\types\lib\types.vcxproj" />
<ProjectReference Include="..\..\buffer\out\lib\bufferout.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\renderer\base\lib\base.vcxproj" />
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj" />
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj" />
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj" />
<ProjectReference Include="..\..\terminal\parser\lib\parser.vcxproj" />

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
</packages>

View File

@@ -1,228 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// A lot of code was taken from
// https://github.com/Maximus5/ConEmu/blob/master/src/ConEmu/ColorFix.cpp
// and then adjusted to fit our style guidelines
#include "pch.h"
#include <Windows.h>
#include "ColorFix.hpp"
static constexpr double gMinThreshold = 12.0;
static constexpr double gExpThreshold = 20.0;
static constexpr double gLStep = 5.0;
static constexpr double rad006 = 0.104719755119659774;
static constexpr double rad025 = 0.436332312998582394;
static constexpr double rad030 = 0.523598775598298873;
static constexpr double rad060 = 1.047197551196597746;
static constexpr double rad063 = 1.099557428756427633;
static constexpr double rad180 = 3.141592653589793238;
static constexpr double rad275 = 4.799655442984406336;
static constexpr double rad360 = 6.283185307179586476;
ColorFix::ColorFix(COLORREF color)
{
rgb = color;
_ToLab();
}
// Method Description:
// - Helper function to calculate HPrime
double ColorFix::_GetHPrimeFn(double x, double y)
{
if (x == 0 && y == 0)
{
return 0;
}
const auto hueAngle = atan2(x, y);
return hueAngle >= 0 ? hueAngle : hueAngle + rad360;
}
// Method Description:
// - Given 2 colors, computes the DeltaE value between them
// Arguments:
// - x1: the first color
// - x2: the second color
// Return Value:
// - The DeltaE value between x1 and x2
double ColorFix::_GetDeltaE(ColorFix x1, ColorFix x2)
{
constexpr double kSubL = 1;
constexpr double kSubC = 1;
constexpr double kSubH = 1;
// Delta L Prime
const double deltaLPrime = x2.L - x1.L;
// L Bar
const double lBar = (x1.L + x2.L) / 2;
// C1 & C2
const double c1 = sqrt(pow(x1.A, 2) + pow(x1.B, 2));
const double c2 = sqrt(pow(x2.A, 2) + pow(x2.B, 2));
// C Bar
const double cBar = (c1 + c2) / 2;
// A Prime 1
const double aPrime1 = x1.A + (x1.A / 2) * (1 - sqrt(pow(cBar, 7) / (pow(cBar, 7) + pow(25.0, 7))));
// A Prime 2
const double aPrime2 = x2.A + (x2.A / 2) * (1 - sqrt(pow(cBar, 7) / (pow(cBar, 7) + pow(25.0, 7))));
// C Prime 1
const double cPrime1 = sqrt(pow(aPrime1, 2) + pow(x1.B, 2));
// C Prime 2
const double cPrime2 = sqrt(pow(aPrime2, 2) + pow(x2.B, 2));
// C Bar Prime
const double cBarPrime = (cPrime1 + cPrime2) / 2;
// Delta C Prime
const double deltaCPrime = cPrime2 - cPrime1;
// S sub L
const double sSubL = 1 + ((0.015 * pow(lBar - 50, 2)) / sqrt(20 + pow(lBar - 50, 2)));
// S sub C
const double sSubC = 1 + 0.045 * cBarPrime;
// h Prime 1
const double hPrime1 = _GetHPrimeFn(x1.B, aPrime1);
// h Prime 2
const double hPrime2 = _GetHPrimeFn(x2.B, aPrime2);
// Delta H Prime
const double deltaHPrime = 0 == c1 || 0 == c2 ? 0 : 2 * sqrt(cPrime1 * cPrime2) * sin(abs(hPrime1 - hPrime2) <= rad180 ? hPrime2 - hPrime1 : (hPrime2 <= hPrime1 ? hPrime2 - hPrime1 + rad360 : hPrime2 - hPrime1 - rad360) / 2);
// H Bar Prime
const double hBarPrime = (abs(hPrime1 - hPrime2) > rad180) ? (hPrime1 + hPrime2 + rad360) / 2 : (hPrime1 + hPrime2) / 2;
// T
const double t = 1 - 0.17 * cos(hBarPrime - rad030) + 0.24 * cos(2 * hBarPrime) + 0.32 * cos(3 * hBarPrime + rad006) - 0.20 * cos(4 * hBarPrime - rad063);
// S sub H
const double sSubH = 1 + 0.015 * cBarPrime * t;
// R sub T
const double rSubT = -2 * sqrt(pow(cBarPrime, 7) / (pow(cBarPrime, 7) + pow(25.0, 7))) * sin(rad060 * exp(-pow((hBarPrime - rad275) / rad025, 2)));
// Put it all together!
const double lightness = deltaLPrime / (kSubL * sSubL);
const double chroma = deltaCPrime / (kSubC * sSubC);
const double hue = deltaHPrime / (kSubH * sSubH);
return sqrt(pow(lightness, 2) + pow(chroma, 2) + pow(hue, 2) + rSubT * chroma * hue);
}
// Method Description:
// - Populates our L, A, B values, based on our r, g, b values
// - Converts a color in rgb format to a color in lab format
// - Reference: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
void ColorFix::_ToLab()
{
double var_R = r / 255.0;
double var_G = g / 255.0;
double var_B = b / 255.0;
var_R = var_R > 0.04045 ? pow(((var_R + 0.055) / 1.055), 2.4) : var_R / 12.92;
var_G = var_G > 0.04045 ? pow(((var_G + 0.055) / 1.055), 2.4) : var_G / 12.92;
var_B = var_B > 0.04045 ? pow(((var_B + 0.055) / 1.055), 2.4) : var_B / 12.92;
var_R = var_R * 100.;
var_G = var_G * 100.;
var_B = var_B * 100.;
//Observer. = 2 degrees, Illuminant = D65
const double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
const double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
const double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
double var_X = X / 95.047; //ref_X = 95.047 (Observer= 2 degrees, Illuminant= D65)
double var_Y = Y / 100.000; //ref_Y = 100.000
double var_Z = Z / 108.883; //ref_Z = 108.883
var_X = var_X > 0.008856 ? pow(var_X, (1. / 3.)) : (7.787 * var_X) + (16. / 116.);
var_Y = var_Y > 0.008856 ? pow(var_Y, (1. / 3.)) : (7.787 * var_Y) + (16. / 116.);
var_Z = var_Z > 0.008856 ? pow(var_Z, (1. / 3.)) : (7.787 * var_Z) + (16. / 116.);
L = (116. * var_Y) - 16.;
A = 500. * (var_X - var_Y);
B = 200. * (var_Y - var_Z);
}
// Method Description:
// - Populates our r, g, b values, based on our L, A, B values
// - Converts a color in lab format to a color in rgb format
// - Reference: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
void ColorFix::_ToRGB()
{
double var_Y = (L + 16.) / 116.;
double var_X = A / 500. + var_Y;
double var_Z = var_Y - B / 200.;
var_Y = (pow(var_Y, 3) > 0.008856) ? pow(var_Y, 3) : (var_Y - 16. / 116.) / 7.787;
var_X = (pow(var_X, 3) > 0.008856) ? pow(var_X, 3) : (var_X - 16. / 116.) / 7.787;
var_Z = (pow(var_Z, 3) > 0.008856) ? pow(var_Z, 3) : (var_Z - 16. / 116.) / 7.787;
double X = 95.047 * var_X; //ref_X = 95.047 (Observer= 2 degrees, Illuminant= D65)
double Y = 100.000 * var_Y; //ref_Y = 100.000
double Z = 108.883 * var_Z; //ref_Z = 108.883
var_X = X / 100.; //X from 0 to 95.047 (Observer = 2 degrees, Illuminant = D65)
var_Y = Y / 100.; //Y from 0 to 100.000
var_Z = Z / 100.; //Z from 0 to 108.883
double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
var_R = var_R > 0.0031308 ? 1.055 * pow(var_R, (1 / 2.4)) - 0.055 : var_R = 12.92 * var_R;
var_G = var_G > 0.0031308 ? 1.055 * pow(var_G, (1 / 2.4)) - 0.055 : var_G = 12.92 * var_G;
var_B = var_B > 0.0031308 ? 1.055 * pow(var_B, (1 / 2.4)) - 0.055 : var_B = 12.92 * var_B;
r = (BYTE)std::clamp(var_R * 255., 0., 255.);
g = (BYTE)std::clamp(var_G * 255., 0., 255.);
b = (BYTE)std::clamp(var_B * 255., 0., 255.);
}
// Method Description:
// - Given foreground and background colors, change the foreground color to
// make it more perceivable if necessary
// - Arguments:
// - fg: the foreground color
// - bg: the background color
// - Return Value:
// - The foreground color after performing any necessary changes to make it more perceivable
COLORREF ColorFix::GetPerceivableColor(COLORREF fg, COLORREF bg)
{
ColorFix backLab(bg);
ColorFix frontLab(fg);
const double de1 = _GetDeltaE(frontLab, backLab);
if (de1 < gMinThreshold)
{
for (int i = 0; i <= 1; i++)
{
const double step = (i == 0) ? gLStep : -gLStep;
frontLab.L += step;
while (((i == 0) && (frontLab.L <= 100)) || ((i == 1) && (frontLab.L >= 0)))
{
const double de2 = _GetDeltaE(frontLab, backLab);
if (de2 >= gExpThreshold)
{
frontLab._ToRGB();
return frontLab.rgb;
}
frontLab.L += step;
}
}
}
return frontLab.rgb;
}

View File

@@ -1,49 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- ColorFix
Abstract:
- Implementation of perceptual color nudging, which allows the Terminal
to slightly shift the foreground color to make it more perceivable on
the current background (for cases where the foreground is very close
to being imperceivable on the background).
Author(s):
- Pankaj Bhojwani - Sep 2021
--*/
#pragma once
struct ColorFix
{
public:
ColorFix(COLORREF color);
static COLORREF GetPerceivableColor(COLORREF fg, COLORREF bg);
// RGB
union
{
struct
{
BYTE r, g, b, dummy;
};
COLORREF rgb;
};
// Lab
struct
{
double L, A, B;
};
private:
static double _GetHPrimeFn(double x, double y);
static double _GetDeltaE(ColorFix x1, ColorFix x2);
void _ToLab();
void _ToRGB();
};

View File

@@ -67,6 +67,5 @@ namespace Microsoft.Terminal.Core
CursorStyle CursorShape;
UInt32 CursorHeight;
Boolean IntenseIsBright;
Boolean AdjustIndistinguishableColors;
};
}

View File

@@ -3,7 +3,6 @@
#pragma once
#include "../../terminal/adapter/DispatchTypes.hpp"
#include "../../terminal/input/terminalInput.hpp"
#include "../../buffer/out/TextAttribute.hpp"
#include "../../types/inc/Viewport.hpp"
@@ -48,9 +47,16 @@ namespace Microsoft::Terminal::Core
virtual bool SetDefaultForeground(const DWORD color) noexcept = 0;
virtual bool SetDefaultBackground(const DWORD color) noexcept = 0;
virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;
virtual bool EnableWin32InputMode(const bool win32InputMode) noexcept = 0;
virtual bool SetCursorKeysMode(const bool applicationMode) noexcept = 0;
virtual bool SetKeypadMode(const bool applicationMode) noexcept = 0;
virtual bool SetScreenMode(const bool reverseMode) noexcept = 0;
virtual bool EnableVT200MouseMode(const bool enabled) noexcept = 0;
virtual bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableSGRExtendedMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableButtonEventMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableAnyEventMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableAlternateScrollMode(const bool enabled) noexcept = 0;
virtual bool EnableXtermBracketedPasteMode(const bool enabled) noexcept = 0;
virtual bool IsXtermBracketedPasteModeEnabled() const = 0;

View File

@@ -53,8 +53,7 @@ Terminal::Terminal() :
_taskbarState{ 0 },
_taskbarProgress{ 0 },
_trimBlockSelection{ false },
_intenseIsBright{ true },
_adjustIndistinguishableColors{ true }
_intenseIsBright{ true }
{
auto dispatch = std::make_unique<TerminalDispatch>(*this);
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
@@ -176,16 +175,11 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
_defaultBg = newBackgroundColor.with_alpha(0);
_defaultFg = appearance.DefaultForeground();
_intenseIsBright = appearance.IntenseIsBright();
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
for (int i = 0; i < 16; i++)
{
_colorTable.at(i) = til::color{ appearance.GetColorTableEntry(i) };
}
if (_adjustIndistinguishableColors)
{
_MakeAdjustedColorArray();
}
CursorType cursorShape = CursorType::VerticalBar;
switch (appearance.CursorShape())
@@ -431,7 +425,21 @@ void Terminal::Write(std::wstring_view stringView)
{
auto lock = LockForWriting();
auto& cursor = _buffer->GetCursor();
const til::point cursorPosBefore{ cursor.GetPosition() };
_stateMachine->ProcessString(stringView);
const til::point cursorPosAfter{ cursor.GetPosition() };
// Firing the CursorPositionChanged event is very expensive so we try not to
// do that when the cursor does not need to be redrawn. We don't do this
// inside _AdjustCursorPosition, only once we're done writing the whole run
// of output.
if (cursorPosBefore != cursorPosAfter)
{
_NotifyTerminalCursorPositionChanged();
}
}
void Terminal::WritePastedText(std::wstring_view stringView)
@@ -1093,13 +1101,6 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)
COORD delta{ 0, -rowsPushedOffTopOfBuffer };
_buffer->GetRenderTarget().TriggerScroll(&delta);
}
// Firing the CursorPositionChanged event is very expensive so we try not to do that when
// the cursor does not need to be redrawn.
if (!cursor.IsDeferDrawing())
{
_NotifyTerminalCursorPositionChanged();
}
}
void Terminal::UserScrollViewport(const int viewTop)
@@ -1210,7 +1211,9 @@ try
{
const gsl::span<COLORREF> tableView = { _colorTable.data(), _colorTable.size() };
// First set up the basic 256 colors
Utils::InitializeColorTable(tableView);
Utils::Initialize256ColorTable(tableView);
// Then use fill the first 16 values with the Campbell scheme
Utils::InitializeCampbellColorTable(tableView);
// Then make sure all the values have an alpha of 255
Utils::SetColorTableAlpha(tableView, 0xff);
}

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