Compare commits

..

238 Commits

Author SHA1 Message Date
Dustin L. Howett
78854c8674 Migrate spelling-0.0.21 changes from main 2021-07-20 03:58:47 +02:00
Leonard Hecker
e7d00cab8e wip 2021-07-20 03:58:47 +02:00
Leonard Hecker
dbf9343320 wip 2021-07-20 01:07:48 +02:00
Leonard Hecker
a9c50f9bf7 wip 2021-07-18 01:16:33 +02:00
Carlos Zamora
8947909121 Add a KeyChordListener to the Settings UI (#10652)
## Summary of the Pull Request
Replaces the key chord editor in the actions page with a listener instead of a plain text box.

## References
#6900 - Settings UI Epic

## Detailed Description of the Pull Request / Additional comments
- `Actions` page:
   - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction`
   - `ProposedKeys` is now a `Control::KeyChord`
   - removes key chord validation (now we don't need it)
   - removes accept/cancel shortcuts (nowhere we could use it now)
- `KeyChordListener`:
   - `Keys`: dependency property that hooks us up to a system to the committed setting value
      - this is the key binding view model, which propagates the change to the settings model clone on "accept changes"
   - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box)
   - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected
   - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model
   - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation)

## Validation Steps Performed
- Tested a few key chords:
   - single key: <kbd>X</kbd>
   - key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd>
   - plain modifier: <kbd>Ctrl</kbd>
   - key that is used by text box: <kbd>Ctrl+A</kbd>
   - key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd>
   - key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd>
   - key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd>
- Known issue:
   - global key taken by Windows Terminal: (i.e. quake mode keybinding)
      - Behavior: global key binding executed
      - Expected: key chord recorded

## Demo
![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-16 22:11:55 +00:00
PankajBhojwani
293c36d42f Fix unfocused appearance editor not appearing/disappearing correctly (#10675)
## Summary of the Pull Request
Sends the additional xaml notification when the user presses the '+' or delete button for unfocused appearances

## PR Checklist
* [x] Closes #10673
* [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
It works now
2021-07-16 17:18:40 +00:00
Dustin Howett
cf8f411b8f Merge remote-tracking branch 'openconsole/inbox' 2021-07-15 20:56:58 -05:00
Dustin Howett
ee6ca81d70 Migrate OSS up to 84e30bcd3 2021-07-15 14:58:36 -05:00
Dustin Howett
b609266d29 Migrate OSS up to a0527a1db (Codepage Font Change) 2021-07-15 14:57:55 -05:00
Dustin Howett
59e2835736 Migrate OSS up to cdecfcd67 (GDI Surrogates) 2021-07-15 14:57:30 -05:00
Dustin Howett
3bf5436122 Migrate OSS up to d6da6ba35 2021-07-15 14:56:58 -05:00
Dustin Howett
5ea778b2b8 Migrate OSS up to 79a18f082 (A11y Block Range) 2021-07-15 14:56:46 -05:00
Dustin Howett
cabb83db61 Migrate OSS up to d3b9a780d 2021-07-15 14:56:06 -05:00
Dustin Howett
769e910e35 Migrate OSS up to b7fc0f2d4 (PTO/ETO Change) 2021-07-15 14:55:29 -05:00
Dustin Howett
1d02f82ab7 Migrate OSS up to 2770228e0 2021-07-15 14:31:16 -05:00
gabrielconl
84e30bcd3a Fix color picker minimum width (#10663)
Removed custom min width which caused a weird space on the right side. Corner radius and other properties should also work properly now.
2021-07-15 14:39:25 +00:00
Leonard Hecker
f68324cd09 Fix output stuttering using a ticket lock (#10653)
`SRWLOCK`, as used by `std::shared_mutex`, is a inherently unfair mutex
and makes no guarantee whatsoever whether a thread may acquire the lock
in a timely manner. This is problematic for our renderer which relies on
being able to acquire the lock in a timely and predictable manner.
Drawing stalls of up to one minute have been observed in tests.

This issue can be solved with a primitive ticket lock, which is 10x
slower than a `SRWLOCK` but still sufficiently fast for our use case
(10M locks per second per thread). It's likely that any non-trivial lock
duration will diminish the difference to "negligible".

## Validation Steps Performed

* It still blends ✔️
2021-07-14 23:41:22 +00:00
Leonard Hecker
fca87b2bb5 Clean up KeyChordSerialization (#10654)
This commit is a preparation for upcoming changes to
KeyChordSerialization for #7539 and #10203.  It introduces several
string helpers to simplify key chord parsing and get rid of our implicit
dependency on locale sensitive functions, which are known to behave
erratically.

Additionally key chord serialization used to depend on iteration order
of a hashmap which caused different strings to be returned for the same
key chord. This commit fixes the iteration order and will always return
the same string.

## Validation Steps Performed

* Key bindings are correctly parsed ✔️
* Key bindings are correctly serialized 
2021-07-14 21:22:24 +00:00
Dustin Howett
c12835783d version: bump to 1.11 on main 2021-07-14 15:12:24 -05:00
PankajBhojwani
56bbe86f96 Don't override success value when resetting mouse mode in hard reset (#10661)
Quick fix for an error made in #10602 

References #8613
Closes #10658
2021-07-14 16:46:34 +00:00
PankajBhojwani
d13c37cd60 Allow creating and editing unfocused appearances in the SUI (#10317)
## Summary of the Pull Request
Adds unfocused appearance creation/configuration in the SUI

There is now an 'Unfocused Appearance' section at the bottom of the 'Appearance' tab in a profile. There is a '+' button to create an unfocused appearance if one does not exist, or a delete button to delete the unfocused appearance if one exists (only one of these buttons is visible at a time). 

## PR Checklist
* [ ] Closes #xxx
* [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
![unfocusedSUI](https://user-images.githubusercontent.com/26824113/125523613-48aefe28-b4cf-46a2-91c9-2ba3ea89e071.gif)
2021-07-13 23:33:22 +00:00
Leonard Hecker
32fbd4cbb6 Enable /Zc:preprocessor (#10593)
This commit is a preparation for upcoming changes to KeyChordSerialization for #7539 and #10203.
In order to support variadic macros, /Zc:preprocessor was enabled, which required changing unrelated parts of the project.

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

## Validation Steps Performed

* Project still compiles ✔️
2021-07-13 23:00:11 +00:00
Josh Soref
6d7723e3be Upgrade check-spelling to v0.0.19 (#10646)
Updates check-spelling to 0.0.19

https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p

I'm pinning `actions/checkout` to @v2 instead of micromanaging the
version. We have reasonable faith that GitHub will do a good job of
maintaining their version branch.

I'll probably introduce a version branch for check-spelling in the near
future as well.  The job name change is for future bits -- I originally
copied the name from a template and didn't understand its significance
-- eventually it'll actually be used by the workflow. And if one uses
`act`, having distinct / well named jobs is actually useful.
2021-07-13 11:21:44 -05:00
Dustin L. Howett
e37fd5e546 Update Xaml Toolkit App Host to 6.1.3 (#10640)
This is required for some inbox compliance tasks regarding symbol availability.
2021-07-12 22:58:02 +00:00
Mike Griese
59166faa27 Update the quakeMode action name (#10641)
As in #10210. This string was already in the resources (so it should already be localized!)

* closes #10210.
* I work here
* tests? we don't got no stinkin' tests


![image](https://user-images.githubusercontent.com/18356694/125360281-45ddd280-e331-11eb-9798-6f087f33af2f.png)
2021-07-12 22:31:17 +00:00
Mim van den Bos
19f8b9c3ca Encapsulate settings main frame to prevent overflow (#10619)
When navigating the settings (or saving/discarding) the animation of the main content overflows the bar with the save and discard buttons. If the main content is encapsulated in a ScrollView the issue goes away.

Fixes one of the issues in #10609

## Validation Steps Performed
Clicked around a whole bunch and have not seen the overflow happen again. Verified that on tabs where scroll is necessary it can still be scrolled, and reflow of elements still functions.
2021-07-12 21:50:11 +00:00
Mim van den Bos
17e68a09a8 Use WinRT VirtualKeyModifiers instead of a custom enum (#10603)
Replaces `KeyModifiers` with the pretty much equivalent
`VirtualKeyModifiers` enum in winrt.

After doing this I noticed #10593 which changes the KeyChords a lot, but
it seems these PRs are still compatible

The issue also mentions replacing Vkey with
`Windows::System::VirtualKey`, but I chose not to because that enum only
includes a subset of the keys terminal supports here (no VK_OEM_* keys)

## Validation Steps Performed
Changed key bind in config, and confirmed it still works after
restarting terminal

Closes #877
2021-07-12 21:24:26 +00:00
Mim van den Bos
0980a0d50f Specify sln file to use for razzle nuget restore (#10606)
After the introduction of scratch.sln, the nuget restore in razzle.cmd fails. This fixes it by specifying the sln file to use.

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

## Validation Steps Performed
Ran razzle
2021-07-12 13:50:14 -07:00
PankajBhojwani
1d33429673 Update RIS to reset mouse mode and encoding (#10602)
## Summary of the Pull Request

RIS resets mouse mode and encoding

## PR Checklist
* [x] Closes #8613 
* [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
2021-07-12 18:50:05 +00:00
Mim van den Bos
ef8ba20bee Include profile nav menu items to consider for retaining position (#10618)
## Summary of the Pull Request

When discarding or saving settings, the current navigation should be retained.

## References

Issue introduced by #10390

## PR Checklist

* [x] Closes #10617 
* [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

## Detailed Description of the Pull Request / Additional comments

`menuItemsSTL` is filled with all _non_ profile navItems, then `menuItemsSTL` fills `menuItems`, then the profile navItems are added to `menuItems`. So to include the profile nav items in the iteration, `menuItems` needs to be used

## Validation Steps Performed

Spam discard and save buttons
2021-07-12 20:44:39 +02:00
Carlos Zamora
a0e5085b49 Expose Text Attributes to UI Automation (#10336)
## Summary of the Pull Request
This implements `GetAttributeValue` and `FindAttribute` for `UiaTextRangeBase` (the shared `ITextRangeProvider` for Conhost and Windows Terminal). This also updates `UiaTracing` to collect more useful information on these function calls. 

## References
#7000 - Epic
[Text Attribute Identifiers](https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-textattribute-ids)
[ITextRangeProvider::GetAttributeValue](https://docs.microsoft.com/en-us/windows/win32/api/uiautomationcore/nf-uiautomationcore-itextrangeprovider-getattributevalue)
[ITextRangeProvider::FindAttribute](https://docs.microsoft.com/en-us/windows/win32/api/uiautomationcore/nf-uiautomationcore-itextrangeprovider-findattribute)

## PR Checklist
* [X] Closes #2161 
* [X] Tests added/passed

## Detailed Description of the Pull Request / Additional comments
- `TextBuffer`:
   - Exposes a new `TextBufferCellIterator` that takes in an end position. This simplifies the logic drastically as we can now use this iterator to navigate through the text buffer. The iterator can also expose the position in the buffer.
- `UiaTextRangeBase`:
   - Shared logic & helper functions:
      - Most of the text attributes are stored as `TextAttribute`s in the text buffer. To extract them, we generate an attribute verification function via `_getAttrVerificationFn()`, then use that to verify if a given cell has the desired attribute.
      - A few attributes are special (i.e. font name, font size, and "is read only"), in that they are (1) acquired differently and (2) consistent across the entire text buffer. These are handled separate from the attribute verification function.
   - `GetAttributeValue`: Retrieve the attribute verification of the first cell in the range. Then, verify that the entire range has that attribute by iterating through the text range. If a cell does not have that attribute, return the "reserved mixed attribute value".
   - `FindAttribute`: Iterate through the text range and leverage the attribute verification function to find the first contiguous range with that attribute. Then, make the end exclusive and output a `UiaTextRangeBase`. This function must be able to perform a search backwards, so we abstract the "start" and "end" into `resultFirstAnchor` and `resultSecondAnchor`, then perform post processing to output a valid `UiaTextRangeBase`.
- `UiaTracing`:
   - `GetAttributeValue`: Log uia text range, desired attribute, resulting attribute metadata, and the type of the result.
   - `FindAttribute`: Log uia text range, desired attribute and attribute metadata, if we were searching backwards, the type of the result, and the resulting text range.
   - `AttributeType` is a nice way to understand/record if the result was either of the reserved UIA values, a normal result, or an error.
- `UiaTextRangeTests`:
   - `GetAttributeValue`:
      - verify that we know which attributes we support
      - test each of the known text attributes (expecting 100% code coverage for `_getAttrVerificationFn()`)
   - `FindAttribute`: 
      - test each of the known _special_ text attributes
      - test `IsItalic`. NOTE: I'm explicitly only testing one of the standard text attributes because the logic is largely the same between all of them and they leverage `_getAttrVerificationFn()`.

## Validation Steps Performed
- @codeofdusk has been testing this Conhost build
- Tests added for Conhost and shared implementation
- Windows Terminal changes were manually verified using accessibility insights and NVDA
2021-07-09 23:21:35 +00:00
Dustin L. Howett
d57fb84557 Reintroduce the Defaults page and the Reset buttons (#10588)
This pull request brings back the "Base Layer" page, now renamed to
"Defaults", and the "Reset to inherited value" buttons. The scope of
inheritance for which buttons will display has been widened.

The button will be visible in the following cases:

The user has set a setting for the current profile, and it overrides...

1. ... something in profiles.defaults.
2. ... something in a Fragment Extension profile.
3. ... something from a Dynamic Profile Generator.
4. ... something from the compiled-in defaults.

Compared to the original implementation of reset arrows, cases (1), (3)
and (4) are new. Rationale:

(1) The user can see a setting on the Defaults page, and they need a way
    to reset back to it.

(3) Dynamic profiles are not meaningfully different from fragments, and
    users may need a way to reset back to the default value generated
    for WSL or PowerShell.

(4) The user can see a setting on the Defaults page, **BUT** they are
    not the one who created it. They *still* need a way to get back to
    it.

To support this, I've introduced another origin tag, "User", and renamed
"Custom" to "None". Due to the way origin/override detection works¹, we
cannot otherwise disambiguate between settings that came from the user
and settings that came from the compiled-in defaults.

Changes were required in TerminalSettings such that we could construct a
settings object with a profile that does not have a GUID. In making this
change, I fixed a bit of silliness where we took a profile, extracted
its guid, and used that guid to look up the same profile object. Oops.

I also fixed the PropertyChanged notifier to include the
XxxOverrideSource property.

The presence of the page and the reset arrows is restricted to
Preview- or Dev-branded builds. Stable builds will retain their current
behavior.

¹ `XxxOverrideSource` returns the profile *above* the current profile
  that holds a value for setting `Xxx`. When the value is the
  compiled-in value, `XxxOverrideSource` will be `null`. Since it's
  supposed to be the profile above the current profile, it will also be
  `null` if the profile contains a setting at this layer.
  In short, `null` means "user specified" *or* "compiled in". Oops.

Fixes #10430

Validation
----------

* [x] Tested Release build to make sure it's mostly arrow-free (apart from fragments)
2021-07-09 22:03:41 +00:00
PankajBhojwani
be2b77653f Spec for font features and axes of variation (#10457)
Add a spec for how we could allow users to define font features and axes of variation.

References #1790
2021-07-09 21:01:04 +00:00
PankajBhojwani
c18e0f5008 Add an Appearances xaml object and AppearanceViewModel to TSE (#10066)
Implements an `Appearances` xaml object and an `AppearanceViewModel` in the SettingsEditor project. Updates `Profiles` to use these new objects for its default appearance. 

This is the first step towards getting `UnfocusedAppearance` into the SUI.
2021-07-09 15:43:58 -05:00
PankajBhojwani
a89746a869 Fix all fragments not loading when one is badly formed (#10601)
Adds try-catch blocks to the parts where we layer a fragment onto a profile and create a new profile from a fragment. This allows us to continue looping over the remaining fragments after failing to use a badly-formed one, instead of aborting prematurely.

## PR Checklist
* [x] Closes #10590 

## Validation Steps Performed
Non-badly formed fragments get loaded even if there is a badly formed one somewhere
2021-07-09 20:43:34 +00:00
Chester Liu
f339705ce7 Add fast lookup path for DxFontInfo (#10521)
Fixes the performance regression caused by DxFontInfo.

DxFontInfo introduced in #9201
2021-07-09 20:19:20 +00:00
Ian O'Neill
f152573058 Set working directory when invoked from shell extension (#10546)
Sets the working directory of the terminal when invoked from the shell extension. This ensures that new tabs opened with a starting directory of `.` open in the directory that the terminal was invoked from.

Closes #8933

## Validation Steps Performed
Manually tested - default PowerShell profile set to use home directory, Windows PowerShell profile set to use current directory. Launched via the shell extension and the default profile opened in the explorer directory, as did a new Windows PowerShell tab.
2021-07-09 18:53:52 +00:00
Michael Niksa
91b454ac95 Skip accessibility notifier and all event calculations when we're in PTY mode (#10569)
Change accessibility notifier creation so we do not create one when we're in PTY mode. (Guard all call sites to skip math/event work when the notifier is null.) MSAA events are legacy events that are registered for globally and used by some screen readers to find content in the conhost window. The PTY mode is not responsible for hosting the display content or input window, so it makes sense for it to not broadcast these events and delegate the accessibility requirement to the connected terminal.

## References
- #10537 

## PR Checklist
* [x] Closes #10568
* [x] I work here
* [x] Manual test launches passed.
2021-07-09 18:45:44 +00:00
PankajBhojwani
6409ab91fa Fix the cursor blink VT sequence being ignored (#10589)
Ensure that the cursor blink VT sequence gets flushed to terminal when conhost is attached to a pty

Closes #10543
2021-07-09 18:45:16 +00:00
Alex Alabuzhev
a0527a1dbe #10497: Do not force the font on output codepage change (#10591)
Currently, when the user changes the console codepage (manually or via a script) the GDI engine tries to find and set the "best possible" font. The "best possible" here is charset-wise, it doesn't mean that the font is actually better or more eye-candy for the user.

Example:
- Open cmd
- Set the font to Consolas
- Enter `chcp 932`
- Suddenly, a wild MS Gothic appears!

This kind of makes sense (*"if I'm changing the codepage I probably want to see the national characters"*) but it doesn't happen anywhere else - all other apps just substitute the missing glyphs.

After #10472 / #10478 this magic should finally work here as well. So, do we still need to change the whole font? Terminal doesn't do that after all.

## Validation Steps Performed
Download [932.cmd.txt](https://github.com/microsoft/terminal/files/6697577/932.cmd.txt),
rename to 932.cmd, run it, check if the output is still readable.

Closes #10497
2021-07-08 21:10:35 +00:00
Carlos Zamora
f03cacfa5b Introduce feature flag for editable actions page (#10581)
## Summary of the Pull Request
Adds a feature flag `Feature_EditableActionsPage` that controls whether the Actions page in the Settings UI is read-only vs editable. The editable version is disabled for `Release` builds and enabled everywhere else (i.e. Dev, Preview, etc...).

Validated using `<stage>` `AlwaysEnabled` and `AlwaysDisabled`.

## References
#6900 - Actions Page Epic

## PR Checklist
Closes #10578
2021-07-08 20:55:31 +00:00
Alex Alabuzhev
cdecfcd67f #10477: Handle things above U+FFFF in GDI renderer (#10580)
<!-- 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)? -->
## Implementation of #10477 - handle surrogate pairs in GDI renderer.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #10477
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] 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: #10477

<!-- 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
### Why not let Windows draw surrogate pairs? It can do that.

Basically, the comment says everything:
c90de69250/src/renderer/gdi/paint.cpp (L346-L347)

However, handling things above U+FFFF doesn't really require extra effort. It's enough to:
- Put *all* characters to the output buffer
- Set the first width to cluster width and the rest to 0
- Sit back and relax while Windows does the rest

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

echo 𠜎𠝹𠱓𠱸𠲖𠳏𠳕𠴕𠵼𠵿𠸎
echo 👨👩👧👦
```
Save this as a UTF-8 cmd file and run.

### Before the change
![image](https://user-images.githubusercontent.com/11453922/122832196-ed438880-d2e2-11eb-93dd-931954efedbf.png)

### After the change
![image](https://user-images.githubusercontent.com/11453922/122832217-f2a0d300-d2e2-11eb-99f0-e129e5544667.png)

An example of a third party app working with surrogate pairs in a patched OpenConsole:
![image](https://user-images.githubusercontent.com/11453922/122838225-837cac00-d2ed-11eb-8faf-dbeb52f77916.png)

As discussed, this change doesn't claim to be the full support for surrogate pairs (there are still corner cases possible), but brings it on par with Terminal with minimal effort.
2021-07-08 15:35:11 +00:00
Dustin L. Howett
d6da6ba353 wpf: make sure to pack api-ms-win-core-synch-l1-2-0 (#10587) 2021-07-08 10:31:59 -05:00
Leon Liang
96f4a9daef Add tray icon when quake window is minimized (#10179)
This PR is a small start in a broader "Minimize to Tray" feature (#5727).
This particular change is scoped only to the scenario when a quake window
is minimized. Currently the only way to bring back the quake window
when it's minimized is to press the global hotkey again. This gives another
option - to press the terminal icon in the tray.

Eventually though, minimize to tray will be available for any window, and
I'd like more time to flesh out the general porpoise scenarios and context
menus. Having just a bit in this PR also helps reviewers by keeping it small!
2021-07-08 08:25:43 -07:00
Michael Niksa
1374396f10 Delay load call SetThreadDescription to restore WPF renderer on Win7 (#10582)
Delay load call SetThreadDescription to restore WPF renderer on Win7

## PR Checklist
* [x] Closes something @DHowett asked me to do.
* [x] I work here
* [x] I F5'd it on a version with this function and it still works


## Detailed Description of the Pull Request / Additional comments

I keep forgetting that anything in the WPF control needs to keep working on Win7. Or more specifically... I remember this fact for the DX renderer, but not for the render thread base. Oops. Turns out this particular convenience method to set thread descriptions for visibility inside the debugger (to make my life easier) only works down to 1607 (see https://docs.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription). Since it's just a debugging convenience... skipping it entirely when the procedure is not found should be fine. Also I don't try to load `kernel32.dll` and just get the handle of the existing module (which per the remarks at https://docs.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlew will not increment the module reference count) because `kernel32.dll` pretty much has to be there or we're already in hot water.
2021-07-08 07:58:53 +00:00
Carlos Zamora
192d6debba Add the 'Add new' button to the Actions page (#10550)
## Summary of the Pull Request
This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list.

This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything.

## References
#6900 - Actions page Epic
#9427 - Actions page design doc
#10220 - Actions page PR - set action

## Detailed Description of the Pull Request / Additional comments
- `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before.
- `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model.
- `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action.

## Validation Steps Performed
- Cancel:
   - Deletes the action (because it doesn't truly exist until you confirm changes)
- Accept:
   - Adds the new action.
   - If you attempt to edit it, the delete button is back.
- Add Action:
   - Delete button should not be visible (redundant with 'Cancel')
   - Action should be initialized to a value
   - Key chord should be empty
   - Cannot add another action if a newly added action exists
- Keyboard interaction:
   - escape --> cancel
   - enter --> accept
- Accessibility:
   - "add new" button has a name
- Interaction with other key bindings:
   - editing another action --> delete the "newly added" action (it hasn't been added yet)
   - only one action can be edited at a time
2021-07-07 23:43:40 +00:00
Chester Liu
a50731119a Render SGR 1 ("intensity") as bold in the DX engine (#10498)
This commit adds support for bold text in DxRenderer.

For now, bold fonts are always rendered using DWRITE_FONT_WEIGHT_BOLD
regardless of the base weight.

As yet, this behavior is unconfigurable.

References
Previous refactoring PRs: #9096 (DxFontRenderData) #9201 (DxFontInfo) 
SGR support tracking issue: #6879

Closes #109
2021-07-07 21:07:51 +00:00
Leonard Hecker
305e3df8fa Introduce a api-ms-win-core-synch-l1-2-0 shim for Windows 7 (#10559)
The code in this file was adapted from the STL on the 2021-07-05.

It backports the following Windows 8 functions to Windows 7:
* WaitOnAddress
* WakeByAddressSingle
* WakeByAddressAll

These functions are used within `til`. This commit will allow `til` to be used in the conhost source code.

Validation
* [x] correct .dll loads on Windows 7
* [x] correct .dll loads on Windows 10
* [x] link line for PublicTerminalCore prefers this fake apiset over kernel32
2021-07-07 16:48:28 +00:00
Leonard Hecker
83c6bce73d Fix racy access to _tsfTryRedrawCanvas in TermControl (#10549)
Previously `TermControl::Close` destroyed all `ThrottledFunc`s to ensure they're not scheduling any callbacks on the UI thread, as the call to `Close` signals the point at which the `TermControl` isn't part of the UI thread anymore. `_CursorPositionChanged` tried to prevent access to the potentially deallocated `_tsfTryRedrawCanvas` by checking the `std::shared_ptr` for nullability, but since the deallocation happens on the UI thread and the nullability check on a background thread, this check introduced a race condition.

This commit solves the issue by not deallocating any `ThrottledFunc`s anymore and instead checking the `_closing` flag inside the `ThrottledFunc` callback on the UI thread.

Additionally this commit cleans up some antipatterns around the use of `std::optional`.

## PR Checklist
* [x] Closes #10479
* [x] Closes #10302

## Validation Steps Performed

* Opening and closing tabs doesn't crash ✔️
* Printing long text doesn't crash ✔️
* Manual scrolling doesn't crash ✔️
* ^G / the audible bell doesn't crash ✔️
2021-07-06 21:59:44 +00:00
Chester Liu
59239e3b07 Don't notify a11y event when in ConPTY mode (#10537)
Don't notify a11y event when in ConPTY mode

In support of #10528
2021-07-06 21:15:07 +00:00
Carlos Zamora
79a18f0825 [A11y] Initialize and copy _blockRange in UIA Clone (#10544)
## Summary of the Pull Request
#7960 was caused by `UiaTextRangeBase::_blockRange` not being initialized, thus pointing to random memory. In most cases, we initialize it properly in `RuntimeClassInitialize`, however, the copying version of `RuntimeClassInitialize` doesn't actually copy it over, resulting in it still containing random memory.

NVDA (and other screen readers) occasionally use `Clone` (really just the copy initializer), resulting in this bug occurring randomly.

## PR Checklist
* [X] Closes #7960 
* [X] Tests added/passed

## Validation Steps Performed
Test failed before the change, but passes after the change.
2021-07-06 20:54:51 +00:00
Carlos Zamora
d3b9a780d3 Allow setting the action on Actions page (#10220)
This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action.

## References
#6900 - Actions page Epic
#9427 - Actions page design doc
#9949 - Actions page PR

## Detailed Description of the Pull Request / Additional comments
### Settings Model Changes
- `ActionAndArgs`
   - new ctor that just takes a `ShortcutAction`
- `ActionMap`
   - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents).
   - `RegisterKeyBinding` introduces a new unnamed key binding to the action map.

### Editor Changes
- XAML
   - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from.
- `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs`
- `AvailableActionAndArgs`
   - stores the list of actions to choose from in the combo box
   - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box
   - `Actions` stores and maintains this though. We populate this from the settings model on navigation.
- `ProposedAction` vs `CurrentAction`
   - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box).
   - `CurrentAction` --> settings model
   - `ProposedAction` --> combo box selected item

## Validation Steps Performed
- Cancel:
   - ✔️ change action --> cancel button --> begin editing action again --> original action is selected
- Accept:
   - ✔️ don't change anything
   - ✔️ change action --> OK! --> Save!
      - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette.
   - ✔️ change action & change key chord --> OK! --> Save!
   - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save!
      - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-02 15:35:55 -07:00
PankajBhojwani
9b9b0738c8 Group font options in the json into a single object (#10433)
Introduces `FontConfig`, an object that isolates font-related settings
in our profiles

Users can now define font settings in their json as so:
```
"font":{
    "face": "Consolas",
    "size": 12
}
```

Backwards compatible with the currently expected way of defining font
settings in the json, note however that upon hitting 'Save' in the SUI,
these settings **will be rewritten to the font-object style in the json
(as above)**. 

## Validation Steps Performed
Existing functionality works, new functionality works

References #1790 
Closes #6049
2021-07-01 12:08:46 -05:00
Leonard Hecker
f3e30d07fa Advice users to relaunch after changing the language (#10535)
This commit adds a "(requires relaunch)" suffix to the header of the language picker control.

## PR Checklist
* [x] I work here
* [x] Tests added/passed
2021-07-01 00:31:56 +02:00
Leonard Hecker
ee3259847a Improve parser performance by reducing tracing overhead (#10533)
Passing structures larger than the register size is very expensive
due to Microsoft's x64 calling convention. We could reduce the
overhead by passing the string-view by reference, but this forces us
to allocate the parameters as static string-views on the data
segment of our binary. I've found that passing them as classic
C-strings is more ergonomic instead and fits the need for
high performance in this particular code.
This improves performance for VT-heavy output by 15-20%.

## PR Checklist
* [x] I work here
* [x] Tests added/passed
2021-06-30 02:28:40 +02:00
Leonard Hecker
ab5a8d701d Introduce a basic ApplicationState class (#10513)
This commit introduces a basic ApplicationState class, without being used for anything yet to aid reviewers. At a later point actual usages of this new class may be added separately.

## References

This commit is an initial step towards implementing #8324.

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

## Validation Steps Performed

* Creating a `state.json` with `{"generatedProfiles":["{53e75ed9-2b63-4118-856d-0510c4f6b97e}"]}` updates the ApplicationState, as observed through a debugger ✔️
* Deleting the "generatedProfiles" field sets the corresponding field back to nullopt ✔️
2021-06-30 02:25:44 +02:00
Chester Liu
6a37818c07 Defer _run substr operation in StateMachine::ProcessString (#10471)
Do not eagerly create run by substring to reduce the unnecessary overhead.

Switching from `.substr` to offset/length tracking saves us 7% CPU time.
2021-06-29 17:47:27 -05:00
Chester Liu
4fc283f8b6 Throttle cursor redrawing in outputStream.cpp (#10394)
Try to throttle the cursor redrawing in the conhost world.

The motivation of this is the high CPU usage of `TriggerRedrawCursor` (#10393).

This can be seen as the conhost version of #2960.

This saves 5%~8% of the CPU time.

Supports #10462.
2021-06-28 21:08:22 +00:00
onerandomusername
51e1ae3e8a doc/roadmap: add 1.9 Preview Release Blogpost Link (#10518) 2021-06-28 10:36:15 -05:00
Ian O'Neill
8c057a04a8 Allow closing tabs by index (#10447)
## Summary of the Pull Request
Updates the `closeTab` action to optionally take an index.

## PR Checklist
* [x] Closes #7180
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: MicrosoftDocs/terminal#347
* [x] 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
Added the following configuration to `settings.json` and validated both key combinations behaved as expected. Also opened the command palette and ensured that the actions were displayed.

```json
{ "command": "closeTab", "keys": "ctrl+shift+delete" },
{ "command": { "action": "closeTab", "index": 0 }, "keys": "ctrl+shift+end" }
```
2021-06-25 19:22:52 +00:00
Alexander Sklar
8c00dd7d55 Update WindowExe.manifest (#10499)
Closes #10480
2021-06-23 17:59:07 +00:00
Breece W
848e353b9c Replicate winrt::make<> changes in ScratchIslandApp SampleAppLib (#10494)
Sample scratch app would not compile. It does if we apply #10335 to App.base.h in the scratch app.

Closes #10493
2021-06-23 03:21:07 +00:00
WSLUser
e3b7a44b13 Add Settings UI enum to json schema (#10489)
Noticed the json schema was listing the option as invalid even though it's accepted by WT. So added it to schema to remove the error.

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

## Validation Steps Performed
No longer shows as invalid in VSCode.
2021-06-22 15:05:00 -07:00
Leonard Hecker
0d9a357373 Introduce til/latch.h, til/mutex.h and til/throttled_func.h (#10403)
This commit introduce three new `til` features:
* "til/latch.h": A std::latch clone, until we're on C++20.
* "til/mutex.h": A safe mutex wrapper, which only allows you access to the protected data after locking it. No more forgetting to lock mutexes!
* "til/throttled_func.h": Function invocation throttling used to be available as the `ThrottledFunc` class already. But this class is vastly more efficient and doesn't rely on any WinRT types.

This PR also adds a `til::ends_with` string helper which is `til::starts_with` counterpart.

## Validation Steps Performed

* Scrollbar throttling still works as it used to ✔️
* No performance regressions when printing big.txt ✔️

Closes #10393
2021-06-22 20:16:31 +00:00
Chester Liu
85c485e94f Introduce DxFontInfo (#9201)
This PR Introduces `DxFontInfo` to simplify the logic in
`DxFontRenderData`. 

`DxFontInfo` aims to be the DWrite equivalent of `FontInfo` &
`FontInfoBase` in GDI. It encapsulates the needed information to
represent a displayable font face. It also provides the ability to
resolve a font face based on the available fonts on the system.

## References

This is a follow-up of #9096.
Initial Italic support was introduced by #8580.

The motivation behind this is to support bold & bold-italic text in
Windows Terminal.
2021-06-22 19:31:27 +00:00
Michael Niksa
1b79cc87c3 Fix startup race of resizing ConPTY (#10449)
Fix startup race of resizing ConPTY

- Depending on what the timing and ordering is of the message coming in
  from the signal thread, it may be applied to the startup structure
  after the I/O thread has begun initializing the console buffer
  structures but before it has signaled that it is done and the signal
  thread is ready to make changes directly. This likely happens because
  the end of the I/O thread setup has a weird unlock/lock jog for the
  input thread and the signal thread might have been scheduled in the
  middle of it.
- My resolution here is to ensure that the signal thread just keeps
  storing the latest resize message until it is told that everything is
  initialized. Whomever comes in to tell the signal thread this
  information (under lock) will pickup and run the resize if one came in
  before everything was ready. This should resolve the race.

## Validation Steps Performed
- o-sdn-o confirms this resolves their issue

Closes #10400
2021-06-22 19:23:16 +00:00
Alex Alabuzhev
b7fc0f2d44 Replace PolyTextOutW with ExtTextOutW (#10478)
Replace PolyTextOutW with ExtTextOutW to allow substitution of missing
glyphs from other fonts.

Why not let Windows substitute the glyphs that are missing in the
current font?  Currently the GDI renderer of conhost/OpenConsole uses
`PolyTextOutW` for drawing.  `PolyTextOutW` doesn't try to substitute
any missing glyphs, so the only way to see, say, Hiragana is to change
the _whole font_ to something like MS Gothic (which is eye-bleeding, to
be honest).

A trivial replace `PolyTextOutW` -> `ExtTextOutW` does the trick.

Switch to `PolyTextOutW` happened in Windows 7 along with introduction
of conhost.exe.  Substitution worked in previous Windows versions, where
internal NT interfaces were used.

# Before the change:
![image](https://user-images.githubusercontent.com/11453922/122759189-93ff3900-d291-11eb-89a9-b1d47aa22ed9.png)

# After the change:
![image](https://user-images.githubusercontent.com/11453922/122759316-b4c78e80-d291-11eb-87aa-7cdc2979ae28.png)

Closes #10472
2021-06-22 18:41:17 +00:00
Dustin L. Howett
2770228e09 wpf: fix the TerminalTheme struct to marshal the same on all platforms (#10486)
The CursorStyle enum is declared as being of type `uint` on the C# side,
but as `size_t` on the C++ side. There's a C# size_t impostor we could
use, System.UIntPtr, but I don't want to risk changing the public API of
TerminalTheme and I don't know if it can be used as a base type for an
enum.

Anyway, since we don't have more than four billion cursor types I chose
to narrow the field to a uint32_t and unpack it in TerminalSetTheme.

Fixes #10485
2021-06-22 17:03:18 +00:00
Chester Liu
4f0b57ec8e Prefer FMT_COMPILE for string formatting in VtRenderer (#10426)
Kill `WriteFormattedString` and replace it with `fmt::format_to` to avoid expensive string operations in VtRenderer.

This saves ~8% of the CPU time.

Inspired by https://github.com/microsoft/terminal/issues/10362#issuecomment-856625365

Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2021-06-22 15:39:16 +00:00
Dan Thompson
e2005ca5d7 Merged PR 6176782: [Git2Git] Get rid of dead build macros/#defines FE_IME, W32_SB, etc.
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 40df712b33a40e76aeeac87f823bbb028d2e3972

Related work items: MSFT-32007459
2021-06-21 10:50:52 -07:00
Ian O'Neill
c8f00df170 Fix code-format and test invocation through PowerShell
Fixes the `Invoke-CodeFormat` and `Invoke-OpenConsoleTests` functions in `OpenConsole.psm1` so that they can be run directly from PowerShell.

Addresses the issues found when creating #10447.

`Invoke-CodeFormat` did not work when invoked directly from PowerShell due to a relative path being passed into the .NET function `[IO.File]::WriteAllLines()`. The working directory for .NET objects does not change when you change directory in PowerShell, so the paths were being treated as relative to the initial working directory of the shell - which was not the terminal git repo.

`Invoke-OpenConsoleTests` had 3 issues:
1. The path to `TestHostApp` was wrong.
2. It would attempt to run the "in host app" tests both in the host app and not in the host app.
3. The test configuration in `tests.xml` wasn't in sync with the `runABC.cmd` files, so the remoting and control unit tests didn't run.

## Validation Steps Performed
1. Ran `Invoke-CodeFormat` and `runformat.cmd` from multiple directories and didn't see errors.
2. Ran `Invoke-OpenConsoleTests` and didn't see errors.
2021-06-21 16:52:59 +02:00
Dustin L. Howett
c90de69250 Update Cascadia Code to 2106.17 (#10455)
This update brings some significant changes to the Cascadia family:

* Arabic and Hebrew support
* Italics (the new ones, not the cursive ones)
* Tweaked letterforms and fixed interpolation values for the upright
  faces.

Since we now have four font files, this commit also relocates them to a
much more reasonable place (res/fonts/) and tidies up the build and
exclude rules to make them more extensible in the future.
2021-06-18 20:47:19 +00:00
Dustin L. Howett
b6593216f2 Localize the shell extension's menu item (#10446)
This commit introduces localization for the "Open in Windows Terminal"
menu item and differentiates it based on compile-time branding (rather
than runtime detection!).

@leonMSFT's tray icon pull request had the excellent idea to use the
TerminalApp's resource compartment for auxiliary resources for projects
that can't otherwise be localized the same way. Doing localization in
the shell extension (or WindowsTerminal.exe) would require us to use
MUIRCT and split the build process up to support mui files. That's a
huge amount of work... but this is *not* a huge amount of work.

Fixes #6112
2021-06-17 21:49:56 +00:00
Carlos Zamora
b3b648496e Ensure equality when hashing default args and no args in actions (#10341)
## Summary of the Pull Request
#10297 found a bug in `ActionMap` where the `ToggleCommandPalette` key chord could not be found using `GetKeyBindingForAction`.

This was caused by the following:
- `AddAction`: when adding the action, the `ActionAndArgs` is basically added as `{ToggleCommandPalette, ToggleCommandLineArgs{}}` (Note the default ctor used for the action args)
- `GetKeyBindingForAction`: we're searching for an `ActionAndArgs` structured as `{ToggleCommandPalette, nullptr}`
- Since these are _technically_ two different actions, we are unable to find it.

This issue was fixed by making the `Hash(ActionAndArgs)` function smarter! If the `ActionAndArgs` has no args, but the `ShortcutAction` _supports_ args, generate the args using the default ctor.

By making `Hash()` smarter, everybody benefits from this logic! We can basically now enforce that `ActionAndArgs{ <X>, nullptr } == ActionAndArgs{ <X>, <default_ctor> }`.

## Validation Steps Performed
- Added a test.
- Tested this on #10297's branch and this does fix the bug
2021-06-16 22:43:29 +00:00
Leonard Hecker
1ae6e3b772 Fix crash when unpackaged due to PrimaryLanguageOverride (#10434)
## Summary of the Pull Request

`ApplicationLanguages::PrimaryLanguageOverride` requires packaged activation.
This PR prevents any such application crashes, by skipping any calls to `PrimaryLanguageOverride`, as well as hiding the language selector in the settings UI.

## PR Checklist
* [x] I work here
* [x] 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.

## Validation Steps Performed

When WT is run unpackaged:
* Doesn't crash during start ✔️
* SUI doesn't show the language selector ✔️
2021-06-16 21:08:14 +00:00
Dustin Howett
448684a5f4 Merged PR 6164445: Persist inbox conhost; migrate OSS up to 2bd5791fe
Related work items: MSFT-33707417
2021-06-16 19:54:14 +00:00
Dustin Howett
0d3f85de85 Merged PR 6164397: Migrate OSS up to 872309397
Related work items: MSFT-33790379
2021-06-16 19:47:00 +00:00
Michael Niksa
2bd5791feb Persist inbox conhost; delegate control activities to it via a pipe (#10415)
Persist inbox conhost; delegate control activities to it via a pipe

## PR Checklist
* [x] Closes #10194 - WSL Debug Tap doesn't work
* [x] Closes #10134 - WSL Parameter is Incorrect
* [x] Closes #10413 - Ctrl+C not passed to client
* [x] Closes #10414 - Leftover processes on abrupt termination
* [x] Might help #10251 - Win+X Powershell sometimes fails to attach
* [x] I work here
* [x] Manually tested with assorted launch scenarios

## Detailed Description of the Pull Request / Additional comments
It turns out that there's a bit of ownership that goes on with the original inbox `conhost.exe` and the operating system/driver. The PID of that original `conhost.exe` is stowed when the initial connection is established and it is verified for several activities. This means that the plan of letting it go completely away and having the `OpenConsole.exe` take over all of its activities must be slightly revised. 

I have tested the following two alternatives to keeping `conhost.exe` around and they do not work:
1. Replacing the original owner `conhost.exe` with `OpenConsole.exe` - A.) The driver does not allow this. Once the owner is registered, it cannot be replaced. B.) There's no way of updating this information inside the client process space and it is kept there too in the `kernelbase`/`conclnt` data from its initial connection.
2. Attempting to pick up the first packet (to determine headed/headless and other initial connection information that we use to determine whether handoff is appropriate or not) prior to registering any owner at all. - The driver doesn't allow this either. The owner must be registered prior to a packet coming through.

Put this mental model in your head:
CMD --> Conhost (inbox) --> OpenConsole (WT Package) --> Terminal (WT Package)

So since the `conhost.exe` needs to stick around, here's what I'm doing in this PR:
- `conhost.exe` in the OS will receive back the `OpenConsole.exe` process handle on a successful handoff and is expected to remain alive until the `OpenConsole.exe` exits. It's now waiting on that before it terminates itself.
- `conhost.exe` in the OS will establish a signal channel pipe and listen for control commands from `OpenConsole.exe` in a very similar fashion to how the `ConPTY` signal pipe operates between the Terminal and the PTY (provided by `OpenConsole.exe` in this particular example.) When `OpenConsole.exe` needs to do something that would be verified by the OS and rejected... it will instead signal the original `conhost.exe` to do that thing and it will go through.
- `conhost.exe` will give its own handle through to `OpenConsole.exe` so it can monitor its lifetime and cleanup. If the owner is gone, the session should end.
- Assorted handle cleanup that was leading to improper exits. I was confused between `.reset()` and `.release()` for some of the `wil::unique_any<T>` handling and it lead to leaked handles. The leaked handles meant that threads weren't aware of the other sides collapsing and wouldn't cleanup/terminate appropriately.

How does this fix things?
- For the WSL cases... WSL was specifically looking up the owner PID of the console session from the driver. That was the `conhost.exe` PID. If it exits, that PID isn't valid and is recycled. Thus the parameter is incorrect or other inappropriate WSL setup behaviors.
- Ctrl+C not passed... this is a signal the operating system rejects from a PID that is not the owner. This is now relayed through the original owner and it works.
- Leftover processes... I believe I explained this was both not-enough-monitoring of each others' process lifetimes coupled with mishandling of release/resetting handles and leaking them.
- Powershell sometimes fails to attach... my theory on this one is that it's a race that became upset when the `conhost.exe` disappeared while something about Powershell/.NET was still starting, much like the WSL one. I believe now that it is sticking around, it will be fine.

Also, this WILL require an OS update to complete improvement of functionality and I have revised the interface ID. This is considered an acceptable breaking change with no mitigation because we said this feature was an alpha preview.  

## Validation Steps Performed
- Launched WSL with defapp set, it works
- Launched WSL with defapp set and the debug tap on, it works and opens in two tabs
- Launched CMD, ran ping, did Ctrl+C, it now receives it
- Launched Win+X powershell a ton of times. It seems fine now
- Launched cmd, powershell, wsl, etc. Killed assorted processes in the chain (client/conhost/openconsole/windowsterminal) and observed in Process Explorer (with a long delta timer so I could see it) that they all successfully tear down now without leftovers.
2021-06-16 19:23:37 +00:00
Michael Niksa
872309397a Rev wil to latest version (#10435)
Rev wil to latest version
2021-06-15 23:11:16 +00:00
kovdu
813f385c08 Don't dispatch the Toggle Command Palette action to keep the just closed Command Palette closed. (#10423)
An exception was introduced for the 'Toggle Command Palette' action to **not** being dispatched. Otherwise the command palette that was just closed will become visible again.

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

## Detailed Description of the Pull Request / Additional comments
- Selecting the `Toggle command palette` item in the command palette will now properly close the command palette.
- Opening and closing the Command Palette through shortcut keys is still working fine.
- Other command palette items are still working fine as well.
2021-06-14 23:32:31 +00:00
Leonard Hecker
296037a0fa Remove CONSOLE_API_MSG::UpdateUserBufferPointers hack (#10326)
## Summary of the Pull Request

This commit introduces a copy constructor/operator for
`_CONSOLE_API_MSG`. The change is not trivial as the struct contains a
union of unnamed structs that cannot be copied using regular language
features. As such a copy operator using `memcpy` was implemented.
Additionally all access specifiers were removed, as those allow a C++
compiler to reorder struct members. This would break message passing.
This commit is a good opportunity to prevent such miscompilations
proactively.

## Validation Steps Performed

* Command prompts of WSL2 fish-shell and pwsh still work ✔️

Closes #10076
2021-06-14 19:52:40 +00:00
kovdu
1cc383f865 Cancel the preview of nested commands when moving back on the stack. (#10392)
<!-- 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
Immediately cancelling the preview when the user is navigating back from a nested command.

<!-- 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 #10165 
* [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
Basically 2 changes are done here:
- Allow the click handler to run for the back button when the button has focus and user hits the enter key (similarly as hitting space now).
- Now immediately cancelling the preview when the user is navigating back. Felt nicer to do it immediately at that point then keeping the preview active until the user hits cancel to close the palette. So the preview is already cancelled at step **5** instead of 6 as mentioned in the reproduction steps here https://github.com/microsoft/terminal/issues/10165#issue-899838383. But of course let me know if you're not agreeing here 😀 .
 

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
- Open 'Color Scheme' and verified preview is still working fine when selecting different schemes.
- After tabbing back to the Back button verified that when hitting enter or space the preview is cancelled and the original color scheme is being used again.
- Then after going back to 'Color Scheme' previews are still working ok.
- After hitting Enter on one of the Color Schemes the scheme still becomes active as before.
2021-06-14 17:20:30 +00:00
Ikko Ashimine
52dd988b3d doc: fix typo in TAEF.md (#10424)
Fixed typo.
```
enviroment -> environment
```

* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
2021-06-14 10:06:01 -07:00
Carlos Zamora
1fcfb618ad Fix edit button color in light theme (#10412)
## Summary of the Pull Request
Fixes a bug where the edit button in the actions page would have white text when in light theme. Now, we just fallback to XAML's built-in value (black in light theme and white in dark theme).

## References
#6900 - Epic
Closes #10406
2021-06-14 16:51:15 +00:00
Dustin L. Howett
92f0700d5d Force the execution policy on the til::feature powershell script (#10411)
It was not set to `bypass`, which gave @carlos-zamora some trouble.

This commit brings it in line with the Windows build rule.
2021-06-11 20:14:18 +00:00
Dustin Howett
b98d4e5493 Fix spelling from inbox merge 2021-06-11 13:51:38 -05:00
Dustin Howett
8f2605df0d Merge remote-tracking branch 'openconsole/inbox' into main 2021-06-11 13:46:46 -05:00
Dustin Howett
34e2ce1885 Merged PR 6147892: Make til::feature build in the OS
This commit makes the feature staging header build in OS razzle.

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

Related work items: MSFT-33722503
2021-06-11 17:57:36 +00:00
Dustin Howett
d75ff17cbb Merged PR 6147681: Migrate OSS up to b034fc9ae
Related work items: MSFT-33722503
2021-06-11 17:04:24 +00:00
Leonard Hecker
b034fc9ae5 Fix SUI race conditions when reloading settings (#10390)
## Summary of the Pull Request

This commit fixes various race conditions regarding the settings UI. It's unsafe to write to class members from background threads without acquiring mutexes or yielding to the main thread first.
By changing the settings reload code path to yield to the main thread early, we're able to cut down on code complexity and unsafe member accesses.

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

## Validation Steps Performed

* Settings UI reloads without crashing ✔️
2021-06-11 00:38:10 +00:00
Dustin L. Howett
5bb8148ef9 Convert four INSIDE_WINDOWS blocks to til features (#10404)
This pull request converts four of our existing `#ifdef` (or `#ifndef`)
`INSIDE_WINDOWS` blocks to til::features:

* Attempting to establish a handoff session (inside Windows only)
* The ability to *receive* a handoff session (outside Windows only)
* The DX engine (outside Windows only) and shaders (also outside only)
* Whether we use numpad event synthesis for clipboard/conpty (inside
  Windows only)

Most of these are using the preprocessor verison of til::feature, only
because it is more difficult to gate the inclusion of headers on
constant expressions. I'd love to prefer the compile time version.
2021-06-10 23:48:54 +00:00
Leonard Hecker
e34897cd1f Add a language switcher using PrimaryLanguageOverride (#10309)
## Summary of the Pull Request

This PR adds a global "language" setting, which may be set to any supported BCP 47 tag.
Additionally a ComboBox is added to the settings UI under "Appearance", listing all languages with their localized names.

This PR introduces one new issue: If you change the language while the app is running, the UI will be in a torn state, as not all UI elements refresh automatically if the `PrimaryLanguageOverride` is changed.

## PR Checklist
* [x] Closes #5497
* [x] I work here
* [x] 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
* [x] Schema updated

## Validation Steps Performed

* UI language changes when changing the "language" in settings.json before starting WT / while WT is running. ✔️
* "language" field is removed from settings.json if "Use system default" is selected. ✔️
* "language" field is added or updated in settings.json if any other language is selected. ✔️
* Removes qps- languages if debugFeatures is false. ✔️
* Correctly refreshes all UI elements with the new language. 
2021-06-10 23:24:21 +00:00
Dustin L. Howett
31a39b3b12 Add support for branch- and branding-based feature flagging (#10361)
This pull request implements a "feature flagging" system that will let
us turn Terminal and conhost features on/off by branch, "release" status
or branding (Dev, Preview, etc.).

It's loosely modelled after the Windows OS concept of "Velocity," but
only insofar as it is driven by an XML document and there's a tool that
emits a header file for you to include.

It only supports toggling features at compile time, and the feature flag
evaluators are intended to be fully constant expressions.

Features are added to `src\features.xml` and marked with a "stage". For
now, the only stages available are `AlwaysDisabled` and `AlwaysEnabled`.
Features can be toggled to different states using branch and branding
tokens, as documented in the included feature flag docs.

For a given feature Feature_XYZ, we will emit two fixtures visible to
the compiler:

1. A preprocessor define `TIL_FEATURE_XYZ_ENABLED` (usable from MIDL,
   C++ and C)
2. A feature class type `Feature_XYZ` with a static constexpr member
   `IsEnabled()` (usable from C++, designed for `if constexpr()`).

Like Velocity, we rely on the compiler to eliminate dead code caused by
things that compile down to `if constexpr (false)`. :)

Michael suggested that we could use `WindowsInbox` as a branding to
determine when we were being built inside Windows to supplant our use of
the `__INSIDE_WINDOWS` preprocessor token. It was brilliant.

Design Decisions
----------------

* Emitting the header as part of an MSBuild project
   * WHY: This allows the MSBuild engine to ensure that the build is
     only run once, even in a parallel build situation.
* Only having one feature flag document for the entire project
   * WHY: Ease.
* Forcibly including `TilFeatureStaging` with `/FI` for all CL compiler
  invocations.
   * WHY: If this is a project-wide feature system, we should make it as
     easy as possible to use.
* Emitting preprocessor definitions instead of constexpr/consteval
   * WHY: Removing entire functions/includes is impossible with `if
     constexpr`.
   * WHY: MIDL cannot use a `static constexpr bool`, but it can rely on
     the C preprocessor to remove text.
* Using MSBuild to emit the text instead of PowerShell
   * WHY: This allows us to leverage MSBuild's `WriteOnlyWhenDifferent`
     task parameter to avoid changing the file's modification time when
     it would have resulted in the same contents. This lets us use the
     same FeatureStaging header across multiple builds and multiple
     branches and brandings _assuming that they do not result in a
     feature flag change_.
   * The risk in using a force-include is always that it, for some
     reason, determines that the entire project is out of date. We've
     gone to great lengths to make sure that it only does so if the
     features _actually materially changed_.
2021-06-10 23:09:52 +00:00
Carlos Zamora
9294ecc8e5 Bugfix: serialize iterable commands (#10373)
## Summary of the Pull Request
Fixes a bug where top-level iterable commands were not serialized.

## PR Checklist
* [X] Closes #10365 
* [X] Tests added/passed

## Detailed Description of the Pull Request / Additional comments
- `Command::ToJson`:
   - iterable commands deserve the same treatment as nested commands
- `ActionMap`:
   - Similar to how we store nested commands, iterable commands need to be handled separately from standard commands. Then, when generating the name map, we make sure we export the iterable commands at the same time we export the nested commands.
2021-06-10 18:25:27 +00:00
Luan Vitor Simião Oliveira
8157605058 profile.schema: add missing actions and commands keys (#10384)
Add missing keys to the schema:
- globalSummon (and args: desktop, monitor, name, dropdownDuration, toggleVisibility)
- quakeMode
- iterateOn
- commands

Also enforces required keys for commands and deprecates "keybindings"

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

## Detailed Description of the Pull Request / Additional comments
There were some other pending keys mentioned on the issue, but I don't think they are pending anymore.

## Validation Steps Performed
Changed the `"$schema"` value in my settings.json to point to the edited one.
2021-06-10 11:10:48 -07:00
Casper Verhaar
0788042540 Replace feedback button with command palette button in dropdown (#10297)
Replaces the "feedback" button in the dropdown menu with a "command palette"
button.

* [x] Closes #10171

![image](https://user-images.githubusercontent.com/34449626/120193627-eca45e80-c21c-11eb-83bb-40b6539bce13.png)
2021-06-10 18:08:47 +00:00
Mike Griese
fe283fc28b Add a Scratch.sln for prototyping (#10067)
#### ⚠️ This targets #10051

## Summary of the Pull Request

This PR creates a `Samples` solution which can be used for quickly testing our particular WinUI + Xaml Islands + wapproj setup, with a `TermControl`. This lets us quickly prototype and minimally repro xaml islands bugs, but also lets us iterate quickly on changes in the process model. I'll be using this in the future to prove that the out-of-proc control works (for tear-out), without having to tear up the entire `TerminalApp` all at once.

While I'll be leaning on this extensively for tear-out prototyping, I've also found myself wanting this kind of sample sln many times in the past. We run into bugs all the time where we're not sure if they're XAML Islands bugs or Terminal bugs. However, standing up a scratch sln with MUX hooked up, and a `XamlApplication` from the toolkit, and XAML Islands is time consuming. This sample sln should let us validate if bugs are XI bugs or Terminal bugs much easier.

## References
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5

## PR Checklist
* [x] Closes one bullet point of https://github.com/microsoft/terminal/projects/5#card-50760312
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

This is _largely_ a copy-pasta of our existing projects, in massively simplified form. I'm gonna wontfix most comments on the code that was copy-pasta'd. If it's bad here, it's probably also bad in the real version in `OpenConsole.sln`.

* I made an entirely new `.sln` for this, so that these samples wouldn't need to build in CI. They're not critical code, they're literally just for prototyping.
* `TerminalAppLib` & `TerminalApp` became `SampleAppLib` and `SampleApp`. This is just a simple application hosting a single `TermControl`. It references the winmds and dlls from the main `OpenConsole.sln`, but in a way that would be more like a project consuming a nuget feed of the control, rather than a `ProjectReference`.
  - It still does all the `App.xaml` and `Toolkit.XamlApplication` stuff that TerminalApp does, so that it can load MUX resources, and do MUX-y things.
* `WindowsTerminal` became `WindowExe`. I tore out all of the `NonClientIslandWindow` stuff - this is just a window with a xaml island.
* `CascadiaPackage` became `Package`. It does the vclibs hack again for the `TerminalConnection` dlls (because this package can't actually determine that `TerminalConnection.dll` requires `cprest*.dll`), as well as for `windowsterminal.exe` (which we'll need in the future for out-of-proc controls). I got rid of all the Dev/Preview/Release asset machinations as well.

Wherever possible, I changed filenames slightly so that they won't get accitdentally opened when someone tries to open a file by name in their editor (**cough** sublime's <kbd>ctrl+p</kbd> menu **cough**).

## Validation Steps Performed

The sample app launches, and displays a TermControl. What else do you want? <sup>(_rhetorical, not a prompt for a wishlist_)</sup>

(cherry picked from commit 30d6cf4839fca8ac8203f6c2489b02a4088b851e)
2021-06-10 12:56:47 -05:00
Michael Niksa
0f42ee189d Summon, not toggle visibility, window on command line dispatch (#10396)
Summon, not toggle visibility, window on command line dispatch

## PR Checklist
* [x] Closes #10292 
* [x] I work here
* [x] Manual test

## Detailed Description of the Pull Request / Additional comments
- This is the same as #10389, just a different route. I didn't realize it at the time.

## Validation Steps Performed
- Opened a window. Dispatched the `wt -w 0 - p <profile>` and watched it join/summon instead of minimize the active WT.
2021-06-10 17:22:22 +00:00
Dustin Howett
a42cef9208 Merge remote-tracking branch 'openconsole/inbox' into main 2021-06-10 10:55:08 -05:00
Dustin Howett
efc9116830 Merged PR 6142815: OS build fixes on top of 94d39b758
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev df66d8161fb17594c817c9ca88a559a8ea006194
2021-06-10 15:52:14 +00:00
gabrielconl
d0d3cc6a75 Terminal color picker tweaks (#10219)
The flyout wasn't very polished, so I did some adjustments.
It's all visual changes, functionality should be the same.

* made the flyout use OverlayCornerRadius and 16px padding (to match WinUI 2.6)
* changed ColorPicker to muxc:ColorPicker for new styles (the color schemes picker too)
* changed "Custom" Button into a ToggleButton
  * no longer needs ellipsis - localization files should be updated
* OK button was moved to the right and uses accent color
* adjusted margins and padding
* tweaked the color boxes to _look_ like the ones in color schemes

![collapsednew](https://user-images.githubusercontent.com/84711285/119713282-33cfcf80-be6a-11eb-9ad9-d18a97b1058a.png) ![expandednew](https://user-images.githubusercontent.com/84711285/119713295-35999300-be6a-11eb-8423-c1c03526b23a.png)

## Validation Steps Performed

* Color picker in settings UI still works ✔️
* Color picker for tabs still works ✔️
2021-06-10 15:49:52 +00:00
Michael Niksa
3c81b51b78 Activate window only (no toggle) when inbound connection arrives (#10389)
Activate window only (no toggle) when inbound connection arrives

## PR Checklist
* [x] Closes #10386
* [x] I work here
* [x] Manual test passed.

## Detailed Description of the Pull Request / Additional comments
The default for the `SummonWindowBehavior` is a toggle of the visibility state. I didn't realize that. We do not want that for inbound connections. We want always-brought-to-front.

## Validation Steps Performed
- Made the change. Launched Terminal as default as active window. Runbox'd another command. It didn't hide itself like it used to. Stays visible.
2021-06-10 06:42:11 +00:00
Dustin Howett
66f0a9cd70 Merged PR 6140256: Migrate OSS up to 94d39b758
Related work items: MSFT-33686498
2021-06-09 23:03:04 +00:00
Dustin Howett
c801029e3e Reflect recent OS build changes, incl. a version of GH-10166
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 577c9d07360d55609a888d5494de10585024168c

This also reverts 563e20b25e (inbox).

Related work items: #32957145, #33103239
2021-06-09 22:57:38 +00:00
Marcel Wagner
becc254f67 Add percentage sign to opacity slider values (#10369)
This PR adds a new PercentageSignConverter that appends the percentage sign to a number. The new converter is being used by the Acrylic opacity slider label and the Background image opacity slider label.

* [x] Closes #10289
2021-06-09 22:45:06 +00:00
Michael Niksa
94d39b7580 Lock for writing in ControlCore::SetBackgroundOpacity (#10357)
## PR Checklist
* [x] Closes random crash that @lhecker sent me on Teams
* [x] I work here.

## Detailed Description of the Pull Request / Additional comments
- Any change to the renderer engine has to be done under lock. Leonard gave me a crash where the dirty rectangles changed out from under the renderer thread. By inspection, only one spot in `ControlCore` is modifying the engine outside of lock.... here. The dump is too far along to definitively prove the issue and it's sort of a race so its difficult to repro. But the theory is sound that all writes to the dirty regions must be done under lock. So here's a fix.
2021-06-09 16:55:41 +00:00
Michael Niksa
76d2aaddcf Restore embedded manifests to say 18362 (#10370)
Restore embedded manifests to say 18362 or unpackaged activation won't work (for helix testing.)

## PR Checklist
* [x] Closes #10265 
* [x] I work here
* [x] Tests now pass

## Detailed Description of the Pull Request / Additional comments
- Unpackaged activation uses the embedded manifest inside the exe. We use unpackaged activation to run our tests in Helix as it's easier that way. Turns out the 1903/19h1 OS thinks 19041 isn't greater than the minimum XAML islands version of 18226 and blocks the load of `TerminalApp.dll` causing a crash (fail fast) on launch. For **REASONS**, 18362 is considered greater than 18226. 
- Packaged activation will use the value in the .appxmanifest and everything is somehow still fine there even with it saying 19041 now.

## Validation Steps Performed
- Kicking a Helix-run off on this branch: https://dev.azure.com/ms/terminal/_build/results?buildId=177336&view=results
2021-06-09 16:23:26 +00:00
Michael Niksa
235f011d6c Restore helix runs by passing parameters (#10367)
Restore helix runs by passing parameters

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

## Detailed Description of the Pull Request / Additional comments
It looks like at some point the configuration and platform variables got messed up passing into the Helix steps and preventing the Powershell scripts from setting up the Helix payload correctly. This restores them to functionality.

## Validation Steps Performed
- Ran it in the pipeline
2021-06-08 18:57:30 +00:00
Leonard Hecker
d7f2a39aeb Enable incremental linking for debug builds (#10342)
## Summary of the Pull Request

Incremental linking was disabled for debug builds only by mistake in the past.
It can't hurt to have it enabled for debug builds.

## PR Checklist
* [x] I work here
* [x] Project still builds
2021-06-04 23:52:49 +00:00
Emmanuel Alap
4eb2c30abd Update profiles schema to draft 2020-12 (#10280)
Update profiles schema to draft 2020-12 because as mentioned in https://github.com/microsoft/vscode/issues/98724#issuecomment-786502628, OpenAPI Specification 3.1 defines using JSON Schema 2020-12 and VS Code already has early implementation around it.

Basically, this just gets rid of the following error shown by VS Code when editing the settings.json file
```
Draft 2019-09 schemas are not yet fully supported.
```

## PR Checklist
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Schema updated.
2021-06-04 16:41:44 -07:00
Ayushman Singh Chauhan
1011dcebf4 DOC: Fix camelCase (or capitalization) (#10318)
Docs have been updated (for bug fixes/features)

docs update => proper capitalisation would be better. 👍: Github

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

### Other information:
Signed-off-by: Ayushman Singh Chauhan <ascb508@gmail.com>
2021-06-04 16:06:10 -07:00
Marcel Wagner
2879fcf65b Fix some places where we weren't using winrt::make (#10335)
This fixes some places where we were in fact not using winrt::make<>

Related to #10264
Closes #10323
2021-06-04 22:22:06 +00:00
Carlos Zamora
c9dc4198ac Polish code for actions page (#10173)
Applies feedback from https://github.com/microsoft/terminal/pull/9949#pullrequestreview-662590658

Highlights include:
- bugfix: make all edit buttons stay visible if the user is using assistive technology
- rename a few functions and resources to match the correct naming scheme
- update the localized text for a conflicting key chord being assigned
- provide better comments throughout the actions page code

## References
#9949 - Original PR
Closes #10168
2021-06-03 22:49:44 +00:00
PankajBhojwani
2fed4c4255 Cleanup from bell flash PR (#10307)
Just come cleanup I did not manage to get to before #9270 merged. 

Specifically:

- We only initialize the animation and timer if we need them
- We don't repeatedly destroy/create the timer

## Validation Steps Performed
It still works
2021-06-02 18:49:33 +00:00
James Holderness
147cde214f Make the xaml formatting script work outside the root directory (#10268)
## Summary of the Pull Request

When the `runformat` script was updated to include xaml formatting, the new code failed to work if run from anywhere other than the project root. This PR updates the script so it can be run from anywhere.

## PR Checklist
* [x] Closes #9768
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] 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

## Detailed Description of the Pull Request / Additional comments

There were a couple of places in the script where it was collecting the list of xaml files by doing `git ls-files **/*.xaml`. That obviously relies on the code being executed from within the root of the project. I've now updated those queries to prefix the path with the `$root` variable, which points to the project root.

## Validation Steps Performed

I've run the `runformat` script from within the tools directory and confirmed that it now works correctly from there. I've tested by changing some formatting in both .cpp and .xaml files, and also saved some .xaml files with a BOM to make sure those were appropriately stripped.
2021-06-02 13:29:47 -05:00
Dustin L. Howett
e3281ce354 Enable winrt::make<> detection (#10264)
C++/WinRT has a way to ensure that we use `make<>` instead of allocating
WinRT objects on the stack, but until 10.0.19041 the XAML compiler
generated code that violated that rule.

Because of how make detection is implemented, it must create a derived
type (and so WinRT implementation types can't be `final`).
2021-06-01 22:33:53 +00:00
Dustin L. Howett
f3ca1ed136 Work around an ARM64 compiler crash by splitting a coroutine up (#10306)
Built and tested in PackageES

(cherry picked from commit fd06b0ce60)
2021-06-01 11:57:17 -05:00
Mike Griese
89ca2ae05f Don't throw in GetProposedDimensions (#10260)
I cannot for the life of me repro the original bug. I've got fonts with bad permissions SxS, I've tried installing a font twice, I've tried stopping the font cache service. No idea how to manually repro the original bug.

BUT theoretically, this function should never throw. So lets just switch this to a `LOG_IF_FAILED`, and hope that this goes away? 

* [x] Fixes #10211?
* [x] built & ran manually.

Unclear if this can get cherry-picked trivially to 1.8. Code's pretty trivial though so if we need another PR for that, it can be arranged.
2021-05-28 21:57:34 +00:00
Michael Niksa
d8647e01c1 Switch FAIL_FAST to LOG for starting inbound connection server on monarch startup (#10261)
Stop startup crash by logging when monarch fails to register inbound connections, but still crash when COM attempted to start us

## References
- See also #10243 

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

## Detailed Description of the Pull Request / Additional comments
- This should stop the crash on launch until we can get the internal teams to resolve the catalog issue
- I left the COM -Embedding start fail fast though so it won't take forever to time out (as default timeout is 3-5 minutes). I will change that if it becomes necessary.

## Validation Steps Performed
- I basically have to guess at this one based on the crash dump and Watson logs because it happens sporadically when the platform messes up on us.
2021-05-28 20:57:48 +00:00
Dustin L. Howett
31d78dceb5 Ignore closeOnExit when a conn. moves from Connecting to Failed (#10263)
ConptyConnection has two different failure modes:

1. We failed to initialize the pseudoconsole or create the process
2. The process exited with an error code.

Until this commit, they were treated the same way: closeOnExit=always
would force the pane/tab to be destroyed. This was very bad in case 1,
where we would display a (possibly useful) error message and then
immediately close the window.

This was made even worse by the change in #10045. We removed
startingDirectory validation and promoted it to an error message (so
that we could eventually let the connection handle startingDirectory in
its own way.) This of course revealed that a number of users had set
invalid starting directories… and those users included some who set
closeOnExit to always. Boom: instant "terminal opens and crashes"¹

In this commit, we introduce detection for a connection that fails
before it's been established. When that happens, we will ignore the
user's closeOnExit mode.

¹ It only looks like a crash; it's actually _technically_ functioning
properly.

Closes #10225.
2021-05-28 14:22:43 -05:00
Mike Griese
eee1623f33 Add link to FAQ to issue template 2021-05-28 10:09:35 -05:00
Michael Niksa
b2c2a4c159 Prevent crashes in Settings UI launch on OS versions before package management extensions (#10238)
Prevent crashes in Settings UI launch on OS versions before package management extensions

## PR Checklist
* [x] Closes #10106 
* [x] I work here
* [x] Manual tests passed.

## Detailed Description of the Pull Request / Additional comments
- On older OS versions like 18363, some of the COM interfaces we use to look up information from the OS application package management catalog (to find default terminals) are unavailable. This returns `E_NOINTERFACE`. This then ends up returning an empty list of items and null as a selected item. 
- I had intended for that to not return that particular error all the way up and just log it because the console and terminal lookup functions always return at least one element: the one representing the `conhost.exe` that is already on the machine.
- I have changed the "default packages" lookup to log instead of return failures like E_NOINTERFACE such that it can continue processing and make the "package" of the hardcoded `conhost.exe` default no matter what. (It will still return an error if there are somehow 0 packages because that code changed or some other catastrophic event happened...)
- I have also changed the Model to have a nulled DefaultTerminal model object (as all winrt objects are nullable) instead of using an optional. I did this because XAML is perfectly happy receiving a `nullptr` for a selected item and will just not select anything. By contrast, if it has an exception occur... it will just bubble that out and crash.

## Validation Steps Performed
- Simulated no items returned from list and nullptr returned to XAML on Current() method of Model. Validated XAML will happily select no item from list (and is fine with an empty list of items... that is it doesn't crash).
- Simulated downlevel OS returning package management errors in lookup catalog functions after the hardcoded default is added to the list. Ensured that this error is only logged, the remainder of the package identification functions make the hardcoded default package, and it is presented as your one and only option in the XAML.
2021-05-27 17:53:00 +00:00
Michael Niksa
e694f36ad2 Summon this window when it receives an inbound connection (#10217)
Summon the listening window when it receives an inbound connection

## PR Checklist
* [x] Closes #9460
* [x] I work here.
* [x] Manual test.

## Detailed Description of the Pull Request / Additional comments
- We cannot just send our window to foreground by simply calling user32 on the window handle. But fortunately, the remoting behavior already has a summon window function with a workaround for the Quake functionality.
- This bubbles up an event from the TerminalApp's Page to the WindowsTerminal's Apphost so it can call the same window summoning behavior in IslandWindow as is triggered when the Monarch dictates this out of the Microsoft.Terminal.Remoting project.

## Validation Steps Performed
- Opened the Terminal with it registered as DefTerm. Activated some other windows to the foreground. Start > Run > Cmd. Tab connects and opens in existing Terminal and it is brought to foreground.
- With no running Terminal and registered as DefTerm, do Start > Run > Cmd. New Terminal is spawned and it is brought to foreground
2021-05-27 17:14:12 +00:00
Leonard Hecker
5d6eec6cde Fix compilation with VS16.10 and later (#10208)
## Summary of the Pull Request

VS16.10 and later contain two regressions:
* Marking the use of `pshpack*.h` in system headers with C4103
* The newly included, builtin `AssemblyReference.xaml` is missing the `AssemblyReferences` project capability

## PR Checklist
* [x] I work here

## Validation Steps Performed

Built the project with VS16.10 and VS17.0.
2021-05-26 20:11:38 +00:00
Michael Niksa
43d5713a02 Correct Default Application Selector styles for high contrast and to change with OS theme dark/light toggle (#10185)
Correct Default Application Selector styles for high contrast and to change with OS theme dark/light toggle

## References
- https://docs.microsoft.com/windows/uwp/design/controls-and-patterns/xaml-theme-resources

## PR Checklist
* [x] Closes #10181
* [x] I work here
* [x] Manual tests passed

## Detailed Description of the Pull Request / Additional comments
1. If I'm going to override colors, I need to define styles in a resource dictionary with Light, Dark, and HighContrast variants so it can be appropriate for each of those. 
2. For HighContrast, I need to not mess with text colors and let them follow the default settings. 
3. For using System Brushes, I need to use a `ThemeResource` binding not a `StaticResource` binding. The former lets it change when you flip the OS toggle Light/Dark. The latter is stuck to whatever it was when the page loaded.

## Validation Steps Performed
- Loaded in light mode. Flipped to dark. Watched it change live. Checked both unselected and rollover/selected to ensure it was fine.
- Loaded in dark mode. Flipped to light. Watched it change live. Checked both unselected and rollover/selected to ensure it was fine.
- Flipped to HC. Watched it change live. Confirmed that unselected is black/white contrast and the roll over has the cyan/black. (No longer uses special second-line brush for HC, matches the controls I modeled this one on from OS Settings).
2021-05-26 05:39:26 +00:00
Dustin Howett
7687dd7b90 version: bump to 1.10 on main 2021-05-25 12:00:17 -05:00
PankajBhojwani
227ec3777a Add a setting to flash the pane when BEL is emitted (#9270)
<!-- 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
Adds a new bellStyle called `window`. When `window` is set and a BEL is emitted, we flash the pane that emitted it. 

Additionally, changes bellStyle in the SUI to a list of checkboxes instead of radio buttons, to match bellStyle being a flag-enum. Deprecates 'BellStyle::Visual' in the schema, but still allows it to be set in the json (it maps to `Window | Taskbar`)

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

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #xxx
* [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

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
GIF in Teams
2021-05-24 22:51:03 +00:00
Michael Niksa
27582a9186 [Defapp] Use real HPCON for PTY management; Have Monarch always listen for connections (#10170)
[Defapp] Use real HPCON for PTY management; Have Monarch always listen for connections

## PR Checklist
* [x] Closes #9464
* [x] Related to #9475 - incomplete fix
* [x] I work here.
* [x] Manual test

## Detailed Description of the Pull Request / Additional comments
- Sometimes peasants can't manage to accept a connection appropriately because I wrote defterm before @zadjii-msft's monarch/peasant architecture. The simple solution here is to just make the monarch always be listening for inbound connections. Then COM won't start a peasant with -Embedding just to ask the monarch where it should go. It'll just join the active window. I didn't close 9475 because it should follow monarch policies on which window to join... and it doesn't yet.
- A lot of interesting things are happening because this didn't have a real HPCON. So I passed through the remaining handles (and re-GUID-ed the interface) that made it possible for me to pack the right process handles and such into an HPCON on the inbound connection and monitor that like any other ConptyConnection. This should resolve some of the process exit behaviors and signal channel things like resizing.
2021-05-24 21:56:46 +00:00
David Kaplan
31e58809cc Add cooked data read tracing (#10166)
Added trace to conhost to instrument buffers that are cooked prior to being passed to the console.
* [x] I've discussed this with core contributors already (internal)

VALIDATION
- Ensured trace is correctly logged in ETL (via TraceLog)
2021-05-24 16:24:01 -05:00
Mike Griese
52560ff818 Hook up the keybindings to the SUI, redux (#10121)
## Summary of the Pull Request

This is a redux of #8882. 

From the original:

>  This is really similar to what we're doing with the `CommandPalette`. We're adding a ~~Preview~~`KeyDown` handler to the SUI `MainPage`, that connects to `TerminalPage::_HandleKey`. That allows the SUI a chance to search the keymap to dispatch actions for keybindings, similar to how the command palette does it. 
> 
> This also means it's now possible for the SUI to invoke _all_ the actions available to the Terminal. This includes the ones like `IncreaseFontSize`, which require a _Terminal_ to actually do something. So we have to make sure all the calls to `_GetActiveControl` actually check that the result is non-null before using it. 
> 
> A bunch of the actions do nothing now from a SUI tab, others behave _weird_. Like "Rename tab" / "Open Tab Renamer" do nothing. "Duplicate Tab" again does nothing - we try making a new settings tab, which just focuses the settings tab again. "Copy text" definitely does nothing, same with paste.

I don't know why I thought this wouldn't work. I thought we'd have to do this in `PreviewKeyDown` or something, which led to [weirdness](https://github.com/microsoft/terminal/pull/8882#issuecomment-767088554). Turns out, we don't need it to be in `PreviewKeyDown`. It can just be in the SUI's `KeyDown`.

## References
* Original: #8882
* Workaround was in #8885


## PR Checklist
* [x] Closes #8767
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

The special case handler from #8885 is no longer needed

## Validation Steps Performed

* Switching tabs with Ctrl+Tab works
* Command palette works
* fullscreen, focus mode works
* close window works
* copy paste on Ctrl+C/V works, even when bound
* Select all text in textboxes works
* tab navigation through UI elements works
2021-05-24 19:18:38 +00:00
PankajBhojwani
0d61466afe Pass through double clicks and hover events in Win32 mouse mode (#10138)
Each mouse-down event's time and position is now stored, and if we
process a left-mouse-down event at the same position as the previous one
and within the double click time we set the double click flag. 

Also adds a case statement to `_UpdateSGRMouseButtonState` so that we
send hover events instead of ignoring them. 

Note: The 'right-click menu in far manager shows up at the wrong
location' bug still exists with this, as it seems to use the cursor
position as told by user32.

Related to #376

## Validation Steps Performed
Double click in far manager works, hover in far manager works (hovering
over items in the right-click menu correctly highlights them)
2021-05-24 17:24:28 +00:00
kovdu
dd348dccda Clear all state tracking nested commands when switching command mode (#10164)
Went for option 2 proposed here:
https://github.com/microsoft/terminal/issues/10140#issuecomment-845193132. 

Disabling back space in the nested entry didn't felt as the nicest
solution.  Instead now all state that keeps track of nested commands is
cleared when switching beteen modes.

## Validation Steps Performed
- Validated the specified issue is fixed by this change:. now after
  entering a sub command and hitting backspace the palette no longer
  shows the sub command item (here `< Select color scheme...` ).
- Validated that switching between all modes (command line, actions, tab
  search & tab switch) still work as expected.
- Validated as well that all modes still work as expected.

Didn't add unit tests, but happy to try that out if this would be
required. 

Closes #10140
2021-05-24 17:10:39 +00:00
Dustin L. Howett
0dedb93cde rle: fix build with clang by adding a deduction guide (#10154) 2021-05-24 13:33:43 +00:00
Dustin L. Howett
89af44488f Emit fixup debug info for internal tooling (#10151)
See MSFT-33187224 for more information.

This may impact debuggability; I have no idea how to tell.
2021-05-24 13:33:20 +00:00
Mike Griese
3f82613a3d Add support for focusPane action, focus-pane subcommand (#10142)
## Summary of the Pull Request

Adds support for the `focusPane` action, and the `focus-pane` subcommand. These allow the user to focus a pane by it's ID. 

* `focusPane` accepts an `id`, identifying the id of the pane to focus.
* `focus-pane`, `fp` requires the parameter `--target,-t` to ID the pane it's going to focus.

## PR Checklist
* [x] Closes #5803
* [x] Closes #5464
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - oh no

## Detailed Description of the Pull Request / Additional comments

The ID isn't _totally_ useful right now, since users can't see them. But they're there, and used in-order. This is just slightly more ergonomic for complicated commandlines than `mf up; mf left`

## Validation Steps Performed

Tested in command palette
Tested a variety of commandlines. `wtd -w 0 mf down ; sp` and `wtd -w 0 fp -t 1 ; sp` gave me special difficulty.
2021-05-21 21:55:57 +00:00
Mike Griese
d6288fae99 Stop quake mode from forcing focus mode (#10150)
Now it just launches in focus mode, but you can _leave_ focus mode just fine.

I can't iterate on this more today - VS decided that it _needed_ an update ☹️ 

* [x] I work here
* [x] Is polish
* [x] @cinnamon-msft: We'll need to update the docs to reflect this.

see also: #8888, comments in that thread
2021-05-21 16:37:02 -05:00
Don-Vito
ee86799f85 Fix profile selection upon discarding changes in SUI (#10147)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/8881
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

## Detailed Description of the Pull Request / Additional comments
* Preserve profile GUID upon item Tag creation. 
* Use this GUID rather than the current profile GUID to select an item
upon settings update.

So even if the profile was renamed and the GUID has changed,
the GUID in the tag remains unchanged and can be found
upon discarding.
2021-05-21 12:34:25 -05:00
Mike Griese
20a722ce50 Fix crash on saving the settings twice (#10148)
## Summary of the Pull Request

Check for null before serializing the default terminal. Because the _currentDefaultTerminal is only initialized when the `Launch` page is navigated to, this _could_ be null if you navigate to another page, save, then save again. 


## PR Checklist
* [x] Closes #10003
* [x] I work here
* [n/a] Tests added/passed
* [n/a] Requires documentation to be updated

## Validation Steps Performed

It crashed consistently before, it doesn't now.
2021-05-21 16:38:52 +00:00
Dustin L. Howett
84f6a29d89 Attempt to heal settings files damaged by #9962 (#10143)
The bug that caused #9962 resulted in folks getting profiles written to
their settings that didn't contain any identifying information (name or
guid), sometimes multiple times.

These profiles look (somewhat) like this:

```json
{ "colorScheme": "Campbell" },
{},
```

An empty profile serves no purpose -- it shows up in the list as being
named "Default", and it only launches CMD (unless the commandline is the
thing that the user successfully changed.)

We can heal the settings file by simply ignoring those profiles that
have *no identifying information* (a guid or a name that can be
converted into a guid).

Validation
----------
I created a number of profiles that fit this format and made sure that
they were ignored on load and destroyed on save.

## PR Checklist
* [x] Closes an annoyance we discovered after 9962.
2021-05-21 16:36:10 +00:00
Luan Vitor Simião Oliveira
504e610841 openConsole.psm1: fix unapproved verb warning (#10145)
<!-- 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

<!-- 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 #10097
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] 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
2021-05-21 16:11:54 +00:00
Carlos Zamora
ff8fdbd243 Introduce serialization for actions (#9926)
## Summary of the Pull Request

This PR builds on the `ActionMap` PR (#6900) by leveraging `ActionMap` to serialize actions. From the top down, the process is now as follows:
- `CascadiaSettings`: remove the hack of copying whatever we had for actions before.
- `GlobalAppSettings`: serialize the `ActionMap` to `"actions": []`
- `ActionMap`: iterate over the internal `_ActionMap` (list of actions) and serialize each `Command`
- `Command`: **THIS IS WHERE THE MAGIC HAPPENS!** For _each_ key mapping, serialize an action. Only the first one needs to include the name and icon.
- `ActionAndArgs`: Find the relevant `IActionArgs` parser and serialize the `ActionAndArgs`.
- `ActionArgs`: **ANNOYING CHANGE** Serialize any args that are set. We _need_ each setting to be saved as a `std::optional`. As with inheritance, this allows us to distinguish an explicit setting to the default value (sometimes `null`) vs an implicit "give me the default value". This allows us to serialize only the relevant details of each action, rather than writing _all_ of the args.

## References
- #8100: Inheritance/Layering for lists
   - This tracks layering and better serialization for color schemes _and_ actions. This PR resolves half of that issue. The next step is to apply the concepts used in this PR (and #9621) to solve the similar problem for color schemes.
- #6900: Actions page

## Validation Steps Performed
Tests added!
2021-05-20 18:44:04 +00:00
Leonard Hecker
13f0b8e007 Split ThrottledFunc into Leading and Trailing variants (#10133)
## Summary of the Pull Request

This replaces `ThrottledFunc` with two variants:
* `ThrottledFuncLeading` invokes the callback immediately and blocks further calls for the given duration
* `ThrottledFuncTrailing` blocks calls for the given duration and then invokes the callback

## References

* #9270 - `ThrottledFuncLeading` will allow the pane to flash immediately for a BEL, but block further BELs until the animation finished

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

## Validation Steps Performed

* [x] Ensured scrolling still works
2021-05-20 17:31:47 +00:00
Leonard Hecker
a8e4bedae3 Introduce til::rle - a run length encoded vector (#10099)
## Summary of the Pull Request

Introduces `til::rle`, a vector-like container which stores elements of
type T in a run length encoded format. This allows efficient compaction
of repeated elements within the vector.

## References

* #8000 - Supports buffer rewrite work. A re-use of `til::rle` will be
  useful as a column counter as we pursue NxM storage and presentation.
* #3075 - The new iterators allow skipping forward by multiple units,
  which wasn't possible under `TextBuffer-/OutputCellIterator`.
  Additionally it also allows a bulk insertions.
* #8787 and #410 - High probability this should be `pmr`-ified
  like `bitmap` for things like `chafa` and `cacafire`
  which are changing the run length frequently.

## PR Checklist

* [x] Closes #8741
* [x] I work here.
* [x] Tests added.
* [x] Tests passed.

## Validation Steps Performed

* [x] Ran `cacafire` in `OpenConsole.exe` and it looked beautiful
* [x] Ran new suite of `RunLengthEncodingTests.cpp`

Co-authored-by: Michael Niksa <miniksa@microsoft.com>
2021-05-20 17:27:50 +00:00
Leonard Hecker
eaeab7a807 Upgrade Windows SDK to 19041 (#10118)
## Summary of the Pull Request

Upgrade the Windows SDK to 19041 by setting `WindowsTargetPlatformMinVersion` to 17763 and `WindowsTargetPlatformVersion` to 19041.

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

## Validation Steps Performed

General usage of the Windows Terminal application appears fine.
2021-05-20 16:04:25 +00:00
UnrealApex
c3bf8a5d25 doc: Added links to folders and headers mentioned (#10111)
Closes #10110.
2021-05-19 17:39:58 -05:00
Mike Griese
a4ebeb0a56 This fixes summoning _quake as the MRU window (#10108)
## Summary of the Pull Request

This fixes a bug where if you had the `_quake` window open, and you tried to `globalSummon` it (not with the `quakeMode` action, but just with a plain-old `globalSummon` to activate the MRU window), we'd _create a new window_ instead of just summoning the `_quake` window.

## References
* regressed in #9956 

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-60325142
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

It's basically a one-line fix, I just had to update the function signature for `_getMostRecentPeasantID` to allow us to use it differently for glomming vs summoning. When glomming, `ignoreQuakeWindow` should be true. When summoning, `ignoreQuakeWindow` should be false.
2021-05-19 11:14:09 -05:00
Mike Griese
b5edb77058 Bind quakeMode to "win+`" by default (#10122)
I'd personally chose to just bind `globalSummon` to <kbd>win+`</kbd>, but _I do as I'm told_.

* [x] I work here
* [x] @cinnamon-msft mentioned this
* [x] Docs
2021-05-18 22:56:42 +00:00
Dustin L. Howett
3a27386e25 (1.9 port) Fix a number of shutdown crashes in TermControl (#10117)
1. The TSFInputControl may get a layout event after it has been removed
   from service (and no longer has a XAML tree)
   * Two fixes:
      * first, guard the layour updater from accessing detached xaml
	objects
      * second, shut down all pending throttled functions during close
	(not destruction!¹)
2. The TermControlAutomationPeer may be destructed before its events
   fire.
3. The TermControlAutomationPeer may receive a notification after it has
   been detached from XAML (and therefore has no dispatcher).

¹ Close happens before the control is removed from the XAML tree;
destruction happens some time later. We must detach all UI-bound events
in Close so that they don't fire between when we detach and when we
destruct.

Fixes MSFT-32496693
Fixes MSFT-32496158
Fixes MSFT-32509759
Fixes MSFT-32871913

(cherry picked from commit 661fde5937)
2021-05-18 17:36:40 -05:00
Carlos Zamora
996a680ec3 Revert "Add the profile, page icons to the page headers (#10046)" (#10124)
This reverts commit a3a2a4102d.

#10046 causes a crash on save. MainPage::UpdateSettings() is unable to update the navigation view's selected item due to an "incorrect parameter". This is particularly strange to see because #10046 only modifies the navigation view's header, not the menu items themselves. Reverting this change fixes that crash (verified).

Reopens #9694
2021-05-18 17:35:50 -05:00
Carlos Zamora
c66910b685 Make Actions page editable (#9949)
## Summary of the Pull Request

This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely.

## References

#9621 - ActionMap
#9926 - ActionMap serialization
#9428 - ActionMap Spec
#6900 - Actions page
#9427 - Actions page design doc

## Detailed Description of the Pull Request / Additional comments

### Settings Model Changes

- `Command::Copy()` now copies the `ActionAndArgs`
- `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten.
- `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord.
- `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated.

### Editor Changes

- `Actions.xaml` is mainly split into two parts:
   - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable).
   - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model.
- `KeyBindingViewModel` is a view model object that controls the UI and the settings model. 

There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes...
- a binary search by name on `Actions::KeyBindingList`
- presenting an error when the provided key chord is invalid.

## Demo
![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 21:37:16 +00:00
Mike Griese
24f80bd9ba Don't yeet focus to the control when the tab renamer is opened (#10114)
This is a hotfix to #10048. When the tab renamer is opened, we need to make sure to not immediately steal focus from it.

* [x] closes #10112
* [x] I work here
* [x] tested manually
2021-05-18 18:48:57 +00:00
Mike Griese
e3d673ecd4 Hide _quake window on minimize ALWAYS (#10113)
## Summary of the Pull Request

This is a scoped implementation of "hide on minimize", only to the `_quake` window. When minimized, the `_quake` window won't appear in the taskbar. IT ALSO WON'T APPEAR IN THE TRAY, BECAUSE WE DON'T HAVE ONE YET.

I talked about this with @DHowett, and it seemed cool. Other windows will still minimize normally.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888
* minimize to tray: #5727 

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-61246940
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated - probably yea, but something <sub>something <sub>something</sub></sub>

## Detailed Description of the Pull Request / Additional comments

After playing with it, it is in fact, cool.

ALSO `LOG_IF_WIN32_BOOL_FALSE` should DEFINITELY not be used with `ShowWindow`. [`ShowWindow`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow#return-value) returns false if the window was previously hidden, but doesn't `SetLastError`, so that macro will _throw_.

## Validation Steps Performed


```jsonc
        { "keys": "ctrl+`", "command": { "action": "quakeMode" } },
        { "keys": "ctrl+1", "command": { "action": "globalSummon", "name": "_quake" } },
        // { "keys": "ctrl+1", "command": { "action": "globalSummon" } },
        // { "keys": "ctrl+2", "command": { "action": "globalSummon", "desktop": "toCurrent" } },
        // { "keys": "ctrl+2", "command": { "action": "globalSummon", "toggleVisibility": false } },
        // { "keys": "ctrl+2", "command": { "action": "globalSummon", "dropdownDuration": 2000 } },
        { "keys": "ctrl+2", "command": { "action": "globalSummon", "monitor": "any" } },
        // { "keys": "ctrl+3", "command": { "action": "globalSummon", "desktop": "onCurrent" } },
        { "keys": "ctrl+3", "command": { "action": "globalSummon", "monitor": "toMouse" } },
        // { "keys": "ctrl+4", "command": { "action": "globalSummon", "desktop": "any" } },
        { "keys": "ctrl+4", "command": { "action": "globalSummon", "monitor": "toMouse", "dropdownDuration": 500 } },
        { "keys": "ctrl+5", "command": { "action": "globalSummon", "dropdownDuration": 500 } },
```
2021-05-18 10:44:42 +00:00
Mike Griese
3866771b1b Add "monitor": "any"|"toCurrent"|"toMouse" setting to globalSummon (#10092)
#### ⚠️ this pr targets #9977

## Summary of the Pull Request

This adds support for part of the `monitor` property for `globalSummon`. It also goes a little off-spec:

```json
"monitor": "any"|"toCurrent"|"toMouse"
```

* `monitor`: This controls the monitor that the window will be summoned from/to
  - `"any"`: Summon the MRU window, regardless of which monitor it's currently on.
  - `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor with the current **foreground** window.
  - [**NEW**] `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse** cursor is.

When I was playing with this, It felt like `toMouse` was always what I wanted, not `toCurrent`. We can always just comment that out if we think that's contentious - I'm aware I didn't originally spec that.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-60325291
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated 😢 

## Detailed Description of the Pull Request / Additional comments

I made `toMouse` the default because it felt better. fite-me.jpg 

## Validation Steps Performed
my ever evolving blob:

```jsonc
    { "keys": "ctrl+`", "command": { "action": "quakeMode" } },
    { "keys": "ctrl+1", "command": { "action": "globalSummon" } },
    // { "keys": "ctrl+2", "command": { "action": "globalSummon", "desktop": "toCurrent" } },
    // { "keys": "ctrl+2", "command": { "action": "globalSummon", "toggleVisibility": false } },
    // { "keys": "ctrl+2", "command": { "action": "globalSummon", "dropdownDuration": 2000 } },
    { "keys": "ctrl+2", "command": { "action": "globalSummon", "monitor": "any" } },
    // { "keys": "ctrl+3", "command": { "action": "globalSummon", "desktop": "onCurrent" } },
    { "keys": "ctrl+3", "command": { "action": "globalSummon", "monitor": "toMouse" } },
    // { "keys": "ctrl+4", "command": { "action": "globalSummon", "desktop": "any" } },
    { "keys": "ctrl+4", "command": { "action": "globalSummon", "monitor": "toMouse", "dropdownDuration": 500 } },
    { "keys": "ctrl+5", "command": { "action": "globalSummon", "dropdownDuration": 500 } },
```
2021-05-17 12:57:08 +00:00
Mike Griese
6e11780ca6 Add property to control dropdown speed of global summon (#9977)
## Summary of the Pull Request

Adds the `dropdownDuration` property to `globalSummon`. This controls how fast the window appears on the screen when summoned from minimized. It similarly controls the speed for sliding out of view when the window is dismissed with `"toggleVisibility": true`.

`dropdownDuration` specifies the duration in **milliseconds**. This defaults to `0` for `globalSummon`, and defaults to `200` for `quakeMode`. 200 was picked because, according to [`AnimateWindow`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-animatewindow): 

>  Typically, an animation takes 200 milliseconds to play.

Do note that you won't be able to interact with the window during the animation! Input sent during the dropdown will arrive at the end of the animation, but input sent during the slide-up _won't_. Avoid setting this to large values!

The gifs are in Teams. 

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-59030824
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

I had the following previously in the doc comments, but it feels better in the PR body:

- This was chosen because it was easier to implement and generally nicer than:
  * `AnimateWindow`, which would show the window borders for the duration of
    the animation, and occasionally just plain not work. Additionally, for
    `AnimateWindow` to work, the window much not be visible, so we'd need to
    first restore the window, then hide it, then animate it. That would flash
    the taskbar.
  * `SetWindowRgn` on the root HWND, which caused the xaml content to shift to
    the left, and caused a black bar to be drawn on the right of the window.
    Presumably, `SetWindowRgn` and `DwmExtendFrameIntoClientArea` did not play
    well with each other.
  * `SetWindowPos(..., SWP_NOSENDCHANGING)`, which worked the absolute best for
    longer animations, and is the closest to the actual implementation of
    `AnimateWindow`. This would resize the ROOT window, without sending resizes
    to the XAML island, allowing the content to _not_ reflow. but for a
    duration of 200ms, would only ever display ~2 frames. That's basically
    not even animation anymore, it's now just an "appear". Since that's how
    long the default animation is, if felt silly to have it basically not
    work by default.
- If a future reader would like to implement this better, **they should feel
  free to**, and not mistake my notes here as expertise. These are research
  notes into the dark and terrible land that is Win32 programming. I'm no expert. 

## Validation Steps Performed

This is the blob of json I'm testing with these days:

```jsonc
        { "keys": "ctrl+`", "command": { "action": "quakeMode" } },
        { "keys": "ctrl+1", "command": { "action": "globalSummon" } },
        // { "keys": "ctrl+2", "command": { "action": "globalSummon", "desktop": "toCurrent" } },
        // { "keys": "ctrl+2", "command": { "action": "globalSummon", "toggleVisibility": false } },
        { "keys": "ctrl+2", "command": { "action": "globalSummon", "dropdownDuration": 2000 } },
        { "keys": "ctrl+3", "command": { "action": "globalSummon", "desktop": "onCurrent" } },
        { "keys": "ctrl+4", "command": { "action": "globalSummon", "desktop": "any" } },
```

* <kbd>ctrl+\`</kbd> will summon the quake window with a _quick_ animation
* <kbd>ctrl+2</kbd> will summon the window with a  s l o w  animation
2021-05-17 07:28:46 -05:00
PankajBhojwani
7a41be5cd4 Add a setting to disable URL detection (#10022)
<!-- 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
Adds a global setting, `experimental.detectHyperlinks`, that controls whether we automatically detect links and make them clickable. Default is set to true.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #9981 
* [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
* [x] Schema updated.
* [x] I work here

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
When `detectHyperlinks` is set to false, links do not underline on hover and are not clickable.
2021-05-17 04:20:09 +00:00
Leon Liang
f7458a31fd Fix tabColor arg crash in CommandPalette (#10096)
While a user is formulating their hex string for a `tabColor` arg
in the CommandPalette, we try to parse the string one char at
a time as it comes in. `ColorFromHexString` doesn't like anything
except a well formed hex string so it'll throw. We can probably eat
any error that comes out of this because we should only care to set 
the TabColor once the string provided is a valid hex str.

Closes #10053
2021-05-16 21:51:51 -05:00
PankajBhojwani
f3cf321e87 Show a preview of the control in the SUI (#9527)
In the 'Appearance' tab of a profile, show a preview of what the control looks like

## PR Checklist
* [x] Closes #9122
2021-05-16 21:26:47 -05:00
Michael Niksa
66fdc645f7 Set keyword flags on all tracelog events (#10098)
Set keyword flags on all events so those sharing a provider with
telemetry do not fire unless tracing is enabled

## PR Checklist
* [x] Closes #10093 
* [x] I work here
* [x] Tests passed
* [x] Documentation added in `til.h` about how keywords work and at the
  only other site of keywords we define in the Host project tracing
  files.

## Detailed Description of the Pull Request / Additional comments
I initially thought that we would need to split providers here to
accomplish this... but @DHowett helped me realize that might be a lot of
additional metadata and bloat binary size. So with help from a friend
from fundamentals, I realized that we could use Keywords to
differentiate here. We can no longer define 0 keywords as that
represents an any/all scenario. Every `TraceLoggingWrite` event now
needs a keyword. When our events have a keyword, they're not included in
any trace. Additionally, when we have an explicit keyword to check that
is different from the ones used for the telemetry pipeline, we can
ensure that we only do "hard work" to generate debug trace data when an
"ALL" type listener like TraceView or Windows Performance Recorder with
our profiles is listening to these providers for ALL keyworded events. 

## Validation Steps Performed
- [x] - Built with full release build config to confirm performance is
  worse than dev builds BECAUSE of the telemetry event collector camping
  our provider and triggering full trace event generation on shared
  providers.
- [x] - Built with full release build config to enable statistics
  collection and validated trace event collection is excluded and trace
  event short-circuits work with this change.
- [x] - Checked that TraceView still sees both telemetry and tracing
  events
- [x] - Checked that WPR with our .wprp profile sees both telemetry and
  tracing events
2021-05-14 23:14:26 +00:00
Josh Soref
bbe8275f69 ci: spelling: update to v0.0.18 (#10035)
Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>

<!-- 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

Upgrade check-spelling to [v0.0.18](https://github.com/check-spelling/check-spelling/releases/tag/v0.0.18)

<!-- 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
* [ ] Closes #xxx
* [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

I've replaced the `dictionary` directory with `allow` and `reject`. When terminal got check-spelling, I didn't have a way to do `allow`/`reject` (but they were added a while ago). With this release, the bot will complain about items that are in user managed files that wouldn't be valid, this is mostly `-`s in dictionary files, but it also includes numbers `0`..`9` and `_`. If a specific token needs to be accepted but not its sub-elements, the item should be added to `patterns.txt` instead  (`D2DERR_SHADER_COMPILE_FAILED` is an example).

With this version, check-spelling defaults to only considering tokens with at least 3 letters. It's possible to tune it back to 2 (or even 1), but in testing, the 2 character tokens have ended up not being worthwhile.  (This can be [adjusted](https://github.com/check-spelling/check-spelling/wiki/Configuration#shortest_word) if it turns out that people manage to misspell two character tokens often enough to justify checking them.)

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

I ran a number of passes of the spell checker in https://github.com/check-spelling/terminal/actions (note: I tend to delete this repository, so this link may be dead at some point, and action run logs expire).
2021-05-14 08:28:37 -05:00
Michael Niksa
7dadde5dd6 Implement PGO in pipelines for AMD64 architecture; supply training test scenarios (#10071)
Implement PGO in pipelines for AMD64 architecture; supply training test scenarios

## References
- #3075 - Relevant to speed interests there and other linked issues.

## PR Checklist
* [x] Closes #6963
* [x] I work here.
* [x] New UIA Tests added and passed. Manual build runs also tested.

## Detailed Description of the Pull Request / Additional comments
- Creates a new pipeline run for creating instrumented binaries for Profile Guided Optimization (PGO).
- Creates a new suite of UIA tests on the full Windows Terminal app to run PGO training scenarios on instrumented binaries (and incidentally can be used to write other UIA tests later for the full Terminal app.)
- Creates a new NuGet artifact to store trained PGO databases (PGD files) at `Microsoft.Internal.Windows.Terminal.PGODatabase`
- Creates a new NuGet artifact to supply large-scale test content for automated tests at `Microsoft.Internal.Windows.Terminal.TestContent`
- Adjusts the release pipeline to run binaries in PGO optimized mode where content from PGO databases is leveraged at link time to optimize the final release build

The following binaries are trained:
- 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

In the future, adding `<PgoTarget>true</PgoTarget>` to a new `vcxproj` file will automatically enroll the DLL/EXE for PGO instrumentation and optimization going forward.

Two training test scenarios are implemented:
- Smoke test the Terminal by just opening it and typing a bit of text then exiting. (Should help focus on the standard launch path.)
- Optimize bulk text output by launching terminal, outputting `big.txt`, then exiting.

Additional scenarios can be contributed to the `WindowsTerminal_UIATests` project with the `[TestProperty("IsPGO", "true")]` annotation to add them to the suite of scenarios for PGO.

**NOTE:** There are currently no weights applied to the various test scenarios. We will revisit that in the future when/if necessary.

## Validation Steps Performed
- [x] - Training run completed at https://dev.azure.com/ms/terminal/_build?definitionId=492&_a=summary
- [x] - Optimization run completed locally (by forcing `PGOBuildMode` to `Optimize` on my local machine, manually retrieving the databases with NuGet, and building).
- [x] - Validated locally that x86 and ARM64 do not get trained and automatically skip optimization as databases are not present for them.
- [x] - Smoke tested optimized binary versus latest releases. `big.txt` output through CMD is ~11-12seconds prior to PGO and just over 8 seconds with PGO.
2021-05-13 21:12:30 +00:00
Mike Griese
a3a2a4102d Add the profile, page icons to the page headers (#10046)
## Summary of the Pull Request

Adds the profile icons to the page header. I had to manually create the header, and manually bind it to the `Icon` and `Content` of each `NavViewItem`. 

It's important that each `NavViewItem`'s icon is set as an `IconSource`, so that we can bind to it. If it's just a plain old `FontIcon`, then we can't re-use it. 

Additionally, I removed the manual sizing of all font icons to font size 12. That would make font icons _tiny_ in the header. Now, they'll properly re-use the size of the `NavigationViewTitleHeaderContentControlTextStyle` in the nav view header. This involved also manually making the icons smaller on the `AddProfile` page and in the `CommandPalette`.

As per usual, images are in Teams


## PR Checklist
* [x] Closes #9694
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated

## Validation Steps Performed
* Checked (bitmap|font) icons in tabs
* (bitmap|font) icons in the flyout
* (bitmap|font) icons in command palette
* (bitmap|font) icons in the nav view
* (bitmap|font) icons in the header
* (bitmap|font) icons in the add profile page
2021-05-13 10:35:53 +00:00
Mike Griese
bfc4838042 Disable path validation, add warning (#10045)
This is primarily being done to unblock #9223.

Prior to this, we'd validate that the user's `startingDirectory` existed
here. If it was invalid, we'd gracefully fall back to `%USERPROFILE%`.

However, that could cause hangs when combined with WSL. When the WSL
filesystem is slow to respond, we'll end up waiting indefinitely for
their filesystem driver to respond. This can result in the whole terminal
becoming unresponsive.

Similarly, with #9223 we want users to be able to specify WSL paths in a
profile, but this bit of validation logic totally prevents that from working,
because it'll just replace the path with `%USERPROFILE%`.

If the path is eventually invalid, we'll display warning in the
`ConptyConnection`, when the process fails to launch.

Closes #9541
Closes #9114

![image](https://user-images.githubusercontent.com/18356694/117318675-426d2d00-ae50-11eb-9cc0-0b23c397472c.png)
2021-05-12 17:36:11 +00:00
Mike Griese
9f45963e73 Use DComp surface handle for Swap Chain management (#10023)
## Summary of the Pull Request

This PR changes the DxEngine to create a swapchain HANDLE, then have the TermControl attach _that_ handle to the SwapChainPanel, rather than returning the swapchain via a `IDXGISwapChain1`.

I didn't write this code originally, @miniksa helped me out. The original commit was so succinct that I didn't think there was anything else to add or take away.

I'm going to need this for tear-out (#1256), so that I can have the content process create swap chain handles, then duplicate those handles out to the window process that will end up embedding the content.

## References

* [`DCompositionCreateSurfaceHandle`](https://docs.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-dcompositioncreatesurfacehandle)
* [`CreateSwapChainForCompositionSurfaceHandle`](https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_3/nf-dxgi1_3-idxgifactorymedia-createswapchainforcompositionsurfacehandle)
* [`CreateSwapChainForComposition`](https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgifactory2-createswapchainforcomposition)
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

This reverts commit c113b65d9b.

That commit reverted 30b8335479

## Validation Steps Performed

* [x] Built and ran the Terminal, it still seems to work
* [x] Does a TDR still work? or do we need to recreate the handle, or something.
* [x] Does this work on Win7? I honestly have no idea how DX compatibility works. Presumably, the WPF version uses the `ForHwnd` path, so this will still work, but I don't know if this will suddenly fail to launch on Win7 or something. Tagging in @miniksa.
2021-05-12 11:54:17 -05:00
Dustin L. Howett
e0bd76b30d Make sure we run CG component detection on main (#10078)
I believe that there is a hidden "default branch" setting in Azure
DevOps, and ours is set to "master". CG only attempts to automatically
inject to builds off the default branch... and because we're a GitHub
repo running builds in AzDO we _can't change what the default branch
is_. Oops.
2021-05-12 02:47:45 +00:00
Mike Griese
8564b269c4 In specific scenarios, focus the active control (#10048)
A redo of #6290. That PR was overkill. In that one, we'd toss focus back to the active control any time that the tab view item got focus. That's maybe not the _best_ solution.

Instead, this PR is precision strikes. We're re-using a lot of what we already have from #9260. 
* When the context menu is closed, yeet focus to the control.
* When the renamer is dismissed, yeet focus to the control.
* When the TabViewItem is tapped (meaning no one else handled it), yeet focus to the control.

### checklist 
* [x] I work here
* [ ] This is UI so it doesn't have tests
* [x] Closes #3609
* [x] Closes #5750
* [x] Closes #6680

### scenarios:

* [x] focus the window by clicking on the tab -> Control is focused. 
* [x] Open the color picker with the context menu, can move the focus inside the picker with the arrow keys.
* [x] Dismiss the picker with esc -> Control is focused. 
* [x] Dismiss the picker with enter -> Control is focused. 
* [x] Dismiss the renamer with esc -> Control is focused. 
* [x] Dismiss the renamer with enter -> Control is focused. 
* [x] Dismiss the context menu with esc -> Control is focused. 
* [x] Start renaming, then click on the tab -> Rename is committed, Control is focused. 
* [x] Start renaming, then click on the text box -> focus is still in the text box
2021-05-11 23:55:49 +00:00
Dustin L. Howett
258a6ce8a1 Add a test for GH-9692/MSFT-33127449 (#10077)
This test has some load bearing specifics in it.

In short, it must trigger multiple boost::small_vector growths. The
vector is reused for the lifetime of the console (!) so it must be
forced to act the way the repro requires.

Oh, and the test needs to be run with Application Verifier +Heap.

This validates the fix in c0ab9cb5b5.
2021-05-11 23:16:39 +00:00
Leonard Hecker
43040ef9d0 Fix crash on exit introduced in ac265aa (#10042)
## Summary of the Pull Request

ControlCore::AttachUiaEngine receives a IRenderEngine as a raw pointer,
which TermControl owns. We must ensure that we first destroy the
ControlCore before the UiaEngine instance (both owned by TermControl).
Otherwise a deallocated IRenderEngine is accessed when
ControlCore calls Renderer::TriggerTeardown.

## References

This crash was introduced in #10031.

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

## Validation Steps Performed

* Run accevent.exe to cause a UiaEngine to be attached to a TermControl.
* Close the current tab
* Ensured no crashes occur
2021-05-11 23:03:08 +00:00
Dustin Howett
440b626ee3 Revert "Initial implementation of fine-grained text analysis (#9202)"
This reverts commit 1c414a7723.

Fixes #10034.
2021-05-11 14:14:17 -05:00
Dustin Howett
b132fbe4a6 Merge remote-tracking branch 'openconsole/inbox' into HEAD 2021-05-11 12:11:27 -05:00
Dustin Howett
c0ab9cb5b5 Merged PR 6034984: Fix a crash caused by improper buffer management w/ multiple clients
Until there's a "Wait", there's usually only one API message inflight at
a time.

In our quest for performance, we put that single API message in charge
of its own buffer management: instead of allocating buffers on the heap
and deleting them later (storing pointers to them at the far corners of
the earth), it would instead allocate them from small internal pools (if
possible) and only heap allocate (transparently) if necessary. The
pointers flung to the corners of the earth would be pointers (1) back
into the API_MSG or (2) to a heap block owned by boost::small_vector.

It took us months to realize that those bare pointers were being held by
COOKED_READ and RAW_READ and not actually being updated when the API
message was _copied_ as it was shuffled off to the background to become
a "Wait" message.

It turns out that it's trivially possible to crash the console by
sending two API calls--one that waits and one that completes
immediately--when the waiting message or the "wait completer" has a
bunch of dangling pointers in it. It further turns out that some
accessibility software (like JAWS) attaches directly to the console
session, much like winpty and ConEmu and friends. They're trying to read
out the buffer (API call!) and sometimes there's a shell waiting for
input (API call!). Oops.

In this commit, we fix up the message's internal pointers (in lieu of
giving it a proper copy constructor; see GH-10076) and then tell the
wait completion routine (which is going to be a COOKED_READ, RAW_READ,
DirectRead or WriteData) about the new buffer location.

This is a scoped fix that should be replaced (TODO GH-10076) with a
final one after Ask mode.

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

References GH-10076

Fixes MSFT-33127449
Fixes GH-9692
2021-05-11 16:56:43 +00:00
Dustin Howett
563e20b25e Merged PR 6013951: Reflect OS build changes for "Implicit Binary Deps" rollout
The ES folks removed support for implicit binary dependencies in test projects, which required our testmd to change to include its dependency on testnetv5.

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

Related work items: MSFT-31480819
2021-05-11 16:46:37 +00:00
kovdu
0e8d5f24c4 Keep the last selected pivot active when navigating over profile pages (#10047)
## PR Checklist
* [x] Closes #9920 
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA

## Validation Steps Performed

- When opening a profile page and selecting a random pivot, when then navigating away from the profile page to another item and navigating back to the same profile the last selected pivot was still active.
- When opening a profile page and selecting a random pivot, when then navigating away from the profile page to a second profile the last selected pivot was immediately active on the second profile.
- When selecting random pivots and navigating only between other profile pages the last selected pivot was always active on the opened profile page.

What felt a bit strange at first sight was:
- open a profile page, select a random pivot
- start adding a new profile
- the last selected pivot is immediately active and not the "General" pivot what might be the obvious pivot to show when a user  wants to add a new profile.

After playing a bit more with this this started to feel ok. Since as a user you might go to "Add new profile" immediately anyway instead of opening other profiles first.  

Just explicitly highlighting this last point since maybe someone prefers that we need to make sure to always start with the 'General' pivot when adding a new profile and then this fix is not correct.
2021-05-07 04:13:06 +00:00
PankajBhojwani
b3775bc2b0 [Conpty] Pass through request for mouse mode to the Terminal (#9970)
<!-- 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
When the client application sets the console input mode with the `ENABLE_MOUSE_INPUT` flag, we send along the appropriate VT sequences to the connected terminal (if there is one).

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

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #xxx
* [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

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Far manager works
2021-05-07 02:46:11 +00:00
PankajBhojwani
f518235599 Allow trailing semicolon when parsing OSC 9;4 (#10024)
## Summary of the Pull Request
When we parse OSC 9;4, allow a trailing semicolon (i.e. allow `9;4;` or something like `9;4;3;`). 

## PR Checklist
* [x] Closes #9960 
* [X] Tests added/passed

## Validation Steps Performed
OSC 9;4 sequences with or without trailing semicolons work
2021-05-05 18:12:55 +00:00
Carlos Zamora
22fd06e19b Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).

## References
#9428 - Spec
#6900 - Actions page

Closes #7441

## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.

#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.

Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.

Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.

The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.

## Validation Steps Performed

All local tests pass.
2021-05-04 21:50:13 -07:00
Carlos Zamora
5713cd2148 [Spec] Settings Model - Actions (#9428)
This spec covers the settings model work required to create the Actions page in the settings UI (designed in #9427). 

Overall, the idea is to promote `Command` to include the actual `KeyChord`, then introduce an `ActionMap` that handles all of the responsibilities of `KeyMapping` and more (as well as general action management).

[Markdown view](https://github.com/microsoft/terminal/blob/dev/cazamor/spec/tsm-actions/doc/specs/%23885%20-%20Terminal%20Settings%20Model/Actions%20Addendum.md)
2021-05-05 04:49:06 +00:00
PankajBhojwani
b53bd672d7 Create a new page for "Add new profile" in the SUI (#9352)
- Whenever we add a new profile setting from now on we have to update
  `Profile::CopySettings` _and_ `CascadiaSettings::DuplicateProfile` 👎 

Notes from bug bash (checked bugs have been resolved):

- [ ] The duplicate list can be very long if you have profiles
- [x] DH: "Create new" seems too vague. "New empty profile" or something
  seems a little clearer to me.
- [x] There is no deduplication counter for name
- [x] Crash when your settings file is corrupt and we had to fall back
  to the defaults and you duplicate a profile
- [x] Crash due to #10003

## PR Checklist
* [x] Closes #9121
2021-05-05 04:15:25 +00:00
Don-Vito
cb55cec275 Teach CmdPal search to use user locale (#9943)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9941
* [x] CLA signed.

## Detailed Description of the Pull Request / Additional comments
The bug is due to us using std::tolower, while the default locale is not user's locale.
The fix here is to use the same approach as upon sorting: lstrcmpi.
While there are additional methods to do locale aware comparison,
here we convert chars to string and call lstrcmpi.
While this approach seems somewhat inefficient it ensures consistency
(with the order of locales that lstrcmi tries to apply internally).
2021-05-04 23:31:15 +00:00
Mike Griese
c3ca94ceca First three interactivity fixes (#9980)
## Summary of the Pull Request

This PR encompasses the first three bugs we found post-#9820.

### A: Mousedown, select, SCROLL does a weird thing with endpoints that doesn't happen in stable

We were using the terminal position to set the selection anchor, when we should have used the pixel position.

This is fixed in 4f4df01.

### B: Trackpad scrolling down with small increments seems buggy

This one's the most complicated.  The touchpad sends very many small scroll deltas, less than one row at a time. The control scrollbar can store a `double`, so small deltas can accumulate. Originally, these would accumulate in the scrollbar, and we'd only read that out as an `int` in the scrollbar updater, which is throttled. 

In the interactivity split, there's no place for us to store that double. We immediately narrow to an `int` for `ControlInteractivity::_updateScrollbar`. 

So this introduces a double inside `ControlInteractivity` as a fake scrollbar, with which to accumulate to. 

This is fixed in 33d29fa...0fefc5b

### C:  Looks like there's a selection issue when you click and drag too quickly.

The diff for this one is:

<table>

<tr><td>1.8</td><td>main</td></tr>
<tr>

<td>

```c++
if (_singleClickTouchdownPos)
{
    // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point
    auto& touchdownPoint{ *_singleClickTouchdownPos };
    auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) };
    const til::size fontSize{ _actualFont.GetSize() };

    const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _renderEngine->GetScaling());
    if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f))
    {
        _terminal->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint));
        // stop tracking the touchdown point
        _singleClickTouchdownPos = std::nullopt;
    }
}
```

</td>

<td>

```c++
if (_singleClickTouchdownPos)
{
    // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point
    auto& touchdownPoint{ *_singleClickTouchdownPos };
    float dx = ::base::saturated_cast<float>(pixelPosition.x() - touchdownPoint.x());
    float dy = ::base::saturated_cast<float>(pixelPosition.y() - touchdownPoint.y());
    auto distance{ std::sqrtf(std::powf(dx, 2) +
                              std::powf(dy, 2)) };

    const auto fontSizeInDips{ _core->FontSizeInDips() };
    if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f))
    {
        _core->SetSelectionAnchor(terminalPosition);
        // stop tracking the touchdown point
        _singleClickTouchdownPos = std::nullopt;
    }
}
```

</td>
</tr>
</table>

```c++
        _terminal->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint));
```

vs

```c++
        _core->SetSelectionAnchor(terminalPosition);
```

We're now using the location of the drag event as the selection anchor, instead of the location that the user initially clicked. Oops.


## PR Checklist
* [x] Checks three boxes, though I'll be shocked if they're the last.
* [x] I work here
* [x] Tests added/passed 🎉🎉🎉
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

All three have tests, 🙌🙌🙌🙌

## Validation Steps Performed

Manual, and automated via tests
2021-05-04 22:54:02 +00:00
MPela
2b4c20bd6e Fix dropdown showing in up direction (#10009)
## Summary of the Pull Request
Let the dropdown menu open downwards if there's enough space, when clicking on the down arrow.

## PR Checklist
* [X] Closes #8924 
* [X] CLA signed.

## Detailed Description of the Pull Request / Additional comments
Set the placement of the flyout to BottomEdgeAlignedLeft, as was done when opening the menu from the key binding.

## Validation Steps Performed
Manual tests
2021-05-04 21:21:21 +00:00
Mike Griese
7d71b4b9ba Only move the window to the current desktop when it isn't on that one already (#10025)
## Summary of the Pull Request

This is to mitigate MSFT:33035972. If you call `MoveWindowToDesktop` while an app is set to "Show windows from this app on all desktops", the OS will clear that "Show windows from this app on all desktops" state. But it _won't_ clear that state from the task view, so it'll just plain look broken.

We can mitigate this just by checking if we're already on the current desktop first. "Show windows from this app on all desktops" windows will _always_ be on every desktop, so that API will return true, and we can avoid tearing the state.

## References
* added in #9954 

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-60325102
* [x] I work here
* [ ] Tests aren't possible
* [n/a] Requires documentation to be updated

## Validation Steps Performed
* it works again
2021-05-04 21:20:01 +00:00
Javier
31414aa364 [WPF] Allows setting the WPF control background when setting the terminal theme (#10026)
When syncing terminals across users (i.e. Liveshare shared terminals),
the terminal size is synced. This leads to having unused space around
the terminal which is the same color as the terminal's background
causing confusion as to what space is usable within the terminal.

Instead this change allows consumers to set the background color of the
control, separate from the terminal renderer's background, which makes
it easier to identify the edges of the terminal.
2021-05-04 21:18:25 +00:00
Leonard Hecker
ac265aab99 Fix TerminalControl crash on exit (#10031)
## Summary of the Pull Request

ControlCore's _renderer (IRenderTarget) is allocated as std::unique_ptr,
but is given to Terminal::CreateFromSettings as a reference.
ControlCore::Close deallocates the _renderer, but if ThrottledFuncs
are still scheduled to call ControlCore::UpdatePatternLocations
it'll cause Terminal::UpdatePatterns to be called, which in turn ends up
accessing the deallocated IRenderTarget reference and lead to a crash.

A proper solution with shared pointers is nontrivial and should be
attempted at a later point in time. This solution moves the teardown of
the _renderer into ControlCore::~ControlCore, where we can be certain
that no further strong references are held by ThrottledFuncs.

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

## Validation Steps Performed

The crash is a race condition and inherently hard to reproduce.
During validation this PR didn't appear to introduce new crashes.
2021-05-04 21:17:37 +00:00
James Holderness
2559ed6efa Introduce a mechanism for passing through DCS data strings (#9307)
This PR introduces a mechanism via which DCS data strings can be passed
through directly to the dispatch method that will be handling them, so
the data can be processed as it is received, rather than being buffered
in the state machine. This also simplifies the way string termination is
handled, so it now more closely matches the behaviour of the original
DEC terminals.

* Initial support for DCS sequences was introduced in PR #6328.
* Handling of DCS (and other) C1 controls was added in PR #7340.
* This is a prerequisite for Sixel (#448) and Soft Font (#9164) support.

The way this now works, a `DCS` sequence is dispatched as soon as the
final character of the `VTID` is received. Based on that ID, the
`OutputStateMachineEngine` should forward the call to the corresponding
dispatch method, and its the responsibility of that method to return an
appropriate handler function for the sequence.

From then on, the `StateMachine` will pass on all of the remaining bytes
in the data string to the handler function. When a data string is
terminated (with `CAN`, `SUB`, or `ESC`), the `StateMachine` will pass
on one final `ESC` character to let the handler know that the sequence
is finished. The handler can also end a sequence prematurely by
returning false, and then all remaining data bytes will be ignored.

Note that once a `DCS` sequence has been dispatched, it's not possible
to abort the data string. Both `CAN` and `SUB` are considered valid
forms of termination, and an `ESC` doesn't necessarily have to be
followed by a `\` for the string terminator. This is because the data
string is typically processed as it's received. For example, when
outputting a Sixel image, you wouldn't erase the parts that had already
been displayed if the data string is terminated early.

With this new way of handling the string termination, I was also able to
simplify some of the `StateMachine` processing, and get rid of a few
states that are no longer necessary. These changes don't apply to the
`OSC` sequences, though, since we're more likely to want to match the
XTerm behavior for those cases (which requires a valid `ST` control for
the sequence to be accepted).

## Validation Steps Performed

For the unit tests, I've had to make a few changes to some of the
`OutputEngineTests` to account for the updated `StateMachine`
processing. I've also added a new `StateMachineTest` to confirm that the
data strings are correctly passed through to the string handler under
all forms of termination.

To test whether the framework is actually usable, I've been working on
DRCS Soft Font support branched off of this PR, and haven't encountered
any problems. To test the throughput speed, I also hacked together a
basic Sixel parser, and that seemed to perform reasonably well.

Closes #7316
2021-04-30 19:17:30 +00:00
Cliff Koh
1ecf20b00a Fix link to Fabric Bot (#9988)
<!-- 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
👋 Just a minor change to fix an outdated link.

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

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #xxx
* [ ] 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
Original link was demised late 2020. Updated link to be correct.

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2021-04-30 13:09:22 +00:00
Mike Griese
30d2d2c76d When the window is summoned and is already active, minimize it. (#9963)
This adds a `toggleVisibility` parameter to `globalSummon`. 
* When `true` (default): when you press the global summon keybinding, and the window is currently the foreground window, we'll minimize the window.
* When `false`, we'll just do nothing.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Checks a box in #8888
* [x] closes https://github.com/microsoft/terminal/projects/5#card-59030814
* [x] I work here
* [ ] No tests for this one.
* [ ] yes yes eventually I'll come back on the docs

## Detailed Description of the Pull Request / Additional comments

I've got nothing extra to add here. This one's pretty simple. I'm only targeting #9954 since that one laid so much foundation to build on, with the `SummonBehavior`

## Validation Steps Performed

Played with this for a while, and it's amazing.
2021-04-28 18:57:14 -05:00
Mike Griese
65b22b9abb Add desktop param to globalSummon; set _quake = toCurrent (#9954)
This adds support for the `desktop` param to the `globalSummon` action. It accepts 3 values:
* `toCurrent` (default): The window moves to the current desktop when it's summoned
* `any`: We don't care what desktop the window is on. We'll go to the desktop the window is on when we summon it.
* `onCurrent`: We'll only try to summon the MRU window on this desktop when summoning a window. 
  * When combined with `name`, if there's a window matching `name`, we'll move it to this desktop. 
  * If there's not a window on this desktop, and `name` is omitted, then we'll make a new window.

`quakeMode` was also updated to use `toCurrent` behavior by default.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Checks some boxes in #8888
* [x] closes https://github.com/microsoft/terminal/projects/5#card-59030845
* [x] I work here
* [x] Tests added 
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

S/O to https://github.com/microsoft/PowerToys, who graciously let us use `VirtualDesktopUtils` for figuring out what desktop is the current desktop. Yea, that's all we needed that entire file for. No, there isn't an API for this (_surprised-pikachu.png_)

## Validation Steps Performed

Played with this for a while, and it's amazing.
2021-04-28 17:25:48 -05:00
Mike Griese
d08271e734 Add globalSummon action (#9854)
Adds support for two new actions:
* `globalSummon`, which can be used to activate a window using a _global_ (READ: OS-level) hotkey.
  - accepts an optional `name` argument. When provided, this will attempt to summon with the given name. When omitted, we'll try to summon the most recent window.
* `quakeMode` which is `globalSummon` for the `_quake` window.

These actions are stored in the actions array, but are read by the `WindowsTerminal` level and bound to the OS in `IslandWindow`. The monarch registers for these keybindings with the OS. When one is pressed, the monarch will recieve a `WM_HOTKEY` message. It'll use that to look up the corresponding action args. It'll use those to try and summon the right window.

## References

* #8888: Quake mode megathread
* #9274: Spec (**guys seriously i just need one more ✔️**)
* #9785: The start of granting "\_quake" super powers

## PR Checklist
* [x] Closes #653 - I'm gonna say this closes it for now, though we have _many_ follow-ups in #8888
* [x] I work here
* [x] Tests added/passed

## Validation Steps Performed

* Validated that it works with `win` keys
* Validated that it works without `win` keys
* Validated that it hot-reloads
* Validated that it moves to the new monarch
* Validated that you can bind both `globalSummon` and `quakeMode` at the same time and do different things
* Validated that you can bind `globalSummon` with a name and it creates that name if it doesn't already exist
2021-04-28 17:13:28 -05:00
Chester Liu
1c414a7723 Initial implementation of fine-grained text analysis (#9202)
This PR aims to optimize the text analysis process by breaking the text
into simple & complex runs according to the result of
`GetTextComplexity`. For simple runs, we can skip certain processing
steps to improve the analysis performance.

Previous to this PR, we rely on the result of `AnalyzeBidi`,
`AnalyzeScript` and `AnalyzeNumberSubstitution` to both break the text
into different runs and attach the corresponding
bidi/script/number_substitution information to the run. Thanks to #6695
we have the chance to skip the expensive analysis process when we found
the *entire text* is determined to be simple.

Inspired by https://github.com/microsoft/cascadia-code/issues/411 and
discussions in #9156, I found that the "entire text simplicity" is often
hard to meet. In order to fully utilize the complexity information of
the text, we need to first break the text into simple & complex ranges.
These ranges are also the initial runs prior to the
bidi/script/number_substitution analysis. This way we can skip the text
analysis for simple runs to speed up the process.

VALIDATION
Build & run cmatrix, cacafire, cat big.txt with it.

Initial simple run PR: #6695
Closes #9156
2021-04-28 18:10:08 +00:00
Carlos Zamora
8f93f76214 Serialize stub for dynamic profiles (#9964)
#9962 was caused by a serialization bug. _Technically_, `ToJson` works
as intended: if the current layer has any values set, write them out to
the json. However, on first load, the dynamic profile `Profile` objects
are actually empty (because they inherit from base layer, then the
dynamic profile generator). This means that `ToJson` writes the dynamic
profiles as empty objects `{}`. Then, on reload, we see that the dynamic
profiles aren't in the JSON, and we write them again.

To get around this issue, we added a simple check to `Profile::ToJson`:
if we have a source, make sure we write out the name, guid, hidden, and
source. This is intended to align with `Profile::GenerateStub`.

Closes #9962
2021-04-28 17:59:05 +00:00
Dustin Howett
3809bb556b Revert "Prevent the virtual viewport bottom being moved up unintentionally (#9770)"
This reverts commit 74909c0c65.

Reopens #9754
Closes #9872
2021-04-28 12:45:09 -05:00
Chester Liu
c5fcbede78 Fix implicitly narrowing conversion in textBuffer (#9972)
Explicitly using `SHORT` instead of `auto` to prevent `int -> short` narrowing.
2021-04-28 11:45:29 -05:00
Chester Liu
4457a6dedc Fix code health failure (#9974)
<!-- 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

Fixes code health failure since 66b9b9d6f1

<!-- 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
* [ ] Closes #xxx
* [ ] 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
2021-04-28 13:24:19 +00:00
Michael Niksa
b7fa32881d Implement UI for choosing default terminal inside Settings page (#9907)
Implement dropdown menu for choosing a default terminal application from inside the Windows Terminal Settings UI

## PR Checklist
* [x] Closes #9463 
* [x] I work here.
* [x] Manual tests passed
* [x] https://github.com/MicrosoftDocs/terminal/issues/314 (and cross reference #9462)

## Detailed Description of the Pull Request / Additional comments
- Adds dropdown menu and a template card for displaying the available default applications (using the same lookup code as the console property sheet `console.dll`)
- Adds model to TSM for adapting the data for display and binding on XAML
- Lookup occurs on every page reload. Persistence only happens on Save Changes.
- Manifest changed for Terminal to add capability to opt-out of registry redirection so we can edit this setting

## Validation Steps Performed
- [x] Flipped the menu and pressed Save Changes and launched cmd from run box... it moved between the two.
- [x] Flipped system theme from light to dark and ensured secondary color looked good
- [x] Flipped the status with a different mechanism (conhost propsheet) and then reopened settings page and confirmed it loaded the updated status
2021-04-28 10:43:30 +00:00
Leonard Hecker
810ce6911b Remove bug fixes which aren't needed in VS 16.9 (#9953)
## Summary of the Pull Request

I came across a few build system bug fixes, which served their purpose now that VS 16.9 has been released.

## PR Checklist
* [x] I work here
* [x] Project still compiles
2021-04-28 10:43:05 +00:00
Mike Griese
7c439bac2c Exempt the _quake window from glomming (#9956)
## Summary of the Pull Request

We don't want it acting as the "most recent window" for windowing behavior.
The most recent window should always be some other window.

This is being made as an atomic commit because we're probably 50% sure on this
one. Maybe people do want new tabs to open up in the quake window! If they're
running from the commandline, that's easy. If they're running from the shell
context menu, that's **H**ard / impossible currently. $20 someone asks for
that if we ship this. That of course might just fall into "explorer context
menu settings" though.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Checks a box in #8888
* [x] closes https://github.com/microsoft/terminal/projects/5#card-59030791
* [x] I work here
* [x] Tests added 
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

I mean, this one's super straightforward, not sure what else there is to add.

## Validation Steps Performed

Played with this, it works exactly as you'd think.
2021-04-28 10:37:10 +00:00
Kayla Cinnamon
c95ed72aab doc: Add logos to README (#9925) 2021-04-27 19:13:23 -05:00
Dustin Howett
f72e39a0f6 Update spellbot for the inbox merge 2021-04-27 18:24:46 -05:00
Dustin Howett
c11cab71a4 Merge remote-tracking branch 'openconsole/inbox' into HEAD 2021-04-27 18:18:52 -05:00
Dustin Howett
66b9b9d6f1 Merged PR 5984262: [Git2Git] Merged PR 5982901: Reintroduce GetQuickCharWidth for numpad event synthesis
When we encounter clipboard input that cannot be mapped to a keyboard
key, we try our best to map it to an event. If if is an alphanumeric
character or a wide glyph (per the old width algorithm), we will pass it
through as the UnicodeChar of a key event. If it's *not* wide and *not*
alphanumeric, we will synthesize a set of Alt+NumPad events.

Those events comprise a set containing...

1. Alt Down (modifiers = LAlt, UnicodeChar = 0)
2. Numpad 0 Down/Up (modifiers = LAlt, UnicodeChar = 0)
3. Numpad 1 Down/Up (modifiers = LAlt, UnicodeChar = 0)
4. Numpad 2 Down/Up (modifiers = LAlt, UnicodeChar = 0)
5. Alt Up (modifiers = 0, UnicodeChar = [THE CHARACTER])

Because of event group 5, application developers seem to have taken a
dependency on receiving Alt Up + Character and don't seek to recompose
the original character from its numpad representation.

In pull request GH-8035 (!5394370), we stripped the old width algorithm
out and replaced it with a lookup table (finally!). Unfortunately, that
broke clipboard input for Chinese text as it was no longer considered
"Wide" for the purposes of detecting whether we should use numpad
events.

This commit introduces a version of GetQuickCharWidth that fulfills the
exact contract CharToKeyEvents needs, and doesn't answer for a codepoint
more. We'll use it in Windows to fix MSFT-32901370.

The Terminal analogue of this bug, GH-9052, is fixed by *never emitting
numpad events again.* We think this is okay because it looks like nobody
was ever handling numpad events... and that we were only using them as a
way to communicate within conhost (which we're *also* not using) and any
public exposition of event 5 as a contract was unintended.

VALIDATION
----------
I took this new implementation (with an early return) and the old
implementation and compared whether they would yield a numpad event or a
key event over the entire supported codepoint space [0000..FFFF].

They matched.

Fixes MSFT-32901370
Fixes GH-9052

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 224751bbb061f5f59d794c2c9bdac5a9674ebde6
2021-04-27 23:17:53 +00:00
Mike Griese
8910a16fd0 Split TermControl into a Core, Interactivity, and Control layer (#9820)
## Summary of the Pull Request

Brace yourselves, it's finally here. This PR does the dirty work of splitting the monolithic `TermControl` into three components. These components are: 

* `ControlCore`: This encapsulates the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. This is intended to everything that someone might need to stand up a terminal instance in a control, but without any regard for how the UX works.
* `ControlInteractivity`: This is a wrapper for the `ControlCore`, which holds the logic for things like double-click, right click copy/paste, selection, etc. This is intended to be a UI framework-independent abstraction. The methods this layer exposes can be called the same from both the WinUI TermControl and the WPF control.
* `TermControl`: This is the UWP control. It's got a Core and Interactivity inside it, which it uses for the actual logic of the terminal itself. TermControl's main responsibility is now 

By splitting into smaller pieces, it will enable us to
* write unit tests for the `Core` and `Interactivity` bits, which we desparately need
* Combine `ControlCore` and `ControlInteractivity` in an out-of-proc core process in the future, to enable tab tearout.

However, we're not doing that work quite yet. There's still lots of work to be done to enable that, thought this is likely the biggest portion.

Ideally, this would just be methods moved wholesale from one file to another. Unfortunately, there are a bunch of cases where that didn't work as well as expected. Especially when trying to better enforce the boundary between the classes. 

We've got a couple tests here that I've added. These are partially examples, and partially things I ran into while implementing this. A bunch of things from #7001 can go in now that we have this.

This PR is gonna be a huge pain to review - 38 files with 3,730 additions and 1,661 deletions is nothing to scoff at. It will also conflict 100% with anything that's targeting `TermControl`. I'm hoping we can review this over the course of the next week and just be done with it, and leave plenty of runway for 1.9 bugs in post.

## References

* In pursuit of #1256
* Proc Model: #5000
* https://github.com/microsoft/terminal/projects/5

## PR Checklist
* [x] Closes #6842
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

* I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names.
* I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` need to know". In the future, these will all need to be handled specially, because they might involve an RPC call to retrieve the info from the core (or cache it) in the window process.
* I've added more `EventArgs` to make more events proper `TypedEvent`s.
* I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore.
* ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @miniksa wrote this originally in 30b8335, I'm just finally committing it here. We'll need that in the future for the out-of-proc stuff.~~
  * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it.
* I've changed the acrylic handler a decent amount. But added tests!
* All the `ThrottledFunc` things are left in `TermControl`. Some might be able to move down into core/interactivity, but once we figure out how to use a different kind of Dispatcher (because a UI thread won't necessarily exist for those components).
* I've undoubtably messed up the merging of the locking around the appearance config stuff recently

## Validation Steps Performed

I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 15:50:45 +00:00
Dustin L. Howett
8d50609ba1 Update the bug report template for 04-21 schema (#9961) 2021-04-26 17:06:12 -05:00
Mike Griese
dc6631355f Make the window name _quake special (#9785)
## Summary of the Pull Request

This PR adds some special behavior to the window named "\_quake".
* When creating the quake window, it ignores "initialRows" and "initialCols" and opens on the top half of the monitor.
  - It uses `initialPosition` to determine which monitor this is
* It cannot be moved
* It can only be vertically resized on the bottom border.
* It's always in focus mode.
  - We should probably have an issue tracking "Allow showing tabs in focus mode"? Maybe?
  - This one element is maybe the one I'm least attached to

When renaming a window to "\_quake", it adopts all those behaviors as well. It does not exit focus mode when leaving QM, nor does it resize back. That seemed unnecessary. 

## References

* As spec'ed in #9274
* See also #8888

## PR Checklist
* [x] In the pursuit of #653 
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated, but I'm not gonna do any of that till quake mode is totally done. 

## Detailed Description of the Pull Request / Additional comments

Note that this doesn't do things like:
* dropdown
* global hotkey summon 
* summon to the current monitor 
* summon to the current desktop

I'm doing #653 _very_ piecemeal, to try and make the PRs less egregious.

## Validation Steps Performed

* validated that center on launch still works
* validated that QM works on different monitors based on `initialPosition`
* validated entering/exiting QM behaves as expected

## TODO!
* [ ] When snapping the quake window between desktops with <kbd>win+shift+arrow</kbd>, the window doesn't horizontally re-size to the new monitor dimensions. It should.
2021-04-26 19:36:23 +00:00
Don-Vito
3d09c7de1b Make whitespace trimming in block selection configurable (#9807)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9706
* [x] CLA signed.
* [ ] Tests added/passed
* [x] Documentation updated here: https://github.com/MicrosoftDocs/terminal/pull/313
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. 

## Detailed Description of the Pull Request / Additional comments
Added global flag named `trimBlockSelection` set to `false` by default.
The setting was added to Interactions menu of the SUI.
2021-04-23 22:36:51 +00:00
Don-Vito
51920d9b46 Fix TabManagement to use tab object rather than index (#9924)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/8374
* [x] CLA signed. 
* [x] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

## Detailed Description of the Pull Request / Additional comments
The majority of the work was already done earlier.
The fix is only in _SetFocusedTab, that runs asynchronously
and thus might result in a race or even overflow.
All other changes are decorative.

## Validation Steps Performed
UT and manual tests
2021-04-23 22:25:20 +00:00
Mike Griese
aa54de1d64 Add a success dialog to window renaming (#9808)
I added a `RenameSucceededText` property to the `TerminalPage` which returns the
formatted message `Successfully renamed window to "{WindowNameForDisplay()}"`

This _doesn't_ pop the dialog when you `wt -w foo` for the first time. Only
_subsequent_ renames.

## References
* Added in #9662
* Closes #9804
2021-04-22 21:15:58 +00:00
Leonard Hecker
cf8ac0eb07 Add myself to the readme's team list (#9916) 2021-04-22 03:43:19 +00:00
Mike Griese
8c6e13d90e Spec for Quake Mode (#9274)
### ⇒ [doc link](https://github.com/microsoft/terminal/blob/dev/migrie/s/653-quake-mode/doc/specs/%23653%20-%20Quake%20Mode/%23653%20-%20Quake%20Mode.md) ⇐

## Summary of the Pull Request

After reading through 114+ comments in #653 and related issues, I think I've finally wrapped my head around all the possible scenarios for quake mode. <!-- Speak now or forever hold your peace. --> This also includes "minimize to tray", because the two are a powerful combination. With the work already prototyped in [`dev/migrie/f/653-QUAKE-MODE`](https://github.com/microsoft/terminal/tree/dev/migrie/f/653-QUAKE-MODE), [I'm starting to believe](https://j.gifs.com/58vKNx.gif) that we could actually land this in 2.0.


### Abstract

> Many existing terminals support a feature whereby a user can press a keybinding
> anywhere in the OS, and summon their terminal application. Oftentimes the act of
> summoning this window is accompanied by a "dropdown" animation, where the window
> slides in to view from the top of the screen. This global summon action is often
> referred to as "quake mode", a reference to the videogame Quake who's console
> slid in from the top.
> 
> This spec addresses both of the following two issues:
> * "Quake Mode" ([#653])
> * "Minimize to tray" ([#5727])


## PR Checklist
* [x] Specs: #653, #5727
* [x] References: #5000, #4472, #2227, #7240, #8135
* [x] I work here

## Detailed Description of the Pull Request / Additional comments
_\*<sup>\*</sup><sub>\*</sub> read the spec  <sub>\*</sub><sup>\*</sup>\*_
2021-04-21 21:43:42 +00:00
Mike Griese
913cf4b1a8 Initialize the text buffer with the default attributes on a resize (#5792)
When we resize the text buffer, initialize the buffer with the
_default_¹ attributes, not the _current_ ones. If we use the current
attributes, then we can get into scenarios where something like `vim` is
running, and left the attributes set to something other than the
defaults, and when we resized the buffer, we'd fill it up with color, as
opposed to whatever the default would be.

This PR instead initializes the buffers with the default colors. It also
makes sure to set the active attributes of the newly created buffers
back to whatever the current attributes of the old buffer were.

[1]: For the Terminal, the default attributes are "default on default".
For conhost, the default attributes are whatever the result of
`Settings::GetDefaultAttributes` is, which could be any combo of the
legacy indices and the default color.

## PR Checklist
* [x] Closes #3848
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Validation Steps Performed
* ran tests
2021-04-21 21:34:28 +00:00
Mike Griese
546322b5c1 Enable previewing the color scheme in the command palette (#9794)
## Summary of the Pull Request

Allow schemes to be previewed as the user hovers over them in the Command Palette.

![preview-set-color-scheme](https://user-images.githubusercontent.com/18356694/114557761-9a3cbd80-9c2f-11eb-987f-eb0c89ee1fa6.gif)

## References
* Branched off of #8392, which is why the commit history is so polluted. 330a8e8 : 544b2fd has the interesting commits
* #5400: cmdpal megathread

### Potential follow-ups
* changing the font size
* changing the font face
* changing the opacity of acrylic

## PR Checklist
* [x] Closes #6689, a last straggling FHL PR
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated - I don't think so

## Detailed Description of the Pull Request / Additional comments

This works by inserting a "preview" `TerminalSettings` into the settings hierarchy, before the `TermControl`'s runtime settings, and after the ones from the actual `CascadiaSettings`. This allows us to modify that preview settings object, then discard it when we're done with the preview.

This could also be used for other settings in the future - I built it to be extensible to other `ShortcutAction`s, though I haven't implemented those yet.

## Validation Steps Performed

* Select a colorscheme - it becomes the active one
* `colortool -x <scheme>` after selecting a scheme - colortool overrides the selected scheme
* Select a colorscheme after a `colortool -x <scheme>` after selecting a scheme - the scheme in the palette becomes the active one
* Pressing <kbd>esc</kbd> at any point to dismiss the command palette - scheme returns to the previous one
* reloading the settings - returns to the scheme in the settings
2021-04-21 20:35:06 +00:00
hms5232
d7e176998c Add URL link to docs text in README.md (#9911)
Add link to "aka.ms/terminal-docs" text in README, thus making more easier to arrive the docs.
2021-04-21 15:53:44 +00:00
Kayra Kaygın
dfb48f45c2 doc, tools: Improve docs around using clang-format with VS (#9782)
* Improved the clarity of the extra step involving
generation of a clang-format.exe when using VisualStudio

* Added Get-Format function to OpenConsole.psm1 and
updated the documentation accordingly.

Closes #9777.
2021-04-21 10:51:58 -05:00
Don-Vito
6b4f70e985 Fix tab and hyperlink tooltips to wrap long text (#9913)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9869
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.
2021-04-21 15:40:17 +00:00
Don-Vito
ad625a041d [Quick and Dirty] Copy runtime tab title when duplicating tabs (#9813)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9723
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

## Detailed Description of the Pull Request / Additional comments
Quick and dirty. 
A better solution is to allow passing all "runtime settings" upon tab creation.
2021-04-21 10:54:18 +00:00
PankajBhojwani
ad34291632 Fix for configuring starting directory in SUI when defaults sets it to null (#9862)
## Summary of the Pull Request
Remove an unnecessary check in `Profiles.cpp` that was preventing us from enabling the text box and browse button when the user unchecks 'use parent process directory'

## PR Checklist
* [x] Closes #9847 
* [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
Played around with it and it works.
2021-04-21 10:53:41 +00:00
MPela
2065fa7b76 Add Close menu items to the context menu flyout (#9859)
## Summary of the Pull Request
Add the "Close other tabs"/"Close tabs to the right" menu items straight to the tab context menu to work around #8238.
We can't add them into a dedicated sub-menu until the upstream crash is fixed.

## References
#8238 

## PR Checklist
* [X] Closes #8238
* [X] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated
* [ ] 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. 

## Detailed Description of the Pull Request / Additional comments
Moved the creation of the close menu items to a single function. Once the originating crash is fixed, the sub-menu can be restored by just replacing a few lines of code.

## Validation Steps Performed
![immagine](https://user-images.githubusercontent.com/1140981/115059601-0dbc2480-9ee7-11eb-9889-d9ef8e6e7613.png)
2021-04-21 10:53:19 +00:00
Dustin L. Howett
21b2e01643 Work around a compiler bug w/ coroutines and exceptions (#9893)
There is a bug in the compiler that we trip over when we handle the
exception generated by Package::Current inside a coroutine. It appears
to destruct an invalid instance of winrt::factory_guard_count.

Learned from the compiler folks: "coroutine frame pointer wasn't being
stored ... properly".

Fixes #9821
2021-04-19 20:27:30 +00:00
jBarrineau
7e2a0e193a Del 'Community Guidance Req' from CONTRIBUTING.md (#9873)
<!-- 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

CONTRIBUTING.md currently has documentation suggesting to file a 'Community Guidance Request' if a user doesn't know how to do something.  This issue was identified by @hessedoneen in #9765 .  Per @zadjii-msft  this option has never really existed, and should be struck from CONTRIBUTING.md .  This PR does just that.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #9765 
* [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 -->

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

Review CONTRIBUTING.md and see that it no longer refers to filing 'Community Guidance Requests'
2021-04-19 16:20:42 +00:00
Chester Liu
b68ee23bf8 Initial Implementation for tab stops in TerminalDispatch (#9597)
* [x] Supports #1883
* [X] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [X] Tests added/passed
2021-04-16 16:26:28 +00:00
Don-Vito
05e7ea1423 Delay close tab on middle-click till pointer released (#9842)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9836
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. 

Not sure what is the reason for handling right button. 
But delaying it to PointerReleased seems not to regress anything.
2021-04-15 12:45:55 -05:00
Kayla Cinnamon
8bcb47339d doc: Add tabColor to JSON schema (#9843) 2021-04-15 12:32:18 -05:00
James Holderness
74909c0c65 Prevent the virtual viewport bottom being moved up unintentionally (#9770)
## Summary of the Pull Request

The "virtual bottom" marks the last line of the mutable viewport area, which is the part of the buffer that VT sequences can write to. This region should typically only move downwards, as new lines are added to the buffer, but there were a number of cases where it was incorrectly being moved up. This PR attempts to fix that.

## PR Checklist
* [x] Closes #9754
* [x] CLA signed.
* [x] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] 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: #9754

## Detailed Description of the Pull Request / Additional comments

When a call is made to `UpdateBottom`, we now clamp the value so it's at least as low as the current viewport bottom (i.e. if the viewport has moved down, we want the virtual bottom to move down too), but no lower than the bottom of the buffer (we don't want it to be out of range).

There is one special case where we do actually want the virtual bottom to move up - when the scrollback has been cleared with an `ED3` escape sequence. So in that case we needed a new `ConGetSet` API (`ResetBottom`) to reset the virtual bottom to the top of the buffer (essentially one less than the viewport height, since the virtual bottom points to the last line of the viewport).

## Validation Steps Performed

I had to reset the virtual bottom manually in some parts of the `ScreenBufferTests`, since some of the tests were relying on the virtual bottom being automatically reset when the viewport was reset, which is no longer the case.

I've also added a new test to verify that the virtual bottom doesn't move upwards if an update is triggered while the visible viewport is scrolled up. This essentially reproduces the test case from issue #9754, which I've also manually confirmed is fixed.
2021-04-15 17:07:59 +00:00
Dustin Howett
d7f690d7fc Merged PR 5938254: Migrate OSS up to dba66da18
Related work items: MSFT-32512353
2021-04-15 16:59:04 +00:00
Dustin Howett
c90215b4e1 Merged PR 5923545: Reflect OS build fixes on top of ab6f41f4b
We needed to suppress a bunch of the handoff establishing code inside Windows.
2021-04-15 16:55:01 +00:00
Michael Niksa
dba66da18d Add -ForceNoHandoff for compatibility; stop handoff for double-click launches (#9802)
Add flag that will ensure we do not handoff to a registered default console. Also for a bonus, allow double-click launches or explicit command line launches of conhost.exe with a binary argument to open with the inbox one.

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

## Validation Steps Performed
* [x] Automated tests for parsing
* [x] Enable defapp, double click conhost.exe, opens as itself
* [x] Enable defapp, run conhost.exe runbox, opens as itself
* [x] Enable defapp, run conhost.exe powershell.exe runbox, opens as itself
* [x] Runbox cmd.exe/pwsh.exe trigger defapp handoff to Terminal
* [x] Shortcut to cmd.exe/pwsh.exe trigger defapp handoff to Terminal
* [x] Use CHOP tool to launch conhost with a server handle triggers handoff to Terminal
* [x] Use CHOP tool to launch conhost with a server handle and -ForceNoHandoff opens as itself
2021-04-15 16:54:04 +00:00
Mike Griese
eddb99e9b2 Add support for the win key in keybindings (#9783)
## Summary of the Pull Request

Does what it says on the can. People can now use `win` in a keybinding to
indicate that the chord needs <kbd>win</kbd>.

## References
* Done for #653
* See also #8888

## PR Checklist
* [x] Closes #3184
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

For the record, I hate this. But it's great for quake mode, so _meh_. There's
shockingly more win keys claimed then you think - many more than the shortcut
guide even shows.

* `win+b`: Focus the tray?
* `win+t`: Focus the taskbar
* `win+p`: Project...
* `win+c`: The powertoys color picker
* `win+v`: cloud clipboard

So the list of valid combos is vanishingly small. It's all about that <kbd>win+~</kbd>

## Validation Steps Performed

Bound
```json
        { "keys": [ "win+`" ], "command": "commandPalette" },
```

and yea, it works as expected
2021-04-15 16:52:28 +00:00
Mahdi Hosseini
3113d2e535 Update terminal-v2-roadmap.md (#9835)
Co-authored-by: Mike Griese <migrie@microsoft.com>
2021-04-15 09:40:34 -07:00
Don-Vito
cdbcc17458 Fix rename window handler to mark action as handled (#9809)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9803
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.
2021-04-14 20:50:38 +00:00
Don-Vito
3368e602fd Fix profile name generation to allocate unique name (#9816)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9714
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. 

## Detailed Description of the Pull Request / Additional comments
Attempts to generate a name Profile X, where X is the index of the new profile (1-based).
As long as name is already taken, generates new name by incrementing X by 1
2021-04-14 17:46:06 +00:00
Dustin Howett
3ae93ebfdd version: bump to 1.9 on main 2021-04-14 12:35:41 -05:00
Mike Griese
4941084c00 Fix the renamer tests (#9815)
## Summary of the Pull Request

Clearly, I didn't run these tests on my last commit where I made the toasts lazy-load.

## References
* broken in in #9662
* 
## PR Checklist
* [x] Closes #9769
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

For whatever reason, these tests are unhappy running back to back, but are just fine running isolated.
2021-04-14 17:11:40 +00:00
Don-Vito
9a2d27e9f6 Limit terminal warning bells to one per second (#9812)
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9776
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. 

## Detailed Description of the Pull Request / Additional comments
Use `ThrottledFunc` in `TermControl` to limit bell emission callback to one per second.
2021-04-14 17:11:19 +00:00
Michael Niksa
7478248564 Add names to threads to make debugging a slight bit easier (#9801)
Add names to threads to make debugging a slight bit easier.

## PR Checklist
* [x] Closes personal todo item.
* [x] I work here.
* [x] Tested manually.

## Detailed Description of the Pull Request / Additional comments
Thread descriptions show up as names in both the Visual Studio debugger, WinDBG debugger, and Windows Performance Analyzer. This makes it faster and easier to identify threads of interest in our processes.

## Validation Steps Performed
* [x] Checked threads were named in OpenConsole.exe running in classic conhost window mode under VS debug
* [x] Checked threads were named in OpenConsole.exe running in conpty mode under VS debug
* [x] Checked threads were named in WindowsTerminal.exe (for a few of the threads around connections)
* [x] Checked that we could also see it in WinDBG
2021-04-14 10:56:52 +00:00
Dustin L. Howett
dab52c46a2 Only update render appearance settings if there's a renderer (#9798)
I ran into this crash when I just opened a new tab.

Fixes MSFT-32485023
2021-04-13 16:17:43 -05:00
Dustin Howett
806c4c5d5c Merged PR 5923087: Migrate OSS up to ab6f41f4b
Related work items: MSFT-32360333, MSFT-32486668, MSFT-32486678
2021-04-13 21:13:50 +00:00
Dustin L. Howett
ab6f41f4bd Remove the splash screen (to save 100kb (compressed!)) (#9795)
We're a Centennial application; we can't even _use_ the splash screen.
2021-04-13 12:52:31 -05:00
Michael Niksa
0f217c173d Add hotkeys to words we use to describe apis 2021-04-13 09:35:05 -07:00
Evan Koschik
bc1ff0b71a Fix restore window position when exiting fullscreen (#9737)
<!-- 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

This change cleans up the Fullscreen implementation for both conhost and Terminal, improving the restore position (where the window goes when exiting fullscreen).

Prior to this change the window wasn't guaranteed to restore somewhere on the window's current monitor when exiting fullscreen. With this change the window will restore always to its current monitor, at a reasonable location (and will 'double restore' (to fullscreen->maximize->restore) after monitor changes while fullscreen, which is the expected user behavior.

<!-- 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 #9746
* [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

A fullscreen window's monitor can change.
 - Win+Shift+left/right migrates a window between monitors.
 - User could open settings, display, and move the monitor or change its DPI.
 - The monitor could be unplugged.
 - The session could be remote and be disconnected.

A fullscreen window stores a 'restore position' when entering fullscreen, used to move the window back 'where it was'. BUT, its unexpected for the window to exit fullscreen and jump to another monitor. This means its previous position must be migrated from the old monitor's work area to the new monitor's work area.

If a window is maximized, it is sized to the work area. Like with fullscreen, a maximized window has a 'restore position', though unlike with fullscreen the restore position for maximized is stored by the system itself. Migration in cases where a maximized (or fullscreen) window's monitor changes is also taken care of by the system. To restore 'safely' to maximized (after changing window styles) a window must only `SetWindowPos(SWP_FRAMECHANGED)`. While technically a maximized window that becomes fullscreen 'is still maximized' (from Win32's perspective), its prudent to also `ShowWindow(SW_MAXIMIZED)` prior to `SWP_FRAMECHANGED` (to explicitly make the window maximized).

If not restoring to maximized, the restore position is adjusted by the new/ old work area. Additionally, the new/ old window DPI is used to adjust the size of the window by the DPI change (keeping the window's logical size the same).
 - The work area origin is checked first (shifting window rect by the change in origin)
 - The DPI is checked next, changing right/ bottom (size only)
 - Each edge of the window is compared against the corresponding edge of the work area, nudging the window back on-screen if hanging offscreen. By shifting right before left, bottom before top, the top-left is guaranteed on-screen. 

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

Tried it out. Seemed to work on my machine.
Jk, ran conhost/ terminal on mixed DPI system, max (or not), fullscreen, win+shift+left/ exit fullscreen/ maximize. Monitor unplug, etc.
2021-04-13 16:33:00 +00:00
598 changed files with 33071 additions and 10562 deletions

View File

@@ -1,14 +1,10 @@
name: "Bug report 🐛"
description: Report errors or unexpected behavior
title: ''
labels: ''
assignees: ''
issue_body: true
body:
- type: markdown
attributes:
value: |
Please make sure to [search for existing issues](https://github.com/microsoft/terminal/issues) before filing a new one!
Please make sure to [search for existing issues](https://github.com/microsoft/terminal/issues) and [check the FAQ](https://github.com/microsoft/terminal/wiki/Frequently-Asked-Questions-(FAQ)) before filing a new one!
If this is an application crash, please also provide a [Feedback Hub](https://aka.ms/terminal-feedback-hub) submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal" and choose "Share My Feedback" after submission to get the link.
@@ -44,7 +40,7 @@ body:
- type: textarea
attributes:
label: Expected Behavior
description: If you want to include screenshots, paste them into the markdown editor below the form or follow up with a separate comment.
description: If you want to include screenshots, paste them into the markdown editor below.
placeholder: What were you expecting?
validations:
required: false

77
.vscode/settings.json vendored
View File

@@ -21,12 +21,85 @@
"xloctime": "cpp",
"multi_span": "cpp",
"pointers": "cpp",
"vector": "cpp"
"vector": "cpp",
"bitset": "cpp",
"deque": "cpp",
"initializer_list": "cpp",
"list": "cpp",
"queue": "cpp",
"random": "cpp",
"regex": "cpp",
"stack": "cpp",
"xhash": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"span": "cpp",
"string_span": "cpp",
"algorithm": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"fstream": "cpp",
"functional": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"locale": "cpp",
"map": "cpp",
"memory_resource": "cpp",
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"set": "cpp",
"shared_mutex": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"string": "cpp",
"system_error": "cpp",
"thread": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"xfacet": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xmemory": "cpp",
"xstddef": "cpp",
"xtr1common": "cpp"
},
"files.exclude": {
"**/bin/**": true,
"**/obj/**": true,
"**/packages/**": true,
"**/generated files/**": true
"**/Generated Files/**": true
}
}

7
.vscode/tasks.json vendored
View File

@@ -9,7 +9,7 @@
"-Command",
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
"Set-MsBuildDevEnvironment;",
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"}};",
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"} TermControl{\"Terminal\\TerminalControl\"}};",
"$target = switch(\"${input:buildModeChoice}\"){Build{\"\"} Rebuild{\":Rebuild\"} Clean{\":Clean\"}};",
"$target = $project + $target;",
"msbuild",
@@ -111,10 +111,11 @@
"description": "OpenConsole or Terminal?",
"options":[
"OpenConsole",
"Terminal"
"Terminal",
"TermControl"
],
"default": "Terminal"
}
]
}
}

View File

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

View File

@@ -43,7 +43,7 @@ If no existing item describes your issue/feature, great - please file a new issu
* Have a question that you don't see answered in docs, videos, etc.? File an issue
* Want to know if we're planning on building a particular feature? File an issue
* Got a great idea for a new feature? File an issue/request/idea
* Don't understand how to do something? File an issue/Community Guidance Request
* Don't understand how to do something? File an issue
* Found an existing issue that describes yours? Great - upvote and add additional commentary / info / repro-steps / etc.
When you hit "New Issue", select the type of issue closest to what you want to report/ask/request:
@@ -111,13 +111,13 @@ However, some issues/features will require careful thought & formal design befor
Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.
Specs will be managed in a very similar manner as code contributions so please follow the "Fork, Branch and Create your PR" below.
Specs will be managed in a very similar manner as code contributions so please follow the "[Fork, Branch and Create your PR](CONTRIBUTING.md#fork-clone-branch-and-create-your-pr)" section below.
### Writing / Contributing-to a Spec
To write/contribute to a spec: fork, branch and commit via PRs, as you would with any code changes.
Specs are written in markdown, stored under the `\doc\spec` folder and named `[issue id] - [spec description].md`.
Specs are written in markdown, stored under the [`\doc\specs`](./doc/specs) folder and named `[issue id] - [spec description].md`.
👉 **It is important to follow the spec templates and complete the requested information**. The available spec templates will help ensure that specs contain the minimum information & decisions necessary to permit development to begin. In particular, specs require you to confirm that you've already discussed the issue/idea with the team in an issue and that you provide the issue ID for reference.

View File

@@ -251,3 +251,49 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
```
# Microsoft Open Source
This product also incorporates source code from other Microsoft open source projects, all licensed under the MIT license.
## `GSL`
**Source**: [https://github.com/microsoft/GSL](https://github.com/microsoft/GSL)
## `Microsoft-UI-XAML`
**Source**: [https://github.com/microsoft/Microsoft-UI-XAML](https://github.com/microsoft/Microsoft-UI-XAML)
## `VirtualDesktopUtils`
**Source**: [https://github.com/microsoft/PowerToys](https://github.com/microsoft/PowerToys)
## `wil`
**Source**: [https://github.com/microsoft/wil](https://github.com/microsoft/wil)
### License
```
The MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```

View File

@@ -175,7 +175,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control.
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
{CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
{1CF55140-EF6A-4736-A403-957E4F7430BB} = {1CF55140-EF6A-4736-A403-957E4F7430BB}
{48D21369-3D7B-4431-9967-24E81292CF62} = {48D21369-3D7B-4431-9967-24E81292CF62}
{48D21369-3D7B-4431-9967-24E81292CF63} = {48D21369-3D7B-4431-9967-24E81292CF63}
{AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F} = {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}"
@@ -393,6 +395,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Control", "src\ca
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests", "src\cascadia\WindowsTerminal_UIATests\WindowsTerminal.UIA.Tests.csproj", "{F19DACD5-0C6E-40DC-B6E4-767A3200542C}"
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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|Any CPU = AuditMode|Any CPU
@@ -3254,6 +3260,84 @@ Global
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x64.Build.0 = Release|x64
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.ActiveCfg = Release|Win32
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.Build.0 = Release|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|Any CPU.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM64.ActiveCfg = Debug|ARM64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x86Test.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x64.ActiveCfg = Debug|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x86.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|Any CPU.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM64.ActiveCfg = Debug|ARM64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM64.Build.0 = Debug|ARM64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x64.ActiveCfg = Debug|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x64.Build.0 = Debug|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x86.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x86.Build.0 = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|Any CPU.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x64Test.ActiveCfg = Debug|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x64.ActiveCfg = Debug|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x86.ActiveCfg = Debug|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|Any CPU.ActiveCfg = Release|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM.ActiveCfg = Release|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM64.ActiveCfg = Release|ARM64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM64.Build.0 = Release|ARM64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x64Test.ActiveCfg = Release|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.ActiveCfg = Release|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.Build.0 = Release|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.ActiveCfg = Release|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.Build.0 = Release|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x64.ActiveCfg = AuditMode|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x64.Build.0 = AuditMode|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x86.Build.0 = AuditMode|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|Any CPU.ActiveCfg = Debug|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM.ActiveCfg = Debug|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM64.ActiveCfg = Debug|ARM64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM64.Build.0 = Debug|ARM64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x64Test.Build.0 = Debug|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x86Test.Build.0 = Debug|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x64.ActiveCfg = Debug|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x64.Build.0 = Debug|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x86.ActiveCfg = Debug|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x86.Build.0 = Debug|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.Build.0 = Fuzzing|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|Any CPU.ActiveCfg = Release|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM.ActiveCfg = Release|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM64.ActiveCfg = Release|ARM64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM64.Build.0 = Release|ARM64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x64Test.ActiveCfg = Release|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x64Test.Build.0 = Release|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x86Test.Build.0 = Release|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.ActiveCfg = Release|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3351,6 +3435,8 @@ Global
{9921CA0A-320C-4460-8623-3A3196E7F4CB} = {59840756-302F-44DF-AA47-441A9D673202}
{05D9052F-D78F-478F-968A-2DE38A6DB996} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{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}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}

View File

@@ -1,3 +1,5 @@
![terminal-logos](https://user-images.githubusercontent.com/48369326/115790869-4c852b00-a37c-11eb-97f1-f61972c7800c.png)
# Welcome to the Windows Terminal, Console and Command-Line repo
This repository contains the source code for:
@@ -241,7 +243,7 @@ Visual Studio.
## Documentation
All project documentation is located at aka.ms/terminal-docs. If you would like
All project documentation is located at [aka.ms/terminal-docs](https://aka.ms/terminal-docs). If you would like
to contribute to the documentation, please submit a pull request on the [Windows
Terminal Documentation repo](https://github.com/MicrosoftDocs/terminal).
@@ -276,6 +278,7 @@ If you would like to ask a question that you feel doesn't warrant an issue
* Carlos Zamora, Developer: [@cazamor_msft](https://twitter.com/cazamor_msft)
* Leon Liang, Developer: [@leonmsft](https://twitter.com/leonmsft)
* Pankaj Bhojwani, Developer
* Leonard Hecker, Developer: [@LeonardHecker](https://twitter.com/LeonardHecker)
## Developer Guidance

221
Scratch.sln Normal file
View File

@@ -0,0 +1,221 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134
MinimumVisualStudioVersion = 10.0.40219.1
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Package", "scratch\ScratchIslandApp\Package\Package.wapproj", "{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleAppLib", "scratch\ScratchIslandApp\SampleApp\SampleAppLib.vcxproj", "{A4394404-37F7-41C1-802B-49788D3720E3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleApp", "scratch\ScratchIslandApp\SampleApp\dll\SampleApp.vcxproj", "{26C51792-41A3-4FE0-AB5E-8B69D557BF91}"
ProjectSection(ProjectDependencies) = postProject
{A4394404-37F7-41C1-802B-49788D3720E3} = {A4394404-37F7-41C1-802B-49788D3720E3}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowExe", "scratch\ScratchIslandApp\WindowExe\WindowExe.vcxproj", "{B4427499-9FDE-4208-B456-5BC580637633}"
ProjectSection(ProjectDependencies) = postProject
{26C51792-41A3-4FE0-AB5E-8B69D557BF91} = {26C51792-41A3-4FE0-AB5E-8B69D557BF91}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common Props", "Common Props", "{53DD5520-E64C-4C06-B472-7CE62CA539C9}"
ProjectSection(SolutionItems) = preProject
src\common.build.post.props = src\common.build.post.props
src\common.build.pre.props = src\common.build.pre.props
src\common.build.tests.props = src\common.build.tests.props
common.openconsole.props = common.openconsole.props
src\cppwinrt.build.post.props = src\cppwinrt.build.post.props
src\cppwinrt.build.pre.props = src\cppwinrt.build.pre.props
src\wap-common.build.post.props = src\wap-common.build.post.props
src\wap-common.build.pre.props = src\wap-common.build.pre.props
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxproj", "{6BAE5851-50D5-4934-8D5E-30361A8A40F3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types", "src\types\lib\types.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820263}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|ARM64 = AuditMode|ARM64
AuditMode|x64 = AuditMode|x64
AuditMode|x86 = AuditMode|x86
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Fuzzing|ARM64 = Fuzzing|ARM64
Fuzzing|x64 = Fuzzing|x64
Fuzzing|x86 = Fuzzing|x86
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.ActiveCfg = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Build.0 = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Deploy.0 = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.ActiveCfg = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Build.0 = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Deploy.0 = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.ActiveCfg = Release|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Build.0 = Release|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Deploy.0 = Release|x86
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.ActiveCfg = AuditMode|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.Build.0 = AuditMode|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.Build.0 = AuditMode|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.ActiveCfg = Debug|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.Build.0 = Debug|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.ActiveCfg = Debug|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.Build.0 = Debug|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.ActiveCfg = Debug|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.Build.0 = Debug|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.Build.0 = Fuzzing|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.ActiveCfg = Release|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.Build.0 = Release|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.ActiveCfg = Release|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.Build.0 = Release|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.ActiveCfg = Release|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.Build.0 = Release|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.ActiveCfg = AuditMode|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.Build.0 = AuditMode|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.Build.0 = AuditMode|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.ActiveCfg = Debug|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.Build.0 = Debug|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.ActiveCfg = Debug|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.Build.0 = Debug|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.ActiveCfg = Debug|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.Build.0 = Debug|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.Build.0 = Fuzzing|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.ActiveCfg = Release|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.Build.0 = Release|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.ActiveCfg = Release|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.Build.0 = Release|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.ActiveCfg = Release|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.Build.0 = Release|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.ActiveCfg = AuditMode|x64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.Build.0 = AuditMode|x64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.Build.0 = AuditMode|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.Build.0 = Debug|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.ActiveCfg = Debug|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.Build.0 = Debug|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.ActiveCfg = Debug|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.Build.0 = Debug|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.Build.0 = Fuzzing|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.ActiveCfg = Release|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.Build.0 = Release|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.ActiveCfg = Release|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.Build.0 = Release|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.ActiveCfg = Release|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.Build.0 = Release|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.ActiveCfg = AuditMode|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.Build.0 = AuditMode|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.Build.0 = AuditMode|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.ActiveCfg = Debug|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.Build.0 = Debug|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.ActiveCfg = Debug|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.Build.0 = Debug|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.ActiveCfg = Debug|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.Build.0 = Debug|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.Build.0 = Fuzzing|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.ActiveCfg = Release|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.Build.0 = Release|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.ActiveCfg = Release|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.Build.0 = Release|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.ActiveCfg = Release|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.Build.0 = Release|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.ActiveCfg = AuditMode|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.Build.0 = AuditMode|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.Build.0 = AuditMode|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.ActiveCfg = Debug|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.Build.0 = Debug|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.ActiveCfg = Debug|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.Build.0 = Debug|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.ActiveCfg = Debug|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.Build.0 = Debug|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.Build.0 = Fuzzing|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.ActiveCfg = Release|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.Build.0 = Release|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.ActiveCfg = Release|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.Build.0 = Release|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.ActiveCfg = Release|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
{18D09A24-8240-42D6-8CB6-236EEE820263} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {05EAE315-9188-4D7B-B889-7D5F480A8915}
EndGlobalSection
EndGlobal

View File

@@ -29,4 +29,147 @@ function GetQueryTestRunsUri
$baseUri = GetAzureDevOpsBaseUri -CollectionUri $CollectionUri -TeamProject $TeamProject
$queryUri = "$baseUri/_apis/test/runs?buildUri=$BuildUri$includeRunDetailsParameter&api-version=5.0"
return $queryUri
}
function Get-HelixJobTypeFromTestRun
{
Param ($testRun)
$testRunSingleResultUri = "$($testRun.url)/results?`$top=1&`$skip=0&api-version=5.1"
$singleTestResult = Invoke-RestMethod -Uri $testRunSingleResultUri -Method Get -Headers $azureDevOpsRestApiHeaders
$count = $singleTestResult.value.Length
if($count -eq 0)
{
# If the count is 0, then results have not yet been reported for this run.
# We only care about completed runs with results, so it is ok to just return 'UNKNOWN' for this run.
return "UNKNOWN"
}
else
{
$info = ConvertFrom-Json $singleTestResult.value.comment
$helixJobId = $info.HelixJobId
$job = Invoke-RestMethodWithRetries "https://helix.dot.net/api/2019-06-17/jobs/${helixJobId}?access_token=${HelixAccessToken}"
return $job.Type
}
}
function Append-HelixAccessTokenToUrl
{
Param ([string]$url, [string]$token)
if($url.Contains("?"))
{
$url = "$($url)&access_token=$($token)"
}
else
{
$url = "$($url)?access_token=$($token)"
}
return $url
}
# The Helix Rest api is sometimes unreliable. So we call these apis with retry logic.
# Note: The Azure DevOps apis are stable and do not need to be called with this retry logic.
$helixApiRetries = 0
$helixApiRetriesMax = 10
function Download-StringWithRetries
{
Param ([string]$fileName, [string]$url)
$result = ""
$done = $false
while(!($done))
{
try
{
Write-Host "Downloading $fileName"
$result = (New-Object System.Net.WebClient).DownloadString($url)
$done = $true
}
catch
{
Write-Host "Failed to download $fileName $($PSItem.Exception)"
$helixApiRetries = $helixApiRetries + 1
if($helixApiRetries -lt $helixApiRetriesMax)
{
Write-Host "Sleep and retry download of $fileName"
Start-Sleep 60
}
else
{
throw "Failed to download $fileName"
}
}
}
return $result
}
function Invoke-RestMethodWithRetries
{
Param ([string]$url,$Headers)
$result = @()
$done = $false
while(!($done))
{
try
{
$result = Invoke-RestMethod -Uri $url -Method Get -Headers $Headers
$done = $true
}
catch
{
Write-Host "Failed to invoke Rest method $($PSItem.Exception)"
$helixApiRetries = $helixApiRetries + 1
if($helixApiRetries -lt $helixApiRetriesMax)
{
Write-Host "Sleep and retry invoke"
Start-Sleep 60
}
else
{
throw "Failed to invoke Rest method"
}
}
}
return $result
}
function Download-FileWithRetries
{
Param ([string]$fileurl, [string]$destination)
$done = $false
while(!($done))
{
try
{
Write-Host "Downloading $destination"
$webClient.DownloadFile($fileurl, $destination)
$done = $true
}
catch
{
Write-Host "Failed to download $destination $($PSItem.Exception)"
$helixApiRetries = $helixApiRetries + 1
if($helixApiRetries -lt $helixApiRetriesMax)
{
Write-Host "Sleep and retry download of $destination"
Start-Sleep 60
}
else
{
throw "Failed to download $destination"
}
}
}
}

View File

@@ -9,7 +9,7 @@ $payloadDir = "HelixPayload\$Configuration\$Platform"
$repoDirectory = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "..\..\"
$nugetPackagesDir = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "packages"
# Create the payload directory. Remove it if it already exists.
If(test-path $payloadDir)
{
@@ -19,11 +19,13 @@ New-Item -ItemType Directory -Force -Path $payloadDir
# Copy files from nuget packages
Copy-Item "$nugetPackagesDir\microsoft.windows.apps.test.1.0.181203002\lib\netcoreapp2.1\*.dll" $payloadDir
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\*" $payloadDir
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\CoreClr\*" $payloadDir
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\*" $payloadDir
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\NetFx4.5\*" $payloadDir
New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\"
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\"
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\"
New-Item -ItemType Directory -Force -Path "$payloadDir\content\"
Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.1\content\*" "$payloadDir\content\"
function Copy-If-Exists
{
@@ -52,3 +54,13 @@ Copy-Item "build\helix\HelixTestHelpers.cs" "$payloadDir"
Copy-Item "build\helix\runtests.cmd" $payloadDir
Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir"
Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
# Copy the APPX package from the 'drop' artifact dir
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir\CascadiaPackage.zip
# Rename it to extension of ZIP because Expand-Archive is real sassy on the build machines
# and refuses to unzip it because of its file extension while on a desktop, it just
# does the job without complaining.
# Extract the APPX package
Expand-Archive -LiteralPath $payloadDir\CascadiaPackage.zip -DestinationPath $payloadDir\appx

View File

@@ -9,11 +9,6 @@ Param(
$helixLinkFile = "$OutputFolder\LinksToHelixTestFiles.html"
$accessTokenParam = ""
if($HelixAccessToken)
{
$accessTokenParam = "?access_token=$HelixAccessToken"
}
function Generate-File-Links
{
@@ -45,66 +40,69 @@ $azureDevOpsRestApiHeaders = @{
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
Write-Host "queryUri = $queryUri"
$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
$webClient = New-Object System.Net.WebClient
[System.Collections.Generic.List[string]]$workItems = @()
foreach ($testRun in $testRuns.value)
{
$testResults = Invoke-RestMethod -Uri "$($testRun.url)/results?api-version=5.0" -Method Get -Headers $azureDevOpsRestApiHeaders
Write-Host "testRunUri = $testRun.url"
$testResults = Invoke-RestMethodWithRetries "$($testRun.url)/results?api-version=5.0" -Headers $azureDevOpsRestApiHeaders
$isTestRunNameShown = $false
foreach ($testResult in $testResults.value)
{
if ("comment" -in $testResult)
$info = ConvertFrom-Json $testResult.comment
$helixJobId = $info.HelixJobId
$helixWorkItemName = $info.HelixWorkItemName
$workItem = "$helixJobId-$helixWorkItemName"
Write-Host "Helix Work Item = $workItem"
if (-not $workItems.Contains($workItem))
{
$info = ConvertFrom-Json $testResult.comment
$helixJobId = $info.HelixJobId
$helixWorkItemName = $info.HelixWorkItemName
$workItems.Add($workItem)
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam"
$files = Invoke-RestMethodWithRetries $filesQueryUri
$workItem = "$helixJobId-$helixWorkItemName"
if (-not $workItems.Contains($workItem))
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
{
$workItems.Add($workItem)
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam"
$files = Invoke-RestMethod -Uri $filesQueryUri -Method Get
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
if(-Not $isTestRunNameShown)
{
if(-Not $isTestRunNameShown)
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
$isTestRunNameShown = $true
}
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
Generate-File-Links $screenShots "Screenshots"
Generate-File-Links $dumps "CrashDumps"
Generate-File-Links $pgcFiles "PGC files"
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
Generate-File-Links $misc "Misc"
foreach($pgcFile in $pgcFiles)
{
$flavorPath = $testResult.automatedTestName.Split('.')[0]
$archPath = $testResult.automatedTestName.Split('.')[1]
$fileName = $pgcFile.Name
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
$destination = "$fullPath\$fileName"
Write-Host "Copying $($pgcFile.Name) to $destination"
if (-Not (Test-Path $fullPath))
{
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
$isTestRunNameShown = $true
New-Item $fullPath -ItemType Directory
}
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
Generate-File-Links $screenShots "Screenshots"
Generate-File-Links $dumps "CrashDumps"
Generate-File-Links $pgcFiles "PGC files"
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
Generate-File-Links $misc "Misc"
foreach($pgcFile in $pgcFiles)
{
$flavorPath = $pgcFile.Name.Split('.')[0]
$archPath = $pgcFile.Name.Split('.')[1]
$fileName = $pgcFile.Name.Remove(0, $flavorPath.length + $archPath.length + 2)
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
$destination = "$fullPath\$fileName"
$link = $pgcFile.Link
Write-Host "Copying $($pgcFile.Name) to $destination"
Write-Host "Downloading $link to $destination"
if (-Not (Test-Path $fullPath))
{
New-Item $fullPath -ItemType Directory
}
$link = "$($pgcFile.Link)$accessTokenParam"
$webClient.DownloadFile($link, $destination)
}
Download-FileWithRetries $link $destination
}
}
}

View File

@@ -13,6 +13,8 @@
</ItemGroup>
<!-- These .proj files are generated by the build machine prior to running tests via GenerateTestProjFile.ps1. -->
<Import Project="$(ProjFilesPath)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-SettingsModelLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-WindowsTerminalUIATests.proj" Condition=" '$(TestSuite)'=='PgoInstrumentationSuite' " />
</Project>

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="Microsoft.Taef" version="10.58.210305002" targetFramework="native" />
<package id="Microsoft.Internal.Windows.Terminal.TestContent" version="1.0.1" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="microsoft.windows.apps.test" version="1.0.181203002" targetFramework="native" />
<package id="runtime.win-x86.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
<package id="runtime.win-x64.microsoft.netcore.app" version="2.1.0" targetFramework="native" />

View File

@@ -28,7 +28,7 @@ echo %TIME%
powershell -ExecutionPolicy Bypass .\InstallTestAppDependencies.ps1
echo %TIME%
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll WindowsTerminal.UIA.Tests.dll
set testBinaries=
for %%B in (%testBinaryCandidates%) do (
if exist %%B (
@@ -46,7 +46,6 @@ move te.wtl te_original.wtl
copy /y te_original.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
for /f "tokens=* delims=" %%a in ('dir /b *.pgc') do ren "%%a" "%testnameprefix%.%%~na.pgc"
copy /y *.pgc %HELIX_WORKITEM_UPLOAD_ROOT%
set FailedTestQuery=

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="Microsoft.Taef" version="10.58.210305002" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
</packages>

27
build/pipelines/pgo.yml Normal file
View File

@@ -0,0 +1,27 @@
trigger: none
pr: none
variables:
- name: runCodesignValidationInjectionBG
value: false
# 0.0.yyMM.dd##
# 0.0.1904.0900
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
stages:
- stage: Build_x64
displayName: Build x64
dependsOn: []
condition: succeeded()
jobs:
- template: ./templates/build-console-pgo.yml
parameters:
platform: x64
- stage: Publish_PGO_Databases
displayName: Publish PGO databases
dependsOn: ['Build_x64']
jobs:
- template: ./templates/pgo-build-and-publish-nuget-job.yml
parameters:
pgoArtifact: 'PGO'

View File

@@ -20,12 +20,20 @@ jobs:
parameters:
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
# It appears that the Component Governance build task that gets automatically injected stopped working
# when we renamed our main branch.
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
condition: and(succeededOrFailed(), not(eq(variables['Build.Reason'], 'PullRequest')))
- template: helix-runtests-job.yml
parameters:
name: 'RunTestsInHelix'
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
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

View File

@@ -9,6 +9,7 @@ jobs:
variables:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
PGOBuildMode: 'Optimize'
pool:
name: Package ES Lab E

View File

@@ -0,0 +1,51 @@
parameters:
configuration: 'Release'
platform: ''
additionalBuildArguments: ''
minimumExpectedTestsExecutedCount: 1 # Sanity check for minimum expected tests to be reported
rerunPassesRequiredToAvoidFailure: 0
jobs:
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
variables:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
PGOBuildMode: 'Instrument'
pool: "windevbuildagents"
# The public pool is also an option!
# pool: { vmImage: windows-2019 }
steps:
- template: build-console-steps.yml
parameters:
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
- template: helix-runtests-job.yml
parameters:
name: 'RunTestsInHelix'
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
condition: succeeded()
testSuite: 'PgoInstrumentationSuite'
taefQuery: '@IsPgo=true'
configuration: ${{ parameters.configuration }}
platform: ${{ parameters.platform }}
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
- template: helix-processtestresults-job.yml
parameters:
name: 'ProcessTestResults'
pgoArtifact: 'PGO'
dependsOn:
- RunTestsInHelix
condition: succeededOrFailed()
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}
- template: pgo-merge-pgd-job.yml
parameters:
name: 'MergePGD'
dependsOn:
- ProcessTestResults
pgoArtifact: 'PGO'
platform: ${{ parameters.platform }}

View File

@@ -22,7 +22,7 @@ steps:
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 +32,29 @@ steps:
restoreSolution: build/packages.config
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
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
del %TEMP%\vsinstalldir.txt
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
echo VCToolsInstallDir = %VCToolsInstallDir%
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
displayName: 'Retrieve VC tools directory'
- task: CmdLine@1
displayName: 'Display build machine environment variables'
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:
@@ -45,6 +68,9 @@ steps:
- task: PowerShell@2
displayName: 'Check MSIX for common regressions'
# PGO runtime needs its own CRT and it's in the package for convenience.
# That will make this script mad so skip since we're not shipping the PGO Instrumentation one anyway.
condition: ne(variables['PGOBuildMode'], 'Instrument')
inputs:
targetType: inline
script: |
@@ -53,6 +79,7 @@ steps:
- task: powershell@2
displayName: 'Source Index PDBs'
condition: ne(variables['PGOBuildMode'], 'Instrument')
inputs:
targetType: filePath
filePath: build\scripts\Index-Pdbs.ps1
@@ -68,13 +95,25 @@ 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:
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
- task: PowerShell@2
displayName: 'Run Feature Tests (x64 only)'
@@ -82,7 +121,7 @@ steps:
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), eq(variables['BuildPlatform'], 'x64'))
- task: PowerShell@2
displayName: 'Convert Test Logs from WTL to xUnit format'
@@ -90,13 +129,14 @@ steps:
targetType: filePath
filePath: build\Helix\ConvertWttLogToXUnit.ps1
arguments: -WttInputPath '${{ parameters.testLogPath }}' -WttSingleRerunInputPath 'unused.wtl' -WttMultipleRerunInputPath 'unused2.wtl' -XUnitOutputPath 'onBuildMachineResults.xml' -TestNamePrefix '$(BuildConfiguration).$(BuildPlatform)'
condition: or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86'))
condition: and(ne(variables['PGOBuildMode'], 'Instrument'),or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
- task: PublishTestResults@2
displayName: 'Upload converted test logs'
condition: ne(variables['PGOBuildMode'], 'Instrument')
inputs:
testResultsFormat: 'xUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest
testResultsFiles: '**/onBuildMachineResults.xml'
testResultsFiles: '**/onBuildMachineResults.xml'
#searchFolder: '$(System.DefaultWorkingDirectory)' # Optional
#mergeTestResults: false # Optional
#failTaskOnFailedTests: false # Optional
@@ -127,24 +167,47 @@ steps:
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
OverWrite: true
flattenFolders: true
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
condition: succeeded()
- task: CopyFiles@2
displayName: 'Copy outputs needed for test runs to Artifacts'
inputs:
Contents: |
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.exe
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.dll
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.xml
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.exe
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml
**/Microsoft.VCLibs.*.appx
**/TestHostApp/*
**/TestHostApp/*.exe
**/TestHostApp/*.dll
**/TestHostApp/*.xml
!**/*.pdb
!**/*.ipdb
!**/*.obj
!**/*.pch
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
OverWrite: true
flattenFolders: true
condition: and(and(succeeded(), eq(variables['BuildPlatform'], 'x64')), ne(variables['Build.Reason'], 'PullRequest'))
condition: succeeded()
- task: PublishBuildArtifacts@1
displayName: 'Publish All Build Artifacts'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
ArtifactName: 'drop'
- task: CopyFiles@2
displayName: 'Copy PGO databases needed for PGO instrumentation run'
inputs:
Contents: |
**/*.pgd
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO/$(BuildPlatform)'
OverWrite: true
flattenFolders: true
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
- task: PublishBuildArtifacts@1
displayName: 'Publish All PGO Artifacts'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO'
ArtifactName: 'PGO'
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))

View File

@@ -12,4 +12,4 @@ steps:
inputs:
targetType: filePath
filePath: build\Helix\GenerateTestProjFile.ps1
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'

View File

@@ -10,19 +10,11 @@ parameters:
maxParallel: 4
rerunPassesRequiredToAvoidFailure: 5
taefQuery: ''
configuration: ''
platform: ''
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
useBuildOutputFromPipeline: $(System.DefinitionId)
matrix:
# Release_x86:
# buildPlatform: 'x86'
# buildConfiguration: 'release'
# openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
# closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
Release_x64:
buildPlatform: 'x64'
buildConfiguration: 'release'
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
jobs:
- job: ${{ parameters.name }}
@@ -33,10 +25,12 @@ jobs:
timeoutInMinutes: 120
strategy:
maxParallel: ${{ parameters.maxParallel }}
matrix: ${{ parameters.matrix }}
variables:
buildConfiguration: ${{ parameters.configuration }}
buildPlatform: ${{ parameters.platform }}
openHelixTargetQueues: ${{ parameters.openHelixTargetQueues }}
artifactsDir: $(Build.SourcesDirectory)\Artifacts
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\$(buildPlatform)
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\$(buildPlatform)
helixCommonArgs: '/binaryLogger:$(Build.SourcesDirectory)/${{parameters.name}}.$(buildPlatform).$(buildConfiguration).binlog /p:HelixBuild=$(Build.BuildId).$(buildPlatform).$(buildConfiguration) /p:Platform=$(buildPlatform) /p:Configuration=$(buildConfiguration) /p:HelixType=${{parameters.helixType}} /p:TestSuite=${{parameters.testSuite}} /p:ProjFilesPath=$(Build.ArtifactStagingDirectory) /p:rerunPassesRequiredToAvoidFailure=${{parameters.rerunPassesRequiredToAvoidFailure}}'
@@ -97,9 +91,17 @@ jobs:
filename: 'dir'
arguments: '/s $(Build.SourcesDirectory)\HelixPayload'
- task: PowerShell@2
displayName: 'Make artifact directories'
inputs:
targetType: inline
script: |
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\"
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\"
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.LocalTests.dll'
outputProjFileName: 'RunTestsInHelix-TerminalAppLocalTests.proj'
testSuite: '${{ parameters.testSuite }}'
@@ -107,7 +109,7 @@ jobs:
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\SettingsModel.LocalTests.dll'
outputProjFileName: 'RunTestsInHelix-SettingsModelLocalTests.proj'
testSuite: '${{ parameters.testSuite }}'
@@ -116,12 +118,20 @@ jobs:
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\Conhost.UIA.Tests.dll'
outputProjFileName: 'RunTestsInHelix-HostTestsUIA.proj'
testSuite: '${{ parameters.testSuite }}'
taefQuery: ${{ parameters.taefQuery }}
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),or(eq('${{ parameters.testSuite }}','PgoInstrumentationSuite'),eq('${{ parameters.testSuite }}','DevTestSuite')))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\WindowsTerminal.UIA.Tests.dll'
outputProjFileName: 'RunTestsInHelix-WindowsTerminalUIATests.proj'
testSuite: '${{ parameters.testSuite }}'
taefQuery: ${{ parameters.taefQuery }}
- task: PublishBuildArtifacts@1
displayName: 'Publish generated .proj files'
inputs:
@@ -137,4 +147,3 @@ jobs:
projects: build\Helix\RunTestsInHelix.proj
custom: msbuild
arguments: '$(helixCommonArgs) /p:IsExternal=true /p:Creator=Terminal /p:HelixTargetQueues=$(openHelixTargetQueues)'

View File

@@ -0,0 +1,62 @@
# From our friends at MUX: https://github.com/microsoft/microsoft-ui-xaml/blob/main/build/AzurePipelinesTemplates/MUX-BuildAndPublishPGONuGet-Job.yml
parameters:
dependsOn: ''
pgoArtifact: PGO
jobs:
- job: BuildAndPublishPGONuGet
dependsOn: ${{ parameters.dependsOn }}
pool:
vmImage: 'windows-2019'
variables:
artifactsPath: $(Build.SourcesDirectory)\Artifacts
pgoToolsPath: $(Build.SourcesDirectory)\tools\PGODatabase
nuspecPath: $(pgoToolsPath)\NuSpecs
nuspecFilename: PGO.nuspec
steps:
- task: DownloadBuildArtifacts@0
inputs:
artifactName: ${{ parameters.pgoArtifact }}
downloadPath: $(artifactsPath)
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 5.2.0'
inputs:
versionSpec: 5.2.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)
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet pack'
inputs:
command: pack
packagesToPack: '$(nuspecPath)\$(nuspecFilename)'
basePath: '$(nuspecPath)'
packDestination: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: $(Build.ArtifactStagingDirectory)
artifactName: ${{ parameters.pgoArtifact }}
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet push'
inputs:
command: push
publishVstsFeed: Terminal/TerminalDependencies
packagesToPush: $(Build.ArtifactStagingDirectory)/*.nupkg

View File

@@ -0,0 +1,90 @@
parameters:
dependsOn: ''
pgoArtifact: PGO
platform: ''
jobs:
- job: MergePGD
dependsOn: ${{ parameters.dependsOn }}
pool:
vmImage: 'windows-2019'
variables:
artifactsPath: $(Build.SourcesDirectory)\Artifacts
pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }}
buildPlatform: ${{ parameters.platform }}
steps:
# 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
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
del %TEMP%\vsinstalldir.txt
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
echo VCToolsInstallDir = %VCToolsInstallDir%
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
displayName: 'Retrieve VC tools directory'
- 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: CopyFiles@2
displayName: 'Copy merged pgd to artifact staging'
inputs:
sourceFolder: $(pgoArtifactsPath)
contents: '**\$(buildPlatform)\*.pgd'
targetFolder: $(Build.ArtifactStagingDirectory)
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: $(Build.ArtifactStagingDirectory)
artifactName: ${{ parameters.pgoArtifact }}

View File

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

View File

@@ -19,7 +19,7 @@ function Invoke-CheckBadCodeFormatting() {
}
# Manually check the formatting of our .xaml files, without touching them.
Verify-XamlFormat
Test-XamlFormat
}

View File

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

View File

@@ -24,6 +24,8 @@
"/doc/cascadia/",
"/doc/user-docs/",
"/src/tools/MonarchPeasantSample/",
"/scratch/",
"Scratch.sln",
],
"SuffixFilters": [
".dbb",

View File

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

Submodule dep/wil updated: 3c00e7f1d8...2e225973d6

View File

@@ -16,7 +16,7 @@ If you have Visual Studio and related C++ components installed, and you have suc
> Note that you cannot easily run TAEF tests directly through Visual Studio. The `Microsoft.Taef` NuGet package comes with an adapter that will let you browse and execute TAEF tests inside of Visual Studio, but its performance and reliability prevent us from recommending it here.
In a "normal" CMD environment, `te.exe` may not be directly available. Try the following command to set up the development enviroment first:
In a "normal" CMD environment, `te.exe` may not be directly available. Try the following command to set up the development environment first:
```shell
.\tools\razzle.cmd

View File

@@ -127,4 +127,4 @@ When a release is created, if the PR ID number is linked inside the release desc
- Issue message: 🎉This issue was addressed in #{pull request ID}, which has now been successfully released as {release name} {release version}.🎉"
## Admin Panel
[Here](https://fabric-cp.azurewebsites.net/bot/)
[Here](https://portal.fabricbot.ms/bot/?repo=microsoft/terminal)

View File

@@ -9,7 +9,13 @@ git submodule update --init --recursive
OpenConsole.sln may be built from within Visual Studio or from the command-line using a set of convenience scripts & tools in the **/tools** directory:
When using Visual Studio, be sure to set up the path for code formatting. This can be done in Visual Studio by going to Tools > Options > Text Editor > C++ > Formatting and checking "Use custom clang-format.exe file" and choosing the clang-format.exe in the repository at /dep/llvm/clang-format.exe by clicking "browse" right under the check box.
When using Visual Studio, be sure to set up the path for code formatting. To download the required clang-format.exe file, follow one of the building instructions below and run:
```powershell
Import-Module .\tools\OpenConsole.psm1
Set-MsBuildDevEnvironment
Get-Format
```
After, go to Tools > Options > Text Editor > C++ > Formatting and checking "Use custom clang-format.exe file" in Visual Studio and choose the clang-format.exe in the repository at /packages/clang-format.win-x86.10.0.0/tools/clang-format.exe by clicking "browse" right under the check box.
### Building in PowerShell

View File

@@ -6,9 +6,9 @@ Adding a setting to Windows Terminal is fairly straightforward. This guide serve
The Terminal Settings Model (`Microsoft.Terminal.Settings.Model`) is responsible for (de)serializing and exposing settings.
### `GETSET_SETTING` macro
### `INHERITABLE_SETTING` macro
The `GETSET_SETTING` macro can be used to implement inheritance for your new setting and store the setting in the settings model. It takes three parameters:
The `INHERITABLE_SETTING` macro can be used to implement inheritance for your new setting and store the setting in the settings model. It takes three parameters:
- `type`: the type that the setting will be stored as
- `name`: the name of the variable for storage
- `defaultValue`: the value to use if the user does not define the setting anywhere
@@ -20,7 +20,7 @@ This tutorial will add `CloseOnExitMode CloseOnExit` as a profile setting.
1. In `Profile.h`, declare/define the setting:
```c++
GETSET_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
INHERITABLE_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
```
2. In `Profile.idl`, expose the setting via WinRT:
@@ -141,7 +141,7 @@ struct OpenSettingsArgs : public OpenSettingsArgsT<OpenSettingsArgs>
OpenSettingsArgs() = default;
// adds a getter/setter for your argument, and defines the json key
GETSET_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
WINRT_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
static constexpr std::string_view TargetKey{ "target" };
public:
@@ -213,9 +213,9 @@ Terminal-level settings are settings that affect a shell session. Generally, the
- Declare the setting in `IControlSettings.idl` or `ICoreSettings.idl` (whichever is relevant to your setting). If your setting is an enum setting, declare the enum here instead of in the `TerminalSettingsModel` project.
- In `TerminalSettings.h`, declare/define the setting...
```c++
// The GETSET_PROPERTY macro declares/defines a getter setter for the setting.
// Like GETSET_SETTING, it takes in a type, name, and defaultValue.
GETSET_PROPERTY(bool, UseAcrylic, false);
// The WINRT_PROPERTY macro declares/defines a getter setter for the setting.
// Like INHERITABLE_SETTING, it takes in a type, name, and defaultValue.
WINRT_PROPERTY(bool, UseAcrylic, false);
```
- In `TerminalSettings.cpp`...
- update `_ApplyProfileSettings` for profile settings

View File

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

View File

@@ -1,12 +1,12 @@
{
"$id": "https://github.com/microsoft/terminal/blob/main/doc/cascadia/profiles.schema.json",
"$schema": "https://json-schema.org/draft/2019-09/schema#",
"$schema": "https://json-schema.org/draft/2020-12/schema#",
"title": "Microsoft's Windows Terminal Settings Profile Schema",
"definitions": {
"KeyChordSegment": {
"pattern": "^(?<modifier>(ctrl|alt|shift)(?:\\+(ctrl|alt|shift)(?<!\\2))?(?:\\+(ctrl|alt|shift)(?<!\\2|\\3))?\\+)?(?<key>[^\\s+]|app|menu|backspace|tab|enter|esc|escape|space|pgup|pageup|pgdn|pagedown|end|home|left|up|right|down|insert|delete|(?<!shift.+)(?:numpad_?[0-9]|numpad_(?:period|decimal))|numpad_(?:multiply|plus|add|minus|subtract|divide)|f[1-9]|f1[0-9]|f2[0-4]|plus)$",
"pattern": "^(?<modifier>(?<mod1>ctrl|alt|shift|win)(?:\\+(?<mod2>ctrl|alt|shift|win)(?<!\\k<mod1>))?(?:\\+(?<mod3>ctrl|alt|shift|win)(?<!\\k<mod1>|\\k<mod2>))?(?:\\+(?<mod4>ctrl|alt|shift|win)(?<!\\k<mod1>|\\k<mod2>|\\k<mod3>))?\\+)?(?<key>[^\\s+]|app|menu|backspace|tab|enter|esc|escape|space|pgup|pageup|pgdn|pagedown|end|home|left|up|right|down|insert|delete|(?<!shift.+)(?:numpad_?[0-9]|numpad_(?:period|decimal))|numpad_(?:multiply|plus|add|minus|subtract|divide)|f[1-9]|f1[0-9]|f2[0-4]|plus)$",
"type": "string",
"description": "The string should fit the format \"[ctrl+][alt+][shift+]<keyName>\", where each modifier is optional, separated by + symbols, and keyName is either one of the names listed in the table below, or any single key character. The string should be written in full lowercase.\napp, menu\tMENU key\nbackspace\tBACKSPACE key\ntab\tTAB key\nenter\tENTER key\nesc, escape\tESC key\nspace\tSPACEBAR\npgup, pageup\tPAGE UP key\npgdn, pagedown\tPAGE DOWN key\nend\tEND key\nhome\tHOME key\nleft\tLEFT ARROW key\nup\tUP ARROW key\nright\tRIGHT ARROW key\ndown\tDOWN ARROW key\ninsert\tINS key\ndelete\tDEL key\nnumpad_0-numpad_9, numpad0-numpad9\tNumeric keypad keys 0 to 9. Can't be combined with the shift modifier.\nnumpad_multiply\tNumeric keypad MULTIPLY key (*)\nnumpad_plus, numpad_add\tNumeric keypad ADD key (+)\nnumpad_minus, numpad_subtract\tNumeric keypad SUBTRACT key (-)\nnumpad_period, numpad_decimal\tNumeric keypad DECIMAL key (.). Can't be combined with the shift modifier.\nnumpad_divide\tNumeric keypad DIVIDE key (/)\nf1-f24\tF1 to F24 function keys\nplus\tADD key (+)"
"description": "The string should fit the format \"[ctrl+][alt+][shift+][win+]<keyName>\", where each modifier is optional, separated by + symbols, and keyName is either one of the names listed in the table below, or any single key character. The string should be written in full lowercase.\napp, menu\tMENU key\nbackspace\tBACKSPACE key\ntab\tTAB key\nenter\tENTER key\nesc, escape\tESC key\nspace\tSPACEBAR\npgup, pageup\tPAGE UP key\npgdn, pagedown\tPAGE DOWN key\nend\tEND key\nhome\tHOME key\nleft\tLEFT ARROW key\nup\tUP ARROW key\nright\tRIGHT ARROW key\ndown\tDOWN ARROW key\ninsert\tINS key\ndelete\tDEL key\nnumpad_0-numpad_9, numpad0-numpad9\tNumeric keypad keys 0 to 9. Can't be combined with the shift modifier.\nnumpad_multiply\tNumeric keypad MULTIPLY key (*)\nnumpad_plus, numpad_add\tNumeric keypad ADD key (+)\nnumpad_minus, numpad_subtract\tNumeric keypad SUBTRACT key (-)\nnumpad_period, numpad_decimal\tNumeric keypad DECIMAL key (.). Can't be combined with the shift modifier.\nnumpad_divide\tNumeric keypad DIVIDE key (/)\nf1-f24\tF1 to F24 function keys\nplus\tADD key (+)"
},
"Color": {
"default": "#",
@@ -37,7 +37,8 @@
"type": "string",
"enum": [
"audible",
"visual"
"window",
"taskbar"
]
}
},
@@ -45,7 +46,8 @@
"type": "string",
"enum": [
"audible",
"visual",
"taskbar",
"window",
"all",
"none"
]
@@ -163,6 +165,49 @@
},
"type": "object"
},
"FontConfig": {
"properties": {
"face": {
"default": "Cascadia Mono",
"description": "Name of the font face used in the profile.",
"type": "string"
},
"size": {
"default": 12,
"description": "Size of the font in points.",
"minimum": 1,
"type": "integer"
},
"weight": {
"default": "normal",
"description": "Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values:\n -\"thin\"\n -\"extra-light\"\n -\"light\"\n -\"semi-light\"\n -\"normal\" (default)\n -\"medium\"\n -\"semi-bold\"\n -\"bold\"\n -\"extra-bold\"\n -\"black\"\n -\"extra-black\"\n or the corresponding numeric representation of OpenType font weight.",
"oneOf": [
{
"enum": [
"thin",
"extra-light",
"light",
"semi-light",
"normal",
"medium",
"semi-bold",
"bold",
"extra-bold",
"black",
"extra-black"
],
"type": "string"
},
{
"maximum": 990,
"minimum": 100,
"type": "integer"
}
]
}
},
"type": "object"
},
"ProfileGuid": {
"default": "{}",
"pattern": "^\\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\\}$",
@@ -188,6 +233,8 @@
"duplicateTab",
"find",
"findMatch",
"focusPane",
"globalSummon",
"identifyWindow",
"identifyWindows",
"moveFocus",
@@ -203,6 +250,7 @@
"prevTab",
"renameTab",
"openTabRenamer",
"quakeMode",
"resetFontSize",
"resizePane",
"renameWindow",
@@ -643,6 +691,25 @@
}
]
},
"CloseTabAction": {
"description": "Arguments for a closeTab action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "closeTab" },
"index": {
"oneOf": [
{ "type": "integer" },
{ "type": "null" }
],
"default": null,
"description": "Close the tab at this index. If no index is provided, use the focused tab's index."
}
}
}
]
},
"ScrollUpAction": {
"description": "Arguments for a scrollUp action",
"allOf": [
@@ -800,6 +867,79 @@
}
]
},
"FocusPaneAction": {
"description": "Arguments corresponding to a focusPane Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "focusPane" },
"id": {
"type": "string",
"default": "",
"description": "The ID of the pane to focus"
}
}
}
]
},
"GlobalSummonAction": {
"description": "This is a special action that works globally in the OS, rather than only in the context of the terminal window. When pressed, this action will summon the terminal window.",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "globalSummon" },
"desktop": {
"type": "string",
"default": "toCurrent",
"description": "This controls how the terminal should interact with virtual desktops.\n- \"any\": Leave the window on whichever desktop it's already on - will switch to that desktop as the window is activated.\n- \"toCurrent\" (default): Move the window to the current virtual desktop.\n- \"onCurrent\": Only summon the window if it's already on the current virtual desktop. ",
"enum": [
"any",
"toCurrent",
"onCurrent"
]
},
"monitor": {
"type": "string",
"default": "toMouse",
"description": "This controls the monitor that the window will be summoned from/to.\n- \"any\": Summon the most recently used window, regardless of which monitor it's currently on.\n- \"toCurrent\": Summon the most recently used window to the monitor with the current foreground window.\n- \"toMouse\" (default): Summon the most recently used window to the monitor where the mouse cursor is.",
"enum": [
"any",
"toCurrent",
"toMouse"
]
},
"name": {
"type": "string",
"description": "When provided, summon the window whose name or ID matches the given name value. If no such window exists, then create a new window with that name."
},
"dropdownDuration": {
"type": "number",
"minimum": 0,
"default": 0,
"description": "When provided with a positive number, \"slide\" the window in from the top of the screen using an animation that lasts dropdownDuration milliseconds."
},
"toggleVisibility": {
"type": "boolean",
"default": true,
"description": "When true, pressing the assigned keys for this action will dismiss (minimize) the window when the window is currently the foreground window."
}
}
}
]
},
"QuakeModeAction": {
"description": "This action is a special variation of the globalSummon action. It specifically summons a window called \"_quake\". If you would like to change the behavior of the quakeMode action, we recommended creating a new globalSummon entry.",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "quakeMode" }
}
}
]
},
"Keybinding": {
"additionalProperties": false,
"properties": {
@@ -821,6 +961,7 @@
{ "$ref": "#/definitions/WtAction" },
{ "$ref": "#/definitions/CloseOtherTabsAction" },
{ "$ref": "#/definitions/CloseTabsAfterAction" },
{ "$ref": "#/definitions/CloseTabAction" },
{ "$ref": "#/definitions/ScrollUpAction" },
{ "$ref": "#/definitions/ScrollDownAction" },
{ "$ref": "#/definitions/MoveTabAction" },
@@ -830,6 +971,9 @@
{ "$ref": "#/definitions/PrevTabAction" },
{ "$ref": "#/definitions/RenameTabAction" },
{ "$ref": "#/definitions/RenameWindowAction" },
{ "$ref": "#/definitions/FocusPaneAction" },
{ "$ref": "#/definitions/GlobalSummonAction" },
{ "$ref": "#/definitions/QuakeModeAction" },
{ "type": "null" }
]
},
@@ -850,16 +994,38 @@
},
"icon": { "$ref": "#/definitions/Icon" },
"name": {
"description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.",
"description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.\nIf name is a string, it will be the name of the command.\nIf name is a object, the key property of the object will be used to lookup a localized string resource for the command",
"properties": {
"key": {
"type": "string"
}
},
"type": [
"string",
"object",
"null"
]
},
"iterateOn": {
"type": "string",
"description": "Used to create iterable commands based on other objects in your settings. Possible values:\n- \"profiles\" \n- \"schemes\"",
"enum": [
"profiles",
"schemes"
]
},
"commands": {
"description": "List of commands to execute",
"items": {
"$ref": "#/definitions/Keybinding/properties/command"
},
"minItems": 1,
"type": "array"
}
},
"required": [
"command",
"keys"
"anyOf": [
{"required": ["name","commands"]},
{"required": ["command"]}
],
"type": "object"
},
@@ -902,6 +1068,16 @@
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.",
"$ref": "#/definitions/CopyFormat"
},
"trimBlockSelection": {
"default": false,
"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"
},
"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.",
"type": "boolean"
},
"disableAnimations": {
"default": false,
"description": "When set to `true`, visual animations will be disabled across the application.",
@@ -983,13 +1159,26 @@
"type": [ "integer", "string" ],
"deprecated": true
},
"actions": {
"description": "Properties are specific to each custom action.",
"items": {
"$ref": "#/definitions/Keybinding"
},
"type": "array"
},
"keybindings": {
"description": "Properties are specific to each custom key binding.",
"description": "[deprecated] Use actions instead.",
"deprecated": true,
"items": {
"$ref": "#/definitions/Keybinding"
},
"type": "array"
},
"language": {
"default": "",
"description": "Sets an override for the app's preferred language, expressed as a BCP-47 language tag like en-US.",
"type": "string"
},
"theme": {
"default": "system",
"description": "Sets the theme of the application. The special value \"system\" refers to the active Windows system theme.",
@@ -1118,6 +1307,11 @@
"description": "Sets the appearance of the terminal when it is unfocused.",
"type": ["object", "null"]
},
"font": {
"$ref": "#/definitions/FontConfig",
"description": "Sets the font options of the terminal.",
"type": ["object", "null"]
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background.",
"oneOf": [
@@ -1168,7 +1362,7 @@
},
"bellStyle": {
"default": "audible",
"description": "Controls what happens when the application emits a BEL character. When set to \"all\", the Terminal will play a sound and flash the taskbar icon. An array of specific behaviors can also be used. Supported array values include `audible` and `visual`. When set to \"none\", nothing will happen.",
"description": "Controls what happens when the application emits a BEL character. When set to \"all\", the Terminal will play a sound, flash the taskbar icon (if the terminal window is not in focus) and flash the window. An array of specific behaviors can also be used. Supported array values include `audible`, `window` and `taskbar`. When set to \"none\", nothing will happen.",
"$ref": "#/definitions/BellStyle"
},
"closeOnExit": {
@@ -1234,18 +1428,20 @@
},
"fontFace": {
"default": "Cascadia Mono",
"description": "Name of the font face used in the profile.",
"type": "string"
"description": "[deprecated] Define 'face' within the 'font' object instead.",
"type": "string",
"deprecated": true
},
"fontSize": {
"default": 12,
"description": "Size of the font in points.",
"description": "[deprecated] Define 'size' within the 'font' object instead.",
"minimum": 1,
"type": "integer"
"type": "integer",
"deprecated": true
},
"fontWeight": {
"default": "normal",
"description": "Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values:\n -\"thin\"\n -\"extra-light\"\n -\"light\"\n -\"semi-light\"\n -\"normal\" (default)\n -\"medium\"\n -\"semi-bold\"\n -\"bold\"\n -\"extra-bold\"\n -\"black\"\n -\"extra-black\"\n or the corresponding numeric representation of OpenType font weight.",
"description": "[deprecated] Define 'weight' within the 'font' object instead.",
"oneOf": [
{
"enum": [
@@ -1268,7 +1464,8 @@
"minimum": 100,
"type": "integer"
}
]
],
"deprecated": true
},
"foreground": {
"$ref": "#/definitions/Color",

View File

@@ -9,7 +9,7 @@ issue id: #1043
## Abstract
This spec is for task #1043 “Be able to set an initial position for the terminal”. It goes over the details of a new feature that allows users to set the initial position and size of the terminal. Expected behavior and design of this feature is included. Besides, future possible follow-up works are also addressed.
This spec is for task #1043 “Be able to set an initial position for the terminal”. It goes over the details of a new feature that allows users to set the initial position and size of the terminal. Expected behavior and design of this feature is included. Besides, future possible follow-up works are also addressed.
## Inspiration
@@ -17,7 +17,7 @@ The idea is to allow users to set the initial position of the Terminal when they
## Solution Design
For now, the Terminal window is put on a default initial position. The program uses CW_USEDEFAULT in the screen coordinates for top-left corner. We have two different types of window client window and non-client window. However, code path for window creation (WM_CREATE message is shared by the two types of windows) are almost the same for the two types of windows, except that there are some differences in calculation of the width and height of the window.
For now, the Terminal window is put on a default initial position. The program uses CW_USEDEFAULT in the screen coordinates for top-left corner. We have two different types of window client window and non-client window. However, code path for window creation (WM_CREATE message is shared by the two types of windows) are almost the same for the two types of windows, except that there are some differences in calculation of the width and height of the window.
Two new properties should be added in the json settings file:
@@ -92,9 +92,9 @@ For now, this feature only allows the user to set initial position and choose wh
3. We may also consider more launch modes. Like full screen mode and minimized mode.
Github issue for future follow-ups: https://github.com/microsoft/terminal/issues/766
GitHub issue for future follow-ups: https://github.com/microsoft/terminal/issues/766
## Resources
Github issue:
GitHub issue:
https://github.com/microsoft/terminal/issues/1043

View File

@@ -0,0 +1,105 @@
---
author: Pankaj Bhojwani, pabhojwa@microsoft.com
created on: 2021-6-17
last updated: 2021-6-23
issue id: #1790
---
# Font features and axes of variation
## Abstract
This spec outlines how we can allow users to specify font features and axes of variation for fonts in Windows Terminal. Font features include things like being able to specify whether ligatures should be used as well as the specific stylistic set used for a font. Axes of variation commonly include things like weight and slant but can also include fancier things like shadow distance, depending on the font.
## Inspiration
Reference: [#1790](https://github.com/microsoft/terminal/issues/1790)
Currently, if a font has ligatures, we offer no way for a user to disable them. Many users would like the option to do so, and would also like the ability to choose stylistic sets for fonts - for example, at the time of this writing, Cascadia Code offers 4 stylistic sets but we offer no way for users to specify any of them.
In a similar vein, many fonts allow for setting variations on the font along certain attributes, commonly referred to as 'axes of variation'. We can offer users more font customization options by allowing them to configure these font variations.
## Solution Design
### Font features
It is already possible to pass in a list of [font feature structs](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature) to DWrite for it to handle. A font feature struct contains only 2 things:
1. A font feature tag
2. A parameter value
A font feature tag is constructed using a 4-character feature tag and the parameter value defines how the feature is applied. For most features, the parameter value is simply treated as a binary value - a value of 0 means the feature is not applied and a non-zero value means the feature is applied. For example, a font feature struct like {'ss03', 1} enables stylistic set 3 for the font and a font feature struct like {'liga', 0} disables ligatures. (Technically, the feature tag is _constructed_ with the 4-character tag and is not the 4-character tag itself, but they are treated the same in the example here for brevity's sake).
Currently, we pass in to DWrite a null value for the list of features to apply to the font. This causes DWrite to automatically apply a ['standard' list](https://github.com/fdwr/TextLayoutSampler/blob/master/DrawableObject.ixx#L802) of font features to the font. Naturally, passing in our own list of font features to DWrite means DWrite will _only_ apply the features we defined, and no longer apply the standard list. Since the standard list contains 11 features, we need to consider how we can allow users to specify 1 additional feature or delete 1 of the standard features without needing to redefine all the others.
We will do this by allowing users to define a dictionary in their settings.json file, where the keys are the 4-character feature tags and the values are the parameter values. This dictionary will then get applied to our internal dictionary (which will contain the standard list of 11 features with their parameter values), meaning that any new key-value pairs will get added to our dictionary and any existing key-value pairs will get updated. Finally, this 'merged' dictionary will be what we use to construct the list of features to pass into DWrite.
### Axes of variation
Specifying axes of variation is done in an extremely similar manner to the way font features are specified - a 4-character tag is used to specify which font axis is being modified and a numerical value is provided to specify the value the axis should be set to. For example, {'slnt', 20} specifies that the 'slant' axis should be set to 20.
There is also a standard list of axes of variation, and each axis has its own default. We will approach this the same way we approached font features, by allowing users to specify additional features or omit features without needing to redefine the defaults.
## UI/UX Design
Users will be able to add a new setting to their font objects (added in [#10433](https://github.com/microsoft/terminal/pull/10433)). The resultant font object may look something like this
```json
"font": {
"face": "Cascadia Code",
"size": 12,
"features": {
"ss03": 1,
"liga": 0
},
"axes": {
"slnt": 20.5
}
}
```
There is one point to note here about clashing. For example, if a user has the old "weight" setting defined _as well as_ a "wght" axis defined, we will only use the "wght" axis value. We prioritize that value for a few reasons:
1. It is the more recent addition to our settings model. Thus, it is likely that a user that has defined both values probably just forgot to remove the old value.
2. It is the more precise value, it is a specific float value whereas the the old "weight" setting is an enum (that eventually gets mapped to a float value).
## Capabilities
### Accessibility
Should not affect accessibility.
### Security
Should not affect security.
### Reliability
Aside from additional parsing required for the settings file (which inherently offers more locations for parsing to fail), we need to be careful about badly formed/non-existant feature tags or axes specified in the user-defined dictionaries. We must make sure to ignore such declarations (perhaps alongside emitting a warning to the user) and only apply those that are correctly formed and exist.
### Compatibility
Older versions of Windows may not have the DWrite updates that allow for defining font features and axes of variation. We must make sure to fallback to the current implementation in these cases.
### Performance, Power, and Efficiency
Currently when rendering a run of text, if we detect that the given run is simple we will use a shortcut to obtain the glyphs needed, skipping over an expensive `GetGlyphs` call to DWrite. However, when the default feature list is changed in any way (either by adding a new feature or removing one of the defaults), there is no way for us to detect beforehand how the font glyphs would change.
This means that as long as the user requests a change to the default font feature list, we will _always_ skip the shortcut and call the expensive `GetGlyphs` function for every run of text.
This will naturally cause a performance cost that we will have to bear for this feature. However, it is worth noting that there are a fair number of glyphs that will cause a run of text to be deemed "not simple" (and thus cause us to call `GetGlyphs` anyway), for example when using Cascadia Code, any run of text that has the letters 'i', 'j', 'l', 'n', 'w' or 'x' is not considered simple (because those glyphs have localized variants).
## Potential Issues
See performance issues above.
## Future considerations
DWrite additionally offers the ability to vary the font features across runs of text. However, for our initial implementation of this feature, we will only apply font features to the entire buffer. If/when we decide to allow specifying font features for particular runs of text, we can lean into our existing mechanisms of splitting up runs of text to implement that.
We will also need to consider how we want to represent this in the settings UI. This is slightly more complex than other settings since users should be allowed to manually input 4-character tags.
## Resources
[DWRITE_FONT_FEATURE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature)
[DWRITE_FONT_AXIS_VALUE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite_3/ns-dwrite_3-dwrite_font_axis_value)

View File

@@ -123,4 +123,4 @@ This open issue tracks the phase features of Search: https://github.com/microsof
## Resources
Github Issue: https://github.com/microsoft/terminal/issues/605
GitHub Issue: https://github.com/microsoft/terminal/issues/605

View File

@@ -0,0 +1,736 @@
---
author: Mike Griese @zadjii-msft
created on: 2021-02-23
last updated: 2021-05-13
issue id: #653
---
# Quake Mode
## Abstract
Many existing terminals support a feature whereby a user can press a keybinding
anywhere in the OS, and summon their terminal application. Oftentimes the act of
summoning this window is accompanied by a "dropdown" animation, where the window
slides in to view from the top of the screen. This global summon action is often
referred to as "quake mode", a reference to the video game Quake, who's console
slid in from the top.
This spec addresses both of the following two issues:
* "Quake Mode" ([#653])
* "Minimize to tray" ([#5727])
Readers should make sure to have read the [Process Model 2.0 Spec], for
background on Monarch and Peasant processes.
## Background
### Inspiration
For an example of the original Quake console in action, take a look at the
following video (noisy video warning): [Quake 3 sample]. Additionally, plenty of
existing terminal emulators support similar functionality:
* **Tilda** allows the user to specify different keys to summon the window on
different monitors.
* **Guake** alternatively allows the user to either summon the terminal window to
a specific monitor, or whichever monitor the mouse is on. Guake only allows
one single instance, so pressing the global hotkey always summons the same
instance.
### User Stories
The original quake mode thread (#653) is absolutely _filled_ with variations on
how users want to be able to summon their terminal windows. These include, but
are not limited to:
* **Story A** Press a hotkey anywhere to activate the single Terminal window
wherever it was
* **Story B** Press a hotkey anywhere to activate the single Terminal window _on
the current monitor_. If it wasn't previously on that monitor, move it there.
* **Story C** When the Terminal is summoned using the hotkey, have it "slide in"
from the top. Similarly, slide out on deactivate.
* **Story D** <kbd>Ctrl+1</kbd> to activate the terminal on monitor 1,
<kbd>Ctrl+2</kbd> to activate the terminal on monitor 2.
* **Story E** Variable dropdown speed
* **Story F** Minimize to tray, press a hotkey to activate the terminal window
(#5727)
* **Story G** Terminal doesn't appear in alt+tab view, press a hotkey to
activate the single terminal window / the nearest terminal window (I'm not
sure this is distinct from the above)
## Solution Design
To implement this feature, we'll add the following settings:
* a new action, named `globalSummon`.
* a new global, app setting named `minimizeToTray`
* a new global, app setting named `alwaysShowTrayIcon`
* a new action, named `quakeMode`, and a specially named `_quake` window.
### `globalSummon` Action
The `globalSummon` action will be a keybinding the user can use to summon a
Terminal window from anywhere in the OS. Various arguments to the action will
specify which window is summoned, to where, and how the window should behave on
summon.
From a technical perspective, the action will work by using the
[`RegisterHotKey`] function. This API allows us to bind a particular hotkey with
the OS. Whenever that hotkey is pressed, our window message loop will receive a
`WM_HOTKEY`. We'll use the payload of that window message to lookup the action
arguments for that hotkey. Then we'll use those arguments to control which
window is invoked, where, and how the window behaves.
Since `RegisterHotKey` can only be used to register a hotkey _once_ with the OS,
we'll need to make sure it's only ever set up by the Monarch process. We know
that there will only ever be one Monarch for the Terminal at a time, so it's the
perfect process to have the responsibility of managing the global hotkey.
The Monarch will be responsible for calling `RegisterHotKey`, and processing the
`WM_HOTKEY` messages. It will then dispatch method calls to the appropriate
window to summon it. When a Monarch dies and a new process becomes the Monarch,
the new Monarch will re-register for the hotkeys.
#### Where in the settings?
Since users may want to bind multiple keys to summon different windows, we'll
need to allow the user to specify multiple keybindings simultaneously, each with
their own set of args.
We stick all the `globalSummon`s in the actions array, like they're any other
keybinding.
However, these are not keys that are handled by the TerminalApp layer itself.
These are keys that need to be registered with the OS. So while they will be in
the normal `KeyMap`, they will need to be retrieved from that object and
manually passed to the window layer.
> A previous iteration of this spec considered placing the `globalSummon`
> actions in their own top-level array of the settings file, separate from the
> keybindings. This is no longer being considered, because it would not work for
> the case where the user has something like:
> ```json
> { "keys": "ctrl+c", "command": { "action": "globalSummon", "monitor": 1 } },
> { "keys": "ctrl+v", "command": { "action": "copy" } },
> ```
#### Which window, and where?
When looking at the list of requested scenarios, there are lots of different
ways people would like to use the global summon action. Some want the most
recent window activated, always. Others want to have one window _per monitor_.
Some would like to move the window to where the user is currently interacting
with the PC, and others want to activate the window where it already exists.
Trying to properly express all these possible configurations is complex. The
settings should be unambiguous as to what will happen when you press the
keybinding.
I believe that in order to accurately support all the variations that people
might want, we'll need two properties in the `globalSummon` action. These
properties will specify _which_ window we're summoning, and _where_ to summon
the window. To try and satisfy all these scenarios, I'm proposing the following
two arguments to the `globalSummon` action:
```json
"monitor": "any"|"toCurrent"|"toMouse"|"onCurrent"|int,
"desktop": "any"|"toCurrent"|"onCurrent"
```
The way these settings can be combined is in a table below. As an overview:
* `monitor`: This controls the monitor that the window will be summoned from/to
- `"any"`: Summon the MRU window, regardless of which monitor it's currently
on.
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor
with the current **foreground** window.
- `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse**
cursor is.
- `"onCurrent"`: Summon the MRU window **ALREADY ON** the current monitor.
- `int`: Summon the MRU window for the given monitor (as identified by the
"Identify" displays feature in the OS settings)
* `desktop`: This controls how the terminal should interact with virtual desktops.
- `"any"`: Leave the window on whatever desktop it's already on - we'll switch
to that desktop as we activate the window.
- > NOTE: A previous version of this spec had this enum value as `null`.
This was changed to `"any"` for parity with the `monitor` property.
- `"toCurrent"`/omitted: (_default_): Move the window **to** the current
virtual desktop
- `"onCurrent"`: Only summon the window if it's **already on** the current
virtual desktop
Neither `desktop` nor `monitor` is a required parameter - if either is omitted,
the omitted property will default to `toCurrent`.
Together, these settings interact in the following ways:
<!-- This table is formatted for viewing as rendered HTML. It's too complicated
for pure markdown, sorry. -->
<table>
<tr>
<td></td>
<th colspan=3><code>"desktop"</code></th>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<th><code>"monitor"</code></th>
<td><code>any</code><br><strong>Leave where it is</strong></td>
<td><code>"toCurrent"</code><br><strong>Move to current desktop</strong></td>
<td><code>"onCurrent"</code><br><strong>On current desktop only</strong></td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td><code>"any"</code><br> Summon the MRU window</td>
<td>Go to the desktop the window is on (leave position alone)</td>
<td>Move the window to this desktop (leave position alone)</td>
<td>
If there isn't one on this desktop:
* create a new one (default position)
Else:
* activate the one on this desktop (don't move it)
</td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td><code>"toCurrent"</code><br> Summon the MRU window TO the monitor with the foreground window</td>
<td>Go to the desktop the window is on, move to the monitor with the foreground window</td>
<td>Move the window to this desktop, move to the monitor with the foreground window</td>
<td>
If there isn't one on this desktop:
* create a new one (on the monitor with the foreground window)
Else:
* activate the one on this desktop, move to the monitor with the foreground window
</td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td>
<code>"toMouse"</code>
<sup><a href="#footnote-2">[2]</a></sup> <br>
Summon the MRU window TO the monitor with the mouse</td>
<td>Go to the desktop the window is on, move to the monitor with the mouse</td>
<td>Move the window to this desktop, move to the monitor with the mouse</td>
<td>
If there isn't one on this desktop:
* create a new one (on the monitor with the mouse)
Else:
* activate the one on this desktop, move to the monitor with the mouse
</td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td><code>"onCurrent"</code><br> Summon the MRU window for the current monitor</td>
<td>
If there is a window on this monitor on any desktop,
* Go to the desktop the window is on (leave position alone)
else
* Create a new window on this monitor & desktop
</td>
<td>
If there is a window on this monitor on any desktop,
* Move the window to this desktop (leave position alone)
else
* Create a new window on this monitor & desktop
</td>
<td>
If there isn't one on this desktop, (even if there is one on this monitor on
another desktop),
* create a new one on this monitor
Else if ( there is one on this desktop, not this monitor)
* create a new one on this monitor
Else (one on this desktop & monitor)
* Activate the one on this desktop (don't move)
</td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td><code>int</code><br> Summon the MRU window for monitor N</td>
<td>
If there is a window on monitor N on any desktop,
* Go to the desktop the window is on (leave position alone)
else
* Create a new window on this monitor & desktop
</td>
<td>
If there is a window on monitor N on any desktop,
* Move the window to this desktop (leave position alone)
else
* Create a new window on this monitor & desktop
</td>
<td>
If there isn't one on this desktop, (even if there is one on monitor N on
another desktop),
* create a new one on monitor N
Else if ( there is one on this desktop, not monitor N)
* create a new one on monitor N
Else (one on this desktop & monitor N)
* Activate the one on this desktop (don't move)
</td>
</tr>
</table>
##### Stories, revisited
With the above settings, let's re-examine the original user stories, and see how
they fit into the above settings. (_Stories that are omitted aren't relevant to
the discussion of these settings_)
> When the `desktop` param is omitted below, that can be interpreted as "any
> `desktop` value will make sense here"
* **Story A** Press a hotkey anywhere to activate the single Terminal window
wherever it was
- This is `{ "monitor": "any", "desktop": "any" }`
* **Story B** Press a hotkey anywhere to activate the single Terminal window _on
the current monitor_. If it wasn't previously on that monitor, move it there.
- This is `{ "monitor": "toCurrent" }`
* **Story D** <kbd>Ctrl+1</kbd> to activate the terminal on monitor 1,
<kbd>Ctrl+2</kbd> to activate the terminal on monitor 2.
- This is `[ { "keys": "ctrl+1", monitor": 1 }, { "keys": "ctrl+2", monitor": 2 } ]`
As some additional examples:
```json
// Go to the MRU window, wherever it is
{ "keys": "win+1", "command":{ "action":"globalSummon", "monitor":"any", "desktop": "any" } },
// activate the MRU window, and move it to this desktop & this monitor
{ "keys": "win+2", "command":{ "action":"globalSummon", "monitor":"toCurrent", "desktop": "toCurrent" } },
// Since "toCurrent" & "toCurrent" are the default values, just placing a single
// entry here will bind the same behavior:
{ "keys": "win+2", "command": "globalSummon" },
// activate the MRU window on this desktop
{ "keys": "win+3", "command":{ "action":"globalSummon", "monitor":"any", "desktop": "onCurrent" } },
// Activate the MRU window on monitor 2 (from any desktop), and place it on the
// current desktop. If there isn't one on monitor 2, make a new one.
{ "keys": "win+4", "command":{ "action":"globalSummon", "monitor": 2, "desktop": "toCurrent" } },
// Activate the MRU window on monitor 3 (ONLY THIS desktop), or make a new one.
{ "keys": "win+5", "command":{ "action":"globalSummon", "monitor": 3, "desktop": "onCurrent" } },
// Activate the MRU window on this monitor (from any desktop), and place it on
// the current desktop. If there isn't one on this monitor, make a new one.
{ "keys": "win+6", "command":{ "action":"globalSummon", "monitor": "onCurrent", "desktop": "toCurrent" } },
```
#### Summoning a specific window
What if you want to press a keybinding to always summon a specific, named
window? This window might not be the most recent terminal window, nor one that
would be selected by the `monitor` and `desktop` selectors. You could name a
window "Epona", and press `win+e` to always summon the "Epona" window.
We'll add the following property to address this scenario
* `"window": string|int`
- When omitted (_default_): Use monitor and desktop to find the appropriate
MRU window to summon.
- When provided: Always summon the window who's name or ID matches the given
`window` value. If no such window exists, then create a new window with that
name/id.
When provided _with_ `monitor` and `desktop`, `window` behaves in the following
ways:
* `desktop`
- `"any"`: Go to the desktop the given window is already on.
- `"toCurrent"`: If the window is on another virtual desktop, then move it to
the currently active one.
- `"onCurrent"`: If the window is on another virtual desktop, then move it to
the currently active one.
* `monitor`
- `"any"`: Leave the window on the monitor it is already on.
- `"toCurrent"`: If the window is on another monitor, then move it to the
currently active one.
- `"onCurrent"`: If the window is on another monitor, then move it to the
currently active one.
- `<int>`: If the window is on another monitor, then move it to the specified
monitor.
> NOTE: You read that right, `onCurrent` and `toCurrent` both do the same thing
> when `window` is provided. They both already know which window to select, the
> context of moving to the "current" monitor is all that those parameters add.
#### Other properties
Some users would like the terminal to just appear when the global hotkey is
pressed. Others would like the true quake-like experience, where the terminal
window "slides-in" from the top of the monitor. Furthermore, some users would
like to configure the speed at which that dropdown happens. To support this
functionality, the `globalSummon` action will support the following property:
* `"dropdownDuration": float`
- When omitted, `0`, or a negative number: No animation is used
when summoning the window. The summoned window is focused immediately where
it is.
- When a positive number is provided, the terminal will use that value as a
duration (in seconds) to slide the terminal into position when activated.
- The default would be some sensible value. The pane animation is .2s, so
`0.2` might be a reasonable default here.
We could have alternatively provided a `"dropdownSpeed"` setting, that provided
a number of pixels per second. In my opinion, that would be harder for users to
use correctly. I believe that it's easier for users to mentally picture "I'd
like the dropdown to last 100ms" vs "My monitor is 1504px tall, so I need to set
this to 15040 to make the window traverse the entire display in .1s"
> NOTE: `dropdownDuration` will be ignored when the user has animations disabled
> in the OS. In that case, the terminal will just appear, as if it was set to 0.
Some users might want to be able to use the global hotkey to hide the window
when the window is already visible. This would let the hotkey act as a sort of
global toggle for the Terminal window. Others might not like that behavior, and
just want the action to always bring the Terminal into focus, and do nothing if
the terminal is already focused. To facilitate both these use cases, we'll add
the following property:
* `"toggleVisibility": bool`
- When `true`: (_default_) When this hotkey is pressed, and the terminal
window is currently active, minimize the window.
- When `dropdownDuration` is not `0`, then the window will slide back off
the top at the same speed as it would come down.
- When `false`: When this hotkey is pressed, and the terminal window is
currently active, do nothing.
### Quake Mode
In addition to just summoning the window from anywhere, some terminals also
support a special "quake mode" buffer or window. This window is one that closely
emulates the console from quake:
* It's docked to the top of the screen
* It takes the full width of the monitor, and only the bottom can be resized
* It often doesn't have any other UI elements, like tabs
For fun, we'll also be adding a special `"_quake"` window with the same
behavior. If the user names a window `_quake`, then it will behave in the
following special ways:
* On launch, it will ignore the `initialPosition` and
`initialRows`/`initialCols` setting, and instead resize to the top half of the
monitor.
* On launch, it will ignore the `launchMode` setting, and always launch in focus
mode.
- Users can disable focus mode on the `_quake` window if they do want tabs.
* It will not be resizable from any side except the bottom of the window, nor
will it be drag-able.
* It will not be a valid target for the "most recent window" for window
glomming. If it's the only open window, with `"windowingBehavior":
"useExisting*"`, then a new window will be created instead.
- It _is_ still a valid target for something like `wt -w _quake new-tab`
A window at runtime can be renamed to become the `_quake` window (if no other
`_quake` window exists). When it does, it will resize to the position of the
quake window, and enter focus mode.
We'll also be adding a special action `quakeMode`. This action is a special case
of the `globalSummon` action, to specifically invoke the quake window in the
current place. It is basically the same thing as the more elaborate:
```json
{
"monitor": "toCurrent",
"desktop": "toCurrent",
"window": "_quake",
"toggleVisibility": true,
"dropdownDuration": 0.5
},
```
### Minimize to Tray
Many users have requested that the terminal additionally supports minimizing the
window "to the tray icon". This is a bit like when you close the Teams window,
but Teams is actually still running in the system tray, or the "notification
area".
![The Teams tray icon](tray-icon-000.png)
_fig 1: an example of the Teams tray icon in the notification area_.
When users want to be able to "minimize to the tray", they want:
* The window to no longer appear on the taskbar
* The window to no longer appear in the alt-tab order
When minimized to the tray, it's almost as if there's no window for the Terminal
at all. This can be combined with the global hotkey (or the tray icon's context
menu) to quickly restore the window.
The tray icon could be used for a variety of purposes. As a simple start, we
could include the following three options:
```
Focus Terminal
---
Windows > Window 1 - <un-named window>
Window 2 - "This-window-does-have-a-name"
---
Quit
```
Just clicking on the icon would summon the recent terminal window. Right
clicking would show the menu with "Focus Terminal", "Windows" and "Quit" in it, and
"Windows" would have nested entries for each Terminal window.
* "Focus Terminal" would do just that - summon the most recent terminal window,
wherever it is.
* "Windows" would have nested popups for each open Terminal window. Each of
these nested entries would display the name and ID of the window. Clicking
them would summon that window (wherever it may be)
* "Quit" would be akin to quit in browsers - close all open windows
<sup>[[1]](#footnote-1)</sup>.
The tray notification would be visible always when the user has
`"minimizeToTray": true` set in their settings. If the user has that set to
false, but would still like the tray, they can specify `"alwaysShowTrayIcon":
true`. That will cause the tray icon to always be added to the system tray.
There's not a combination of settings where the Terminal is "minimized to the
tray", and there's _no tray icon visible_. We don't want to let users get into a
state where the Terminal is running, but is totally hidden from their control.
From a technical standpoint, the tray icon is managed similar to the global
hotkey. The Monarch process is responsible for setting it up, and processing the
messages. When a Monarch dies and a new process becomes the Monarch, then it
will re-create the tray icon.
## UI/UX Design
To summarize, we're proposing the following set of settings:
```jsonc
{
"minimizeToTray": bool,
"alwaysShowTrayIcon": bool,
"actions": [
{
"keys": KeyChord,
"command": {
"action": "globalSummon",
"dropdownDuration": float,
"toggleVisibility": bool,
"monitor": "any"|"toCurrent"|"onCurrent"|int,
"desktop": "any"|"toCurrent"|"onCurrent"
}
},
{
"keys": KeyChord,
"command": {
"action": "quakeMode"
}
}
]
}
```
## Potential Issues
<table>
<tr>
<td><strong>Compatibility</strong></td>
<td>
As part of this set of changes, we'll also be allowing the <kbd>Win</kbd> key in
keybindings. Generally, the OS reserves the Windows key for its own shortcuts.
For example, <kbd>Win+R</kbd> for the run dialog, <kbd>Win+A</kbd> for the
Action Center, <kbd>Win+V</kbd> for the cloud clipboard, etc. Users will now be
able to use the win key themselves, but they should be aware that the OS has
"first dibs" on any hotkeys involving the Windows key.
</td>
</tr>
<tr>
<td><strong>Mixed elevation</strong></td>
<td>
Only one app at a time gets to register for global hotkeys. However, from the
Terminal's perspective, unelevated and elevated windows will act like different
apps. Each privilege level has its own Monarch. The two are unable to
communicate across the elevation boundary.
This means that if the user often runs terminals in both contexts, then only one
will have the global hotkeys bound. The naive implementation would have the
first elevation level "win" the keybindings.
A different option would be to have elevated windows not register global hotkeys
_at all_. I don't believe that there's any sort of security implication for
having a global hotkey for an elevated window.
A third option would be to have some sort of `"whenElevated": bool?` property
for global hotkeys. This would explicitly enable a given hotkey for unelevated
vs elevated windows.
* `"whenElevated": null`: behave as normal - the first context level to run wins
* `"whenElevated": true`: only register the hotkey when running elevated
* `"whenElevated": false`: only register the hotkey when running unelevated
</td>
</tr>
<tr>
<td><strong>OneCore / Windows 10X</strong></td>
<td>
I'm fairly certain that none of these APIs would work on Windows 10X at all.
These features would have to initially be disabled in a pure UWP version of the
Terminal, until we could find workarounds. Since the window layer is the one
responsible for the management of the hotkeys and the tray icon, we're not too
worried about this.
</td>
</tr>
</table>
* If there are any other applications running that have already registered
hotkeys with `RegisterHotKey`, then it's possible that the Terminal's attempt
to register that hotkey will fail. If that should happen, then we should
display a warning dialog to the user indicating which hotkey will not work
(because it's already used for something else).
* Which is the "current" monitor? The one with the mouse or the one with the
active window? This isn't something that has an obvious answer. Guake
implements this feature where the "current monitor" is the one with the mouse
on it. At least for the first iterations of this action, that's what we'll
use.
`monitor: onCurrent|onCurrentWindow|toCurrent|<int>`
* Currently, running both the Release and Preview versions of the Terminal at
the same time side-by-side is not generally supported. (For example, `wt.exe`
can only ever point at one of two.) If a user binds the same key to a
`globalSummon` or `quakeMode` action, then only one of the apps will actually
be able to successfully claim the global hotkey.
## Implementation plan
Currently, in [`dev/migrie/f/653-QUAKE-MODE`], I have some sample rudimentary
code to implement quake mode support. It allows for only a single global hotkey
that summons the MRU window, without dropdown. That would be a good place for
anyone starting to work on this feature. From there, I imagine the following
work would be needed:
* [ ] Add a `globalSummon` action. `AppHost` would need to be able to get _all_
of these actions, and register all of them. Each one would need to be assigned
a unique ID, so `WM_HOTKEY` can identify which hotkey was pressed.
- This could be committed without any other args to the `globalHotkeys`. In
this initial version, the behavior would be summoning the MRU window,
where it is, no dropdown, to start with. From there, we'd add the
remaining properties:
* [ ] Add support for the `toggleVisibility` property
* [ ] Add support for the `desktop` property to control how window summoning
interacts with virtual desktops
* [ ] Add support for the `monitor` which monitor the window appears on.
* [ ] Add support for the `dropdownDuration` property
* [ ] Add the `minimizeToTray` setting, and implement it without any sort of flyout
* [ ] Add a list of windows to the right-click flyout on the tray icon
* [ ] Add support for the `alwaysShowTrayIcon` setting
* [ ] When the user creates a window named `_quake`, ignore the initial size,
position, and launch mode, and create the window in quake mode instead.
* [ ] Exempt the `_quake` window from window glomming
* [ ] Add the `quakeMode` action, which `globalSummon`'s the `_quake` window.
* [ ] Prevent the `_quake` window from being dragged or resized on the
top/left/right.
### Future Considerations
I don't believe there are any other tracked requests that are planned that
aren't already included in this spec.
* Should the tray icon's list of windows include window titles? Both the name
and title? Maybe something like `({name}|{id}): {title}`? I'd bet that most
people don't end up naming their windows.
* Dropdown duration could be a `float|bool`, with `true`->(whatever the default
is), `false`->0.
- We could have the setting appear as a pair of radio buttons, with the first
disabling dropdown, and the second enabling a text box for inputting an
animation duration.
* It might be an interesting idea to have the ability to dock the quake window
to a specific side of the monitor, not just the top. We could probably do that
with a global setting `"quakeModeDockSide": "top"|"left"|"bottom"|"right"` or
something like that.
* We might want to pre-load the quake window into the tray icon as an entry for
"Quake Mode", and otherwise exclude it from the list of windows in that menu.
* We might think of other things for the Quake Mode window in the future - this
spec is by no means comprehensive. For example, it might make sense for the
quake mode window to automatically open in "always on top" mode.
* It was suggested that the quake mode window could auto-hide when it loses
focus. That's a really neat idea, but we're a little worried about the
implementation. What happens when the IME window gets focus? Or the Start
Menu? Would those end up causing the quake window to prematurely minimize
itself? For that reason, we're leaving this as a future consideration.
* Perhaps there could be a top-level object in the settings like
```json
{
"quakeMode": {
"hideOnFocusLost": true,
"useFocusMode": false,
"profile": "my quake mode profile" ,
"quakeModeDockSide": "bottom"
}
}
```
That would allow the user some further customizations on the quake mode
behaviors.
- This was later converted to the idea in [#9992] - Add per-window-name global
settings
* Another proposed idea was a simplification of some of the summoning modes. `{
"monitor": "any", "desktop": "any" }` is a little long, and maybe not the most
apparent naming. Perhaps we could add another property like `summonMode` that
would act like an alias for a `monitor`, `desktop` combo.
- `"summonMode": "activateInMyFace"`: `{ "monitor": "toCurrent", "desktop": "toCurrent" }`
- `"summonMode": "activateWherever"`: `{ "monitor": "any", "desktop": "any" }`
## Resources
Docs on adding a system tray item:
* https://docs.microsoft.com/en-us/windows/win32/shell/notification-area
* https://www.codeproject.com/Articles/18783/Example-of-a-SysTray-App-in-Win32
Docs regarding hiding a window from the taskbar:
* https://docs.microsoft.com/en-us/previous-versions//bb776822(v=vs.85)#managing-taskbar-buttons
### Footnotes
<a name="footnote-1"><a>[1]: Quitting the terminal is different than closing the
windows one-by-one. Quiting implies an atomic action, for closing all the
windows. Once [#766] lands, this will give us a chance to persist the state of
_all_ open windows. This will allow us to re-open with all the user's windows,
not just the one that happened to be closed last.
<a name="footnote-2"><a>[2]: **Addenda, May 2021**: In the course of
implementation, it became apparent that there's an important UX difference
between summoning _to the monitor with the cursor_ vs _to the monitor with the
foreground window_. `"monitor": "toMouse"` was added as an option, to allow the
user to differentiate between the two behaviors.
[#653]: https://github.com/microsoft/terminal/issues/653
[#766]: https://github.com/microsoft/terminal/issues/766
[#5727]: https://github.com/microsoft/terminal/issues/5727
[#9992]: https://github.com/microsoft/terminal/issues/9992
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md
[Quake 3 sample]: https://youtu.be/ZmR6HQbuHPA?t=27
[`RegisterHotKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey
[`dev/migrie/f/653-QUAKE-MODE`]: https://github.com/microsoft/terminal/tree/dev/migrie/f/653-QUAKE-MODE

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,344 @@
---
author: Carlos Zamora @carlos-zamora
created on: 2021-03-12
last updated: 2021-03-17
issue id: [#885]
---
# Actions in the Settings Model
## Abstract
This spec proposes a refactor of how Windows Terminal actions are stored in the settings model.
The new representation would mainly allow the serialization and deserialization of commands and keybindings.
## Inspiration
A major component that is missing from the Settings UI is the representation of keybindings and commands.
The JSON represents both of these as a combined entry as follows:
```js
{ "icon": "path/to/icon.png", "name": "Copy the selected text", "command": "copy", "keys": "ctrl+c" },
```
In the example above, the copy action is...
- bound to <kbd>ctrl+c</kbd>
- presented as "Copy the selected text" with the "path/to/icon.png" icon
However, at the time of writing this spec, the settings model represents it as...
- (key binding) a `KeyChord` to `ActionAndArgs` entry in a `KeyMapping`
- (command) a `Command` with an associated icon, name, and action (`ActionAndArgs`)
This introduces the following issues:
1. Serialization
- We have no way of knowing when a command and a key binding point to the same action. Thus, we don't
know when to write a "name" to the json.
- We also don't know if the name was auto-generated or set by the user. This can make the JSON much more bloated by
actions with names that would normally be autogenerated.
2. Handling Duplicates
- The same action can be bound to multiple key chords. The command palette combines all of these actions into one entry
because they have the same name. In reality, this same action is just being referenced in different ways.
## Solution Design
I propose that the issues stated above be handled via the following approach.
### Step 1: Consolidating actions
`Command` will be updated to look like the following:
```c++
runtimeclass Command
{
// The path to the icon (or icon itself, if it's an emoji)
String IconPath;
// The associated name. If none is defined, one is auto-generated.
String Name;
// The key binding that can be used to invoke this action.
// NOTE: We're actually holding the KeyChord instead of just the text.
// KeyChordText just serializes the relevant keychord
Microsoft.Terminal.Control.KeyChord Keys;
String KeyChordText;
// The action itself.
ActionAndArgs ActionAndArgs;
// NOTE: nested and iterable command logic will still be here,
// But they are omitted to make this section seem cleaner.
// Future Considerations:
// - [#6899]: Action IDs --> add an identifier here
}
```
The goal here is to consolidate key binding actions and command palette actions into a single class.
This will also require the following supplemental changes:
- `Command::LayerJson`
- This must combine the logic of `KeyMapping::LayerJson` and `Command::LayerJson`.
- Key Chord data
- Internally, store a `vector<KeyChord> _keyMappings` to keep track of all the key chords associated with this action.
- `RegisterKey` and `EraseKey` update `_keyMappings`, and ensure that the latest key registered is at the end of the list.
- `Keys()` simply returns the last entry of `_keyMappings`, which is the latest key chord this action is bound to.
- `KeyChordText())` is exposed to pass the text directly to the command palette.
This depends on `Keys` and, thus, propagate changes automatically.
- Observable properties
- `Command` has observable properties today, but does not need them because `Command` will never change while the app is running.
- Nested and iterable commands
- `HasNestedCommands`, `NestedCommands{ get; }`, `IterateOn` will continue to be exposed.
- A setter for these customizations will not be exposed until we find it necessary (i.e. adding support for customizing it in the Settings UI)
- Command expansion can continue to be exposed here to reduce implementation cost.
- An additional `IsNestedCommand` is necessary to record a case where a nested command is being unbound `{ "commands": null, "name": "foo" }`.
Overall, the `Command` class is simply being promoted to include the `KeyChord` it has.
This allows the implementation cost of this step to be relatively small.
Completion of this step should only cause relatively minor changes to anything that depends on `Command`, because
it is largely the same class. However, key bindings will largely be impacted because we represent key bindings as
a map of `KeyChord`s to `ActionAndArgs`. This leads us to step 2 of this process.
### Step 2: Querying actions
Key bindings and commands are deserialized by basically storing individual actions to a map.
- `KeyMapping` is basically an `IMap<KeyChord, ActionAndArgs>` with a few extra functions. In fact, it actually
stores key binding data to a `std::map<KeyChord, ActionAndArgs>` and directly interacts with it.
- `Command::LayerJson` populates an `IMap<String, Command>` during deserialization as it iterates over every action.
Note that `Command` can be interpreted as a wrapper for `ActionAndArgs` with more stuff here.
It makes sense to store these actions as maps. So, following step 1 above, we can also store and expose actions
something like the following:
```c++
runtimeclass ActionMap
{
ActionAndArgs GetActionByKeyChord(KeyChord keys);
KeyChord GetKeyBindingForAction(ShortcutAction action);
KeyChord GetKeyBindingForAction(ShortcutAction action, IActionArgs actionArgs);
IMapView<String, Command> NameMap { get; };
// Future Considerations:
// - [#6899]: Action IDs --> GetActionByID()
}
```
The getters will return null if a matching action or key chord is not found. Since iterable commands need to be expanded at in TerminalApp, we'll just expose `NameMap`, then let TerminalApp perform the expansion as they do now. Internally, we can store the actions as follows:
```c++
std::map<KeyChord, InternalActionID> _KeyMap;
std::map<InternalActionID, Command> _ActionMap;
```
`InternalActionID` will be a hash of `ActionAndArgs` such that two `ActionAndArgs` with the same `ShortcutAction` and `IActionArgs` output the same hash value.
`GetActionByKeyChord` will use `_KeyMap` to find the `InternalActionID`, then use the `_ActionMap` to find the bound `Command`.
`GetKeyBindingForAction` will hash the provided `ActionAndArgs` (constructed by the given parameters) and check `_ActionMap` for the given `InternalActionID`.
`NameMap` will need to ensure every action in `_ActionMap` is added to the output name map if it has an associated name. This is done by simply iterating over `_ActionMap`. Nested commands must be added separately because they cannot be hashed.
`ActionMap` will have an `AddAction(Command cmd)` that will update the internal state whenever a command is registered. If the given command is valid, we will check for collisions and resolve them. Otherwise, we will consider this an "unbound" action and update the internal state normally. It is important that we don't handle "unbound" actions differently because this ensures that we are explicitly unbinding a key chord.
### Step 3: Settings UI needs
After the former two steps are completed, the new representation of actions in the settings model is now on-par with
what we have today. In order to bind these new actions to the Settings UI, we need the following:
1. Exposing the maps
- `ActionMap::KeyBindings` and `ActionMap::Commands` may need to be added to pass the full list of actions to the Settings UI.
- In doing this, we can already update the Settings UI to include a better view of our actions.
2. Creating a copy of the settings model
- The Settings UI operates by binding the XAML controls to a copy of the settings model.
- Copying the `ActionMap` is fairly simple. Just copy the internal state and ensure that `Command::Copy` is called such that no reference to the original WinRT objects persist. Since we are using `InternalActionID`, we will not have to worry about multiple `Command` references existing within the same `ActionMap`.
3. Modifying the `Command`s
- `ActionMap` must be responsible for changing `Command`s so that we can ensure `ActionMap` always has a correct internal state:
- It is important that `Command` only exposes getters (not setters) to ensure `ActionMap` is up to date.
- If a key chord is being changed, update the `_KeyMap` and the `Command` itself.
- If a key binding is being deleted, add an unbound action to the given key chord.
- This is similar to how color schemes are maintained today.
- In the event that name/key-chord is set to something that's already taken, we need to propagate those changes to
the rest of `ActionMap`. As we do with the JSON, we respect the last name/key-chord set by the user. See [Modifying Actions](#modifying-actions)
in potential issues.
- For the purposes of the key bindings page, we will introduce a `KeyBindingViewModel` to serve as an intermediator between the settings UI and the settings model. The view model will be responsible for things like...
- exposing relevant information to the UI controls
- converting UI control interactions into proper API calls to the settings model
4. Serialization
- `Command::ToJson()` and `ActionMap::ToJson()` should perform most of the work for us. Simply iterate over the `_ActionMap` and call `Command::ToJson` on each action.
- See [Unbinding actions](#unbinding-actions) in potential issues.
## UI/UX Design
N/A
## Capabilities
N/A
### Accessibility
N/A
### Security
N/A
### Reliability
N/A
### Compatibility
N/A
### Performance, Power, and Efficiency
## Potential Issues
### Layering Actions
We need a way to determine where an action came from to minimize how many actions we serialize when we
write to disk. This is a two part approach that happens as we're loading the settings
1. Load defaults.json
- For each of the actions in the JSON...
- Construct the `Command` (basically the `Command::LayerJson` we have today)
- Add it to the `ActionMap`
- this should update the internal state of `ActionMap` appropriately
- if the newly added key chord conflicts with a pre-existing one,
redirect `_KeyMap` to the newly added `Command` instead,
and update the conflicting one.
2. Load settings.json
- Create a child for the `ActionMap`
- The purpose of a parent is to continue a search when the current `ActionMap` can't find a `Command` for a query. The parent is intended to be immutable.
- Load the actions array like normal into the child (see step 1)
Introducing a parent mechanism to `ActionMap` allows it to understand where a `Command` came from. This allows us to minimize the number of actions we serialize when we write to disk, as opposed to serializing the entire list of actions.
`ActionMap` queries will need to check their parent when they cannot find a matching `InternalActionID` in their `_ActionMap`.
Since `NameMap` is generated upon request, we will need to use a `std::set<InternalActionID>` as we generate the `NameMap`. This will ensure that each `Command` is only added to the `NameMap` once. The name map will be generated as follows:
1. Get an accumulated list of `Command`s from our parents
2. Iterate over the list...
- Update `NameMap` with any new `Command`s (tracked by the `std::set<InternalActionID>`)
Nested commands will be saved to their own map since they do not have an `InternalActionID`.
- During `ActionMap`'s population, we must ensure to resolve any conflicts immediately. This means that any new `Command`s that generate a name conflicting with a nested command will take priority (and we'll remove the nested command from its own map). Conversely, if a new nested command conflicts with an existing standard `Command`, we can ignore it because our generation of `NameMap` will handle it.
- When populating `NameMap`, we must first add all of the standard `Command`s. To ensure layering is accomplished correctly, we will need to start from the top-most parent and update `NameMap`. As we go down the inheritance tree, any conflicts are resolved by prioritizing the current layer (the child). This ensures that the current layer takes priority.
- After adding all of the standard `Command`s to the `NameMap`, we can then register all of the nested commands. Since nested commands have no identifier other than a name, we cannot use the `InternalActionID` heuristic. However, as mentioned earlier, we are updating our internal nested command map as we add new actions. So when we are generating the name map, we can assume that all of these nested commands now have priority. Thus, we simply add all of these nested commands to the name map. Any conflicts are resolved in favor of th nested command.
### Modifying Actions
There are several ways a command can be modified:
- change/remove the key chord
- change the name
- change the icon
- change the action
It is important that these modifications are done through `ActionMap` instead of `Command`.
This is to ensure that the `ActionMap` is always aligned with `Command`'s values. `Command` should only expose getters in the projected type to enforce this. Thus, we can add the following functions to `ActionMap`:
```c++
runtimeclass ActionMap
{
void SetKeyChord(Command cmd, KeyChord keys);
void SetName(Command cmd, String name);
void SetIcon(Command cmd, String iconPath);
void SetAction(Command cmd, ShortcutAction action, IActionArgs actionArgs);
}
```
`SetKeyChord` will need to make sure to modify the `_KeyMap` and the provided `Command`.
If the new key chord was already taken, we also need to update the conflicting `Command`
and remove its key chord.
`SetName` will need to make sure to modify the `Command` in `_ActionMap` and regenerate `NameMap`.
`SetIcon` will only need to modify the provided `Command`. We can choose to not expose this in the `ActionMap`, but doing so makes the API consistent.
`SetAction` will need to begin by updating the provided `Command`'s `ActionAndArgs`.
If the generated name is being used, the name will need to be updated. `_ActionMap` will need to be updated with a new `InternalActionID` for the new action. This is a major operation and so all views exposed will need to be regenerated.
Regarding [Layering Actions](#layering-actions), if the `Command` does not exist in the current layer,
but exists in a parent layer, we need to...
0. check if it exists
- use the hash `InternalActionID` to see if it exists in the current layer
- if it doesn't (which is the case we're trying to solve here), call `_GetActionByID(InternalActionID)` to retrieve the `Command` wherever it may be. This helper function simply checks the current layer, if none is found, it recursively checks its parents until a match is found.
1. duplicate it with `Command::Copy`
2. store the duplicate in the current layer
- `ActionMap::AddAction(duplicate)`
3. make the modification to the duplicate
This ensures that the change persists post-serialization.
TerminalApp has no reason to ever call these setters. To ensure that relationship, we will introduce an `IActionMapView` interface that will only expose `ActionMap` query functions. Conversely, `ActionMap` will be exposed to the TerminalSettingsEditor to allow for modifications.
### Unbinding actions
Removing a name is currently omitted from this spec because there
is no Settings UI use case for it at the moment. This scenario is
designed for Command Palette customization.
The only kind of unbinding currently in scope is freeing a key chord such that
no action is executed on that key stroke. To do this, simply `ActionMap::AddAction` a `Command` with...
- `ActionAndArgs`: `ShortcutAction = Invalid` and `IActionArgs = nullptr`
- `Keys` being the provided key chord
In explicitly storing an "unbound" action, we are explicitly saying that this key chord
must be passed through and this string must be removed from the command palette. `AddAction` automatically handles updating the internal state of `ActionMap` and any conflicting `Commands`.
This allows us to output something like this in the JSON:
```js
{ "command": "unbound", "keys": "ctrl+c" }
```
### Consolidated Actions
`AddAction` must be a bit smarter when it comes to the following scenario:
- Given a command that unbinds a key chord: `{ "command": "unbound", "keys": "ctrl+c" }`
- And... that key chord was set in a parent layer `{ "command": "copy", "keys": "ctrl+c" }`
- But... the action has another key chord from a parent layer `{ "command": "copy", "keys": "ctrl+shift+c" }`
`_ActionMap` does not contain any information about a parent layer; it only contains actions introduced in the current layer. Thus, in the scenario above, unbinding `ctrl+c` is what is relevant to `_ActionMap`. However, this may cause some complications for `GetKeyChordForAction`. We cannot simply check our internal `_ActionMap`, because the primary key chord in the entry may be incorrect. Again, this is because `_ActionMap` is only aware of what was bound in the current layer.
To get around this issue, we've introduced `_ConsolidatedActions`. In a way, `_ConsolidatedActions` is similar to `_ActionMap`, except that it consolidates the `Command` data into one entry constructed across the current layer and the parent layers. Specifically, in the scenario above, `_ActionMap` will say that `copy` has no key chords. In fact, `_ActionMap` has no reason to have `copy` at all, because it was not introduced in this layer. Conversely, `_ConsolidatedActions` holds `copy` with a `ctrl+shift+c` binding, which is then returned to `GetKeyChordForAction`.
To maintain `_ConsolidatedActions`, any new action added to the Action Map must also update `_ConsolidatedActions`. It is especially important to handle and propagate collisions to `_ConsolidatedActions`.
When querying Action Map for an ID, we should always check in the following order:
- `_ConsolidatedActions`
- `_ActionMap`
- repeat this process for each parent
This is to ensure that we are returning the correct and wholistic view of a `Command` on a query. Rather than acquiring a `Command` constructed in this layer, we receive one that contains all of the data acquired across the entire Action Map and its parents.
## Future considerations
There are a number of ideas regarding actions that would be fairly trivial to implement given this refactor:
- [#6899]: Action IDs
- As actions grow to become more widespread within Windows Terminal (i.e. dropdown and jumplist integration),
a formal ID system would help users reference the same action throughout the app. With the internal
ID system introduced earlier, we would simply introduce a new
`std:map<string, InternalActionID> _ExternalIDMap` that is updated like the others, and add a `String ID`
property to `Action`.
- [#8100] Source Tracking
- Identifying where a setting came from can be very beneficial in the settings model and UI. For example,
profile settings now have an `OverrideSource` getter that describes what `Profile` object the setting
came from (i.e. base layer, profile generator, etc...). A similar system can be used for `Action` in
that we record if the action was last modified in defaults.json or settings.json.
- There seems to be no desire for action inheritance (i.e. inheriting the name/key-chord from the parent).
So this should be sufficient.
## Resources
[#885]: https://github.com/microsoft/terminal/issues/885
[#6899]: https://github.com/microsoft/terminal/issues/6899
[#8100]: https://github.com/microsoft/terminal/issues/8100
[#8767]: https://github.com/microsoft/terminal/issues/8767
Other references:
[Settings UI: Actions Page]: https://github.com/microsoft/terminal/issues/6900
[Settings UI: Actions Page Design]: https://github.com/microsoft/terminal/pulls/9427
[Action ID Spec]: https://github.com/microsoft/terminal/issues/7175

View File

@@ -27,8 +27,8 @@ Below is the schedule for when milestones will be included in release builds of
| 2020-11-30 | [1.5] in Windows Terminal Preview<br>[1.4] in Windows Terminal | [Windows Terminal Preview 1.5 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-5-release/) |
| 2021-01-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | [Windows Terminal Preview 1.6 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-6-release/) |
| 2021-03-01 | [1.7] in Windows Terminal Preview<br>[1.6] in Windows Terminal | [Windows Terminal Preview 1.7 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-7-release/) |
| 2021-04-30 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | |
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | |
| 2021-04-14 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | [Windows Terminal Preview 1.8 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-8-release/) |
| 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-31 | 1.10 in Windows Terminal Preview<br>[1.9] in Windows Terminal | |
| 2021-08-30 | 1.11 in Windows Terminal Preview<br>1.10 in Windows Terminal | |
| 2021-10-31 | 1.12 in Windows Terminal Preview<br>1.11 in Windows Terminal | |

View File

@@ -23,7 +23,8 @@
<ProjectGuid>{96274800-9574-423E-892A-909FBE2AC8BE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>EchoCon</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

View File

@@ -33,7 +33,7 @@ namespace GUIConsole.ConPTY
}
/// <summary>
/// Start the psuedoconsole and run the process as shown in
/// Start the pseudoconsole and run the process as shown in
/// https://docs.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session#creating-the-pseudoconsole
/// </summary>
/// <param name="command">the command to run, e.g. cmd.exe</param>

View File

@@ -41,7 +41,7 @@ namespace MiniTerm
}
/// <summary>
/// Start the psuedoconsole and run the process as shown in
/// Start the pseudoconsole and run the process as shown in
/// https://docs.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session#creating-the-pseudoconsole
/// </summary>
/// <param name="command">the command to run, e.g. cmd.exe</param>

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap uap3">
<Identity
Name="ScratchApplication"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="1.0.0.0" />
<Properties>
<DisplayName>Sample App</DisplayName>
<PublisherDisplayName>A Lone Developer</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="ms-resource:AppName"
Description="ms-resource:AppDescription"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile
Wide310x150Logo="Images\Wide310x150Logo.png"
Square71x71Logo="Images\SmallTile.png"
Square310x310Logo="Images\LargeTile.png"
ShortName="ms-resource:AppShortName">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo"/>
<uap:ShowOn Tile="wide310x150Logo"/>
<uap:ShowOn Tile="square310x310Logo"/>
</uap:ShowNameOnTiles>
</uap:DefaultTile>
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

View File

@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\wap-common.build.pre.props" />
<PropertyGroup Label="Configuration">
<!--
These two properties are very important!
Without them, msbuild will stomp MinVersion and MaxVersionTested in the
Package.appxmanifest and replace them with whatever our values for
TargetPlatformMinVersion and TargetPlatformVersion are.
-->
<AppxOSMinVersionReplaceManifestVersion>false</AppxOSMinVersionReplaceManifestVersion>
<AppxOSMaxVersionTestedReplaceManifestVersion>false</AppxOSMaxVersionTestedReplaceManifestVersion>
</PropertyGroup>
<PropertyGroup>
<ProjectGuid>cf31505e-3bae-4c0a-81d7-f1eb279f40bb</ProjectGuid>
<EntryPointProjectUniqueName>..\WindowExe\WindowExe.vcxproj</EntryPointProjectUniqueName>
<DebuggerType>NativeOnly</DebuggerType>
</PropertyGroup>
<PropertyGroup Condition="!Exists('Package_TemporaryKey.pfx')">
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
<AppxBundle>Never</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="Exists('Package_TemporaryKey.pfx')">
<AppxPackageSigningEnabled>true</AppxPackageSigningEnabled>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<PackageCertificateKeyFile>Package_TemporaryKey.pfx</PackageCertificateKeyFile>
</PropertyGroup>
<ItemGroup Condition="Exists('Package_TemporaryKey.pfx')">
<None Include="Package_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<!-- Resources -->
<!-- This resw only defines things that are used in this package's AppxManifest,
so it's not in the common resource items. -->
<PRIResource Include="Resources\en-US\Resources.resw" />
<PRIResource Include="Resources\Resources.resw" />
<OCResourceDirectory Include="Resources" />
</ItemGroup>
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
<ItemGroup>
<ProjectReference Include="..\WindowExe\WindowExe.vcxproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<Implementation>$(OpenConsoleCommonOutDir)TerminalConnection\TerminalConnection.dll</Implementation>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Control">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd</HintPath>
<Implementation>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.dll</Implementation>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">
<ItemGroup>
<!-- Stomp all "SourceProject" values for all incoming dependencies to flatten the package. -->
<_TemporaryFilteredWapProjOutput Include="@(_FilteredNonWapProjProjectOutput)" />
<_FilteredNonWapProjProjectOutput Remove="@(_TemporaryFilteredWapProjOutput)" />
<_FilteredNonWapProjProjectOutput Include="@(_TemporaryFilteredWapProjOutput)">
<!-- Blank the SourceProject here to vend all files into the root of the package. -->
<SourceProject>
</SourceProject>
</_FilteredNonWapProjProjectOutput>
</ItemGroup>
</Target>
<!-- Move all the PRI files that would be packaged into the appx into _PriFile so that
GenerateProjectPriFile catches them. This requires us to move payload collection
up before GenerateProjectPriFile, when it is typically _after_ it (because the
DesktopBridge project type is built to only prepare the payload during appx manifest
generation.
Since PRI file generation is _before_ manifest generation (for possibly obvious or
important reasons), that doesn't work for us.
-->
<PropertyGroup>
<!-- Only for MSBuild versions < 16.3.0 -->
<_GenerateProjectPriFileDependsOn Condition="$(MSBuildVersion) &lt; '16.3.0'">OpenConsoleLiftDesktopBridgePriFiles;$(_GenerateProjectPriFileDependsOn)</_GenerateProjectPriFileDependsOn>
</PropertyGroup>
<Target Name="OpenConsoleLiftDesktopBridgePriFiles" DependsOnTargets="_ConvertItems">
<ItemGroup>
<_PriFile Include="@(_NonWapProjProjectOutput)" Condition="'%(Extension)' == '.pri'" />
<!-- Remove all other .pri files from the appx payload. -->
<AppxPackagePayload Remove="@(AppxPackagePayload)" Condition="'%(Extension)' == '.pri'" />
</ItemGroup>
</Target>
<!-- VS 16.3.0 added a rule to the WAP packaging project that removes all non-WAP payload, which we were relying on to
roll up our subproject resources. We have to suppress that rule but keep part of its logic, because that rule is
where the AppxPackagePayload items are created. -->
<PropertyGroup>
<WapProjBeforeGenerateAppxManifestDependsOn>
$([MSBuild]::Unescape('$(WapProjBeforeGenerateAppxManifestDependsOn.Replace('_RemoveAllNonWapUWPItems', '_OpenConsoleRemoveAllNonWapUWPItems'))'))
</WapProjBeforeGenerateAppxManifestDependsOn>
</PropertyGroup>
<Target Name="_OpenConsoleRemoveAllNonWapUWPItems">
<ItemGroup>
<AppxPackagePayload Include="@(WapProjPackageFile)" />
<AppxUploadPackagePayload Include="@(UploadWapProjPackageFile)" />
<!-- 16.3.0 - remove non-resources.pri PRI files since we just forced them back in. -->
<AppxPackagePayload Remove="@(AppxPackagePayload)" Condition="'%(Extension)' == '.pri' and '%(Filename)' != 'resources'" />
<AppxUploadPackagePayload Remove="@(AppxUploadPackagePayload)" Condition="'%(Extension)' == '.pri' and '%(Filename)' != 'resources'" />
</ItemGroup>
</Target>
<!-- **BEGIN VC LIBS HACK** -->
<!--
For our release builds, we're just going to integrate the UWPDesktop CRT into our package and delete the package dependencies.
It's very difficult for users who do not have access to the store to get our dependency packages, and we want to be robust
and deployable everywhere. Since these libraries can be redistributed, it's easiest if we simply redistribute them.
See also the "VC LIBS HACK" section in WindowsTerminal.vcxproj.
-->
<!-- This target removes the FrameworkSdkReferences from before the AppX package targets manifest generation happens.
This is part of the generic machinery that applies to every AppX. -->
<Target Name="_OpenConsoleStripAllDependenciesFromPackageFirstManifest" BeforeTargets="_GenerateCurrentProjectAppxManifest">
<ItemGroup Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
<FrameworkSdkReference Remove="@(FrameworkSdkReference)" />
</ItemGroup>
</Target>
<!-- This target removes the FrameworkSdkPackages from before the *desktop bridge* manifest generation happens. -->
<Target Name="_OpenConsoleStripAllDependenciesFromPackageSecondManifest" BeforeTargets="_GenerateDesktopBridgeAppxManifest" DependsOnTargets="_ResolveVCLibDependencies">
<ItemGroup Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
<FrameworkSdkPackage Remove="@(FrameworkSdkPackage)" />
</ItemGroup>
</Target>
<!-- **END VC LIBS HACK** -->
<!-- This is required to get the package dependency in the AppXManifest. -->
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>

View File

@@ -0,0 +1,126 @@
<?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>Scratch XAML Island App</value>
</data>
<data name="AppShortName" xml:space="preserve">
<value>Scratch App</value>
</data>
</root>

View File

@@ -0,0 +1,123 @@
<?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="AppDescription" xml:space="preserve">
<value>A scratch app for XAML Islands tests</value>
</data>
</root>

View File

@@ -0,0 +1,32 @@
#pragma once
namespace winrt::SampleApp::implementation
{
template<typename D, typename... I>
struct App_baseWithProvider : public App_base<D, ::winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider>
{
using IXamlType = ::winrt::Windows::UI::Xaml::Markup::IXamlType;
IXamlType GetXamlType(::winrt::Windows::UI::Xaml::Interop::TypeName const& type)
{
return _appProvider.GetXamlType(type);
}
IXamlType GetXamlType(::winrt::hstring const& fullName)
{
return _appProvider.GetXamlType(fullName);
}
::winrt::com_array<::winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions()
{
return _appProvider.GetXmlnsDefinitions();
}
private:
bool _contentLoaded{ false };
winrt::SampleApp::XamlMetaDataProvider _appProvider;
};
template<typename D, typename... I>
using AppT2 = App_baseWithProvider<D, I...>;
}

View File

@@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "App.h"
#include "App.g.cpp"
using namespace winrt;
using namespace winrt::Windows::ApplicationModel::Activation;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Navigation;
namespace winrt::SampleApp::implementation
{
App::App()
{
// This is the same trick that Initialize() is about to use to figure out whether we're coming
// from a UWP context or from a Win32 context
// See https://github.com/windows-toolkit/Microsoft.Toolkit.Win32/blob/52611c57d89554f357f281d0c79036426a7d9257/Microsoft.Toolkit.Win32.UI.XamlApplication/XamlApplication.cpp#L42
const auto dispatcherQueue = ::winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
if (dispatcherQueue)
{
_isUwp = true;
}
Initialize();
// Disable XAML's automatic backplating of text when in High Contrast
// mode: we want full control of and responsibility for the foreground
// and background colors that we draw in XAML.
HighContrastAdjustment(::winrt::Windows::UI::Xaml::ApplicationHighContrastAdjustment::None);
}
SampleAppLogic App::Logic()
{
static SampleAppLogic logic;
return logic;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
void App::OnLaunched(LaunchActivatedEventArgs const& /*e*/)
{
// if this is a UWP... it means its our problem to hook up the content to the window here.
if (_isUwp)
{
auto content = Window::Current().Content();
if (content == nullptr)
{
auto logic = Logic();
logic.Create();
auto page = logic.GetRoot().as<MyPage>();
Window::Current().Content(page);
Window::Current().Activate();
}
}
}
}

View File

@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "App.g.h"
#include "App.base.h"
namespace winrt::SampleApp::implementation
{
struct App : AppT2<App>
{
public:
App();
void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&);
SampleApp::SampleAppLogic Logic();
private:
bool _isUwp = false;
};
}
namespace winrt::SampleApp::factory_implementation
{
struct App : AppT<App, implementation::App>
{
};
}

View File

@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "SampleAppLogic.idl";
namespace SampleApp
{
// ADD ARBITRARY APP LOGIC TO SampleAppLogic.idl, NOT HERE.
// This is for XAML platform setup only.
[default_interface] runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
{
App();
SampleAppLogic Logic { get; };
}
}

View File

@@ -0,0 +1,71 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Toolkit:XamlApplication x:Class="SampleApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TA="using:SampleApp"
xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:SampleApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<!--
If you want to prove this works, then add `RequestedTheme="Light"` to
the properties on the XamlApplication
-->
<Toolkit:XamlApplication.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Include the MUX Controls resources -->
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<ResourceDictionary>
<!--
We're going to apply this style to the root Grid acting
as the tab row, because we need to be able to set its
`Background` property to "{ThemeResource
ApplicationPageBackgroundThemeBrush}" so it will be colored
appropriately for the theme, regardless of what we set the
RequestedTheme to
-->
<Style x:Name="BackgroundGridThemeStyle"
TargetType="Grid">
<Setter Property="Background" Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
</Style>
<!--
We need to manually create the error text brush as a
theme-dependent brush. SystemControlErrorTextForegroundBrush
is unfortunately static.
-->
<SolidColorBrush x:Name="ErrorTextBrush"
Color="{ThemeResource SystemErrorTextColor}" />
<!-- Suppress top padding -->
<Thickness x:Key="TabViewHeaderPadding">8,0,8,0</Thickness>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<!-- Define resources for Dark mode here -->
<SolidColorBrush x:Key="TabViewBackground"
Color="#FF333333" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<!-- Define resources for Light mode here -->
<SolidColorBrush x:Key="TabViewBackground"
Color="#FFCCCCCC" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Toolkit:XamlApplication.Resources>
</Toolkit:XamlApplication>

View File

@@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "MyPage.h"
#include <LibraryResources.h>
#include "MyPage.g.cpp"
#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
using namespace std::chrono_literals;
using namespace winrt::Microsoft::Terminal;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
namespace WUX = Windows::UI::Xaml;
using IInspectable = Windows::Foundation::IInspectable;
}
namespace winrt::SampleApp::implementation
{
MyPage::MyPage()
{
InitializeComponent();
}
void MyPage::Create()
{
TerminalConnection::EchoConnection conn{};
auto settings = winrt::make_self<ControlUnitTests::MockControlSettings>();
Control::TermControl control{ *settings, conn };
InProcContent().Children().Append(control);
// Once the control loads (and not before that), write some text for debugging:
control.Initialized([conn](auto&&, auto&&) {
conn.WriteInput(L"This TermControl is hosted in-proc...");
});
}
// Method Description:
// - Gets the title of the currently focused terminal control. If there
// isn't a control selected for any reason, returns "Windows Terminal"
// Arguments:
// - <none>
// Return Value:
// - the title of the focused control if there is one, else "Windows Terminal"
hstring MyPage::Title()
{
return { L"Sample Application" };
}
}

View File

@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "MyPage.g.h"
#include "../../../src/cascadia/inc/cppwinrt_utils.h"
namespace winrt::SampleApp::implementation
{
struct MyPage : MyPageT<MyPage>
{
public:
MyPage();
void Create();
hstring Title();
private:
friend struct MyPageT<MyPage>; // for Xaml to bind events
};
}
namespace winrt::SampleApp::factory_implementation
{
BASIC_FACTORY(MyPage);
}

View File

@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace SampleApp
{
[default_interface] runtimeclass MyPage : Windows.UI.Xaml.Controls.Page
{
MyPage();
}
}

View File

@@ -0,0 +1,56 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Page x:Class="SampleApp.MyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:SampleApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
xmlns:terminal="using:Microsoft.Terminal.Control"
mc:Ignorable="d">
<Grid x:Name="Root"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button x:Name="TabRow"
Grid.Row="0">
&quot;Tabs&quot;
</Button>
<Grid x:Name="TabContent"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid x:Name="InProcContent"
Grid.Column="0"
Padding="16"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#ff0000" />
<Grid x:Name="OutOfProcContent"
Grid.Column="1"
Padding="16"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#0000ff" />
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "MySettings.h"
#include "MySettings.g.cpp"
namespace winrt::SampleApp::implementation
{
}

View File

@@ -0,0 +1,97 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
--*/
#pragma once
#include "../../inc/cppwinrt_utils.h"
#include <DefaultSettings.h>
#include <conattrs.hpp>
#include "MySettings.g.h"
namespace winrt::SampleApp::implementation
{
struct MySettings : MySettingsT<MySettings>
{
public:
MySettings() = default;
// --------------------------- Core Settings ---------------------------
// All of these settings are defined in ICoreSettings.
WINRT_PROPERTY(til::color, DefaultForeground, DEFAULT_FOREGROUND);
WINRT_PROPERTY(til::color, DefaultBackground, DEFAULT_BACKGROUND);
WINRT_PROPERTY(til::color, SelectionBackground, DEFAULT_FOREGROUND);
WINRT_PROPERTY(int32_t, HistorySize, DEFAULT_HISTORY_SIZE);
WINRT_PROPERTY(int32_t, InitialRows, 30);
WINRT_PROPERTY(int32_t, InitialCols, 80);
WINRT_PROPERTY(bool, SnapOnInput, true);
WINRT_PROPERTY(bool, AltGrAliasing, true);
WINRT_PROPERTY(til::color, CursorColor, DEFAULT_CURSOR_COLOR);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Core::CursorStyle, CursorShape, winrt::Microsoft::Terminal::Core::CursorStyle::Vintage);
WINRT_PROPERTY(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
WINRT_PROPERTY(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
WINRT_PROPERTY(bool, CopyOnSelect, false);
WINRT_PROPERTY(bool, InputServiceWarning, true);
WINRT_PROPERTY(bool, FocusFollowMouse, false);
WINRT_PROPERTY(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, TabColor, nullptr);
WINRT_PROPERTY(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, StartingTabColor, nullptr);
winrt::Microsoft::Terminal::Core::ICoreAppearance UnfocusedAppearance() { return {}; };
WINRT_PROPERTY(bool, TrimBlockSelection, false);
// ------------------------ End of Core Settings -----------------------
WINRT_PROPERTY(winrt::hstring, ProfileName);
WINRT_PROPERTY(bool, UseAcrylic, false);
WINRT_PROPERTY(double, TintOpacity, 0.5);
WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
WINRT_PROPERTY(winrt::hstring, FontFace, L"Consolas");
WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE);
WINRT_PROPERTY(winrt::Windows::UI::Text::FontWeight, FontWeight);
WINRT_PROPERTY(winrt::hstring, BackgroundImage);
WINRT_PROPERTY(double, BackgroundImageOpacity, 1.0);
WINRT_PROPERTY(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill);
WINRT_PROPERTY(winrt::Windows::UI::Xaml::HorizontalAlignment, BackgroundImageHorizontalAlignment, winrt::Windows::UI::Xaml::HorizontalAlignment::Center);
WINRT_PROPERTY(winrt::Windows::UI::Xaml::VerticalAlignment, BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::IKeyBindings, KeyBindings, nullptr);
WINRT_PROPERTY(winrt::hstring, Commandline);
WINRT_PROPERTY(winrt::hstring, StartingDirectory);
WINRT_PROPERTY(winrt::hstring, StartingTitle);
WINRT_PROPERTY(bool, SuppressApplicationTitle);
WINRT_PROPERTY(winrt::hstring, EnvironmentVariables);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
WINRT_PROPERTY(bool, RetroTerminalEffect, false);
WINRT_PROPERTY(bool, ForceFullRepaintRendering, false);
WINRT_PROPERTY(bool, SoftwareRendering, false);
WINRT_PROPERTY(bool, ForceVTInput, false);
WINRT_PROPERTY(winrt::hstring, PixelShaderPath);
WINRT_PROPERTY(bool, DetectURLs, true);
private:
std::array<winrt::Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE> _ColorTable;
public:
winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept { return _ColorTable.at(index); }
std::array<winrt::Microsoft::Terminal::Core::Color, 16> ColorTable() { return _ColorTable; }
void ColorTable(std::array<winrt::Microsoft::Terminal::Core::Color, 16> /*colors*/) {}
};
}
namespace winrt::SampleApp::factory_implementation
{
BASIC_FACTORY(MySettings);
}

View File

@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace SampleApp
{
[default_interface] runtimeclass MySettings : Microsoft.Terminal.Core.ICoreSettings,
Microsoft.Terminal.Control.IControlSettings,
Microsoft.Terminal.Core.ICoreAppearance,
Microsoft.Terminal.Control.IControlAppearance
{
MySettings();
}
}

View File

@@ -0,0 +1,120 @@
<?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>
</root>

View File

@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{a4394404-37f7-41c1-802b-49788d3720e3}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>SampleApp</RootNamespace>
<ProjectName>SampleAppLib</ProjectName>
<TargetName>SampleAppLib</TargetName>
<ConfigurationType>StaticLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
<!--
This is an override that, puzzlingly, _forces XBF (XAML binary) embedding_.
We have to do this to overcome a layout issue in the WAP packaging project.
When we do this, the XBF ends up in resources.pri.
-->
<DisableEmbeddedXbf>false</DisableEmbeddedXbf>
<XamlComponentResourceLocation>nested</XamlComponentResourceLocation>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<ItemDefinitionGroup>
<ClCompile>
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
on being compiled with RTTI (/GR). -->
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
</ItemDefinitionGroup>
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- HERE BE DRAGONS:
For any types that use XAML information, if their .idl and .h aren't
marked DependentUpon the corresponding .xaml file, XamlTypeInfo.g.h won't
pick it up correctly. -->
<ApplicationDefinition Include="App.xaml">
<SubType>Designer</SubType>
</ApplicationDefinition>
</ItemGroup>
<!-- When we add other user controls, they should go in here as so: -->
<ItemGroup>
<Page Include="MyPage.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="App.base.h" />
<ClInclude Include="MySettings.h" />
<ClInclude Include="MyPage.h">
<DependentUpon>MyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="App.h">
<DependentUpon>App.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="SampleAppLogic.h">
<DependentUpon>SampleAppLogic.idl</DependentUpon>
</ClInclude>
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<ClCompile Include="init.cpp" />
<ClCompile Include="MySettings.cpp" />
<ClCompile Include="MyPage.cpp">
<DependentUpon>MyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="App.cpp">
<DependentUpon>App.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="SampleAppLogic.cpp">
<DependentUpon>SampleAppLogic.idl</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<!-- If you add idl files here, make sure to include their implementation's
header in SampleApp.vcxproj (as well as in this file) -->
<Midl Include="App.idl">
<DependentUpon>App.xaml</DependentUpon>
</Midl>
<Midl Include="SampleAppLogic.idl" />
<Midl Include="MySettings.idl" />
<Midl Include="MyPage.idl">
<DependentUpon>MyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<PRIResource Include="Resources\en-US\Resources.resw" />
<OCResourceDirectory Include="Resources" />
<None Include="packages.config" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See
https://github.com/Microsoft/msbuild/issues/3746 - it looks like MsBuild
just has a bug in it.-->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>Warning</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
<!-- ========================== Other References ========================= -->
<ItemGroup>
<!-- Manually add references to each of our dependent winmds. Mark them as
private=false and CopyLocalSatelliteAssemblies=false, so that we don't
propagate them upwards (which can make referencing this project result in
duplicate type definitions)-->
<Reference Include="Microsoft.Terminal.Core">
<HintPath>$(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Control">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>$(OpenConsoleCommonOutDir)\ConTypes.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<!-- ========================= Globals ======================== -->
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
<!--
By default, the PRI file will contain resource paths beginning with the
project name. Since we enabled XBF embedding, this *also* includes App.xbf.
Well, App.xbf is hardcoded by the framework to be found at the resource ROOT.
To make that happen, we have to disable the prepending of the project name
to the App xaml files.
-->
<PropertyGroup>
<_GenerateProjectPriFileDependsOn>OpenConsolePlaceAppXbfAtRootOfResourceTree;$(_GenerateProjectPriFileDependsOn)</_GenerateProjectPriFileDependsOn>
</PropertyGroup>
<Target Name="OpenConsolePlaceAppXbfAtRootOfResourceTree" DependsOnTargets="GetPackagingOutputs">
<ItemGroup>
<_RelocatedAppXamlData Include="@(PackagingOutputs)" Condition="'%(Filename)' == 'App' and ('%(Extension)' == '.xaml' or '%(Extension)' == '.xbf')" />
<PackagingOutputs Remove="@(_RelocatedAppXamlData)" />
<PackagingOutputs Include="@(_RelocatedAppXamlData)">
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>

View File

@@ -0,0 +1,84 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleAppLogic.h"
#include "SampleAppLogic.g.cpp"
#include <LibraryResources.h>
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::System;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
using IInspectable = Windows::Foundation::IInspectable;
}
namespace winrt::SampleApp::implementation
{
// Function Description:
// - Get the SampleAppLogic for the current active Xaml application, or null if there isn't one.
// Return value:
// - A pointer (bare) to the SampleAppLogic, or nullptr. The app logic outlives all other objects,
// unless the application is in a terrible way, so this is "safe."
SampleAppLogic* SampleAppLogic::Current() noexcept
try
{
if (auto currentXamlApp{ winrt::Windows::UI::Xaml::Application::Current().try_as<winrt::SampleApp::App>() })
{
if (auto SampleAppLogicPointer{ winrt::get_self<SampleAppLogic>(currentXamlApp.Logic()) })
{
return SampleAppLogicPointer;
}
}
return nullptr;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return nullptr;
}
SampleAppLogic::SampleAppLogic()
{
// For your own sanity, it's better to do setup outside the ctor.
// If you do any setup in the ctor that ends up throwing an exception,
// then it might look like App just failed to activate, which will
// cause you to chase down the rabbit hole of "why is App not
// registered?" when it definitely is.
// The MyPage has to be constructed during our construction, to
// make sure that there's a terminal page for callers of
// SetTitleBarContent
_root = winrt::make_self<MyPage>();
}
// Method Description:
// - Build the UI for the terminal app. Before this method is called, it
// should not be assumed that the SampleApp is usable. The Settings
// should be loaded before this is called, either with LoadSettings or
// GetLaunchDimensions (which will call LoadSettings)
// Arguments:
// - <none>
// Return Value:
// - <none>
void SampleAppLogic::Create()
{
_root->Create();
}
UIElement SampleAppLogic::GetRoot() noexcept
{
return _root.as<winrt::Windows::UI::Xaml::Controls::Control>();
}
hstring SampleAppLogic::Title()
{
return _root->Title();
}
}

View File

@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "SampleAppLogic.g.h"
#include "MyPage.h"
#include "../../../src/cascadia/inc/cppwinrt_utils.h"
namespace winrt::SampleApp::implementation
{
struct SampleAppLogic : SampleAppLogicT<SampleAppLogic>
{
public:
static SampleAppLogic* Current() noexcept;
SampleAppLogic();
~SampleAppLogic() = default;
void Create();
Windows::UI::Xaml::UIElement GetRoot() noexcept;
winrt::hstring Title();
private:
// If you add controls here, but forget to null them either here or in
// the ctor, you're going to have a bad time. It'll mysteriously fail to
// activate the SampleAppLogic.
// ALSO: If you add any UIElements as roots here, make sure they're
// updated in _ApplyTheme. The root currently is _root.
winrt::com_ptr<MyPage> _root{ nullptr };
};
}
namespace winrt::SampleApp::factory_implementation
{
struct SampleAppLogic : SampleAppLogicT<SampleAppLogic, implementation::SampleAppLogic>
{
};
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace SampleApp
{
[default_interface] runtimeclass SampleAppLogic
{
SampleAppLogic();
void Create();
Windows.UI.Xaml.UIElement GetRoot();
String Title { get; };
}
}

View File

@@ -0,0 +1,3 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{26c51792-41a3-4fe0-ab5e-8b69d557bf91}</ProjectGuid>
<ProjectName>SampleApp</ProjectName>
<RootNamespace>SampleApp</RootNamespace>
<!-- cppwinrt.build.pre.props depends on these settings: -->
<!-- build a dll, not exe (Application) -->
<ConfigurationType>DynamicLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<!-- sets a bunch of Windows Universal properties -->
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- DON'T PUT XAML FILES HERE! Put them in SampleAppLib.vcxproj -->
</ItemGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<!-- Only put headers for winrt types in here. Don't put other header files
in here - put them in SampleAppLib.vcxproj instead! -->
<ClInclude Include="pch.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<!-- Don't put source files in here - put them in SampleAppLib.vcxproj instead! -->
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<!-- DON'T PUT IDL FILES HERE! Put them in App.vcxproj -->
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<None Include="$(ProjectName).def" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<!-- Reference SampleAppLib here, so we can use it's App.winmd as
our App.winmd. This didn't work correctly in VS2017, you'd need to
manually reference the lib -->
<ProjectReference Include="$(OpenConsoleDir)scratch\ScratchIslandApp\SampleApp\SampleAppLib.vcxproj">
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<!-- Manually include the Terminal.Core winmd, so we know where those types
are defined. We don't want to include it as a project reference, because
that would make us link that lib into our own binary. -->
<Reference Include="Microsoft.Terminal.Core">
<HintPath>$(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Control">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!-- SampleAppLib contains a DllMain that we need to force the use of. -->
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
</Project>

View File

@@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// pch.h
// Header for platform projection include files
//
#pragma once
// This file can be empty - the pch.h in SampleApp/lib does the heavy lifting
// of including all the headers we need. As this project is just a dll wrapper,
// we don't actually need anything in here.

View File

@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation
// Licensed under the MIT license.
#include "pch.h"
#include <LibraryResources.h>
#include <WilErrorReporting.h>
BOOL WINAPI DllMain(HINSTANCE /*hInstDll*/, DWORD /*reason*/, LPVOID /*reserved*/)
{
return TRUE;
}
UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"SampleApp/Resources")

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
</packages>

View File

@@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@@ -0,0 +1,71 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// pch.h
// Header for platform projection include files
//
#pragma once
#define WIN32_LEAN_AND_MEAN
#define NOMCX
#define NOHELP
#define NOCOMM
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#define BLOCK_TIL
#include <LibraryIncludes.h>
// This is inexplicable, but for whatever reason, cppwinrt conflicts with the
// SDK definition of this function, so the only fix is to undef it.
// from WinBase.h
// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
#include <wil/cppwinrt.h>
#include <unknwn.h>
#include <hstring.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.Metadata.h>
#include <winrt/Windows.Graphics.Display.h>
#include <winrt/windows.ui.core.h>
#include <winrt/Windows.ui.input.h>
#include <winrt/Windows.UI.Text.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
#include <winrt/Windows.UI.Xaml.Data.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/Windows.UI.Xaml.Media.Animation.h>
#include <winrt/Windows.ui.xaml.input.h>
#include <winrt/Windows.UI.Xaml.Hosting.h>
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.ViewManagement.h"
#include <winrt/Microsoft.Toolkit.Win32.UI.XamlHost.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
#include <winrt/Windows.System.h>
// Including TraceLogging essentials for the binary
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DECLARE_PROVIDER(g_hSampleAppProvider);
#include <telemetry/ProjectTelemetry.h>
#include <TraceLoggingActivity.h>
#include <shellapi.h>
#include <shobjidl_core.h>
#include <winrt/Microsoft.Terminal.Core.h>
#include <winrt/Microsoft.Terminal.Control.h>
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View File

@@ -0,0 +1,78 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleAppHost.h"
#include "../types/inc/Viewport.hpp"
#include "../types/inc/utils.hpp"
#include "../types/inc/User32Utils.hpp"
#include "resource.h"
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Hosting;
using namespace winrt::Windows::Foundation::Numerics;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Console::Types;
SampleAppHost::SampleAppHost() noexcept :
_app{},
_logic{ nullptr }, // don't make one, we're going to take a ref on app's
_window{ nullptr }
{
_logic = _app.Logic(); // get a ref to app's logic
_window = std::make_unique<SampleIslandWindow>();
_window->MakeWindow();
}
SampleAppHost::~SampleAppHost()
{
// destruction order is important for proper teardown here
_window = nullptr;
_app.Close();
_app = nullptr;
}
// Method Description:
// - Initializes the XAML island, creates the terminal app, and sets the
// island's content to that of the terminal app's content. Also registers some
// callbacks with TermApp.
// !!! IMPORTANT!!!
// This must be called *AFTER* WindowsXamlManager::InitializeForCurrentThread.
// If it isn't, then we won't be able to create the XAML island.
// Arguments:
// - <none>
// Return Value:
// - <none>
void SampleAppHost::Initialize()
{
_window->Initialize();
_logic.Create();
_window->UpdateTitle(_logic.Title());
// Set up the content of the application. If the app has a custom titlebar,
// set that content as well.
_window->SetContent(_logic.GetRoot());
_window->OnAppInitialized();
// THIS IS A HACK
//
// We've got a weird crash that happens terribly inconsistently, only in
// Debug mode. Apparently, there's some weird ref-counting magic that goes
// on during teardown, and our Application doesn't get closed quite right,
// which can cause us to crash into the debugger. This of course, only
// happens on exit, and happens somewhere in the XamlHost.dll code.
//
// Crazily, if we _manually leak the Application_ here, then the crash
// doesn't happen. This doesn't matter, because we really want the
// Application to live for _the entire lifetime of the process_, so the only
// time when this object would actually need to get cleaned up is _during
// exit_. So we can safely leak this Application object, and have it just
// get cleaned up normally when our process exits.
::winrt::SampleApp::App a{ _app };
::winrt::detach_abi(a);
}

View File

@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleIslandWindow.h"
class SampleAppHost
{
public:
SampleAppHost() noexcept;
virtual ~SampleAppHost();
void Initialize();
private:
std::unique_ptr<SampleIslandWindow> _window;
winrt::SampleApp::App _app;
winrt::SampleApp::SampleAppLogic _logic;
};

View File

@@ -0,0 +1,228 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
// Custom window messages
#define CM_UPDATE_TITLE (WM_USER)
#include <wil/resource.h>
template<typename T>
class BaseWindow
{
public:
virtual ~BaseWindow() = 0;
static T* GetThisFromHandle(HWND const window) noexcept
{
return reinterpret_cast<T*>(GetWindowLongPtr(window, GWLP_USERDATA));
}
[[nodiscard]] static LRESULT __stdcall WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
{
WINRT_ASSERT(window);
if (WM_NCCREATE == message)
{
auto cs = reinterpret_cast<CREATESTRUCT*>(lparam);
T* that = static_cast<T*>(cs->lpCreateParams);
WINRT_ASSERT(that);
WINRT_ASSERT(!that->_window);
that->_window = wil::unique_hwnd(window);
return that->_OnNcCreate(wparam, lparam);
}
else if (T* that = GetThisFromHandle(window))
{
return that->MessageHandler(message, wparam, lparam);
}
return DefWindowProc(window, message, wparam, lparam);
}
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
{
switch (message)
{
case WM_DPICHANGED:
{
return HandleDpiChange(_window.get(), wparam, lparam);
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_SIZE:
{
UINT width = LOWORD(lparam);
UINT height = HIWORD(lparam);
switch (wparam)
{
case SIZE_MAXIMIZED:
[[fallthrough]];
case SIZE_RESTORED:
if (_minimized)
{
_minimized = false;
OnRestore();
}
// We always need to fire the resize event, even when we're transitioning from minimized.
// We might be transitioning directly from minimized to maximized, and we'll need
// to trigger any size-related content changes.
OnResize(width, height);
break;
case SIZE_MINIMIZED:
if (!_minimized)
{
_minimized = true;
OnMinimize();
}
break;
default:
// do nothing.
break;
}
break;
}
case CM_UPDATE_TITLE:
{
SetWindowTextW(_window.get(), _title.c_str());
break;
}
}
return DefWindowProc(_window.get(), message, wparam, lparam);
}
// DPI Change handler. on WM_DPICHANGE resize the window
[[nodiscard]] LRESULT HandleDpiChange(const HWND hWnd, const WPARAM wParam, const LPARAM lParam)
{
_inDpiChange = true;
const HWND hWndStatic = GetWindow(hWnd, GW_CHILD);
if (hWndStatic != nullptr)
{
const UINT uDpi = HIWORD(wParam);
// Resize the window
auto lprcNewScale = reinterpret_cast<RECT*>(lParam);
SetWindowPos(hWnd, nullptr, lprcNewScale->left, lprcNewScale->top, lprcNewScale->right - lprcNewScale->left, lprcNewScale->bottom - lprcNewScale->top, SWP_NOZORDER | SWP_NOACTIVATE);
_currentDpi = uDpi;
}
_inDpiChange = false;
return 0;
}
virtual void OnResize(const UINT width, const UINT height) = 0;
virtual void OnMinimize() = 0;
virtual void OnRestore() = 0;
RECT GetWindowRect() const noexcept
{
RECT rc = { 0 };
::GetWindowRect(_window.get(), &rc);
return rc;
}
HWND GetHandle() const noexcept
{
return _window.get();
}
float GetCurrentDpiScale() const noexcept
{
const auto dpi = ::GetDpiForWindow(_window.get());
const auto scale = static_cast<float>(dpi) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
return scale;
}
// Gets the physical size of the client area of the HWND in _window
SIZE GetPhysicalSize() const noexcept
{
RECT rect = {};
GetClientRect(_window.get(), &rect);
const auto windowsWidth = rect.right - rect.left;
const auto windowsHeight = rect.bottom - rect.top;
return SIZE{ windowsWidth, windowsHeight };
}
// Gets the logical (in DIPs) size of a physical size specified by the parameter physicalSize
// Remarks:
// XAML coordinate system is always in Display Independent Pixels (a.k.a DIPs or Logical). However Win32 GDI (because of legacy reasons)
// in DPI mode "Per-Monitor and Per-Monitor (V2) DPI Awareness" is always in physical pixels.
// The formula to transform is:
// logical = (physical / dpi) + 0.5 // 0.5 is to ensure that we pixel snap correctly at the edges, this is necessary with odd DPIs like 1.25, 1.5, 1, .75
// See also:
// https://docs.microsoft.com/en-us/windows/desktop/LearnWin32/dpi-and-device-independent-pixels
// https://docs.microsoft.com/en-us/windows/desktop/hidpi/high-dpi-desktop-application-development-on-windows#per-monitor-and-per-monitor-v2-dpi-awareness
winrt::Windows::Foundation::Size GetLogicalSize(const SIZE physicalSize) const noexcept
{
const auto scale = GetCurrentDpiScale();
// 0.5 is to ensure that we pixel snap correctly at the edges, this is necessary with odd DPIs like 1.25, 1.5, 1, .75
const auto logicalWidth = (physicalSize.cx / scale) + 0.5f;
const auto logicalHeight = (physicalSize.cy / scale) + 0.5f;
return winrt::Windows::Foundation::Size(logicalWidth, logicalHeight);
}
winrt::Windows::Foundation::Size GetLogicalSize() const noexcept
{
return GetLogicalSize(GetPhysicalSize());
}
// Method Description:
// - Sends a message to our message loop to update the title of the window.
// Arguments:
// - newTitle: a string to use as the new title of the window.
// Return Value:
// - <none>
void UpdateTitle(std::wstring_view newTitle)
{
_title = newTitle;
PostMessageW(_window.get(), CM_UPDATE_TITLE, 0, reinterpret_cast<LPARAM>(nullptr));
}
// Method Description:
// Reset the current dpi of the window. This method is only called after we change the
// initial launch position. This makes sure the dpi is consistent with the monitor on which
// the window will launch
void RefreshCurrentDPI()
{
_currentDpi = GetDpiForWindow(_window.get());
}
protected:
using base_type = BaseWindow<T>;
wil::unique_hwnd _window;
unsigned int _currentDpi = 0;
bool _inDpiChange = false;
std::wstring _title = L"";
bool _minimized = false;
// Method Description:
// - This method is called when the window receives the WM_NCCREATE message.
// Return Value:
// - The value returned from the window proc.
virtual [[nodiscard]] LRESULT _OnNcCreate(WPARAM wParam, LPARAM lParam) noexcept
{
SetWindowLongPtr(_window.get(), GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
EnableNonClientDpiScaling(_window.get());
_currentDpi = GetDpiForWindow(_window.get());
return DefWindowProc(_window.get(), WM_NCCREATE, wParam, lParam);
};
};
template<typename T>
inline BaseWindow<T>::~BaseWindow()
{
}

View File

@@ -0,0 +1,220 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleIslandWindow.h"
#include "../types/inc/Viewport.hpp"
#include "resource.h"
#include "icon.h"
extern "C" IMAGE_DOS_HEADER __ImageBase;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Hosting;
using namespace winrt::Windows::Foundation::Numerics;
using namespace ::Microsoft::Console::Types;
#define XAML_HOSTING_WINDOW_CLASS_NAME L"SCRATCH_HOSTING_WINDOW_CLASS"
SampleIslandWindow::SampleIslandWindow() noexcept :
_interopWindowHandle{ nullptr },
_rootGrid{ nullptr },
_source{ nullptr }
{
}
SampleIslandWindow::~SampleIslandWindow()
{
_source.Close();
}
// Method Description:
// - Create the actual window that we'll use for the application.
// Arguments:
// - <none>
// Return Value:
// - <none>
void SampleIslandWindow::MakeWindow() noexcept
{
WNDCLASS wc{};
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hInstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
wc.lpszClassName = XAML_HOSTING_WINDOW_CLASS_NAME;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hIcon = LoadIconW(wc.hInstance, MAKEINTRESOURCEW(IDI_APPICON));
RegisterClass(&wc);
WINRT_ASSERT(!_window);
// Create the window with the default size here - During the creation of the
// window, the system will give us a chance to set its size in WM_CREATE.
// WM_CREATE will be handled synchronously, before CreateWindow returns.
WINRT_VERIFY(CreateWindowEx(0,
wc.lpszClassName,
L"ScratchApp",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
nullptr,
nullptr,
wc.hInstance,
this));
WINRT_ASSERT(_window);
}
// Method Description:
// - Called when no tab is remaining to close the window.
// Arguments:
// - <none>
// Return Value:
// - <none>
void SampleIslandWindow::Close()
{
PostQuitMessage(0);
}
// Method Description:
// - Handles a WM_CREATE message. Calls our create callback, if one's been set.
// Arguments:
// - wParam: unused
// - lParam: the lParam of a WM_CREATE, which is a pointer to a CREATESTRUCTW
// Return Value:
// - <none>
void SampleIslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam) noexcept
{
// Get proposed window rect from create structure
CREATESTRUCTW* pcs = reinterpret_cast<CREATESTRUCTW*>(lParam);
RECT rc;
rc.left = pcs->x;
rc.top = pcs->y;
rc.right = rc.left + pcs->cx;
rc.bottom = rc.top + pcs->cy;
ShowWindow(_window.get(), SW_SHOW);
UpdateWindow(_window.get());
UpdateWindowIconForActiveMetrics(_window.get());
}
void SampleIslandWindow::Initialize()
{
const bool initialized = (_interopWindowHandle != nullptr);
_source = DesktopWindowXamlSource{};
auto interop = _source.as<IDesktopWindowXamlSourceNative>();
winrt::check_hresult(interop->AttachToWindow(_window.get()));
// stash the child interop handle so we can resize it when the main hwnd is resized
interop->get_WindowHandle(&_interopWindowHandle);
_rootGrid = winrt::Windows::UI::Xaml::Controls::Grid();
_source.Content(_rootGrid);
}
void SampleIslandWindow::OnSize(const UINT width, const UINT height)
{
// update the interop window size
SetWindowPos(_interopWindowHandle, nullptr, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE);
if (_rootGrid)
{
const auto size = GetLogicalSize();
_rootGrid.Width(size.Width);
_rootGrid.Height(size.Height);
}
}
[[nodiscard]] LRESULT SampleIslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
{
switch (message)
{
case WM_CREATE:
{
_HandleCreateWindow(wparam, lparam);
return 0;
}
case WM_SETFOCUS:
{
if (_interopWindowHandle != nullptr)
{
// send focus to the child window
SetFocus(_interopWindowHandle);
return 0;
}
break;
}
case WM_MENUCHAR:
{
// GH#891: return this LRESULT here to prevent the app from making a
// bell when alt+key is pressed. A menu is active and the user presses a
// key that does not correspond to any mnemonic or accelerator key,
return MAKELRESULT(0, MNC_CLOSE);
}
case WM_THEMECHANGED:
UpdateWindowIconForActiveMetrics(_window.get());
return 0;
}
return base_type::MessageHandler(message, wparam, lparam);
}
// Method Description:
// - Called when the window has been resized (or maximized)
// Arguments:
// - width: the new width of the window _in pixels_
// - height: the new height of the window _in pixels_
void SampleIslandWindow::OnResize(const UINT width, const UINT height)
{
if (_interopWindowHandle)
{
OnSize(width, height);
}
}
// Method Description:
// - Called when the window is minimized to the taskbar.
void SampleIslandWindow::OnMinimize()
{
}
// Method Description:
// - Called when the window is restored from having been minimized.
void SampleIslandWindow::OnRestore()
{
}
void SampleIslandWindow::SetContent(winrt::Windows::UI::Xaml::UIElement content)
{
_rootGrid.Children().Clear();
_rootGrid.Children().Append(content);
}
void SampleIslandWindow::OnAppInitialized()
{
// Do a quick resize to force the island to paint
const auto size = GetPhysicalSize();
OnSize(size.cx, size.cy);
}
// Method Description:
// - Called when the app wants to change its theme. We'll update the root UI
// element of the entire XAML tree, so that all UI elements get the theme
// applied.
// Arguments:
// - arg: the ElementTheme to use as the new theme for the UI
// Return Value:
// - <none>
void SampleIslandWindow::OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme)
{
_rootGrid.RequestedTheme(requestedTheme);
// Invalidate the window rect, so that we'll repaint any elements we're
// drawing ourselves to match the new theme
::InvalidateRect(_window.get(), nullptr, false);
}

View File

@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleBaseWindow.h"
#include "../../../src/cascadia/inc/cppwinrt_utils.h"
class SampleIslandWindow :
public BaseWindow<SampleIslandWindow>
{
public:
SampleIslandWindow() noexcept;
virtual ~SampleIslandWindow() override;
virtual void MakeWindow() noexcept;
void Close();
virtual void OnSize(const UINT width, const UINT height);
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
void OnResize(const UINT width, const UINT height) override;
void OnMinimize() override;
void OnRestore() override;
virtual void OnAppInitialized();
virtual void SetContent(winrt::Windows::UI::Xaml::UIElement content);
virtual void OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
virtual void Initialize();
protected:
void ForceResize()
{
// Do a quick resize to force the island to paint
const auto size = GetPhysicalSize();
OnSize(size.cx, size.cy);
}
HWND _interopWindowHandle;
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _source;
winrt::Windows::UI::Xaml::Controls::Grid _rootGrid;
void _HandleCreateWindow(const WPARAM wParam, const LPARAM lParam) noexcept;
};

View File

@@ -0,0 +1,122 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleAppHost.h"
#include "resource.h"
#include "../types/inc/User32Utils.hpp"
#include <WilErrorReporting.h>
using namespace winrt;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
using namespace winrt::Windows::UI::Xaml::Hosting;
using namespace winrt::Windows::Foundation::Numerics;
// Routine Description:
// - Takes an image architecture and locates a string resource that maps to that architecture.
// Arguments:
// - imageArchitecture - An IMAGE_FILE_MACHINE architecture enum value
// - See https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants
// Return Value:
// - A string value representing the human-readable name of this architecture.
static std::wstring ImageArchitectureToString(USHORT imageArchitecture)
{
// clang-format off
const auto id = imageArchitecture == IMAGE_FILE_MACHINE_I386 ? IDS_X86_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_AMD64 ? IDS_AMD64_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_ARM64 ? IDS_ARM64_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_ARM ? IDS_ARM_ARCHITECTURE :
IDS_UNKNOWN_ARCHITECTURE;
// clang-format on
return GetStringResource(id);
}
// Routine Description:
// - Blocks the user from launching the application with a message box dialog and early exit
// if the process architecture doesn't match the system platform native architecture.
// - This is because the conhost.exe must match the condrv.sys on the system and the PTY
// infrastructure that powers everything won't work if we have a mismatch.
// Arguments:
// - <none>
// Return Value:
// - <none>
static void EnsureNativeArchitecture()
{
USHORT processMachine{};
USHORT nativeMachine{};
THROW_IF_WIN32_BOOL_FALSE(IsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine));
if (processMachine != IMAGE_FILE_MACHINE_UNKNOWN && processMachine != nativeMachine)
{
const auto formatPattern = GetStringResource(IDS_ERROR_ARCHITECTURE_FORMAT);
const auto nativeArchitecture = ImageArchitectureToString(nativeMachine);
const auto processArchitecture = ImageArchitectureToString(processMachine);
auto buffer{ wil::str_printf<std::wstring>(formatPattern.data(), nativeArchitecture.data(), processArchitecture.data()) };
MessageBoxW(nullptr,
buffer.data(),
GetStringResource(IDS_ERROR_DIALOG_TITLE).data(),
MB_OK | MB_ICONERROR);
ExitProcess(0);
}
}
static bool _messageIsF7Keypress(const MSG& message)
{
return (message.message == WM_KEYDOWN || message.message == WM_SYSKEYDOWN) && message.wParam == VK_F7;
}
static bool _messageIsAltKeyup(const MSG& message)
{
return (message.message == WM_KEYUP || message.message == WM_SYSKEYUP) && message.wParam == VK_MENU;
}
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
// If Terminal is spawned by a shortcut that requests that it run in a new process group
// while attached to a console session, that request is nonsense. That request will, however,
// cause WT to start with Ctrl-C disabled. This wouldn't matter, because it's a Windows-subsystem
// application. Unfortunately, that state is heritable. In short, if you start WT using cmd in
// a weird way, ^C stops working _inside_ the terminal. Mad.
SetConsoleCtrlHandler(NULL, FALSE);
// Block the user from starting if they launched the incorrect architecture version of the project.
// This should only be applicable to developer versions. The package installation process
// should choose and install the correct one from the bundle.
EnsureNativeArchitecture();
// Make sure to call this so we get WM_POINTER messages.
EnableMouseInPointer(true);
// !!! LOAD BEARING !!!
// We must initialize the main thread as a single-threaded apartment before
// constructing any Xaml objects. Failing to do so will cause some issues
// in accessibility somewhere down the line when a UIAutomation object will
// be queried on the wrong thread at the wrong time.
// We used to initialize as STA only _after_ initializing the application
// host, which loaded the settings. The settings needed to be loaded in MTA
// because we were using the Windows.Storage APIs. Since we're no longer
// doing that, we can safely init as STA before any WinRT dispatches.
winrt::init_apartment(winrt::apartment_type::single_threaded);
// Create the SampleAppHost object, which will create both the window and the
// Terminal App. This MUST BE constructed before the Xaml manager as TermApp
// provides an implementation of Windows.UI.Xaml.Application.
SampleAppHost host;
// Initialize the xaml content. This must be called AFTER the
// WindowsXamlManager is initialized.
host.Initialize();
MSG message;
while (GetMessage(&message, nullptr, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return 0;
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 1903 -->
<!-- See https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/xaml-islands -->
<!-- "maxversiontested" is CASE SENSITIVE. Do not change this.-->
<maxversiontested Id="10.0.18362.0"/>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
</assembly>

View File

@@ -0,0 +1,97 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APPICON ICON "..\\..\\..\\res\\terminal.ico"
IDI_APPICON_HC_BLACK ICON "..\\..\\..\\res\\terminal\\images\\terminal_contrast-black.ico"
IDI_APPICON_HC_WHITE ICON "..\\..\\..\\res\\terminal\\images\\terminal_contrast-white.ico"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_ERROR_DIALOG_TITLE "Error"
IDS_HELP_DIALOG_TITLE "Help"
IDS_ERROR_ARCHITECTURE_FORMAT
"This sample is designed to run on your system's native architecture (%s).\nYou are currently using the %s version.\n\nPlease use the version of this sample that matches your system's native architecture."
IDS_X86_ARCHITECTURE "i386"
END
STRINGTABLE
BEGIN
IDS_AMD64_ARCHITECTURE "AMD64"
IDS_ARM64_ARCHITECTURE "ARM64"
IDS_ARM_ARCHITECTURE "ARM"
IDS_UNKNOWN_ARCHITECTURE "Unknown"
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,220 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<PropertyGroup Label="Globals">
<ProjectGuid>{b4427499-9fde-4208-b456-5bc580637633}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WindowExe</RootNamespace>
<ProjectName>WindowExe</ProjectName>
<TargetName>WindowExe</TargetName>
<ConfigurationType>Application</ConfigurationType>
<OpenConsoleUniversalApp>false</OpenConsoleUniversalApp>
<ApplicationType>Windows Store</ApplicationType>
<WindowsStoreApp>true</WindowsStoreApp>
<WindowsAppContainer>false</WindowsAppContainer>
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemDefinitionGroup>
<ClCompile>
<SDLCheck>true</SDLCheck>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(OpenConsoleDir)\src\inc;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\Console;$(OpenConsoleDir)\dep\Win32K;$(OpenConsoleDir)\dep\gsl\include;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<PropertyGroup>
<GenerateManifest>true</GenerateManifest>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<!-- Source Files -->
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="icon.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="SampleAppHost.h" />
<ClInclude Include="SampleBaseWindow.h" />
<ClInclude Include="SampleIslandWindow.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="icon.cpp" />
<ClCompile Include="SampleMain.cpp" />
<ClCompile Include="SampleAppHost.cpp" />
<ClCompile Include="SampleIslandWindow.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WindowExe.rc" />
</ItemGroup>
<ItemGroup>
<Manifest Include="WindowExe.manifest" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<ProjectReference Include="$(OpenConsoleDir)scratch\ScratchIslandApp\SampleApp\dll\SampleApp.vcxproj" />
</ItemGroup>
<!-- ========================== Other References ========================= -->
<ItemGroup>
<!--
!! LOAD BEARING !!
Make sure these winmd's are all Private=true,
CopyLocalSatelliteAssemblies=true, at this layer. Those will force the
packaging project to actually include those winmd's in our final package. If
they're missing, then WinRT will have a hard time marshalling those types
across a process boundary.
Particularly tricky is Microsoft.Terminal.Core.winmd. That winmd doesn't
have its own DLL (it doesn't have any activatable classes, only structs and
interfaces). However, it too is necessary for Terminal.Control to be able to
marshall the Core types across the boundary.
-->
<Reference Include="Microsoft.Terminal.Core">
<HintPath>$(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<Implementation>$(OpenConsoleCommonOutDir)TerminalConnection\TerminalConnection.dll</Implementation>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Control">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd</HintPath>
<Implementation>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.dll</Implementation>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<!--
This ItemGroup and the Globals PropertyGroup below it are required in order
to enable F5 debugging for the unpackaged application
-->
<ItemGroup>
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\debugger_general.xml" />
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\debugger_local_windows.xml" />
</ItemGroup>
<PropertyGroup Label="Globals">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
</Target>
<!-- Override GetPackagingOutputs to roll up all our dependencies.
This ensures that when the WAP packaging project asks what files go into
the package, we tell it.
This is a heavily stripped version of the one in Microsoft.*.AppxPackage.targets.
-->
<PropertyGroup>
<_ContinueOnError Condition="'$(BuildingProject)' == 'true'">true</_ContinueOnError>
<_ContinueOnError Condition="'$(BuildingProject)' != 'true'">false</_ContinueOnError>
</PropertyGroup>
<Target Name="GetPackagingOutputs" Returns="@(PackagingOutputs)">
<MSBuild
Projects="@(ProjectReferenceWithConfiguration)"
Targets="GetPackagingOutputs"
BuildInParallel="$(BuildInParallel)"
Properties="%(ProjectReferenceWithConfiguration.SetConfiguration); %(ProjectReferenceWithConfiguration.SetPlatform)"
Condition="'@(ProjectReferenceWithConfiguration)' != ''
and '%(ProjectReferenceWithConfiguration.BuildReference)' == 'true'
and '%(ProjectReferenceWithConfiguration.ReferenceOutputAssembly)' == 'true'"
ContinueOnError="$(_ContinueOnError)">
<Output TaskParameter="TargetOutputs" ItemName="_PackagingOutputsFromOtherProjects"/>
</MSBuild>
<ItemGroup>
<PackagingOutputs Include="@(_PackagingOutputsFromOtherProjects)" />
</ItemGroup>
<!-- **BEGIN VC LIBS HACK** -->
<PropertyGroup>
<ReasonablePlatform Condition="'$(Platform)'=='Win32'">x86</ReasonablePlatform>
<ReasonablePlatform Condition="'$(ReasonablePlatform)'==''">$(Platform)</ReasonablePlatform>
</PropertyGroup>
<ItemGroup Condition="'$(WindowExeOfficialBuild)'=='true'">
<!-- Add all the CRT libs as content; these must be inside a Target as they are wildcards. -->
<_OpenConsoleVCLibToCopy Include="$(VCToolsRedistInstallDir)\$(ReasonablePlatform)\Microsoft.VC142.CRT\*.dll" />
<PackagingOutputs Include="@(_OpenConsoleVCLibToCopy)">
<ProjectName>$(ProjectName)</ProjectName>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
<!-- **END VC LIBS HACK** -->
<!-- **BEGIN TERMINAL CONNECTION HACK** -->
<!-- This is the same as the above VC libs hack, but for TerminalConnection.
TerminalConnection depends on cpprest*.dll, and if we don't include it in
the packaging output, we'll crash as soon as we try to load
TerminalConnection.dll.
The Sample sln needs to do this manually - the real exe has a
ProjectReference to TerminalConnection.vcxproj and can figure this out on
its own. -->
<ItemGroup>
<_TerminalConnectionDlls Include="$(OpenConsoleCommonOutDir)\TerminalConnection\*.dll" />
<PackagingOutputs Include="@(_TerminalConnectionDlls)">
<ProjectName>$(ProjectName)</ProjectName>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
<!-- **END TERMINAL CONNECTION HACK** -->
<!-- Same thing again here, with WindowsTerminal.exe -->
<ItemGroup>
<_WindowsTerminalExe Include="$(OpenConsoleCommonOutDir)\WindowsTerminal\*.exe" />
<PackagingOutputs Include="@(_WindowsTerminalExe)">
<ProjectName>$(ProjectName)</ProjectName>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
<Import Project="..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" />
</Project>

View File

@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "resource.h"
static int _GetActiveAppIconResource()
{
auto iconResource{ IDI_APPICON };
HIGHCONTRASTW hcInfo{};
hcInfo.cbSize = sizeof(hcInfo);
if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(hcInfo), &hcInfo, 0))
{
if (WI_IsFlagSet(hcInfo.dwFlags, HCF_HIGHCONTRASTON))
{
iconResource = IDI_APPICON_HC_BLACK;
if (0x00FFFFFF == GetSysColor(COLOR_WINDOW)) // white window color == white high contrast
{
iconResource = IDI_APPICON_HC_WHITE;
}
}
}
return iconResource;
}
void UpdateWindowIconForActiveMetrics(HWND window)
{
auto iconResource{ MAKEINTRESOURCEW(_GetActiveAppIconResource()) };
// These handles are loaded with LR_SHARED, so they are safe to "leak".
HANDLE smallIcon{ LoadImageW(wil::GetModuleInstanceHandle(), iconResource, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) };
LOG_LAST_ERROR_IF_NULL(smallIcon);
HANDLE largeIcon{ LoadImageW(wil::GetModuleInstanceHandle(), iconResource, IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_SHARED) };
LOG_LAST_ERROR_IF_NULL(largeIcon);
if (smallIcon)
{
SendMessageW(window, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(smallIcon));
}
if (largeIcon)
{
SendMessageW(window, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(largeIcon));
}
}

View File

@@ -0,0 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
void UpdateWindowIconForActiveMetrics(HWND window);

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
</packages>

View File

@@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@@ -0,0 +1,82 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- pch.h
Abstract:
- Contains external headers to include in the precompile phase of console build process.
- Avoid including internal project headers. Instead include them only in the classes that need them (helps with test project building).
--*/
#pragma once
// Ignore checked iterators warning from VC compiler.
#define _SCL_SECURE_NO_WARNINGS
// Block minwindef.h min/max macros to prevent <algorithm> conflict
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#define NOMCX
#define NOHELP
#define NOCOMM
#include <unknwn.h>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#include <windows.h>
#include <UIAutomation.h>
#include <cstdlib>
#include <cstring>
#include <shellscalingapi.h>
#include <windowsx.h>
#include <ShObjIdl.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#define BLOCK_TIL
#include "../inc/LibraryIncludes.h"
// This is inexplicable, but for whatever reason, cppwinrt conflicts with the
// SDK definition of this function, so the only fix is to undef it.
// from WinBase.h
// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
#include <wil/cppwinrt.h>
// Needed just for XamlIslands to work at all:
#include <winrt/Windows.system.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.UI.Xaml.Hosting.h>
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
// Additional headers for various xaml features. We need:
// * Core so we can resume_foreground with CoreDispatcher
// * Controls for grid
// * Media for ScaleTransform
#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/SampleApp.h>
#include <wil/resource.h>
#include <wil/win32_helpers.h>
// Including TraceLogging essentials for the binary
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DECLARE_PROVIDER(g_hWindowsTerminalProvider);
#include <telemetry/ProjectTelemetry.h>
#include <TraceLoggingActivity.h>
// For commandline argument processing
#include <shellapi.h>
#include <processenv.h>
#include <WinUser.h>
#include "til.h"

View File

@@ -0,0 +1,27 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by WindowsTerminal.rc
//
#define IDI_APPICON 101
#define IDI_APPICON_HC_BLACK 102
#define IDI_APPICON_HC_WHITE 103
#define IDS_ERROR_DIALOG_TITLE 105
#define IDS_HELP_DIALOG_TITLE 106
#define IDS_ERROR_ARCHITECTURE_FORMAT 110
#define IDS_X86_ARCHITECTURE 111
#define IDS_AMD64_ARCHITECTURE 112
#define IDS_ARM64_ARCHITECTURE 113
#define IDS_ARM_ARCHITECTURE 114
#define IDS_UNKNOWN_ARCHITECTURE 115
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{9cf74355-f018-4c19-81ad-9dc6b7f2c6f5}</ProjectGuid>
<RootNamespace>apimswincoresynchl120</RootNamespace>
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="definitions.def" />
</ItemGroup>
<Import Project="$(SolutionDir)src\common.build.post.props" />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib</AdditionalDependencies>
<ModuleDefinitionFile>definitions.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
</Project>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
</ItemGroup>
<ItemGroup>
<None Include="definitions.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,19 @@
LIBRARY
EXPORTS
DeleteSynchronizationBarrier = kernel32.DeleteSynchronizationBarrier
EnterSynchronizationBarrier = kernel32.EnterSynchronizationBarrier
InitOnceBeginInitialize = kernel32.InitOnceBeginInitialize
InitOnceComplete = kernel32.InitOnceComplete
InitOnceExecuteOnce = kernel32.InitOnceExecuteOnce
InitOnceInitialize = kernel32.InitOnceInitialize
InitializeConditionVariable = kernel32.InitializeConditionVariable
InitializeSynchronizationBarrier = kernel32.InitializeSynchronizationBarrier
SignalObjectAndWait = kernel32.SignalObjectAndWait
Sleep = kernel32.Sleep
SleepConditionVariableCS = kernel32.SleepConditionVariableCS
SleepConditionVariableSRW = kernel32.SleepConditionVariableSRW
WaitOnAddress
WakeAllConditionVariable = kernel32.WakeAllConditionVariable
WakeByAddressAll
WakeByAddressSingle
WakeConditionVariable = kernel32.WakeConditionVariable

View File

@@ -0,0 +1,189 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// The code in this file was adapted from the STL on the 2021-07-05. Commit:
// https://github.com/microsoft/STL/blob/e745bad3b1d05b5b19ec652d68abb37865ffa454/stl/src/atomic_wait.cpp
//
// It backports the following Windows 8 functions to Windows 7:
// * WaitOnAddress
// * WakeByAddressSingle
// * WakeByAddressAll
//
#include <cstdint>
#include <new>
#include <winsdkver.h>
#define _WIN32_WINNT 0x0601
#include <sdkddkver.h>
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <intrin.h>
namespace
{
class [[nodiscard]] SRWLockGuard
{
public:
explicit SRWLockGuard(SRWLOCK & lock) noexcept :
_lock(&lock)
{
AcquireSRWLockExclusive(_lock);
}
~SRWLockGuard()
{
ReleaseSRWLockExclusive(_lock);
}
SRWLockGuard(const SRWLockGuard&) = delete;
SRWLockGuard& operator=(const SRWLockGuard&) = delete;
SRWLockGuard(SRWLockGuard &&) = delete;
SRWLockGuard& operator=(SRWLockGuard&&) = delete;
private:
SRWLOCK* _lock;
};
struct WaitContext
{
const volatile void* address;
WaitContext* next;
WaitContext* prev;
CONDITION_VARIABLE cv;
};
struct [[nodiscard]] GuardedWaitContext : WaitContext
{
GuardedWaitContext(const volatile void* storage, WaitContext* head) noexcept :
WaitContext{ storage, head, head->prev, CONDITION_VARIABLE_INIT }
{
prev->next = this;
next->prev = this;
}
~GuardedWaitContext()
{
const auto n = next;
const auto p = prev;
next->prev = p;
prev->next = n;
}
GuardedWaitContext(const GuardedWaitContext&) = delete;
GuardedWaitContext& operator=(const GuardedWaitContext&) = delete;
GuardedWaitContext(GuardedWaitContext &&) = delete;
GuardedWaitContext& operator=(GuardedWaitContext&&) = delete;
};
#pragma warning(push)
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
struct alignas(std::hardware_destructive_interference_size) WaitTableEntry
{
SRWLOCK lock = SRWLOCK_INIT;
WaitContext head = { nullptr, &head, &head, CONDITION_VARIABLE_INIT };
};
#pragma warning(pop)
[[nodiscard]] WaitTableEntry& GetWaitTableEntry(const volatile void* const storage) noexcept
{
// A prime number for the hash table size was chosen to prevent collisions.
constexpr size_t size = 251;
constexpr std::hash<uintptr_t> hasher;
static WaitTableEntry table[size];
#pragma warning(suppress : 26446) // Prefer to use gsl::at() instead of unchecked subscript operator
#pragma warning(suppress : 26482) // Only index into arrays using constant expressions
#pragma warning(suppress : 26490) // Don't use reinterpret_cast
return table[hasher(reinterpret_cast<uintptr_t>(storage)) % size];
}
#pragma warning(suppress : 26429) // Symbol 'comparand' is never tested for nullness, it can be marked as not_null
bool AreEqual(const volatile void* storage, const void* comparand, size_t size) noexcept
{
switch (size)
{
case 1:
return __iso_volatile_load8(static_cast<const volatile __int8*>(storage)) == *static_cast<const __int8*>(comparand);
case 2:
return __iso_volatile_load16(static_cast<const volatile __int16*>(storage)) == *static_cast<const __int16*>(comparand);
case 4:
return __iso_volatile_load32(static_cast<const volatile __int32*>(storage)) == *static_cast<const __int32*>(comparand);
case 8:
return __iso_volatile_load64(static_cast<const volatile __int64*>(storage)) == *static_cast<const __int64*>(comparand);
default:
abort();
}
}
} // unnamed namespace
extern "C" BOOL WINAPI WaitOnAddress(_In_reads_bytes_(AddressSize) volatile VOID* Address, _In_reads_bytes_(AddressSize) PVOID CompareAddress, _In_ SIZE_T AddressSize, _In_opt_ DWORD dwMilliseconds)
{
auto& entry = GetWaitTableEntry(Address);
SRWLockGuard guard{ entry.lock };
GuardedWaitContext context{ Address, &entry.head };
for (;;)
{
// NOTE: under lock to prevent lost wakes
if (!AreEqual(Address, CompareAddress, AddressSize))
{
return TRUE;
}
if (!SleepConditionVariableSRW(&context.cv, &entry.lock, dwMilliseconds, 0))
{
#ifndef NDEBUG
if (GetLastError() != ERROR_TIMEOUT)
{
abort();
}
#endif
return FALSE;
}
if (dwMilliseconds != INFINITE)
{
// spurious wake to recheck the clock
return TRUE;
}
}
}
extern "C" VOID WINAPI WakeByAddressSingle(_In_ PVOID Address)
{
auto& entry = GetWaitTableEntry(Address);
SRWLockGuard guard(entry.lock);
for (auto context = entry.head.next; context != &entry.head; context = context->next)
{
if (context->address == Address)
{
// Can't move wake outside SRWLOCKed section: SRWLOCK also protects the context itself
WakeAllConditionVariable(&context->cv);
// This break; is the difference between WakeByAddressSingle and WakeByAddressAll
break;
}
}
}
extern "C" VOID WINAPI WakeByAddressAll(_In_ PVOID Address)
{
auto& entry = GetWaitTableEntry(Address);
SRWLockGuard guard(entry.lock);
for (auto context = entry.head.next; context != &entry.head; context = context->next)
{
if (context->address == Address)
{
// Can't move wake outside SRWLOCKed section: SRWLOCK also protects the context itself
WakeAllConditionVariable(&context->cv);
}
}
}

View File

@@ -11,18 +11,8 @@
// - attr - the default text attribute
// Return Value:
// - constructed object
ATTR_ROW::ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr) noexcept
{
try
{
_list.emplace_back(TextAttributeRun(cchRowWidth, attr));
}
catch (...)
{
FAIL_FAST_CAUGHT_EXCEPTION();
}
_cchRowWidth = cchRowWidth;
}
ATTR_ROW::ATTR_ROW(const uint16_t width, const TextAttribute attr) :
_data(width, attr) {}
// Routine Description:
// - Sets all properties of the ATTR_ROW to default values
@@ -30,8 +20,7 @@ ATTR_ROW::ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr) noexcept
// - attr - The default text attributes to use on text in this row.
void ATTR_ROW::Reset(const TextAttribute attr)
{
_list.clear();
_list.emplace_back(TextAttributeRun(_cchRowWidth, attr));
_data.replace(0, _data.size(), attr);
}
// Routine Description:
@@ -43,48 +32,9 @@ void ATTR_ROW::Reset(const TextAttribute attr)
// - newWidth - The new width of the row.
// Return Value:
// - <none>, throws exceptions on failures.
void ATTR_ROW::Resize(const size_t newWidth)
void ATTR_ROW::Resize(const uint16_t newWidth)
{
THROW_HR_IF(E_INVALIDARG, 0 == newWidth);
// Easy case. If the new row is longer, increase the length of the last run by how much new space there is.
if (newWidth > _cchRowWidth)
{
// Get the attribute that covers the final column of old width.
const auto runPos = FindAttrIndex(_cchRowWidth - 1, nullptr);
auto& run = _list.at(runPos);
// Extend its length by the additional columns we're adding.
run.SetLength(run.GetLength() + newWidth - _cchRowWidth);
// Store that the new total width we represent is the new width.
_cchRowWidth = newWidth;
}
// harder case: new row is shorter.
else
{
// Get the attribute that covers the final column of the new width
size_t CountOfAttr = 0;
const auto runPos = FindAttrIndex(newWidth - 1, &CountOfAttr);
auto& run = _list.at(runPos);
// CountOfAttr was given to us as "how many columns left from this point forward are covered by the returned run"
// So if the original run was B5 covering a 5 size OldWidth and we have a NewWidth of 3
// then when we called FindAttrIndex, it returned the B5 as the pIndexedRun and a 2 for how many more segments it covers
// after and including the 3rd column.
// B5-2 = B3, which is what we desire to cover the new 3 size buffer.
run.SetLength(run.GetLength() - CountOfAttr + 1);
// Store that the new total width we represent is the new width.
_cchRowWidth = newWidth;
// Erase segments after the one we just updated.
_list.erase(_list.cbegin() + runPos + 1, _list.cend());
// NOTE: Under some circumstances here, we have leftover run segments in memory or blank run segments
// in memory. We're not going to waste time redimensioning the array in the heap. We're just noting that the useful
// portions of it have changed.
}
_data.resize_trailing_extent(newWidth);
}
// Routine Description:
@@ -95,104 +45,23 @@ void ATTR_ROW::Resize(const size_t newWidth)
// - the text attribute at column
// Note:
// - will throw on error
TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column) const
TextAttribute ATTR_ROW::GetAttrByColumn(const uint16_t column) const
{
return GetAttrByColumn(column, nullptr);
}
// Routine Description:
// - returns a copy of the TextAttribute at the specified column
// Arguments:
// - column - the column to get the attribute for
// - pApplies - if given, fills how long this attribute will apply for
// Return Value:
// - the text attribute at column
// Note:
// - will throw on error
TextAttribute ATTR_ROW::GetAttrByColumn(const size_t column,
size_t* const pApplies) const
{
THROW_HR_IF(E_INVALIDARG, column >= _cchRowWidth);
const auto runPos = FindAttrIndex(column, pApplies);
return _list.at(runPos).GetAttributes();
}
// Routine Description:
// - reports how many runs we have stored (to be used for some optimizations
// Return Value:
// - Count of runs. 1 means we have 1 color to represent the entire row.
size_t ATTR_ROW::GetNumberOfRuns() const noexcept
{
return _list.size();
}
// Routine Description:
// - This routine finds the nth attribute in this ATTR_ROW.
// Arguments:
// - index - which attribute to find
// - applies - on output, contains corrected length of indexed attr.
// for example, if the attribute string was { 5, BLUE } and the requested
// index was 3, CountOfAttr would be 2.
// Return Value:
// - const reference to attribute run object
size_t ATTR_ROW::FindAttrIndex(const size_t index, size_t* const pApplies) const
{
FAIL_FAST_IF(!(index < _cchRowWidth)); // The requested index cannot be longer than the total length described by this set of Attrs.
size_t cTotalLength = 0;
FAIL_FAST_IF(!(_list.size() > 0)); // There should be a non-zero and positive number of items in the array.
// Scan through the internal array from position 0 adding up the lengths that each attribute applies to
auto runPos = _list.cbegin();
do
{
cTotalLength += runPos->GetLength();
if (cTotalLength > index)
{
// If we've just passed up the requested index with the length we added, break early
break;
}
runPos++;
} while (runPos < _list.cend());
// we should have broken before falling out the while case.
// if we didn't break, then this ATTR_ROW wasn't filled with enough attributes for the entire row of characters
FAIL_FAST_IF(runPos >= _list.cend());
// The remaining iterator position is the position of the attribute that is applicable at the position requested (index)
// Calculate its remaining applicability if requested
// The length on which the found attribute applies is the total length seen so far minus the index we were searching for.
FAIL_FAST_IF(!(cTotalLength > index)); // The length of all attributes we counted up so far should be longer than the index requested or we'll underflow.
if (nullptr != pApplies)
{
const auto attrApplies = cTotalLength - index;
FAIL_FAST_IF(!(attrApplies > 0)); // An attribute applies for >0 characters
// MSFT: 17130145 - will restore this and add a better assert to catch the real issue.
//FAIL_FAST_IF(!(attrApplies <= _cchRowWidth)); // An attribute applies for a maximum of the total length available to us
*pApplies = attrApplies;
}
return runPos - _list.cbegin();
return _data.at(column);
}
// Routine Description:
// - Finds the hyperlink IDs present in this row and returns them
// Return value:
// - The hyperlink IDs present in this row
std::vector<uint16_t> ATTR_ROW::GetHyperlinks()
std::vector<uint16_t> ATTR_ROW::GetHyperlinks() const
{
std::vector<uint16_t> ids;
for (const auto& run : _list)
for (const auto& run : _data.runs())
{
if (run.GetAttributes().IsHyperlink())
if (run.value.IsHyperlink())
{
ids.emplace_back(run.GetAttributes().GetHyperlinkId());
ids.emplace_back(run.value.GetHyperlinkId());
}
}
return ids;
@@ -205,12 +74,10 @@ std::vector<uint16_t> ATTR_ROW::GetHyperlinks()
// - attr - Attribute (color) to fill remaining characters with
// Return Value:
// - <none>
bool ATTR_ROW::SetAttrToEnd(const UINT iStart, const TextAttribute attr)
bool ATTR_ROW::SetAttrToEnd(const uint16_t beginIndex, const TextAttribute attr)
{
size_t const length = _cchRowWidth - iStart;
const TextAttributeRun run(length, attr);
return SUCCEEDED(InsertAttrRuns({ &run, 1 }, iStart, _cchRowWidth - 1, _cchRowWidth));
_data.replace(gsl::narrow<uint16_t>(beginIndex), _data.size(), attr);
return true;
}
// Method Description:
@@ -221,419 +88,47 @@ bool ATTR_ROW::SetAttrToEnd(const UINT iStart, const TextAttribute attr)
// - replaceWith - the new value for the matching runs' attributes.
// Return Value:
// - <none>
void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept
void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith)
{
for (auto& run : _list)
{
if (run.GetAttributes() == toBeReplacedAttr)
{
run.SetAttributes(replaceWith);
}
}
_data.replace_values(toBeReplacedAttr, replaceWith);
}
// Routine Description:
// - Takes a array of attribute runs, and inserts them into this row from startIndex to endIndex.
// - For example, if the current row was was [{4, BLUE}], the merge string
// was [{ 2, RED }], with (StartIndex, EndIndex) = (1, 2),
// then the row would modified to be = [{ 1, BLUE}, {2, RED}, {1, BLUE}].
// - Takes an attribute, and merges it into this row from beginIndex (inclusive) to endIndex (exclusive).
// - For example, if the current row was was [{4, BLUE}], the merge arguments were
// { beginIndex = 1, endIndex = 3, newAttr = RED }, then the row would modified to be
// [{ 1, BLUE}, {2, RED}, {1, BLUE}].
// Arguments:
// - rgInsertAttrs - The array of attrRuns to merge into this row.
// - cInsertAttrs - The number of elements in rgInsertAttrs
// - iStart - The index in the row to place the array of runs.
// - iEnd - the final index of the merge runs
// - BufferWidth - the width of the row.
// - beginIndex, endIndex: The [beginIndex, endIndex) range that's to be replaced with newAttr.
// - newAttr: The attribute to merge into this row.
// Return Value:
// - STATUS_NO_MEMORY if there wasn't enough memory to insert the runs
// otherwise STATUS_SUCCESS if we were successful.
[[nodiscard]] HRESULT ATTR_ROW::InsertAttrRuns(const gsl::span<const TextAttributeRun> newAttrs,
const size_t iStart,
const size_t iEnd,
const size_t cBufferWidth)
// - <none>
void ATTR_ROW::Replace(const uint16_t beginIndex, const uint16_t endIndex, const TextAttribute& newAttr)
{
// Definitions:
// Existing Run = The run length encoded color array we're already storing in memory before this was called.
// Insert Run = The run length encoded color array that someone is asking us to inject into our stored memory run.
// New Run = The run length encoded color array that we have to allocate and rebuild to store internally
// which will replace Existing Run at the end of this function.
// Example:
// cBufferWidth = 10.
// Existing Run: R3 -> G5 -> B2
// Insert Run: Y1 -> N1 at iStart = 5 and iEnd = 6
// (rgInsertAttrs is a 2 length array with Y1->N1 in it and cInsertAttrs = 2)
// Final Run: R3 -> G2 -> Y1 -> N1 -> G1 -> B2
// We'll need to know what the last valid column is for some calculations versus iEnd
// because iEnd is specified to us as an inclusive index value.
// Do the -1 math here now so we don't have to have -1s scattered all over this function.
const size_t iLastBufferCol = cBufferWidth - 1;
// If the insertion size is 1, do some pre-processing to
// see if we can get this done quickly.
if (newAttrs.size() == 1)
{
// Get the new color attribute we're trying to apply
const TextAttribute NewAttr = til::at(newAttrs, 0).GetAttributes();
// If the existing run was only 1 element...
// ...and the new color is the same as the old, we don't have to do anything and can exit quick.
if (_list.size() == 1 && _list.at(0).GetAttributes() == NewAttr)
{
return S_OK;
}
// .. otherwise if we internally have a list of 2 or more and we're about to insert a single color
// it's possible that we just walk left-to-right through the row and find a quick exit.
else if (iStart >= 0 && iStart == iEnd)
{
// First we try to find the run where the insertion happens, using lowerBound and upperBound to track
// where we are currently at.
const auto begin = _list.begin();
size_t lowerBound = 0;
size_t upperBound = 0;
for (size_t i = 0; i < _list.size(); i++)
{
const auto curr = begin + i;
upperBound += curr->GetLength();
if (iStart >= lowerBound && iStart < upperBound)
{
// The run that we try to insert into has the same color as the new one.
// e.g.
// AAAAABBBBBBBCCC
// ^
// AAAAABBBBBBBCCC
//
// 'B' is the new color and '^' represents where iStart is. We don't have to
// do anything.
if (curr->GetAttributes() == NewAttr)
{
return S_OK;
}
// If the current run has length of exactly one, we can simply change the attribute
// of the current run.
// e.g.
// AAAAABCCCCCCCCC
// ^
// AAAAADCCCCCCCCC
//
// Here 'D' is the new color.
if (curr->GetLength() == 1)
{
curr->SetAttributes(NewAttr);
return S_OK;
}
// If the insertion happens at current run's lower boundary...
if (iStart == lowerBound && i > 0)
{
const auto prev = std::prev(curr, 1);
// ... and the previous run has the same color as the new one, we can
// just adjust the counts in the existing two elements in our internal list.
// e.g.
// AAAAABBBBBBBCCC
// ^
// AAAAAABBBBBBCCC
//
// Here 'A' is the new color.
if (NewAttr == prev->GetAttributes())
{
prev->IncrementLength();
curr->DecrementLength();
// If we just reduced the right half to zero, just erase it out of the list.
if (curr->GetLength() == 0)
{
_list.erase(curr);
}
return S_OK;
}
}
// If the insertion happens at current run's upper boundary...
if (iStart == upperBound - 1 && i + 1 < _list.size())
{
// ...then let's try our luck with the next run if possible. This is basically the opposite
// of what we did with the previous run.
// e.g.
// AAAAAABBBBBBCCC
// ^
// AAAAABBBBBBBCCC
//
// Here 'B' is the new color.
const auto next = std::next(curr, 1);
if (NewAttr == next->GetAttributes())
{
curr->DecrementLength();
next->IncrementLength();
if (curr->GetLength() == 0)
{
_list.erase(curr);
}
return S_OK;
}
}
}
// Advance one run in the _list.
lowerBound = upperBound;
// The lowerBound is larger than iStart, which means we fail to find an early exit at the run
// where the insertion happens. We can just break out.
if (lowerBound > iStart)
{
break;
}
}
}
}
// If we're about to cover the entire existing run with a new one, we can also make an optimization.
if (iStart == 0 && iEnd == iLastBufferCol)
{
// Just dump what we're given over what we have and call it a day.
_list.assign(newAttrs.begin(), newAttrs.end());
return S_OK;
}
// In the worst case scenario, we will need a new run that is the length of
// The existing run in memory + The new run in memory + 1.
// This worst case occurs when we inject a new item in the middle of an existing run like so
// Existing R3->B5->G2, Insertion Y2 starting at 5 (in the middle of the B5)
// becomes R3->B2->Y2->B1->G2.
// The original run was 3 long. The insertion run was 1 long. We need 1 more for the
// fact that an existing piece of the run was split in half (to hold the latter half).
const size_t cNewRun = _list.size() + newAttrs.size() + 1;
decltype(_list) newRun;
newRun.reserve(cNewRun);
// We will start analyzing from the beginning of our existing run.
// Use some pointers to keep track of where we are in walking through our runs.
// Get the existing run that we'll be updating/manipulating.
const auto existingRun = _list.begin();
auto pExistingRunPos = existingRun;
const auto pExistingRunEnd = _list.end();
auto pInsertRunPos = newAttrs.begin();
size_t cInsertRunRemaining = newAttrs.size();
size_t iExistingRunCoverage = 0;
// Copy the existing run into the new buffer up to the "start index" where the new run will be injected.
// If the new run starts at 0, we have nothing to copy from the beginning.
if (iStart != 0)
{
// While we're less than the desired insertion position...
while (iExistingRunCoverage < iStart)
{
// Add up how much length we can cover by copying an item from the existing run.
iExistingRunCoverage += pExistingRunPos->GetLength();
// Copy it to the new run buffer and advance both pointers.
newRun.push_back(*pExistingRunPos++);
}
// When we get to this point, we've copied full segments from the original existing run
// into our new run buffer. We will have 1 or more full segments of color attributes and
// we MIGHT have to cut the last copied segment's length back depending on where the inserted
// attributes will fall in the final/new run.
// Some examples:
// - Starting with the original string R3 -> G5 -> B2
// - 1. If the insertion is Y5 at start index 3
// We are trying to get a result/final/new run of R3 -> Y5 -> B2.
// We just copied R3 to the new destination buffer and we cang skip down and start inserting the new attrs.
// - 2. If the insertion is Y3 at start index 5
// We are trying to get a result/final/new run of R3 -> G2 -> Y3 -> B2.
// We just copied R3 -> G5 to the new destination buffer with the code above.
// But the insertion is going to cut out some of the length of the G5.
// We need to fix this up below so it says G2 instead to leave room for the Y3 to fit in
// the new/final run.
// Fetch out the length so we can fix it up based on the below conditions.
size_t length = newRun.back().GetLength();
// If we've covered more cells already than the start of the attributes to be inserted...
if (iExistingRunCoverage > iStart)
{
// ..then subtract some of the length of the final cell we copied.
// We want to take remove the difference in distance between the cells we've covered in the new
// run and the insertion point.
// (This turns G5 into G2 from Example 2 just above)
length -= (iExistingRunCoverage - iStart);
}
// Now we're still on that "last cell copied" into the new run.
// If the color of that existing copied cell matches the color of the first segment
// of the run we're about to insert, we can just increment the length to extend the coverage.
if (newRun.back().GetAttributes() == pInsertRunPos->GetAttributes())
{
length += pInsertRunPos->GetLength();
// Since the color matched, we have already "used up" part of the insert run
// and can skip it in our big "memcopy" step below that will copy the bulk of the insert run.
cInsertRunRemaining--;
pInsertRunPos++;
}
// We're done manipulating the length. Store it back.
newRun.back().SetLength(length);
}
// Bulk copy the majority (or all, depending on circumstance) of the insert run into the final run buffer.
std::copy_n(pInsertRunPos, cInsertRunRemaining, std::back_inserter(newRun));
// We're technically done with the insert run now and have 0 remaining, but won't bother updating its pointers
// and counts any further because we won't use them.
// Now we need to move our pointer for the original existing run forward and update our counts
// on how many cells we could have copied from the source before finishing off the new run.
while (iExistingRunCoverage <= iEnd)
{
FAIL_FAST_IF(!(pExistingRunPos != pExistingRunEnd));
iExistingRunCoverage += pExistingRunPos->GetLength();
pExistingRunPos++;
}
// If we still have original existing run cells remaining, copy them into the final new run.
if (pExistingRunPos != pExistingRunEnd || iExistingRunCoverage != (iEnd + 1))
{
// We advanced the existing run pointer and its count to on or past the end of what the insertion run filled in.
// If this ended up being past the end of what the insertion run covers, we have to account for the cells after
// the insertion run but before the next piece of the original existing run.
// The example in this case is if we had...
// Existing Run = R3 -> G5 -> B2 -> X5
// Insert Run = Y2 @ iStart = 7 and iEnd = 8
// ... then at this point in time, our states would look like...
// New Run so far = R3 -> G4 -> Y2
// Existing Run Pointer is at X5
// Existing run coverage count at 3 + 5 + 2 = 10.
// However, in order to get the final desired New Run
// (which is R3 -> G4 -> Y2 -> B1 -> X5)
// we would need to grab a piece of that B2 we already skipped past.
// iExistingRunCoverage = 10. iEnd = 8. iEnd+1 = 9. 10 > 9. So we skipped something.
if (iExistingRunCoverage > (iEnd + 1))
{
// Back up the existing run pointer so we can grab the piece we skipped.
pExistingRunPos--;
// If the color matches what's already in our run, just increment the count value.
// This case is slightly off from the example above. This case is for if the B2 above was actually Y2.
// That Y2 from the existing run is the same color as the Y2 we just filled a few columns left in the final run
// so we can just adjust the final run's column count instead of adding another segment here.
if (newRun.back().GetAttributes() == pExistingRunPos->GetAttributes())
{
size_t length = newRun.back().GetLength();
length += (iExistingRunCoverage - (iEnd + 1));
newRun.back().SetLength(length);
}
else
{
// If the color didn't match, then we just need to copy the piece we skipped and adjust
// its length for the discrepancy in columns not yet covered by the final/new run.
// Move forward to a blank spot in the new run
newRun.emplace_back();
// Copy the existing run's color information to the new run
newRun.back().SetAttributes(pExistingRunPos->GetAttributes());
// Adjust the length of that copied color to cover only the reduced number of columns needed
// now that some have been replaced by the insert run.
newRun.back().SetLength(iExistingRunCoverage - (iEnd + 1));
}
// Now that we're done recovering a piece of the existing run we skipped, move the pointer forward again.
pExistingRunPos++;
}
// OK. In this case, we didn't skip anything. The end of the insert run fell right at a boundary
// in columns that was in the original existing run.
// However, the next piece of the original existing run might happen to have the same color attribute
// as the final piece of what we just copied.
// As an example...
// Existing Run = R3 -> G5 -> B2.
// Insert Run = B5 @ iStart = 3 and iEnd = 7
// New Run so far = R3 -> B5
// New Run desired when done = R3 -> B7
// Existing run pointer is on B2.
// We want to merge the 2 from the B2 into the B5 so we get B7.
else if (newRun.back().GetAttributes() == pExistingRunPos->GetAttributes())
{
// Add the value from the existing run into the current new run position.
size_t length = newRun.back().GetLength();
length += pExistingRunPos->GetLength();
newRun.back().SetLength(length);
// Advance the existing run position since we consumed its value and merged it in.
pExistingRunPos++;
}
// Now bulk copy any segments left in the original existing run
if (pExistingRunPos < pExistingRunEnd)
{
std::copy_n(pExistingRunPos, (pExistingRunEnd - pExistingRunPos), std::back_inserter(newRun));
}
}
// OK, phew. We're done. Now we just need to free the existing run and store the new run in its place.
_list.swap(newRun);
return S_OK;
}
// Routine Description:
// - packs a vector of TextAttribute into a vector of TextAttributeRun
// Arguments:
// - attrs - text attributes to pack
// Return Value:
// - packed text attribute run
std::vector<TextAttributeRun> ATTR_ROW::PackAttrs(const std::vector<TextAttribute>& attrs)
{
std::vector<TextAttributeRun> runs;
if (attrs.empty())
{
return runs;
}
for (auto attr : attrs)
{
if (runs.empty() || runs.back().GetAttributes() != attr)
{
runs.emplace_back(TextAttributeRun(1, attr));
}
else
{
runs.back().SetLength(runs.back().GetLength() + 1);
}
}
return runs;
_data.replace(beginIndex, endIndex, newAttr);
}
ATTR_ROW::const_iterator ATTR_ROW::begin() const noexcept
{
return AttrRowIterator(this);
return _data.begin();
}
ATTR_ROW::const_iterator ATTR_ROW::end() const noexcept
{
return AttrRowIterator::CreateEndIterator(this);
return _data.end();
}
ATTR_ROW::const_iterator ATTR_ROW::cbegin() const noexcept
{
return AttrRowIterator(this);
return _data.cbegin();
}
ATTR_ROW::const_iterator ATTR_ROW::cend() const noexcept
{
return AttrRowIterator::CreateEndIterator(this);
return _data.cend();
}
bool operator==(const ATTR_ROW& a, const ATTR_ROW& b) noexcept
{
return (a._list.size() == b._list.size() &&
a._list.data() == b._list.data() &&
a._cchRowWidth == b._cchRowWidth);
return a._data == b._data;
}

View File

@@ -20,16 +20,17 @@ Revision History:
#pragma once
#include "TextAttributeRun.hpp"
#include "AttrRowIterator.hpp"
#include "til/rle.h"
#include "TextAttribute.hpp"
class ATTR_ROW final
{
public:
using const_iterator = typename AttrRowIterator;
using rle_vector = til::small_rle<TextAttribute, uint16_t, 1>;
ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr)
noexcept;
public:
using const_iterator = rle_vector::const_iterator;
ATTR_ROW(uint16_t width, TextAttribute attr);
~ATTR_ROW() = default;
@@ -39,28 +40,13 @@ public:
noexcept = default;
ATTR_ROW& operator=(ATTR_ROW&&) noexcept = default;
TextAttribute GetAttrByColumn(const size_t column) const;
TextAttribute GetAttrByColumn(const size_t column,
size_t* const pApplies) const;
TextAttribute GetAttrByColumn(uint16_t column) const;
std::vector<uint16_t> GetHyperlinks() const;
size_t GetNumberOfRuns() const noexcept;
size_t FindAttrIndex(const size_t index,
size_t* const pApplies) const;
std::vector<uint16_t> GetHyperlinks();
bool SetAttrToEnd(const UINT iStart, const TextAttribute attr);
void ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept;
void Resize(const size_t newWidth);
[[nodiscard]] HRESULT InsertAttrRuns(const gsl::span<const TextAttributeRun> newAttrs,
const size_t iStart,
const size_t iEnd,
const size_t cBufferWidth);
static std::vector<TextAttributeRun> PackAttrs(const std::vector<TextAttribute>& attrs);
bool SetAttrToEnd(uint16_t beginIndex, TextAttribute attr);
void ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith);
void Resize(uint16_t newWidth);
void Replace(uint16_t beginIndex, uint16_t endIndex, const TextAttribute& newAttr);
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
@@ -69,17 +55,14 @@ public:
const_iterator cend() const noexcept;
friend bool operator==(const ATTR_ROW& a, const ATTR_ROW& b) noexcept;
friend class AttrRowIterator;
friend class ROW;
private:
void Reset(const TextAttribute attr);
boost::container::small_vector<TextAttributeRun, 1> _list;
size_t _cchRowWidth;
rle_vector _data;
#ifdef UNIT_TESTING
friend class AttrRowTests;
friend class CommonState;
#endif
};

View File

@@ -1,136 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "AttrRowIterator.hpp"
#include "AttrRow.hpp"
AttrRowIterator AttrRowIterator::CreateEndIterator(const ATTR_ROW* const attrRow) noexcept
{
AttrRowIterator it{ attrRow };
it._setToEnd();
return it;
}
AttrRowIterator::AttrRowIterator(const ATTR_ROW* const attrRow) noexcept :
_pAttrRow{ attrRow },
_run{ attrRow->_list.cbegin() },
_currentAttributeIndex{ 0 },
_exceeded{ false }
{
}
AttrRowIterator::operator bool() const noexcept
{
return !_exceeded && _run < _pAttrRow->_list.cend();
}
bool AttrRowIterator::operator==(const AttrRowIterator& it) const noexcept
{
return (_pAttrRow == it._pAttrRow &&
_run == it._run &&
_currentAttributeIndex == it._currentAttributeIndex &&
_exceeded == it._exceeded);
}
bool AttrRowIterator::operator!=(const AttrRowIterator& it) const noexcept
{
return !(*this == it);
}
AttrRowIterator& AttrRowIterator::operator+=(const ptrdiff_t& movement)
{
if (!_exceeded)
{
if (movement >= 0)
{
_increment(gsl::narrow<size_t>(movement));
}
else
{
_decrement(gsl::narrow<size_t>(-movement));
}
}
return *this;
}
AttrRowIterator& AttrRowIterator::operator-=(const ptrdiff_t& movement)
{
return this->operator+=(-movement);
}
const TextAttribute* AttrRowIterator::operator->() const
{
THROW_HR_IF(E_BOUNDS, _exceeded);
return &_run->GetAttributes();
}
const TextAttribute& AttrRowIterator::operator*() const
{
THROW_HR_IF(E_BOUNDS, _exceeded);
return _run->GetAttributes();
}
// Routine Description:
// - increments the index the iterator points to
// Arguments:
// - count - the amount to increment by
void AttrRowIterator::_increment(size_t count) noexcept
{
while (count > 0)
{
const size_t runLength = _run->GetLength();
if (count + _currentAttributeIndex < runLength)
{
_currentAttributeIndex += count;
return;
}
else
{
count -= runLength - _currentAttributeIndex;
++_run;
_currentAttributeIndex = 0;
}
}
}
// Routine Description:
// - decrements the index the iterator points to
// Arguments:
// - count - the amount to decrement by
void AttrRowIterator::_decrement(size_t count) noexcept
{
while (count > 0)
{
// If there's still space within this color attribute to move left, do so.
if (count <= _currentAttributeIndex)
{
_currentAttributeIndex -= count;
return;
}
// If there's not space, move to the previous attribute run
// We'll walk through above on the if branch to move left further (if necessary)
else
{
// make sure we don't go out of bounds
if (_run == _pAttrRow->_list.cbegin())
{
_exceeded = true;
return;
}
count -= _currentAttributeIndex + 1;
--_run;
_currentAttributeIndex = _run->GetLength() - 1;
}
}
}
// Routine Description:
// - sets fields on the iterator to describe the end() state of the ATTR_ROW
void AttrRowIterator::_setToEnd() noexcept
{
_run = _pAttrRow->_list.cend();
_currentAttributeIndex = 0;
}

View File

@@ -1,80 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- AttrRowIterator.hpp
Abstract:
- iterator for ATTR_ROW to walk the TextAttributes of the run
- read only iterator
Author(s):
- Austin Diviness (AustDi) 04-Jun-2018
--*/
#pragma once
#include "TextAttribute.hpp"
#include "TextAttributeRun.hpp"
class ATTR_ROW;
class AttrRowIterator final
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = TextAttribute;
using difference_type = std::ptrdiff_t;
using pointer = TextAttribute*;
using reference = TextAttribute&;
static AttrRowIterator CreateEndIterator(const ATTR_ROW* const attrRow) noexcept;
AttrRowIterator(const ATTR_ROW* const attrRow) noexcept;
operator bool() const noexcept;
bool operator==(const AttrRowIterator& it) const noexcept;
bool operator!=(const AttrRowIterator& it) const noexcept;
AttrRowIterator& operator++() noexcept
{
_increment(1);
return *this;
}
AttrRowIterator operator++(int) noexcept
{
auto copy = *this;
_increment(1);
return copy;
}
AttrRowIterator& operator+=(const ptrdiff_t& movement);
AttrRowIterator& operator-=(const ptrdiff_t& movement);
AttrRowIterator& operator--() noexcept
{
_decrement(1);
return *this;
}
AttrRowIterator operator--(int) noexcept
{
auto copy = *this;
_decrement(1);
return copy;
}
const TextAttribute* operator->() const;
const TextAttribute& operator*() const;
private:
boost::container::small_vector_base<TextAttributeRun>::const_iterator _run;
const ATTR_ROW* _pAttrRow;
size_t _currentAttributeIndex; // index of TextAttribute within the current TextAttributeRun
bool _exceeded;
void _increment(size_t count) noexcept;
void _decrement(size_t count) noexcept;
void _setToEnd() noexcept;
};

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