Compare commits

..

170 Commits

Author SHA1 Message Date
Dustin L. Howett
a223d3f5fa Migrate spelling-0.0.21 changes from main 2021-06-14 19:20:30 +02:00
Dustin L. Howett
efd305e9eb Migrate spelling-0.0.19 changes from main 2021-06-14 19:20:30 +02:00
kovdu
428f2a752b 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.

(cherry picked from commit 1cc383f865)
2021-07-07 13:12:45 -05:00
kovdu
37850bfe7f 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.

(cherry picked from commit 813f385c08)
2021-07-07 13:11:22 -05:00
Dustin L. Howett
3042ac5d2c 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

(cherry picked from commit b6593216f2)
2021-07-07 13:08:03 -05:00
Chester Liu
1934e72d6e Don't notify a11y event when in ConPTY mode (#10537)
Don't notify a11y event when in ConPTY mode

In support of #10528

(cherry picked from commit 59239e3b07)
2021-07-07 13:05:54 -05:00
Dustin L. Howett
caeb5b5db7 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

(cherry picked from commit 2770228e09)
2021-07-07 13:04:57 -05:00
Carlos Zamora
cedbee42e0 [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.

(cherry picked from commit 79a18f0825)
2021-07-07 12:57:32 -05:00
WSLUser
7f63434055 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.

(cherry picked from commit e3b7a44b13)
2021-07-07 12:57:31 -05:00
Dustin L. Howett
bbc4a904ee 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.

(cherry picked from commit c90de69250)
2021-07-07 12:57:31 -05:00
Dustin L. Howett
dbf9ee93a3 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_.

(cherry picked from commit 31a39b3b12)
2021-07-07 12:28:42 -05:00
Leonard Hecker
ebabf32f71 Fix racy access to _tsfTryRedrawCanvas in TermControl in v1.8 2021-07-03 01:37:35 +02:00
Mike Griese
6617eb33ac 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.

(cherry picked from commit 89ca2ae05f)
2021-05-28 17:28:01 -05:00
Dustin Howett
4a3f173e17 Revert "Disable path validation, add warning (#10045)"
This reverts commit 3c30877294.
2021-05-28 11:59:19 -05:00
Dustin Howett
646904c3c2 Fix a bad backport in a3de0d0ec 2021-05-24 17:35:18 -05:00
Dustin Howett
cb4c4f7b73 [STABLE ONLY] Combined revert of Environment Block Changes
Revert "Fix environment block creation (#7401)"

This reverts commit 7886f16714.

(cherry picked from commit e46ba65665)

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

This reverts commit 849243af99.

References #7418

(cherry picked from commit 4204d2535c)
(cherry picked from commit f8e8572c23)
2021-05-24 17:13:53 -05:00
PankajBhojwani
3c64fcd12b 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

(cherry picked from commit f518235599)
2021-05-24 17:08:48 -05:00
Leon Liang
7264d5cc43 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

(cherry picked from commit f7458a31fd)
2021-05-24 17:07:17 -05:00
Leonard Hecker
5756236362 Split ThrottledFunc into Leading and Trailing variants (#10133)
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

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

* [x] I work here
* [ ] Tests added/passed

* [x] Ensured scrolling still works

(cherry picked from commit 13f0b8e007)
2021-05-24 17:04:05 -05:00
Dustin L. Howett
6e907fd5f2 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.

(cherry picked from commit 84f6a29d89)
2021-05-24 17:02:26 -05:00
kovdu
afd6a87de5 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

(cherry picked from commit dd348dccda)
2021-05-24 16:58:06 -05:00
Mike Griese
a3de0d0ece 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

(cherry picked from commit 52560ff818)

# Conflicts:
#	src/cascadia/TerminalApp/TerminalPage.cpp
#	src/cascadia/TerminalApp/TerminalPage.h
2021-05-24 14:23:34 -05:00
Mike Griese
a2ab200e88 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

(cherry picked from commit 24f80bd9ba)
2021-05-24 12:31:29 -05:00
Dustin Howett
90e78ec074 Revert "Revert "In specific scenarios, focus the active control (#10048)""
This reverts commit c8ab75b265.
2021-05-24 12:31:16 -05:00
Mike Griese
3c30877294 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)

(cherry picked from commit bfc4838042)
2021-05-24 11:51:24 -05:00
Dustin L. Howett
e593c46679 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.

(cherry picked from commit 89af44488f)
2021-05-24 11:50:07 -05:00
Michael Niksa
a736712da9 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

(cherry picked from commit 66fdc645f7)

# Conflicts:
#	src/cascadia/Remoting/Monarch.cpp
#	src/cascadia/Remoting/Peasant.cpp
#	src/cascadia/WindowsTerminal/IslandWindow.cpp
2021-05-17 16:39:09 -05:00
Dustin L. Howett
0499604eee Fix a number of shutdown crashes in TermControl (#10115)
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-17 14:23:05 -05:00
Dustin Howett
c8ab75b265 Revert "In specific scenarios, focus the active control (#10048)"
This reverts commit b345d39c1d.
2021-05-14 12:55:18 -05:00
Mike Griese
b345d39c1d 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.

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

* [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

(cherry picked from commit 8564b269c4)
2021-05-14 12:26:58 -05:00
MPela
c4e02e7274 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)

(cherry picked from commit 2065fa7b76)
2021-05-14 12:25:14 -05:00
Dustin Howett
cb7f481c95 Revert "[RELEASE ONLY] Remove the close submenu (#9102)"
This reverts commit c951a70208.
2021-05-14 12:25:08 -05:00
Don-Vito
69397b3797 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).

(cherry picked from commit cb55cec275)
2021-05-14 12:22:04 -05:00
MPela
e7ec200f34 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

(cherry picked from commit 2b4c20bd6e)
2021-05-14 12:22:03 -05:00
Javier
ba07f65eb9 [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.

(cherry picked from commit 31414aa364)
2021-05-14 12:22:03 -05:00
Carlos Zamora
0e810d2c35 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

(cherry picked from commit 8f93f76214)
2021-05-14 12:22:02 -05:00
Mike Griese
ed3feef213 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

(cherry picked from commit aa54de1d64)
2021-05-14 12:22:02 -05:00
Don-Vito
ca71ac4100 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.

(cherry picked from commit 6b4f70e985)
2021-05-14 12:22:02 -05:00
PankajBhojwani
fba9493dbb 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.

(cherry picked from commit ad34291632)
2021-05-14 12:22:01 -05:00
Don-Vito
ac864d2c65 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.

(cherry picked from commit 05e7ea1423)
2021-05-14 12:22:01 -05:00
Don-Vito
89032b8b1c 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.

(cherry picked from commit cdbcc17458)
2021-05-14 12:22:00 -05:00
Don-Vito
c2cb365c62 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

(cherry picked from commit 3368e602fd)
2021-05-14 12:22:00 -05:00
Don-Vito
76a609b3ae 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.

(cherry picked from commit 9a2d27e9f6)
2021-05-14 12:21:55 -05:00
Leonard Hecker
99e0f95318 Fix crash on exit introduced in ac265aa (#10042)
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.

This crash was introduced in #10031.

* [x] I work here
* [x] Tests added/passed

* Run accevent.exe to cause a UiaEngine to be attached to a TermControl.
* Close the current tab
* Ensured no crashes occur

(cherry picked from commit 43040ef9d0)
(cherry picked from commit ad45139bb4)
2021-05-14 12:17:46 -05:00
Leonard Hecker
2c0889223a Backport hotfix ac265aa to v1.8 (#10033)
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.
2021-05-04 17:54:29 -05:00
Dustin L. Howett
aad3855287 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

(cherry picked from commit 21b2e01643)
2021-04-19 16:15:35 -05:00
Kayla Cinnamon
4c09a235cc doc: Add tabColor to JSON schema (#9843)
(cherry picked from commit 8bcb47339d)
2021-04-15 12:32:42 -05:00
Dustin L. Howett
8078db5fd5 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

(cherry picked from commit dab52c46a2)
2021-04-13 16:17:52 -05:00
Evan Koschik
f2afb223f5 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.

(cherry picked from commit bc1ff0b71a)
(cherry picked from commit 14a7e45280)
2021-04-13 15:44:42 -05:00
Dustin L. Howett
9882e9f835 Remove the splash screen (to save 100kb (compressed!)) (#9795)
We're a Centennial application; we can't even _use_ the splash screen.

(cherry picked from commit ab6f41f4bd)
2021-04-13 12:52:42 -05:00
Dustin L. Howett
6072be5436 [RELEASE ONLY] Remove the close submenu (#9102)
There's a platform issue that causes it to crash.
Fixes #8944.

(cherry picked from commit 5fdd1560fd)
(cherry picked from commit c951a70208)
2021-04-13 09:14:05 -05:00
Dustin Howett
bc368b7c29 Disable handoff registration (only) for preview in 1.8
Handoff will still be accepted if the registry is set up properly.
2021-04-13 09:11:21 -05:00
Dustin Howett
2219014385 Merge remote-tracking branch 'openconsole/inbox' into main 2021-04-13 09:06:06 -05:00
Don-Vito
b8e36bae9f Prevent mouse dragging from dismissing existing selection (#9790)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9787
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. 

## Validation Steps Performed
* [x] single click = no selection
* [x] single click and drag = selection starting from first point
* [x] single click in unfocused pane and drag = focus pane, selection starting from first point
* [x] double-click = selects a whole word
* [x] triple-click = selects a whole line
* [x] double-click and drag = selects a whole word, drag selects whole words
* [x] triple-click and drag = selects a whole line, drag selects whole lines
* [x] Shift single-click = defines start point
* [x] second Shift single-click = defines end point
* [x] Shift double-click = selects entire word
* [x] Shift triple-click = selects entire line
* [x] Shift double-click and drag = selects entire word, drag selects whole words
* [x] Mouse mode: Shift single-click = defines start point
* [x] Mouse mode: second Shift single-click = defines end point
* [x] Mouse mode: Shift double-click = selects entire word
* [x] Mouse mode: Shift triple-click = selects entire line
* [x] Mouse mode: Shift double-click and drag = selects entire word, drag selects whole words
* [x] With existing selection: single-click outside the selection and drag = establishes a new selection starting from the click point 
* [x] Click-drag to set selection, shift-click-drag outside of selection = extend selection while dragging
2021-04-12 23:32:22 +00:00
PankajBhojwani
7df4b3c823 Fix for some profiles.defaults settings not working (#9764)
Fix for profiles.defaults.colorScheme not working 
Fix for background image only showing up after a settings reload

Closes #9761
2021-04-12 18:21:56 +00:00
Dustin L. Howett
8f79f7c4c8 Propagate the hosting HWND to the new IFileDialogs (#9789)
This is required to maintain the modality of the dialogs, which we lost
when we moved from Pickers to IFileDialog. The HWND hosting Window API
we dreamed up is incompatible with IModalDialog, because IModalDialog
requires the HWND immediately upon `Show`. We're smuggling it in a
uint64, as is tradition.

zadjii-msft noticed this in #9760.
2021-04-12 16:55:51 +00:00
James Holderness
83bd241cd2 Remove unused methods in ConGetSet and SCREEN_INFORMATION (#9772)
This PR removes the `GetConsoleCursorInfo` and `SetConsoleCursorInfo`
methods from the `ConGetSet` interface, and the `GetScrollingRegion`
method from the `SCREEN_INFORMATION` class. None of these methods are
used anymore.

PR #2764 removed the last usage of `GetScrollingRegion`. 

The `Get/SetConsoleCursorInfo` methods don't seem to have ever been used
in the time that the terminal code has been open source, so whatever
purpose they originally served must have been replaced a long time ago.

The `GetScrollingRegion` method was originally called from the
`ScrollRegion` function, but that usage was removed in PR #2764 when the
margin handling was moved to a higher level.

I've checked that the code still compiles.

Closes #9771
2021-04-12 15:35:14 +00:00
hessedoneen
9a276c6371 Bind Ctrl+Numpad Plus,Minus to the font size controls (#9753)
"ctrl+numpad_plus" command now increases font size and
"ctrl+numpad_minus" command now decreases font size.

Before this only "ctrl+=" and "ctrl+-" controlled font size. Increase in
font size follows previous convention where zooms in arbitrarily large,
but decrease in font size is capped.

## Validation Steps Performed
I first ran "ctrl+=" and "ctrl+-" in my terminal to verify its behavior,
then compared that against "ctrl+numpad_plus" and "ctrl+"numpad_minus".
Both increased and decreased the font size by the same amount, and both
appeared to have a cap for how small they could get, but did not appear
to have a cap for how big they could get.

Closes #7518
2021-04-12 15:07:46 +00:00
Don-Vito
ca9e5e0fb0 Trigger taskbar progress evaluation upon pane activation (#9779)
Trigger TaskbarProgressChanged every time we switch between active panes
(to update the tab header if required).

Closes #9743
2021-04-12 15:05:52 +00:00
Don-Vito
912bd4dadb Remove the icon grid column from the Actions page (#9780)
Closes #9715
2021-04-12 15:04:27 +00:00
Don-Vito
a9a58f7156 Handle switch to tab binding even if tab doesn't exist (#9781)
Closes #9635
2021-04-12 15:03:59 +00:00
Breece W
d367c6b6b0 Smoothen close caption button animation (#9763)
The red close button animation fades to gray then to transparent, when
standard behavior skips the gray part. I manually tested in light/dark/high
contrast mode.

Closes #9762
2021-04-12 13:13:18 +00:00
Dustin L. Howett
959c423e7a Replace Windows.Storage.Pickers with Common File Dialogs (#9760)
Using Pickers from an elevated application yields an
ERROR_ACCESS_DENIED. Of course it does: it was designed for the modern
app platform.

Using the common dialog infrastructure has some downsides¹, but it
doesn't crash and is just as flexible.

I've added some fun templated functions that help us with the
complexity.

Fixes #8957

¹You've got to use raw COM, and it runs in-proc instead of out-of-proc.

## Validation Steps Performed
I tested every picker.
2021-04-12 13:12:08 +00:00
Dustin L. Howett
b310b1cffc Give our NavigationView's acrylic a fallback color (#9752)
It will be a different color than the background, so it will look less
weird when it's unfocused. It also fixes the bug where the navigation
menu is transparent when acrylic is disabled systemwide.

Fixes #9337
2021-04-09 10:43:15 +00:00
PankajBhojwani
9e83655b08 Add support for a profile to specify an "unfocused" appearance (#8392)
This pull request adds an appearance configuration object to our
settings model and app lib, allowing the control to be rendered
differently depending on its state, and then uses it to add support for
an "unfocused" appearance that the terminal will use when it's not in
focus.

To accomplish this, we isolated the appearance-related settings from
Profile (into AppearanceConfig) and TerminalSettings (into the
IControlAppearance and ICoreAppearance interfaces). A bunch of work was
done to make inheritance work.

The unfocused appearance inherits from the focused one _for that
profile_. This is important: If you define a
defaults.unfocusedAppearance, it will apply all of defaults' settings to
any leaf profile when a terminal in that profile is out of focus.

Specified in #8345 
Closes #3062
Closes #2316
2021-04-08 22:46:16 +00:00
Michael Niksa
7f5a19b627 Reduce instances of font fallback dialog (#9734)
Reduce instances of font fallback dialog through package font loading,
basic name trimming, and revised fallback test

- Adjusts the font dialog to only show when we attempt last-chance
  resolution from our hardcoded list of font names with a flag instead
  of with a string comparison by name
- Adds a resolution step to trim the font name by word from the end and
  retry to attempt to resolve a proper font that just has a weight
  suffix
- Adds a second font collection to font loading that will attempt to
  locate all TTF files sitting next to our binary, like in our package

- [x] Wrote my font preference in the JSON as `Cascadia Code Heavy` and
  watched it quietly resolve to just `Cascadia Code` without the dialog.
- [x] Put a font that isn't registered with the system into the layout
  directory for the package, set it as my desired font in Terminal, and
  watched it load just fine.
- [x] Try a font name with different casing and see if dialog doesn't
  pop anymore
- [x] Try a font with different (localized) names like MS ゴシック and
  see if dialog doesn't pop anymore
- [x] Check Win7 with WPF target

Closes #9375
2021-04-08 17:49:07 +00:00
Dustin Howett
8e7a866b06 Merged PR 5903250: [Git2Git] Merged PR 5895926: conhost: fix two moderately high-hitting Watsons
This commit fixes two issues:

1. We were pushing ConsoleWaitBlocks into the wait queue before they
   were fully constructed. This resulted in the wait being called before
   it even had an API message in it. [MSFT-24113101]
2. Drawing DBCS characters and resizing (a lot) would cause a crash
   because of an invalid DBCS cell state. This hits in both Terminal and
   conhost. [MSFT-17364373] [GH-4907]

The DBCS state check was promoted from an NT_ASSERT (which never fired
in release) to a FAIL_FAST in !1794053. The console kept chugging along
without failing in fre for all those years.

Fixes MSFT-24113101
Fixes MSFT-17364373
Fixes GH-4907 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 108e746630749aa7851dd813b19e013ae31ef0db
2021-04-08 17:29:47 +00:00
Chester Liu
ed1cd32f1f Disable warning about multi-line paste when brackted paste is on (#9586)
Closes #7006
2021-04-07 18:13:50 +00:00
Mike Griese
361877cf1b Match the RequestedTheme of our TeachingTips to the set theme (#9732)
## Summary of the Pull Request

Make sure that the window renamer and other toasts follow the requested app theme. We accomplish this by doing something similar to what we do with ContentDialogs. Since TeachingTips aren't in the same XAML root, we have to traverse the entire tree upwards setting RequestedTheme. If we don't, then we'll update the background color of the TeachingTip, but not the text inside it. 

## References
* Added in #9662 and #9523 

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

## Validation Steps Performed
Tested with system theme light & dark, and `theme` set to `light, dark, and unset, and verified that they worked as expected.
2021-04-07 15:27:41 +00:00
Mike Griese
cdf2630204 Add support for LightDismissing the renamer (#9733)
## Summary of the Pull Request

Huh, I guess I missed making the window renamer light-dismissable. This is a oneline fix for that.

Light dismissing is treated as a _cancel_, not as a commit. 

## References
* Added in #9662

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

## Validation Steps Performed

This feels right.
2021-04-07 00:12:41 +00:00
Mike Griese
c3f968b6c6 Stylize the renamer Action button as a Accent button (#9728)
Closes #9719
2021-04-06 14:25:18 -05:00
Don-Vito
e80e9b9e96 Fix marking of new selection start (#9727)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9725
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. 

## Validation Steps Performed
* [x] single click = no selection
* [x] single click and drag = selection starting from first point
* [x] single click in unfocused pane and drag = focus pane, selection starting from first point
* [x] double-click = selects a whole word
* [x] triple-click = selects a whole line
* [x] double-click and drag = selects a whole word, drag selects whole words
* [x] triple-click and drag = selects a whole line, drag selects whole lines
* [x] Shift single-click = defines start point
* [x] second Shift single-click = defines end point
* [x] Shift double-click = selects entire word
* [x] Shift triple-click = selects entire line
* [x] Shift double-click and drag = selects entire word, drag selects whole words
* [x] Mouse mode: Shift single-click = defines start point
* [x] Mouse mode: second Shift single-click = defines end point
* [x] Mouse mode: Shift double-click = selects entire word
* [x] Mouse mode: Shift triple-click = selects entire line
* [x] Mouse mode: Shift double-click and drag = selects entire word, drag selects whole words
* [x] With existing selection: single-click outside the selection and drag = establishes a new selection starting from the click point
2021-04-06 19:17:26 +00:00
Mike Griese
6ca35b4445 Manually handle Enter and Escape in the Window Renamer (#9730)
## Summary of the Pull Request

In exactly the same fashion as the tab renamer, handle <kbd>Enter</kbd> for committing the rename, and <kbd>Escape</kbd> for dismissing the rename.

## References
* Added in #9662

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

## Validation Steps Performed
Played with it - this feels good.
2021-04-06 19:12:08 +00:00
Mike Griese
b0c07ef1eb Add identifyWindow(s?) to the schema (#9726)
Fixes #9721.
2021-04-06 14:11:29 -05:00
Leonard Hecker
faf372f165 Resolve circular reference in ThrottledFunc (#9729)
## Summary of the Pull Request

ThrottledFunc previously created a DispatcherTimer whose Tick callback holds a strong reference to the DispatcherTimer itself.
This causes a reference cycle, inadvertently leaking timer instances.

## PR Checklist

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

## Detailed Description of the Pull Request / Additional comments

I've initially wanted to remove the `ThrottledFunc<>` optimization, but it turns out that this causes a 3% slowdown. That's definitely not a lot, but enough that we can just keep the optimization for the time being.
I've moved the implementation from the .cpp file into the header regardless since the two implementations are extremely similar and it's easier that way to keep them in line.

## Validation Steps Performed

I've ensured that the scrollbar still updates its length when I add new lines to a newly created tab.
2021-04-06 19:07:49 +00:00
Ikko Ashimine
ebd07d7125 Fix typo in replace.h (#9679)
occurences -> occurrences
2021-04-06 10:38:51 -05:00
Mike Griese
24b9a7a247 Create a control unittesting project (#9677)
Does what it says on the can.

This is a follow up to #9472. Now that we have a control .lib, we can add tests for it. 

Unfortunately, the `TermControl` itself is a horrible mess. So this new unittest lib is empty for now. I'm working on actual tests as a part of #6842, but this PR is here to keep the diffs smaller.

Also, apparently `server.vcxproj` had the wrong GUID in it.

* [x] I work here
* [x] Adds tests
2021-04-05 16:07:55 +00:00
Dustin L. Howett
6f754a61eb Fix bad merge in c585a93fc (CloseRequested) that broke closing (#9695)
This fixes right-click > "Close" on TerminalTab

Fixes bug bash issue.
2021-04-05 12:25:06 +00:00
Mike Griese
fb597ed304 Add support for renaming windows (#9662)
## Summary of the Pull Request

This PR adds support for renaming windows.

![window-renaming-000](https://user-images.githubusercontent.com/18356694/113034344-9a30be00-9157-11eb-9443-975f3c294f56.gif)
![window-renaming-001](https://user-images.githubusercontent.com/18356694/113034452-b5033280-9157-11eb-9e35-e5ac80fef0bc.gif)


It does so through two new actions:
* `renameWindow` takes a `name` parameter, and attempts to set the window's name
  to the provided name. This is useful if you always want to hit <kbd>F3</kbd>
  and rename a window to "foo" (READ: probably not that useful)
* `openWindowRenamer` is more interesting: it opens a `TeachingTip` with a
  `TextBox`. When the user hits Ok, it'll request a rename for the provided
  value. This lets the user pick a new name for the window at runtime.

In both cases, if there's already a window with that name, then the monarch will
reject the rename, and pop a `Toast` in the window informing the user that the
rename failed. Nifty!

## References
* Builds on the toasts from #9523
* #5000 - process model megathread

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50771747
* [x] I work here
* [x] Tests addded (and pass with the help of #9660)
* [ ] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

I'm sending this PR while finishing up the tests. I figured I'll have time to sneak them in before I get the necessary reviews.

> PAIN: We can't immediately focus the textbox in the TeachingTip. It's
> not technically focusable until it is opened. However, it doesn't
> provide an even tto tell us when it is opened. That's tracked in
> microsoft/microsoft-ui-xaml#1607. So for now, the user _needs_ to
> click on the text box manually.
> We're also not using a ContentDialog for this, because in Xaml
> Islands a text box in a ContentDialog won't recieve _any_ keypresses.
> Fun!

## Validation Steps Performed

I've been playing with 

```json
        { "keys": "f1", "command": "identifyWindow" },
        { "keys": "f2", "command": "identifyWindows" },
        { "keys": "f3", "command": "openWindowRenamer" },
        { "keys": "f4", "command": { "action": "renameWindow", "name": "foo" } },
        { "keys": "f5", "command": { "action": "renameWindow", "name": "bar" } },
```

and they seem to work as expected
2021-04-02 16:00:04 +00:00
Dustin L. Howett
4b7d955012 dx: add support for inverting all types of cursor (#9665)
This commit introduces support for inverting all types of cursor.

To invert the display without re-rendering any text, we draw the cursor
into a command list and then compose the command list with the existing
renderer using the MASK_INVERT composition flag.

This wouldn't normally work with our renderer because there is no
_background_ color to invert in some cases (such as when acrylic is in
use.)

To work around that, we're taking advantage of @zadjii-msft's two-pass
cursor renderer.

To properly invert the cursor over a transparent background:
(Examples are given below for two cursor types, but this applies to all
of them.)

First, we'll draw a "backplate" in the user's requested background color
(with the alpha channel set to 0xFF). (`firstPass` == true)

    EMPTY BOX  FILLED BOX
    =====      =====
    =   =      =====
    =   =      =====
    =   =      =====
    =====      =====

Second, the glyph is drawn (outside of the cursor renderer).

    EMPTY BOX  FILLED BOX
    ==A==      ==A==
    =A A=      =A=A=
    AAAAA      AAAAA
    A   A      A===A
    A===A      A===A

Last, we'll draw the cursor again in all white and use that as the
*mask* for inverting the already-drawn pixels. (`firstPass` == false) (#
= mask, a = inverted A)

    EMPTY BOX  FILLED BOX
    ##a##      ##a##
    #A A#      #a#a#
    aAAAa      aaaaa
    a   a      a###a
    a###a      a###a

Related to #9610

## Validation Steps Performed
Manual visual validation in all configurations.
2021-04-02 11:18:06 +00:00
Kayla Cinnamon
fd99b012f5 Remove default terminal item from SUI (#9671)
Looks like we forgot to comment out the Default terminal setting from the UI.

Commented it out here.
2021-03-31 18:50:40 +00:00
Mike Griese
c09472347c Add X Macro for fun and for profit (#9667)
**Summary of the Pull Request**

This PR adds an X Macro for defining our ShortcutActions. This means that you can add the action in one place, and have the macro synthesize all sorts of boilerplate for you!

From the `AllShortcutActions.h` file:

> For a clearer explanation of how this file should be used, see:
> https://en.wikipedia.org/wiki/X_Macro
>
> Include this file to be able to quickly define some code in the exact same
> way for _every single shortcut action_. To use:
>
> 1. Include this file
> 2. Define the ON_ALL_ACTIONS macro with what you want each action to show up
>    as. Ex:
>
>    #define ON_ALL_ACTIONS(action) void action##Handler();
>
> 3. Then, use the ALL_SHORTCUT_ACTIONS macro to get the ON_ALL_ACTIONS marcro
>    repeated once for every ShortcutAction
>
> This is used in KeyMapping.idl, ShortcutAction.*, TerminalPage.*, etc. to
> reduce the number of places where we must copy-paste boiler-plate code for
> each action. This is _NOT_ something that should be used when any individual
> case should be customized.

**PR Checklist**
* [x] Scratches an itch
* [x] I work here
* [x] Tests passed
* [n/a] Requires documentation to be updated

**Detailed Description of the Pull Request / Additional comments**

Originally I had this blocked as a follow up to #9662. However, I've grown tired after a month of merging main into this branch, and I'm just shipping it separately. It will inevitably conflict with anyone who has actions in flight currently.

**Validation Steps Performed**
The code still builds exactly as before!
2021-03-31 16:38:25 +00:00
Dustin L. Howett
07c5735471 Move Branding into common props (#9668) 2021-03-30 18:08:53 -05:00
Dustin Howett
940254dd57 Fix variable shadowing in exemain from bad merge
Signed-off-by: Michael Niksa <miniksa@microsoft.com>
2021-03-30 17:43:48 -05:00
Dustin Howett
9d729a50b0 Merge remote-tracking branch 'openconsole/inbox' into HEAD 2021-03-30 16:10:49 -05:00
Gabriel C
8f16fdd817 Fix rightmost tab corner (#9575)
Before and after:
![image](https://user-images.githubusercontent.com/78622729/111928492-710b9000-8abc-11eb-9760-0ecd3eb038fb.png)

The bottom right corner appeared without a radius because of the custom padding.
2021-03-30 21:03:33 +00:00
Mike Griese
5ab78fcafb Another fix for the localtests, March 2021 edition (#9660)
Broadly, the tests were broken by #7489 because there were no `_startupActions`. They relied on the removed codepath that assumed `wt.exe` always set actions, or `AppCommandlineArgs::ValidateStartupCommands` created one by default.

* [x] fixes #9659
* [x] I work here
* [x] the tests pass again
2021-03-30 20:38:43 +00:00
Mike Griese
69df0de6bf Add a sample outline shader (#9646)
I accidentally the whole thing

## References
* Heavily inspired by the original rasterbars shader.

## PR Checklist
* [x] Closes #9010
2021-03-30 15:37:53 -05:00
Dustin L. Howett
295fa38295 Introduce MS.Term.Core.Color to replace W.U.Color for Core/Control/TSM (#9658)
This pull request introduces Microsoft.Terminal.Core.Color as an
alternative to both Windows.UI.Color and uint32_t/COLORREF in the
TerminalCore, ...Control, ...SettingsModel and ...SettingsEditor layers.

M.T.C.Color is trivially convertible to/from til::color and therefore
to/from COLORREF, W.U.Color, and any other color representation we might
need².

I've replaced almost every use of W.U.Color and uint32_t-as-color in the
above layers, with minor exception¹.

The need for this work is twofold.

First: We cannot bear a dependency from TerminalCore (which should,
on paper, be Windows 7 compatible) on Windows.UI or any other WinRT
namespace.

This work removes one big dependency on Windows.UI, but it does not go
all the way.

Second: TerminalCore chose to communicate mostly in packed uint32s
(COLORREF), which was inherently lossy and dangerous.

¹ The UI layers (TerminalControl, TerminalApp) still use
Windows.UI.Color as they are intimately connected to the UWP XAML UI.

² In the future, we might even be able to *use* the alpha channel...

## PR Checklist
* [x] I ran into the need for this when I introduced cursor inversion
* [X] Fixes a longstanding itch

## Validation Steps Performed
Built and ran all tests for the impacted layers, even the local ones!
2021-03-30 20:15:49 +00:00
Mike Griese
03ea0f49ad Add an action for identifying windows (#9523)
## Summary of the Pull Request

This is a follow up to #9300. Now that we have names on our windows, it would be nice to see who is named what. So this adds two actions:

* `identifyWindow`: This action will pop up a little toast (#8592) displaying the name and ID of the window, and is bound by default.
![identify-window-toast-000](https://user-images.githubusercontent.com/18356694/111529085-bf710580-872f-11eb-8880-b0b617596cfc.gif)

* `identifyWindows`: This action will request that ALL windows pop up that toast. This is meant to feel like the "Identify" button on the Windows display settings. However, sometimes, it's wonky. 
  ![teaching-tip-dismiss-001](https://user-images.githubusercontent.com/18356694/111529292-fe06c000-872f-11eb-8d4a-5688e4ce1175.gif)
  That's being tracked upstream on https://github.com/microsoft/microsoft-ui-xaml/issues/4382
  Because it's so wonky, we won't bind that by default. Maybe if we get that fixed, then we'll change the default binding from `identifyWindow` to `identifyWindows`


## References

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

## Detailed Description of the Pull Request / Additional comments

You may note that there are some macros to make interacting with lots and lots of actions easier. There's a lot of boilerplate whenever you need to make a new action, so I thought: "Can we make that easier?" 

Turns out you can make it a _LOT_ easier, but that work is still behind another PR after this one. Get excited
2021-03-30 16:08:03 +00:00
Don-Vito
c585a93fc9 Separate between Close Tab Requested and Tab Closed flows (#9574)
## Summary of the Pull Request
Currently, both when the tab is already closed, and when there is a
request to close a tab (might be rejected), we go through the same flow
in TerminalPage.

This might leave the system in inconsistent state, as the side-effects
of closing will persist even if the closing was aborted.

This PR separates between the two flows, by introducing a CloseRequested
event to the TabBase.

This event is used to inform the upper tier (the terminal page) about
the request and to trigger the same logic that happens when the tab is
closed directly from the terminal page (e.g., by clicking close on the
tab view).

The Closed event will be  used only to handle the actual closing of the
tab. It will ensure that the tab gets removed from the terminal page if
required.

As a result, it a read-only pane will be closed non-interactively (aka
connection exits), the tab closed flow will be invoked, and no user
prompt will be shown.

## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9572
* [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.
2021-03-30 15:58:35 +00:00
Carlos Zamora
19fb9b21da Remove Base Layer from Settings UI (#9655)
Removes base layer (aka profiles.defaults) from the Settings UI. `SettingContainer` was also updated to not present a revert arrow when overriding a base layer value.

The new experience is now as follows:
- The revert arrow will only appear if you are overriding a value from a fragment extension.
- Users are still able to fully interact with `profiles.defaults` in their settings.json. Doing so still propagates those changes to their profiles as normal. In this case, the Settings UI presents the base layer value as the one that you selected.

#6800 - Settings UI Epic
Closes #9539
2021-03-30 15:15:37 +00:00
Michael Niksa
c7d2a818b0 Change TAEF nuget package to use new Microsoft.Taef name; Update to 10.58 release build version. (#9656)
Change TAEF nuget package to use new Microsoft.Taef name; Update to 10.58 release build version.

## PR Checklist
* [x] Closes email from Phil letting us know TAEF has a new release build and a rename.
* [x] Closes annoying duplicate TAEF import warning in `Parser.UnitTests.vcxproj`
* [x] I work here.
* [ ] Need to see the tests run off CI to confirm this is fine for those environments and Helix

## Validation Steps Performed
* [x] Build/run tests locally
* [ ] Build/run unit and feature tests in CI
* [ ] Build/run Helix-lab tests in CI
2021-03-30 10:58:11 +00:00
kovdu
cf5dc285a9 Sort fonts alphabetically (#9653)
Validated this only by following the issue description and verified fonts appeared to be sorted alphabetically now.

Closes #9594
2021-03-29 15:36:28 -07:00
Mike Griese
3323dc5724 Auto-format our XAML files and enforce in CI (#9589)
This adds [`XamlStyler.Console`] to our solution, and calls it when we
format the code, to also format
our .xaml files. 
* `XamlStyler.Console` is a dotnet tool so it needs to be restored with
  `dotnet tool restore`
* I've added a set of rules to approximately follow [@cmaneu's XAML guidelines].
  Those guidelines also recommend things based on the code-behind, which
  this tool can't figure out, but also _don't matter that much_.
* There's an extra step to strip BOMs from the output, since Xaml Styler
  adds a BOM by default. Some had them before and others didn't. BOMs
  have been nothing but trouble though.

[`XamlStyler.Console`]: https://github.com/Xavalon/XamlStyler
[@cmaneu's XAML guidelines]: https://github.com/cmaneu/xaml-coding-guidelines
2021-03-29 17:09:38 -05:00
Don-Vito
c19aa89123 Add splitMode to the args for split-pane (as -D for duplicate) (#9652)
Closes #9579
2021-03-29 17:06:05 -05:00
Michael Niksa
d6954244ad Fix ARM64 build by defining WIN32 (#9654)
By default from ARM64 architecture projects, `WIN32` is not defined. It
is supposed to be for this proxy stub to work. So I've set it with the
preprocessor for this project.

## PR Checklist
* [x] Closes release build failure after #7489 
* [x] I work here.
* [x] Built on my machine.

## Detailed Description of the Pull Request / Additional comments

`WIN32` appears to convey two meanings depending on who you are:
- To most of Windows, `WIN32` appears to mean the Win32 API surface and
  sometimes the major OS version that goes with it. (Specifically in
  contrast to 16-bit Windows.)
- To others, `WIN32` appears to mean a 32-bit processor or a synonym of
  `x86`.

This is generally not a problem for a few reasons:
- VS defines `WIN32` in the default targets/props only for the `x86`
  processor type. **BUT**
- Windows defines `WIN32` if it's not already defined in both
  `minwinbase.h` and `ole2.h` which generally speaking manage to get
  compiled into practically everything especially since `minwinbase.h`
  tends to sneak itself in somehow through `windows.h` and that's
  **THE** include to use the Windows API surface.
- Windows also defines `WIN32` for itself unconditionally and relatively
  globally when building itself.

However, it's a problem here because: 
- `rpcproxy.h` is the only header included in `dlldata.c`, a file
  generated automatically by `midl.exe` in the SDK when making a proxy
  stub.
- `rpcproxy.h` only defines its contents for a proxy when `WIN32` or
  `_M_AMD64` are found.
- Therefore, it's defined pretty naturally for x86 and AMD64 targets
  from VS, but not for ARM64.
- ARM64 support is pretty new and those who are attempting to build for
  ARM64 and against the public SDK with Visual Studio for a classic COM
  proxy... seems like a relatively unlikely combination.

I will follow up with the Visual Studio, Windows SDK, and MIDL/COM teams
to try to remove this pitfall from the public tooling. But for now, this
is the fix.
2021-03-29 16:43:58 -05:00
Dragos Sambotin
477c4d9986 Merged PR 5854784: [Git2Git] When V1 console fails to load, fail upwards to V2
This change introduces a fallback from v1 to v2 for SKUs of Windows that do not compose v1.

Related work items: MSFT-29352720
2021-03-29 15:40:27 -05:00
Michael Niksa
b67f40f4c4 Switch to create function as it will open if exists and create if not. 2021-03-29 15:35:16 -05:00
Dustin Howett
25527789c0 Reflect testlist change from OS 2021-03-29 15:24:43 -05:00
Mike Griese
eac3eea484 Add a --colorScheme param to new-tab, split-pane (#9602)
This is entirely self-serving. In my go-to config, I like having some of
the panes for a given profile in a different color scheme. This will let
a user pass `--colorScheme <scheme name>` to manually override the
scheme for that profile. Neat!
2021-03-29 20:04:39 +00:00
Mike Griese
ba543c0696 minor refactor: Move Tab management into its own file (#9629)
I think we can all agree that `TerminalPage.cpp` is an unruly beast of a
file. It's got everything. It does everything. It can sometimes be a bit
hard to work with, because of simply how big it is. This PR tries to
alleviate this by making `TerminalPage.cpp` just a little smaller. It
does so by moving pretty much everything related to tab management into
its own file, `TabManagement.cpp`. These methods that have moved are all
the same as they were before, and they're still members of
`TerminalPage`. But now they're all in one place. 

I tried to move all the references to `_tabs` in `TerminalPage.cpp`, but
there's still a few that I left behind. Mostly because I felt that
moving those would be too gnarly a code change for an otherwise simple
cut&paste PR.

There are a few new methods I introduced:
* `_TabDragStarted` and `_TabDragCompleted`: These were lambdas before,
  promoted to full methods. 
* `_DismissTabContextMenus`: Remove all the right-click context menus
  from the tabs
* `_FocusCurrentTab`: This one's a bit trickier, we were actually doing
  this in a few different places, so I tried consolidating.
* `_HasMultipleTabs`: This doesn't need explaining.
* `_RemoveAllTabs`: Really, just encapsulation for the sake of removing
  a `_tabs` from `TerminalPage.cpp`
* `_ResizeTabContent`: Really, just encapsulation for the sake of
  removing a `_tabs` from `TerminalPage.cpp`

In the future, some enterprising young soul could try promoting that
file to its own class, and hiding `_tabs` (and `_mruTabs`) inside it.
Probably would need to take a reference to TerminalPage's `_tabView` and
`_newTabButton`. I'm not doing that right now, because I already hate
the idea of the ...

>  920 additions and 847 deletions.

... I'm making you look at already.

## Other thoughts

Some of the calls might be a little arbitrary - `_OpenNewTab` and
`_CreateNewTabFromSettings` probably should stay in `TerminalPage`? Or
at least elements of those might need to get split up better. Similarly
`TerminalPage::_OpenSettingsUI` stayed in `TerminalPage.cpp`, but it
does a lot of the same work as `_CreateNewTabFromSettings`. I'm not
saying this is the definitive places for these methods - it's code we're
working with, not stone ☺️
2021-03-29 19:53:39 +00:00
Dustin Howett
8470857016 Fix the preview package manifest
We missed this one.
2021-03-29 12:23:57 -05:00
Don-Vito
704836e45d Prevent arrow keys from dismissing tab renamer (#9633)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9632
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.
2021-03-29 17:23:09 +00:00
Mike Griese
5a78566628 Make TerminalConnection depend on OpenConsoleProxy (#9649)
Building code merged with `main` this morning, and I hit a error where
the `TerminalConnection` project needed `ITerminalHandoff` something or
other, but that hadn't been built yet. I suspect that's because the
`OpenConsoleProxy` project needs to be built first, but it isn't set as
a dependency.

I suspect once that project is built once, this isn't ever an issue, but
I hadn't done that yet.

This fixed the build for me locally. 

* [x] fixes local dev builds
* [x] also updates the name of the TerminalControl project in the .sln,
      because apparently VS didn't like that.
2021-03-29 11:57:18 -05:00
Chester Liu
806d992a06 Prefer constexpr over const across the codebase (#9587)
Supports #2941

Previous PRs: #3362 #3416
2021-03-29 16:03:16 +00:00
Dustin L. Howett
12275c8599 Add a Fuzzing configuration and a version of conhost that can be fuzzed (#9604)
This commit introduces a new build configuration, "Fuzzing", which
enables the new address sanitizer (shipped in VS 16.9) and code
coverage over the entire solution. Only a small subset of projects
(those comprising original conhost, right now) are selected to build in
this configuration, and even then only in Fuzzing|x64.

It also adds a fuzzing-adapted build of conhost, which makes no server
connections and handles no client applications. To do this, I've
replicated a bit of the console startup routine into fuzzmain.cpp and
made up some fake data. This is the bare minimum required to boot up
Win32 interactivity (or VT interactivity!) and pretend that a process
has connected.

If we don't pretend that a process has connected, "conhost" will exit
immediately. If we don't forge the process list, conhost will exit. If
we can't provide a server handle, we can't provide a "device comm".

Minor changes were necessary to server/host such that they would accept
a preexisting "device comm". We use this new behavior to provide a
"null" one that only hangs up threads and otherwise responds to requests
successfully.

This fuzzing-adapted build links LLVM's libFuzzer, which is an excellent
coverage-based fuzzer that will produce a corpus of inputs that exercise
unique codepaths. Eventually, we can use this to generate known-"good"
inputs for anything.

I've gone ahead and added a fuzz function that yeets bytes directly into
WriteCharsLegacy, which was the original reason I went down this path.

The implementation of LLVMFuzzerTestOneInput should be replaced with
whatever you want to fuzz.
2021-03-29 14:23:30 +00:00
Dustin L. Howett
ea3e56db81 Add some read and write locks around pattern tree manipulation (#9618)
We have been seeing some crashes (#9410) originating from a
use-after-free or a double-free in the renderer. The renderer is
iterating over the dirty rects from the render engine¹ and the rect list
is being freed out from under it.

Things like this are usually the result of somebody manipulating the
renderer's state outside of lock.

Therefore, this pull request introduces some targeted locking fixes
around manipulation of the pattern buffer (which, in turn, changes the
renderer state.)

¹ This was not a problem until #8621, which made the renderer return a
span instead of a copy for the list of dirty rects.

## Validation

I ran Terminal under App Verifier, and introduced a manul delay (under
lock) in the renderer such that the invalid map would definitely have
been invalidated between the renderer taking the lock and the renderer
handling the frame. AppVerif failed us without these locking changes,
and did not do so once they were introduced.

Closes #9410.
2021-03-26 22:11:08 +00:00
Michael Niksa
906edf7002 Implement Default Terminal (#7489)
- Implements the default application behavior and handoff mechanisms
  between console and terminal. The inbox portion is done already. This
  adds the ability for our OpenConsole.exe to accept the incoming server
  connection from the Windows OS, stand up a PTY session, start the
  Windows Terminal as a listener for an incoming connection, and then
  send it the incoming PTY connection for it to launch a tab.
- The tab is launched with default settings at the moment.
- You must configure the default application using the `conhost.exe`
  propsheet or with the registry keys. Finishing the setting inside
  Windows Terminal will be a todo after this is complete. The OS
  Settings panel work to surface this setting is a dependency delivered
  by another team and you will not see it here.

## Validation Steps Performed
- [x] Manual adjust of registry keys to the delegation conhost/terminal
  behavior
- [x] Adjustment of the delegation options with the propsheet
- [x] Launching things from the run box manually and watching them show
  in Terminal
- [x] Launching things from shortcuts and watching them show in the
  Terminal   

Documentation on how it works will be a TODO post completion in #9462

References #7414 - Default Terminal spec

Closes #492
2021-03-26 17:09:49 -05:00
Dustin L. Howett
690fbbbc27 Add a WPR profile containing all of Terminal's ETW providers (#9630) 2021-03-26 11:46:14 -05:00
John Stephens
005b8cc5e0 Link to WinMM.Lib for PlaySound with 19041 (#9624)
The PlaySound functions were removed from OneCoreUAP_apiset.Lib in Windows 10 SDK 19041 because they did not actually belong there. Link to WinMM.Lib for PlaySoundW.

### Validation Steps Performed

* Built for x64 from repository root with: `MSBuild.exe -property:TargetPlatformVersion=10.0.19041.0`
* Installed CascadiaPackage_0.0.1.0_x64_Debug.msix and launched on 19042.867
2021-03-26 11:35:17 -05:00
Don-Vito
e02d9a48e3 Fix wrong item template selection in CmdPal (#9487)
There seems to be a bug in WinUI (see microsoft/microsoft-ui-xaml#2121)
that results in heterogeneous `ModernCollectionBasePanel`  configured
with `DataTemplateSelector` and virtualization enabled to recycle a
container even if its `ContentTemplate` is wrong.

I considered few options of handling this:
* Disabling virtualization (by replacing item container template with
  some non-virtualizing panel (e.g., `StackPanel`,
  `VirtualizingStackPanel` with `VirtualizationMode`=`Standard`)
* Replacing `DataTemplateSelector` approach with `ChoosingItemContainer`
  event handling approach, which allows you to manage the item container
  (`ListViewItem`) allocation process.

I have chosen the last one, as it should limit the amount of
allocations, and might allow optimizations in the future.
 
The solution introduces:
* A container for `ListViewItem`s in the form of a map of sets:
  * The key of this map is a data template (e.g., `TabItemDataTemplate`)
  * The value in the set is the container
* `ChoosingItemContainer` event handler that looks for available item in
  the container or creates a new one
* `ContainerContentChanging` event handler that returns the recycled
  item to the container

Closes #9288
2021-03-24 20:11:35 -05:00
Dustin L. Howett
da1e1a693e WriteCharsLegacy: Add some notes in comments and rename WC_ECHO (#9605)
This commit clarifies some things inside WriteCharsLegacy by adding
comments and renaming parameter and enum names. It does not change any
logic.

`WC_ECHO` was used extensively to mean only one thing: whether to print
a control character like `\x18` (Ctrl+X>) as `^X`. It's been renamed
to make that abundantly clear.
2021-03-24 16:26:50 -05:00
Don-Vito
da24f7d939 Allow overriding tab switcher mode on command level (#9507)
## Summary of the Pull Request

Currently, when the MRU is enabled we lose the keybinding allowing us to 
go forward/backward (aka right/left in LTR) in the tab view.

To fix that, this PR introduces "tabSwitcherMode" optional parameter to 
the prevTab / nextTab commands.
If it is not provided the global setting will be used.


So if you want to go to adjacent tabs, even if MRU is enabled on the
system level you can use:
```
{ "command": { "action": "prevTab", "tabSwitcherMode": "inOrder" }, "keys": "ctrl+f1"}
{ "command": { "action": "nextTab", "tabSwitcherMode": "inOrder" }, "keys": "ctrl+f2"}
```
or even
```
{"command": { "action": "prevTab", "tabSwitcherMode": "disabled" }, "keys": "ctrl+f1"}
{ "command": { "action": "nextTab", "tabSwitcherMode": "disabled" }, "keys": "ctrl+f2"}
```
if you don't want tab switcher to show up

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9330
* [x] CLA signed. 
* [x] Tests added/passed
* [ ] Documentation updated - not yet. Waiting for approval.
* [x] Schema updated.
* [ ] I've discussed this with core contributors already.
2021-03-23 22:00:07 +00:00
Dustin L. Howett
da3f02a6e2 Command Palette: announce various mode and state changes to UIA (#9582)
This commit introduces a few different announcements to the command
palette.

When you delete the `>`, it will announce that you have entered
"command-line mode". When you reintroduce the `>`, it will announce that
you are in "action search mode."

When you enter a nested command, it will announce that you are looking
at "more options for new tab..." or "more options for select color
scheme...".

When you search and find nothing, it will announce that there were no
matching commands (or tabs!)

Related to #7907.
2021-03-23 08:24:27 -05:00
Dustin L. Howett
d972ea2c28 Replace conhost's fmt::format strings with FMT_COMPILEd ones (#9581)
This reduces by 10% the binary size of OpenConsole x64 Release.

Note   | OpenConsole.exe
------ | ---------------------------
Before | 1156096
After  | 1037312
Delta  | -118784
%Delta | -10.27%
2021-03-23 02:21:18 +00:00
Don-Vito
a5ff7459b7 Prevent tab context menu from closing root pane directly (#9571)
## Summary of the Pull Request
Currently a repeated attempt to close a read-only tab from context menu,
will bring the terminal into invalid state if user dismisses close action.

There are two root causes for this:
1. The tab close menu triggers the closing of the root pane
(rather than invoking close tab flow in the Terminal Page).
2. Currently panes are not aware that the closing was canceled,
and thus they trigger the Closed event, putting the system in a weird state,
where the Closed handlers were invoked, but the Pane remains.

This PR mitigates #9502, by addressing the first root cause
(the fix is trivial and hopefully can be serviced).
Moreover, it addresses the only existing UI flow that can trigger the issue.

The remaining problematic flow will occur when the connection is closed.
I have created a separate Issue to track it: 
https://github.com/microsoft/terminal/issues/9572
as I guess the PR for it might be more complex.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9502
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.
2021-03-22 20:48:18 +00:00
Dustin L. Howett
544bd44851 Update {fmt} to 7.1.3 (#9580)
{fmt} 7.1.3 includes a number of changes, which I will summarize here:

* Switched to Dragonbox for float formatting (quoted, "20-30x faster"
  than ostringstream)
* Significantly improves `FMT_COMPILE` (compile-time format string)
2021-03-22 13:07:04 -05:00
Don-Vito
9bd097f4ad Fix read-only tab dialog to cancel tab closing when dismissed (#9573)
Currently dismissing "are you sure you wish to close read-only tab or pane" 
dialog by pressing `ESC` will not abort tab closing
(aka the tab will be closed!)

The reason for this, is that we cancel, only if the "Cancel" is pressed
(aka result=PrimaryButton, while ESC returns result=None).

This PR fixes this, by doing what we usually do:
* Putting Cancel in the CloseButton (which is also triggered by ESC)
* Aborting the action if the result is not a Primary Button

However, since we want Cancel to be a default action,
we set CloseButton to be the DefaultButton  in XAML
2021-03-22 11:02:30 +00:00
Dustin L. Howett
9069fcab79 Remove the shell extension's dependency on fmt for huge savings (#9552)
Yeah, this one-line change shaves off almost half the binary.

Binary size savings (x64 Release):

Note   | WindowsTerminalShellExt.dll
------ | ---------------------------
Before | 130048
After  | 73728
Delta  | -56320
%Delta | -43.3%
2021-03-21 16:56:31 +00:00
Dustin L. Howett
f4d487efef github: migrate our bug report template to an issue form (#9538) 2021-03-19 12:03:43 -05:00
Mike Griese
fb734d166c Move events out of TermControl.h ; Use TYPED_EVENT in more places (#9526)
This is a small refactor on my way to much bigger, more painful refactors. This PR does five things:

* `TermControl.*` has historically had all the control-relevant EventArgs defined in the same file as TermControl. That's just added clutter to the files, clutter that could have been in it's own place.  We'll move all those event arg to their own files. 
* We'll also move `IDirectKeyListener` to its own file while we're at it.
* We'll update some of `TermControl`'s old `DEFINE`/`DECLARE_TYPED_EVENT` macros to the newer `TYPED_EVENT` macro, which is a bit nicer. 
* We'll change `TermControl.TitleChanged` to a typed event. I needed that for a future PR, so let's just do it here
* While we're updating `TYPED_EVENT` macros, let's do `TerminalPage` too.  

### checklist 
* [x] I work here
* [x] This is work for #1256, but we've got a long way to go before that works.
2021-03-18 22:02:39 +00:00
Mike Griese
2ed367fb49 Fix build break where Microsoft.Terminal.Control.dll is empty (#9537)
TIL that the `<None Include="Foo.def" />` line in our projects is
actually totally meaningless. The important line is the one that's in
`cppwinrt.build.pre.props`, where we declare 

```xml
<ModuleDefinitionFile Condition="Exists('$(ProjectName).def')">$(ProjectName).def</ModuleDefinitionFile>
```

So if you change a project's name, and not the `.def` file, then the
linker will just _not use the `.def` file at all_.

More importantly, this seemingly doesn't matter in debug builds. In a
Debug build, the linker will happily still include `WINRT_CanUnloadNow`
and `WINRT_GetActivationFactory` in the exports from the dll, even
without the `.def`. But in a Release build, the linker is much more
agressive about pruning symbols that aren't referenced, and without
those two, NONE of the symbols are eventually referenced.

This PR fixes `Microsoft.Terminal.Control` by renaming the `.def`, and
makes it marginally harder for someone to make the same mistake in the
future.

## References
* Regressed in #9472 

## PR Checklist
* [x] Closes #9529
* [x] I work here
2021-03-18 16:14:21 +00:00
Dustin L. Howett
acdcdcaccb Shell Extension: Remove C++/WinRT authoring dependency (#9525)
We don't need to use C++/WinRT's component authoring capabilities to be
a COM component. It's easier for us if we're not (and it makes the build
slightly faster!)

Binary size savings (x64 Release):

Note   | WindowsTerminalShellExt.dll
------ | ---------------------------
Before | 136192
After  | 130048
Delta  | 6144
%Delta | 4.5%
2021-03-17 21:52:32 +00:00
Mike Griese
d749df70ed Rename Microsoft.Terminal.TerminalControl to .Control; Split into dll & lib (#9472)
**BE NOT AFRAID**. I know that there's 107 files in this PR, but almost
all of it is just find/replacing `TerminalControl` with `Control`.

This is the start of the work to move TermControl into multiple pieces,
for #5000. The PR starts this work by:
* Splits `TerminalControl` into separate lib and dll projects. We'll
  want control tests in the future, and for that, we'll need a lib.
* Moves `ICoreSettings` back into the `Microsoft.Terminal.Core`
  namespace. We'll have other types in there soon too. 
  * I could not tell you why this works suddenly. New VS versions? New
    cppwinrt version? Maybe we're just better at dealing with mdmerge
    bugs these days.
* RENAMES  `Microsoft.Terminal.TerminalControl` to
  `Microsoft.Terminal.Control`. This touches pretty much every file in
  the sln. Sorry about that (not sorry). 

An upcoming PR will move much of the logic in TermControl into a new
`ControlCore` class that we'll add in `Microsoft.Terminal.Core`.
`ControlCore` will then be unittest-able in the
`UnitTests_TerminalCore`, which will help prevent regressions like #9455 

## Detailed Description of the Pull Request / Additional comments
You're really gonna want to clean the sln first, then merge this into
your branch, then rebuild. It's very likely that old winmds will get
left behind. If you see something like 

```
Error    MDM2007    Cannot create type
Microsoft.Terminal.TerminalControl.KeyModifiers in read-only metadata
file Microsoft.Terminal.TerminalControl.
```

then that's what happened to you.
2021-03-17 20:47:24 +00:00
Dustin L. Howett
a979e52f7c Teach OpenConsole.psm1 to support multiple terminal checkouts (#9509)
OpenConsole.psm1 cached its root directory on import, which made it very
difficult to move into another Terminal clone and _do things_ (like code
formatting).

By resolving the root directory again per-cmdlet, we gain the ability
to...

```powershell
cd terminal
import-module ./tools/openconsole.psm1
cd ../terminal-2
invoke-codeformat
```

... and have it format the correct directory (terminal-2) instead of the
incorrect one (terminal).

This does unfortunately break the openconsole cmdlets _inside dep/wil
and dep/gsl_ because they are separate git repositories. This is taken
as an acceptable cost.
2021-03-17 15:42:17 -05:00
Dustin L. Howett
1519236f2b Disambiguate the shell extension CLSIDs to allow usage SXS (#9510)
Fixes #6416
2021-03-17 20:32:45 +00:00
Mike Griese
43c469fc95 Add support for naming windows with the -w parameter (#9300)
This finishes the implementation of `--window` to also accept a string
as the "name" of the window. So you can say 

```sh
wt -w foo new-tab
wt -w foo split-pane
```

and have both those commands execute in the same window, the one named
"foo". This is just slightly more ergonomic than manually using the IDs
of windows. In the future, I'll be working on renaming windows, and
displaying these names. 

> #### `--window,-w <window-id>`
> Run these commands in the given Windows Terminal session. This enables opening
> new tabs, splits, etc. in already running Windows Terminal windows.
> * If `window-id` is `0`, run the given commands in _the current window_.
> * If `window-id` is a negative number, or the reserved name `new`, run the
>   commands in a _new_ Terminal window.
> * If `window-id` is the ID or name of an existing window, then run the
>   commandline in that window.
> * If `window-id` is _not_ the ID or name of an existing window, create a new
>   window. That window will be assigned the ID or name provided in the
>   commandline. The provided subcommands will be run in that new window.
> * If `window-id` is omitted, then obey the value of `windowingBehavior` when
>   determining which window to run the command in.

Before this PR, I think we didn't actually properly support assigning
the id with `wt -w 12345`. If `12345` didn't exist, it would make a new
window, but just assign it the next id, not assign it 12345.

## References
* #4472, #8135
* https://github.com/microsoft/terminal/projects/5

## Validation Steps Performed
Ran tests
Messed with naming windows, working as expected.

Closes https://github.com/microsoft/terminal/projects/5#card-51431478
2021-03-17 19:28:01 +00:00
Kayla Cinnamon
8346968881 Update roadmap to reflect new release cadence (#9366)
We're switching to a 6-week release cadence and are also shifting the 2.0 release to this winter.
2021-03-17 14:24:00 -05:00
Luan Vitor Simião Oliveira
c5124956a9 OpenConsole.psm1: use DevShell module; tidy up for PowerShell 6+ (#9508)
Saw this while snooping around, the gci command on PowerShell core seems
to store the full path in the variable as oppose to just the leaf.

The other modification is to use the PowerShell module that vs ships to
setup the environment.
2021-03-16 12:29:38 -05:00
Carlos Zamora
44f1ba6d4d Move TerminalSettings from TermApp to TerminalSettingsModel (#9318)
This accomplishes the first step towards embedding a preview on the Profiles/ColorSchemes page, by moving the `TerminalSettings` object over to the Terminal Settings Model project. We'll leverage this in a later PR to construct an embedded terminal in the settings UI.

`TerminalSettings` had to see a few more functions exposed in the IDL
(including some inheritance stuff).

Refresh the JSON to make TerminalSettings do it's thing across all the
open terminals.

References #9122 - Terminal Preview
References #6800 - SUI Epic
2021-03-15 23:15:25 +00:00
Geoff Lawrence
99b09c08d5 doc: add PowerShell install instructions added (#9474) 2021-03-15 12:29:20 -05:00
PankajBhojwani
fbdfc4d446 Check if found folder is not null when loading fragments (#9477)
When loading fragments, check if the public folder is not null first

Closes #9473
2021-03-15 16:34:30 +00:00
Don-Vito
28da6c4ecb Invalidate nested command with no valid subcommands (#9495)
Currently, when loading command with sub-commands that fail to parse,
we result with command that:
* Is not considered nested (has no sub-commands)
* Has no action of its own

The commit contains a few changes:
1. Protection in the dispatch that will prevent NPE
2. Change in the command parsing that will no load
a command if all its sub-commands failed to parse
3. We will add a warning in this case (the solution is somewhat
hacky, due to the hack that was there previously)

When such command is passed to a dispatch we crash with NPE.

Closes #9448
2021-03-15 16:34:06 +00:00
PankajBhojwani
b76087f561 Add a helper function to initialize TermControls in TerminalPage (#9296)
Since #8602 merged, we need to pass a child of the settings object to
the TermControl upon initializing it. Since this happens in a few places
in `TerminalPage`, its probably best to use a helper. 

Closes #9292
2021-03-12 20:08:10 +00:00
Don-Vito
efc92de19f Fix selection on multi-click with no shift (#9455)
When working on #9403 I completely forgot that
double-click and triple-click should work even without shift.
Fixed it by allowing multi-selection even if not shift is pressed.

Closes #9453

## Validation Steps Performed
* [x] single click = no selection
* [x] single click and drag = selection starting from first point
* [x] single click in unfocused pane and drag = focus pane, selection starting from first point
* [x] double-click = selects a whole word
* [x] triple-click = selects a whole line
* [x] double-click and drag = selects a whole word, drag selects whole words
* [x] triple-click and drag = selects a whole line, drag selects whole lines
* [x] Shift single-click = defines start point
* [x] second Shift single-click = defines end point
* [x] Shift double-click = selects entire word
* [x] Shift triple-click = selects entire line
* [x] Shift double-click and drag = selects entire word, drag selects whole words
* [x] Mouse mode: Shift single-click = defines start point
* [x] Mouse mode: second Shift single-click = defines end point
* [x] Mouse mode: Shift double-click = selects entire word
* [x] Mouse mode: Shift triple-click = selects entire line
* [x] Mouse mode: Shift double-click and drag = selects entire word, drag selects whole words
2021-03-12 03:37:57 +00:00
Dustin Howett
af896cd4bc Merge remote-tracking branch 'openconsole/inbox' into HEAD 2021-03-10 17:59:49 -06:00
Dustin Howett
1a1b4ff21e Merged PR 5777834: Parenthesis in incorrect spot for default app policy check.
Parenthesis in incorrect spot for default app policy check.

Related work items: MSFT-32071839

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 537ab5dfd9cc6af60b570697e77bba4b45822e05
2021-03-10 23:59:12 +00:00
Dustin L. Howett
691e02ef1c Force DebugFull PDBs on all build types (#9441)
I've also taken the opportunity to kill the xxxFullPDB trick. The
intermediate PDB is allowed to remain "vc141.pdb" or whatever it wants
to be. PDBs are now simply named after their projects, as was always
tradition.
2021-03-10 23:49:03 +00:00
Dustin L. Howett
3029bb8a68 Update C++/WinRT to 2.0.210309.3 (#9437)
This update shrinks our binaries a little bit.

From a representative build on VS 16.8:

       | App     | Control | Connection | TSE     | WT     | Total   | msix (zip) |
       | --      | --      | --         | --      | --     | --      | --         |
Before | 2610176 | 1006592 | 433152     | 1352192 | 321536 | 5723648 | 8336910    |
After  | 2532352 | 986624  | 431104     | 1312768 | 313344 | 5576192 | 8287648    |
Delta  | 77824   | 19968   | 2048       | 39424   | 8192   | 147456  | 49262      |
%Delta | 2.98%   | 1.98%   | 0.47%      | 2.92%   | 2.55%  | 2.58%   | 0.59%      |
2021-03-10 16:04:59 -06:00
Dustin L. Howett
1e4c6978b7 submodule check: actually check for a real file in the repo (#9438)
Git may create folders for submodules; let's make sure they're populated.
2021-03-10 21:14:30 +00:00
Don-Vito
6cd4e03a58 Allow interaction with hyperlinks in mouse mode (#9396)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9117
* [x] CLA signed. 
* [x] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. 

## Detailed Description of the Pull Request / Additional comments
In mouse mode:
* Underline hyperlinks
* Activate hyperlink on ctrl+click rather than sending input to VT
2021-03-10 18:42:11 +00:00
PankajBhojwani
a47ed99272 Allow shift+click on a profile to open a new window (#9429)
<!-- 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
Shift+click on a profile to open a new wt window with that profile. Or, shift+click on the '+' button to open a new wt window with the default profile. 

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #9395 
* [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
Manual testing
2021-03-10 18:32:54 +00:00
Dustin Howett
95b031e27c ci: fix spelling issues from inbox merge 2021-03-09 17:46:43 -08:00
Dustin Howett
8f9ccc55d1 Merge inbox changes into main
This includes:
* The property sheet work for #492
* A fix for til::pmr on ARM inside Windows
2021-03-09 17:38:59 -08:00
Dustin Howett
3909cc103a Merged PR 5770253: [Git2Git] Merged PR 5760120: Add propsheet chooser to Windows
[Git2Git] Merged PR 5760120: Add propsheet chooser to Windows

Now the inbox console propsheet can choose which terminal is default

Related work items: MSFT-32007202 #492

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev d80f506858bd990c267de6cefae7ff55707b3a57
2021-03-10 01:19:04 +00:00
Eric Tian
8358f8d93f Display correct tooltip when window is maximized (#9412)
## Summary of the Pull Request
Instead of displaying "Maximize" in the tooltip for the maximize/restore button even when the window is maximized, it now displays "Restore Down".

## References
Fixes #5693

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

## Validation Steps Performed
Tested manually.
2021-03-09 17:41:29 +00:00
Eugene Samoylov
48d59e8304 [Settings UI] Represent Cursor Height as a slider (#9386)
Change the vintage cursor height number box to a slider.

## References
Related:  #9370

## PR Checklist
* [x] Closes #9377
* [x] zadjii-msft edit: Now _this one_ closes #9175
* [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

It seems like the cursor height couldn't be lower than 25 percent regardless of the given value, so I've changed the `MinCursorHeightPercent` in CustomTextRenderer header file.

## Validation Steps Performed
Manual validation

![CursorHeightSlider](https://user-images.githubusercontent.com/39456018/110041939-bf076080-7d66-11eb-8d58-ba9a84922803.gif)
2021-03-09 17:13:32 +00:00
Don-Vito
83f2a3bb3d Fix selection logic with shift on multi-click (#9403)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9382
* [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
The selection with shift is quite broken in 1.6.

It started with #8611 that introduces cell selection on `shift+click`.
This change resulted in the following defect:
`shift+double-click`, `shift+triple-click` select only parts  of the word.
The reason for this is that the first `shift+click` establishes the selection,
while the consequent clicks simply extend it to the relevant boundary
(aka word / line boundary)

However, the logic was broken even before #8611.
For instance, `shift+triple-click` had exactly the same handicap:
`shift+double-click` was establishing the selection and the
third click was simply extending it to the line boundary.

This PR addresses the both defects in the following manner:
upon multi-click that starts new selection we establish
a new selection on every consequent click using appropriate mode
(cell/word/line) rather than trying to extend one.
For this purpose we remember the position that started the selection.
2021-03-08 19:15:46 +00:00
Carlos Zamora
87fa526fb7 Represent font face as a combo box in SUI (#9275)
## Summary of the Pull Request

This replaces the Profiles > Font Face text box with a combo box.

## References
#6800 - Settings UI Epic

## Detailed Description of the Pull Request / Additional comments

- Enumerating the fonts
  - [This doc](https://docs.microsoft.com/en-us/windows/win32/directwrite/font-enumeration) was the main reference used to enumerate the fonts. It was mildly adapted to use WinRT instead of WRL.
- Updating the UI
  - Similar to other combo box settings, `Profiles` keeps a reference to the current value. We use that as a way to update the settings model. If an invalid value is used, we fallback to `Cascadia Mono`.
  - A checkbox was added to let the user select from all of the installed fonts, or just the monospace ones.

## Demo
![Font Face Combo Box Demo](https://user-images.githubusercontent.com/11050425/109342917-6cd3b600-7821-11eb-8df9-fb988b037e02.gif)
2021-03-08 16:45:12 +00:00
Don-Vito
c6a31710d9 Allow configuring suppressApplicationTitle in new tab/pane/window commands (#9392)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9345
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated - not yet, will be once conceptually approved
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. 

## Detailed Description of the Pull Request / Additional comments
Introduce optional `suppressApplicationTitle` in to `NewTerminalArgs`.
When set (either to true or false) overrides profile configuration.

Introduce `--suppressApplicationTitle` flag to command line arguments.
When provided for sub=command, 
sets the value in the relevant `NewTerminalArgs` to `true`
2021-03-08 15:23:50 +00:00
Don-Vito
19bd0c94e7 Fix TermControl initialization to pre-seed working dir (#9397)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/8969
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

<!-- 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-03-08 14:56:36 +00:00
Don-Vito
629c06d0ad Introduce duplicate tab menu (#9388)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9373
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.
2021-03-08 12:16:56 +00:00
Don-Vito
1202f89399 Fix overflow in scroll-to-bottom (#9389)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9353
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.
2021-03-05 21:18:54 +00:00
Carlos Zamora
4a95341caf Change SettingsTab close icon to be smaller (#9324)
We were using the wrong close icon for the settings tab. This is a side effect of `TerminalTab` overriding `TabBase`'s implementation.

#6800 - Settings UI Epic

Closes #9317
2021-03-04 19:31:57 +00:00
Mike Griese
3cf7677d17 Replace some of our macros to reduce confusion, increase success (#9376)
As mentioned in https://github.com/microsoft/terminal/issues/9354#issuecomment-790034728

`GETSET_SETTING` is too visually similar to `GETSET_PROPERTY`, but with a _VERY_ different meaning. I think that merely changing the name of the macro would make it harder for us to make this mistake again.
2021-03-04 11:27:03 -08:00
Eugene Samoylov
ac3fecb134 [Settings UI] Clamp vintage cursor height and history size (#9370)
## Summary of the Pull Request
Add `Minimum` and `Maximum` for the cursor height numberbox in the SUI.
Add `Minimum` for the history size numberbox in the SUI.

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

## Validation Steps Performed
Manual validation
2021-03-04 17:47:23 +00:00
PankajBhojwani
5aaf5b4d59 Fix pixel shaders not loading (#9371)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Fix for #9354 

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #9354 
* [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
2021-03-04 17:19:21 +00:00
Carlos Zamora
2961a104af Add localization comments to settings UI (#9367)
We've received feedback from the localization team that the strings need some comments to provide more context.

## References
Closes [MSFT-31929817](https://microsoft.visualstudio.com/OS/_workitems/edit/31929817)
#9328 - Chinese translation issues
#9238 - French translation issues
2021-03-03 16:28:48 -08:00
Michael Niksa
7b1a660e59 Create settings/tasks definitions for VScode builds and registration (#9297)
I wanted to start using VScode. It wasn't easy. I wrote some tasks that allow us to build the various flavors of OpenConsole and Windows Terminal from one of the tasks. I also wrote a task that allows registration of the loose Windows Terminal package and a shortcut one to launch it. 

Also it was grinding away at its own Intellisense forever because it was indexing obj, bin, packages, etc. I excluded those.

Things should be easier now for folks in general. I expect we'll make more task types in the future.
2021-02-26 18:50:15 +00:00
Dustin L. Howett
cb03b97e67 Update Cascadia Code to 2102.25 (#9295)
This update fixes some issues in Cascadia Code's February update:

microsoft/cascadia-code#406 - updated anchor type to lock with the other equals-related ligatures
microsoft/cascadia-code#408 - corrected component used for glyph to align with Unicode
microsoft/cascadia-code#412 - updated locl features removing iacute_j ligature and Catalan substitution
microsoft/cascadia-code#414 - increased overlaps of middle glyph for arrow ligatures
microsoft/cascadia-code#415 - reduces width of macronbelow
microsoft/cascadia-code#416 - rolls back name ID 4 modification as JetBrains cannot process it correctly
microsoft/cascadia-code#428 - rolls back variation of the underline to prevent MVAR table generation

Full changelist:
* Repositioned tilde in related ligatures. Previously it was higher than the standard one.
* Added missing vietnamese anchors on acute and grave (futureproofing).
* Corrected / made consistent greater & less positioning in </> and <$> related ligatures.
* Otherwise reviewed hinting
2021-02-25 14:47:03 -08:00
PankajBhojwani
f26c246c7c Fix updating with fragments ignoring original profile settings (#9293)
Turns out we were adding the fragment source to profiles we update. This
PR fixes it so we keep the original source. 

## Validation Steps Performed
Existing profile settings are maintained

Closes #9290
2021-02-25 22:44:43 +00:00
Carlos Zamora
649c546960 Update dropdown's settings keyboard accelerator (#9294)
Fixes a bug introduced by #9224 where the wrong keyboard accelerator
would appear in the new tab dropdown. We were looking for the "settings
file" version of the action, as opposed to the "settings UI" version. 

## References
#9224 - Settings UI as default
#6800 - Settings UI Epic
2021-02-25 22:44:24 +00:00
PankajBhojwani
a930aa390e Fix settings not updating on reload (#9289)
In #8602, we started passing a child of the `TerminalSettings` to the
control upon tab initialization, but forgot to do the same when new
controls get created on a pane split. 

## Validation Steps Performed
Settings reload with multiple panes works

Closes #9280
2021-02-25 13:00:20 -08:00
Carlos Zamora
d1bf0fcd1e Add help text to 'more options' in command palette (#9271)
Similar to #9262. This creates another data template specifically for
command palette items that open up more options. We leverage the
localization key from #9262 to apply help text to this template
automatically.

Using the data template approach, we now have no need for the
`HasNestedComandsVisibilityConverter`, so that set of files is now
deleted. The logic to detect nested commands was moved to the template
selector.

## Validation Steps Performed
Tested using NVDA.

Addresses #7908 better
2021-02-24 12:02:09 -08:00
Dustin L. Howett
66033dcb01 Exclude MonarchPeasantPackage from AnyCPU/DotNet*Test configs (#9272)
Visual Studio automatically enabled this package to build in all
configurations. This results in a build error when we go to pack the WPF
control.
2021-02-24 11:34:34 -08:00
Dustin Howett
95f63a9100 [PICK] Cherry-pick loc key from 83d35c119 2021-02-23 18:57:57 -08:00
Dustin Howett
6654f0d155 version: bump to 1.4 on master 2021-02-23 16:35:25 -08:00
Dustin Howett
ce99c2a349 Merged PR 5704731: Migrate OSS up to e6aa90222
Related work items: MSFT-9667854, MSFT-31783834
2021-02-19 19:45:33 +00:00
Dustin Howett
ce0505073c Merged PR 5695814: Migrate OSS up to 847749f19
Dustin L. Howett (3)
* Fix the Host Proxy DLL reference in ServerLib (GH-9129)
* ci: fix spelling
* Format the incoming inbox code

Michael Niksa (1)
* Eliminate more transient allocations: Titles and invalid rectangles and bitmap runs and utf8 conversions (GH-8621)

Related work items: MSFT-31755835
2021-02-17 22:04:25 +00:00
385 changed files with 14927 additions and 7074 deletions

12
.config/dotnet-tools.json Normal file
View File

@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"XamlStyler.Console": {
"version": "3.2008.4",
"commands": [
"xstyler"
]
}
}
}

View File

@@ -1,54 +0,0 @@
---
name: "Bug report 🐛"
about: Report errors or unexpected behavior
title: ''
labels: ''
assignees: ''
---
<!--
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING:
1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement.
2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement.
3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number).
4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement.
5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement.
All good? Then proceed!
-->
<!--
This bug tracker is monitored by Windows Terminal development team and other technical folks.
**Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**.
Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue.
If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link.
Please use this form and describe your issue, concisely but precisely, with as much detail as possible.
-->
# Environment
```none
Windows build number: [run `[Environment]::OSVersion` for powershell, or `ver` for cmd]
Windows Terminal version (if applicable):
Any other software?
```
# Steps to reproduce
<!-- A description of how to trigger this bug. -->
# Expected behavior
<!-- A description of what you're expecting, possibly containing screenshots or reference material. -->
# Actual behavior
<!-- What's actually happening? -->

57
.github/ISSUE_TEMPLATE/Bug_Report.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
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!
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.
- type: input
attributes:
label: Windows Terminal version (or Windows build number)
placeholder: "10.0.19042.0, 1.7.3651.0"
description: |
If you are reporting an issue in Windows Terminal, you can find the version in the about dialog.
If you are reporting an issue with the Windows Console, please run `ver` or `[Environment]::OSVersion`.
validations:
required: true
- type: textarea
attributes:
label: Other Software
description: If you're reporting a bug about our interaction with other software, what software? What versions?
placeholder: |
vim 8.2 (inside WSL)
OpenSSH_for_Windows_8.1p1
My Cool Application v0.3 (include a code snippet if it would help!)
validations:
required: false
- type: textarea
attributes:
label: Steps to reproduce
placeholder: Tell us the steps required to trigger your bug.
validations:
required: true
- 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.
placeholder: What were you expecting?
validations:
required: false
- type: textarea
attributes:
label: Actual Behavior
placeholder: What happened instead?
validations:
required: true

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="vswhere" version="2.6.7" />
</packages>
</packages>

13
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,13 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": [
"ms-vscode.cpptools"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [
]
}

24
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,24 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug OpenConsole by Launching (x64, debug)",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}\\bin\\x64\\debug\\openconsole.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
},
{
"name": "Debug Terminal by Attaching (You go build/register/launch it first.)",
"type": "cppvsdbg",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}

32
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,32 @@
{
"C_Cpp.default.browse.databaseFilename": "${workspaceFolder}\\.vscode\\.BROWSE.VC.DB",
"C_Cpp.default.browse.path": [
"${workspaceFolder}"
],
"C_Cpp.loggingLevel": "None",
"files.associations": {
"xstring": "cpp",
"*.idl": "cpp",
"array": "cpp",
"future": "cpp",
"istream": "cpp",
"memory": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"variant": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"multi_span": "cpp",
"pointers": "cpp",
"vector": "cpp"
},
"files.exclude": {
"**/bin/**": true,
"**/obj/**": true,
"**/packages/**": true,
"**/generated files/**": true
}
}

120
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,120 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "process",
"label": "Build Terminal/Console",
"command": "powershell.exe",
"args": [
"-Command",
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
"Set-MsBuildDevEnvironment;",
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"}};",
"$target = switch(\"${input:buildModeChoice}\"){Build{\"\"} Rebuild{\":Rebuild\"} Clean{\":Clean\"}};",
"$target = $project + $target;",
"msbuild",
"${workspaceFolder}\\OpenConsole.sln",
"/p:Configuration=${input:configChoice}",
"/p:Platform=${input:platformChoice}",
"/p:AppxSymbolPackageEnabled=false", // This takes a long time, so false if we don't really need it.
"/t:$target",
"/m", // Parallel builds
"/verbosity:minimal"
],
"problemMatcher": ["$msCompile"],
"group": {
"kind": "build",
"isDefault": true
},
"runOptions": {
"reevaluateOnRerun": false,
"instanceLimit": 1,
"runOn": "default"
}
},
{
"type": "process",
"label": "Register Windows Terminal x64 Debug",
"command": "powershell.exe",
"args": [
"-Command",
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
"Set-MsBuildDevEnvironment;",
"Set-Location -Path ${workspaceFolder}\\src\\cascadia\\CascadiaPackage\\AppPackages\\CascadiaPackage_0.0.1.0_x64_Debug_Test;",
"if ((Get-AppxPackage -Name 'WindowsTerminalDev*') -ne $null) { Remove-AppxPackage 'WindowsTerminalDev_0.0.1.0_x64__8wekyb3d8bbwe'};",
"New-Item ..\\loose -Type Directory -Force;",
"makeappx unpack /v /o /p .\\CascadiaPackage_0.0.1.0_x64_Debug.msix /d ..\\Loose\\;",
"Add-AppxPackage -Path ..\\loose\\AppxManifest.xml -Register -ForceUpdateFromAnyVersion -ForceApplicationShutdown"
],
"problemMatcher": ["$msCompile"],
"group": {
"kind": "build"
}
},
{
"type": "process",
"label": "Run Windows Terminal Dev",
"command": "wtd.exe",
"args": [
],
"problemMatcher": ["$msCompile"],
},
{
"type": "process",
"label": "Run Code Format",
"command": "powershell.exe",
"args": [
"-Command",
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
"Set-MsBuildDevEnvironment;",
"Invoke-CodeFormat",
],
"problemMatcher": ["$msCompile"],
}
],
"inputs":[
{
"id": "platformChoice",
"type": "pickString",
"description": "Processor architecture choice",
"options":[
"x64",
"x86",
"arm64"
],
"default": "x64"
},
{
"id": "configChoice",
"type": "pickString",
"description": "Debug or release?",
"options":[
"Debug",
"Release"
],
"default": "Debug"
},
{
"id": "buildModeChoice",
"type": "pickString",
"description": "Build, rebuild, or clean?",
"options":[
"Build",
"Rebuild",
"Clean"
],
"default": "Build"
},
{
"id": "buildProjectChoice",
"type": "pickString",
"description": "OpenConsole or Terminal?",
"options":[
"OpenConsole",
"Terminal"
],
"default": "Terminal"
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -33,10 +33,23 @@ This is our preferred method.
#### Via GitHub
For users who are unable to install Terminal from the Microsoft Store, Terminal
builds can be manually downloaded from this repository's [Releases
For users who are unable to install Windows Terminal from the Microsoft Store,
released builds can be manually downloaded from this repository's [Releases
page](https://github.com/microsoft/terminal/releases).
Download the `Microsoft.WindowsTerminal_<versionNumber>.msixbundle` file from
the **Assets** section. To install the app, you can simply double-click on the
`.msixbundle` file, and the app installer should automatically run. If that
fails for any reason, you can try the following command at a PowerShell prompt:
```powershell
# NOTE: If you are using PowerShell 7+, please run
# Import-Module Appx -UseWindowsPowerShell
# before using Add-AppxPackage.
Add-AppxPackage Microsoft.WindowsTerminal_<versionNumber>.msixbundle
```
> 🔴 Note: If you install Terminal manually:
>
> * Terminal will not auto-update when new builds are released so you will need

41
XamlStyler.json Normal file
View File

@@ -0,0 +1,41 @@
{
"AttributesTolerance": 1,
"KeepFirstAttributeOnSameLine": true,
"MaxAttributeCharactersPerLine": 0,
"MaxAttributesPerLine": 1,
"NewlineExemptionElements": "RadialGradientBrush, GradientStop, LinearGradientBrush, ScaleTransform, SkewTransform, RotateTransform, TranslateTransform, Trigger, Condition, Setter",
"SeparateByGroups": false,
"AttributeIndentation": 0,
"AttributeIndentationStyle": 1,
"RemoveDesignTimeReferences": false,
"EnableAttributeReordering": true,
"AttributeOrderingRuleGroups": [
"x:Class",
"xmlns, xmlns:x",
"xmlns:*",
"x:Key, Key, x:Name, Name, x:Uid, Uid, Title",
"Grid.Row, Grid.RowSpan, Grid.Column, Grid.ColumnSpan, Canvas.Left, Canvas.Top, Canvas.Right, Canvas.Bottom",
"Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight",
"Margin, Padding, HorizontalAlignment, VerticalAlignment, HorizontalContentAlignment, VerticalContentAlignment, Panel.ZIndex",
"*:*, *",
"PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
"mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText",
"Storyboard.*, From, To, Duration"
],
"FirstLineAttributes": "",
"OrderAttributesByName": true,
"PutEndingBracketOnNewLine": false,
"RemoveEndingTagOfEmptyElement": true,
"SpaceBeforeClosingSlash": true,
"RootElementLineBreakRule": 0,
"ReorderVSM": 2,
"ReorderGridChildren": false,
"ReorderCanvasChildren": false,
"ReorderSetters": 0,
"FormatMarkupExtension": true,
"NoNewLineMarkupExtensions": "x:Bind, Binding",
"ThicknessSeparator": 2,
"ThicknessAttributes": "Margin, Padding, BorderThickness, ThumbnailClipMargin",
"FormatOnSave": true,
"CommentPadding": 2,
}

View File

@@ -19,8 +19,8 @@ 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\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$Platform\*" $payloadDir
Copy-Item "$nugetPackagesDir\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$Platform\CoreClr\*" $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
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\"

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="TAEF.Redist.Wlk" version="10.57.200731005-develop" targetFramework="native" />
<package id="Microsoft.Taef" version="10.58.210305002" 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

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

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\taef.redist.wlk.10.57.200731005-develop\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
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 }}'

View File

@@ -36,7 +36,7 @@ jobs:
matrix: ${{ parameters.matrix }}
variables:
artifactsDir: $(Build.SourcesDirectory)\Artifacts
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$(buildPlatform)
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\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}}'

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- THIS PROJECT CANNOT BE LOADED INTO THE SOLUTION. -->
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Any CPU">
<Configuration>Release</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Fuzzing|Any CPU">
<Configuration>Fuzzing</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="AuditMode|Any CPU">
<Configuration>AuditMode</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Any CPU">
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>d97c3c61-53cd-4e72-919b-9a0940e038f9</ProjectGuid>
</PropertyGroup>
<PropertyGroup>
<IntermediateOutputPath>$(SolutionDir)obj\$(Configuration)\GenerateFeatureFlags\</IntermediateOutputPath>
<OpenConsoleCommonOutDir>$(SolutionDir)bin\$(Configuration)\</OpenConsoleCommonOutDir>
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Preview'">Preview</_WTBrandingName>
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Release'">Release</_WTBrandingName>
<_WTBrandingName Condition="'$(_WTBrandingName)'==''">Dev</_WTBrandingName>
</PropertyGroup>
<Target Name="_GenerateBranchAndBrandingCache">
<Exec Command="git.exe rev-parse --abbrev-ref HEAD"
CustomWarningRegularExpression="^fatal:.*"
ConsoleToMsBuild="true"
IgnoreExitCode="true">
<Output TaskParameter="ConsoleOutput" ItemName="_GitBranchLines" />
</Exec>
<ItemGroup>
<_BrandingLines Include="$(_WTBrandingName)" />
</ItemGroup>
<WriteLinesToFile File="$(IntermediateOutputPath)branch_branding_cache.txt"
Lines="@(_GitBranchLines);@(_BrandingLines)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)branch_branding_cache.txt" />
<_BranchBrandingCacheFiles Include="$(IntermediateOutputPath)branch_branding_cache.txt" />
</ItemGroup>
</Target>
<Target Name="_RunFeatureFlagScript"
Inputs="@(FeatureFlagFile);@(_BranchBrandingCacheFiles)"
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
DependsOnTargets="_GenerateBranchAndBrandingCache">
<MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" />
<Exec
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command &quot;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&quot; -Path &quot;%(FeatureFlagFile.FullPath)&quot; -Branding $(_WTBrandingName)"
ConsoleToMsBuild="true"
StandardOutputImportance="low">
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />
</Exec>
<!--
We gather the feature flag output in MSBuild and emit the file so that we can take advantage of
WriteOnlyWhenDifferent. Doing this ensures that we don't rebuild the world when the branch changes
(if it results in a new TilFeatureStaging.h that would have had the same content/features as the previous one)
-->
<WriteLinesToFile File="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
Lines="@(_FeatureFlagFileLines)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
<ItemGroup>
<FileWrites Include="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h" />
</ItemGroup>
</Target>
<Target Name="Build" DependsOnTargets="_RunFeatureFlagScript" />
<Target Name="Clean">
<Delete Files="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h" />
</Target>
<ItemGroup>
<FeatureFlagFile Include="$(SolutionDir)\src\features.xml" />
</ItemGroup>
</Project>

View File

@@ -3,12 +3,24 @@
# Checks for code formatting errors. Will throw exception if any are found.
function Invoke-CheckBadCodeFormatting() {
Import-Module ./tools/OpenConsole.psm1
Invoke-CodeFormat
# Don't run the XAML formatter in this step - even if it changes nothing,
# it'll still touch all the .xaml files.
Invoke-CodeFormat -IgnoreXaml
# returns a non-zero exit code if there are any diffs in the tracked files in the repo
git diff-index --quiet HEAD --
if ($lastExitCode -eq 1) {
# Write the list of files that need updating to the log
git diff-index --name-only HEAD
throw "code formatting bad, run Invoke-CodeFormat on branch"
}
# Manually check the formatting of our .xaml files, without touching them.
Verify-XamlFormat
}
Invoke-CheckBadCodeFormatting

View File

@@ -58,7 +58,7 @@ Try {
### Check the activatable class entries for a few DLLs we need.
$inProcServers = $Manifest.Package.Extensions.Extension.InProcessServer.Path
$RequiredInProcServers = ("TerminalApp.dll", "TerminalControl.dll", "TerminalConnection.dll")
$RequiredInProcServers = ("TerminalApp.dll", "Microsoft.Terminal.Control.dll", "Microsoft.Terminal.Remoting.dll", "Microsoft.Terminal.Settings.Editor.dll", "Microsoft.Terminal.Settings.Model.dll", "TerminalConnection.dll")
Write-Verbose "InProc Servers: $inProcServers"

View File

@@ -19,6 +19,7 @@
"/.github/",
"/samples/",
"/res/terminal/",
"/res/fonts/",
"/doc/specs/",
"/doc/cascadia/",
"/doc/user-docs/",
@@ -38,6 +39,7 @@
".wrn",
".rec",
".err",
"XamlStyler.json",
".xlsx"
]
}

View File

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

View File

@@ -12,9 +12,9 @@ Use the [TAEF Verify Macros for C++](https://docs.microsoft.com/en-us/windows-ha
### Running Tests
If you have Visual Studio and related C++ components installed, and you have successfully restored NuGets, you should have the TAEF test runner `te.exe` available locally as part of the `Taef.Redist.Wlk` package.
If you have Visual Studio and related C++ components installed, and you have successfully restored NuGets, you should have the TAEF test runner `te.exe` available locally as part of the `Microsoft.Taef` package.
> Note that you cannot easily run TAEF tests directly through Visual Studio. The `Taef.Redist.Wlk` 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.
> 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:

View File

@@ -166,7 +166,7 @@ should be working just the same as before.
Now that you have a static library project, you can start building your unittest
dll. Start by creating a new directory for your unittest code, and creating a
`.vcxproj` for a TAEF unittest dll. For the Terminal solution, we use the TAEF
nuget package `Taef.Redist.Wlk`.
nuget package `Microsoft.Taef`.
### Referencing your C++/WinRT static lib

View File

@@ -52,6 +52,117 @@
}
]
},
"AppearanceConfig": {
"properties": {
"colorScheme": {
"description": "The name of a color scheme to use when unfocused.",
"type": "string"
},
"foreground": {
"$ref": "#/definitions/Color",
"default": "#cccccc",
"description": "Sets the text color when unfocused. Overrides \"foreground\" from the color scheme. Uses hex color format: \"#rrggbb\".",
"type": ["string", "null"]
},
"background": {
"$ref": "#/definitions/Color",
"default": "#0c0c0c",
"description": "Sets the background color of the text when unfocused. Overrides \"background\" from the color scheme. Uses hex color format: \"#rrggbb\".",
"type": ["string", "null"]
},
"selectionBackground": {
"oneOf": [
{"$ref": "#/definitions/Color"},
{ "type": "null" }
],
"description": "Sets the background color of selected text when unfocused. Overrides selectionBackground set in the color scheme. Uses hex color format: \"#rrggbb\"."
},
"cursorColor": {
"oneOf": [
{ "$ref": "#/definitions/Color" },
{"type": "null"}
],
"description": "Sets the color of the cursor when unfocused. Overrides the cursor color from the color scheme. Uses hex color format: \"#rrggbb\"."
},
"cursorShape": {
"default": "bar",
"description": "Sets the shape of the cursor when unfocused. Possible values:\n -\"bar\" ( ┃, default )\n -\"doubleUnderscore\" ( ‗ )\n -\"emptyBox\" ( ▯ )\n -\"filledBox\" ( █ )\n -\"underscore\" ( ▁ )\n -\"vintage\" ( ▃ )",
"enum": [
"bar",
"doubleUnderscore",
"emptyBox",
"filledBox",
"underscore",
"vintage"
],
"type": "string"
},
"cursorHeight": {
"description": "Sets the percentage height of the cursor (when unfocused) starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 1-100.",
"maximum": 100,
"minimum": 1,
"type": ["integer","null"],
"default": 25
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background when unfocused.",
"oneOf": [
{
"type": ["string", null]
},
{
"enum": [
"desktopWallpaper"
]
}
],
"type": [ "string", "null" ]
},
"backgroundImageOpacity": {
"default": 1.0,
"description": "Sets the transparency of the background image when unfocused. Accepts floating point values from 0-1.",
"maximum": 1.0,
"minimum": 0.0,
"type": "number"
},
"backgroundImageStretchMode": {
"default": "uniformToFill",
"description": "Sets how the background image is resized to fill the window when unfocused.",
"enum": [
"fill",
"none",
"uniform",
"uniformToFill"
],
"type": "string"
},
"backgroundImageAlignment": {
"default": "center",
"enum": [
"bottom",
"bottomLeft",
"bottomRight",
"center",
"left",
"right",
"top",
"topLeft",
"topRight"
],
"description": "Sets how the background image aligns to the boundaries of the window when unfocused. Possible values: \"center\", \"left\", \"top\", \"right\", \"bottom\", \"topLeft\", \"topRight\", \"bottomLeft\", \"bottomRight\"",
"type": "string"
},
"experimental.retroTerminalEffect": {
"description": "When set to true, enable retro terminal effects when unfocused. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "boolean"
},
"experimental.pixelShaderPath": {
"description": "Use to set a path to a pixel shader to use with the Terminal when unfocused. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "string"
}
},
"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}\\}$",
@@ -77,6 +188,8 @@
"duplicateTab",
"find",
"findMatch",
"identifyWindow",
"identifyWindows",
"moveFocus",
"moveTab",
"newTab",
@@ -85,12 +198,14 @@
"openNewTabDropdown",
"openSettings",
"openTabColorPicker",
"openWindowRenamer",
"paste",
"prevTab",
"renameTab",
"openTabRenamer",
"resetFontSize",
"resizePane",
"renameWindow",
"scrollDown",
"scrollDownPage",
"scrollUp",
@@ -222,10 +337,32 @@
"$ref": "#/definitions/Color",
"default": null,
"description": "If provided, will set the tab's color to the given value"
},
"suppressApplicationTitle": {
"type": "boolean",
"default": "false",
"description": "When set to true, tabTitle overrides the default title of the tab and any title change messages from the application will be suppressed. When set to false, tabTitle behaves as normal"
},
"colorScheme": {
"description": "The name of a color scheme to use, instead of the one specified by the profile",
"type": "string"
}
},
"type": "object"
},
"SwitchToAdjacentTabArgs" : {
"oneOf": [
{ "type": "null" },
{
"enum": [
"mru",
"inOrder",
"disabled"
],
"type": "string"
}
]
},
"ShortcutAction": {
"properties": {
"action": {
@@ -404,12 +541,14 @@
"action": { "type": "string", "pattern": "openSettings" },
"target": {
"type": "string",
"default": "settingsFile",
"description": "The settings file to open.",
"default": "settingsUI",
"description": "Opens Settings UI or settings file.",
"enum": [
"settingsFile",
"defaultsFile",
"allFiles"
"allFiles",
"settingsUI"
]
}
}
@@ -597,6 +736,70 @@
}
]
},
"PrevTabAction": {
"description": "Arguments corresponding to a Previous Tab Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type":"string", "pattern": "prevTab" },
"tabSwitcherMode": {
"$ref": "#/definitions/SwitchToAdjacentTabArgs",
"default": null,
"description": "Move to the previous tab using \"tabSwitcherMode\". If no mode is provided, use the one globally defined one."
}
}
}
]
},
"NextTabAction": {
"description": "Arguments corresponding to a Next Tab Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type":"string", "pattern": "nextTab" },
"tabSwitcherMode": {
"$ref": "#/definitions/SwitchToAdjacentTabArgs",
"default": null,
"description": "Move to the next tab using \"tabSwitcherMode\". If no mode is provided, use the one globally defined one."
}
}
}
]
},
"RenameTabAction": {
"description": "Arguments corresponding to a renameTab Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "renameTab" },
"title": {
"type": "string",
"default": "",
"description": "A title to assign to the tab. If omitted or null, this action will restore the tab's title to the original value."
}
}
}
]
},
"RenameWindowAction": {
"description": "Arguments corresponding to a renameWindow Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "renameWindow" },
"name": {
"type": "string",
"default": "",
"description": "A name to assign to the window."
}
}
}
]
},
"Keybinding": {
"additionalProperties": false,
"properties": {
@@ -623,6 +826,10 @@
{ "$ref": "#/definitions/MoveTabAction" },
{ "$ref": "#/definitions/FindMatchAction" },
{ "$ref": "#/definitions/NewWindowAction" },
{ "$ref": "#/definitions/NextTabAction" },
{ "$ref": "#/definitions/PrevTabAction" },
{ "$ref": "#/definitions/RenameTabAction" },
{ "$ref": "#/definitions/RenameWindowAction" },
{ "type": "null" }
]
},
@@ -906,6 +1113,11 @@
"description": "Sets the background color of the text. Overrides \"background\" from the color scheme. Uses hex color format: \"#rrggbb\".",
"type": ["string", "null"]
},
"unfocusedAppearance": {
"$ref": "#/definitions/AppearanceConfig",
"description": "Sets the appearance of the terminal when it is unfocused.",
"type": ["object", "null"]
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background.",
"oneOf": [
@@ -993,9 +1205,9 @@
"description": "Sets the color of the cursor. Overrides the cursor color from the color scheme. Uses hex color format: \"#rrggbb\"."
},
"cursorHeight": {
"description": "Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 25-100.",
"description": "Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 1-100.",
"maximum": 100,
"minimum": 25,
"minimum": 1,
"type": ["integer","null"],
"default": 25
},

65
doc/feature_flags.md Normal file
View File

@@ -0,0 +1,65 @@
# til::feature
Feature flags are controlled by an XML document stored at `src/features.xml`.
## Example Document
```xml
<?xml version="1.0"?>
<featureStaging xmlns="http://microsoft.com/TilFeatureStaging-Schema.xsd">
<feature>
<!-- This will produce Feature_XYZ::IsEnabled() and TIL_FEATURE_XYZ_ENABLED (preprocessor) -->
<name>Feature_XYZ</name>
<description>Does a cool thing</description>
<!-- GitHub deliverable number; optional -->
<id>1234</id>
<!-- Whether the feature defaults to enabled or disabled -->
<stage>AlwaysEnabled|AlwaysDisabled</stage>
<!-- Branch wildcards where the feature should be *DISABLED* -->
<alwaysDisabledBranchTokens>
<branchToken>branch/with/wildcard/*</branchToken>
<!-- ... more branchTokens ... -->
</alwaysDisabledBranchTokens>
<!-- Just like alwaysDisabledBranchTokens, but for *ENABLING* the feature. -->
<alwaysEnabledBranchTokens>
<branchToken>...</branchToken>
</alwaysEnabledBranchTokens>
<!-- Brandings where the feature should be *DISABLED* -->
<alwaysDisabledBrandingTokens>
<!-- Valid brandings include Dev, Preview, Release, WindowsInbox -->
<brandingToken>Release</brandingToken>
<!-- ... more brandingTokens ... -->
</alwaysDisabledBrandingTokens>
<!-- Just like alwaysDisabledBrandingTokens, but for *ENABLING* the feature -->
<alwaysEnabledBrandingTokens>
<branchToken>...</branchToken>
</alwaysEnabledBrandingTokens>
<!-- Unequivocally disable this feature in Release -->
<alwaysDisabledReleaseTokens />
</feature>
</featureStaging>
```
## Notes
Features that are disabled for Release using `alwaysDisabledReleaseTokens` are
*always* disabled in Release, even if they come from a branch that would have
been enabled by the wildcard.
### Precedence
1. `alwaysDisabledReleaseTokens`
2. Enabled branches
3. Disabled branches
* The longest branch token that matches your branch will win.
3. Enabled brandings
4. Disabled brandings
5. The feature's default state

View File

@@ -2,17 +2,16 @@
## Overview
This document outlines the roadmap towards delivering Windows Terminal 2.0 by Spring 2021.
This document outlines the roadmap towards delivering Windows Terminal 2.0 by Winter 2021.
## Milestones
The Windows Terminal project is engineered and delivered as a set of 4-week milestones. New features will go into [Windows Terminal Preview](https://aka.ms/terminal-preview) first, then a month after they've been in Preview, those features will move into [Windows Terminal](https://aka.ms/terminal).
Windows Terminal is engineered and delivered as a set of 6-week milestones. New features will go into [Windows Terminal Preview](https://aka.ms/terminal-preview) first, then a month after they've been in Preview, those features will move into [Windows Terminal](https://aka.ms/terminal).
| Duration | Activity | Releases |
| --- | --- | --- |
| 2 weeks | Dev Work<br/> <ul><li>Fixes / Features for future Windows Releases</li><li>Fixes / Features for Windows Terminal</li></ul> | Release to Internal Selfhosters at end of week 2 |
| 1 week | Quality & Stability<br/> <ul><li>Bug Fixes</li><li>Perf & Stability</li><li>UI Polish</li><li>Tests</li><li>etc.</li></ul>| Push to Microsoft Store at end of week 3 |
| 4 weeks | Dev Work<br/> <ul><li>Fixes / Features for future Windows Releases</li><li>Fixes / Features for Windows Terminal</li></ul> | Release to Internal Selfhosters at end of week 4 |
| 1 week | Quality & Stability<br/> <ul><li>Bug Fixes</li><li>Perf & Stability</li><li>UI Polish</li><li>Tests</li><li>etc.</li></ul>| Push to Microsoft Store at end of week 5 |
| 1 week | Release <br/> <ul><li>Available from [Microsoft Store](https://aka.ms/terminal) & [GitHub Releases](https://github.com/microsoft/terminal/releases)</li><li>Release Notes & Announcement Blog published</li><li>Engineering System Maintenance</li><li>Community Engagement</li><li>Docs</li><li>Future Milestone Planning</li></ul> | Release available from Microsoft Store & GitHub Releases |
## Terminal Roadmap / Timeline
@@ -26,12 +25,15 @@ Below is the schedule for when milestones will be included in release builds of
| 2020-08-31 | [1.3] in Windows Terminal Preview<br>[1.2] in Windows Terminal | [Windows Terminal Preview 1.3 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-3-release/) |
| 2020-09-30 | [1.4] in Windows Terminal Preview<br>[1.3] in Windows Terminal | [Windows Terminal Preview 1.4 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-4-release/) |
| 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/) |
| 2020-12-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | |
| 2021-01-31 | 1.7 in Windows Terminal Preview<br>[1.6] in Windows Terminal | |
| 2021-02-28 | 1.8 in Windows Terminal Preview<br>1.8 in Windows Terminal | |
| 2021-03-31 | 1.9 in Windows Terminal Preview<br>1.9 in Windows Terminal | |
| 2021-04-30 | 2.0 RC in Windows Terminal Preview<br>2.0 RC in Windows Terminal | |
| 2021-05-31 | [2.0] in Windows Terminal Preview<br>[2.0] in Windows Terminal | |
| 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-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 | |
| 2021-11-30 | 2.0 RC in Windows Terminal Preview<br>2.0 RC in Windows Terminal | |
| 2021-12-31 | [2.0] in Windows Terminal Preview<br>[2.0] in Windows Terminal | |
## Issue Triage & Prioritization
@@ -84,6 +86,9 @@ Feature Notes:
[1.4]: https://github.com/microsoft/terminal/milestone/28
[1.5]: https://github.com/microsoft/terminal/milestone/30
[1.6]: https://github.com/microsoft/terminal/milestone/31
[1.7]: https://github.com/microsoft/terminal/milestone/32
[1.8]: https://github.com/microsoft/terminal/milestone/33
[1.9]: https://github.com/microsoft/terminal/milestone/34
[2.0]: https://github.com/microsoft/terminal/milestone/22
[#1564]: https://github.com/microsoft/terminal/issues/1564
[#6720]: https://github.com/microsoft/terminal/pull/6720

Binary file not shown.

Binary file not shown.

View File

@@ -6,16 +6,3 @@ The images in this directory do not fall under the same [license](https://raw.gi
of the Windows Terminal code.
Please consult the [license](./LICENSE) in this directory for terms applicable to the image assets in this directory.
## Fonts
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
of the Windows Terminal code.
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
### Fonts Included
* Cascadia Code, Cascadia Mono (2102.25)
* from microsoft/cascadia-code@911dc421f333e3b72b97381d16fee5b71eb48f04

BIN
res/fonts/CascadiaCode.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
res/fonts/CascadiaMono.ttf Normal file

Binary file not shown.

Binary file not shown.

12
res/fonts/README.md Normal file
View File

@@ -0,0 +1,12 @@
# Windows Terminal and Console Assets (Fonts)
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
of the Windows Terminal code.
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
### Fonts Included
* Cascadia Code, Cascadia Mono (2106.17)
* from microsoft/cascadia-code@fb0bce69c1c12f6c298b8bc1c1d181868f5daa9a

View File

@@ -1,8 +1,6 @@
<Application x:Class="GUIConsole.Wpf.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
<Application x:Class="GUIConsole.Wpf.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources />
</Application>

View File

@@ -1,84 +1,100 @@
<Window x:Class="GUIConsole.Wpf.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
Background="#C7000000"
AllowsTransparency="True"
WindowStyle="None"
MouseDown="Window_MouseDown"
BorderThickness="1"
BorderBrush="LightSlateGray"
KeyDown="Window_KeyDown"
Loaded="Window_Loaded">
<Window.Resources>
<Style x:Key="TitleBarButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="FontFamily" Value="Segoe MDL2 Assets"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Width" Value="46"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
<Style x:Key="CloseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource TitleBarButtonStyle}">
<Setter Property="Content" Value="&#xE10A;"/>
<!--Remove the default Button template's Triggers, otherwise they'll override our trigger below.-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Button.Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="TitleBarTitle" Grid.Column="0" VerticalAlignment="Center" Padding="10 0" Foreground="White">
GUIConsole
</TextBlock>
<StackPanel x:Name="TitleBarButtons" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top">
<Button x:Name="MinimizeButton"
Click="MinimizeButton_Click"
Content="&#xE108;"
Style="{StaticResource TitleBarButtonStyle}"/>
<Button x:Name="MaximizeRestoreButton"
Click="MaximizeRestoreButton_Click"
Content="&#xE922;"
FontSize="12"
Style="{StaticResource TitleBarButtonStyle}"/>
<Button x:Name="CloseButton"
Click="CloseButton_Click"
FontSize="12"
Style="{StaticResource CloseButtonStyle}"/>
</StackPanel>
</Grid>
<ScrollViewer x:Name="TerminalHistoryViewer" Grid.Row="1" ScrollChanged="ScrollViewer_ScrollChanged">
<TextBlock x:Name="TerminalHistoryBlock" FontFamily="Consolas" TextWrapping="Wrap" Foreground="White"/>
</ScrollViewer>
</Grid>
</Window>
<Window x:Class="GUIConsole.Wpf.MainWindow"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
AllowsTransparency="True"
Background="#C7000000"
BorderBrush="LightSlateGray"
BorderThickness="1"
KeyDown="Window_KeyDown"
Loaded="Window_Loaded"
MouseDown="Window_MouseDown"
WindowStyle="None"
mc:Ignorable="d">
<Window.Resources>
<Style x:Key="TitleBarButtonStyle"
TargetType="{x:Type Button}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="FontFamily" Value="Segoe MDL2 Assets" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Height" Value="32" />
<Setter Property="Width" Value="46" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="White" />
<Setter Property="BorderThickness" Value="0" />
</Style>
<Style x:Key="CloseButtonStyle"
BasedOn="{StaticResource TitleBarButtonStyle}"
TargetType="{x:Type Button}">
<Setter Property="Content" Value="&#xE10A;" />
<!-- Remove the default Button template's Triggers, otherwise they'll override our trigger below. -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Button.Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="TitleBarTitle"
Grid.Column="0"
Padding="10,0"
VerticalAlignment="Center"
Foreground="White">
GUIConsole
</TextBlock>
<StackPanel x:Name="TitleBarButtons"
Grid.Column="1"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button x:Name="MinimizeButton"
Click="MinimizeButton_Click"
Content="&#xE108;"
Style="{StaticResource TitleBarButtonStyle}" />
<Button x:Name="MaximizeRestoreButton"
Click="MaximizeRestoreButton_Click"
Content="&#xE922;"
FontSize="12"
Style="{StaticResource TitleBarButtonStyle}" />
<Button x:Name="CloseButton"
Click="CloseButton_Click"
FontSize="12"
Style="{StaticResource CloseButtonStyle}" />
</StackPanel>
</Grid>
<ScrollViewer x:Name="TerminalHistoryViewer"
Grid.Row="1"
ScrollChanged="ScrollViewer_ScrollChanged">
<TextBlock x:Name="TerminalHistoryBlock"
FontFamily="Consolas"
Foreground="White"
TextWrapping="Wrap" />
</ScrollViewer>
</Grid>
</Window>

View File

@@ -0,0 +1,66 @@
// A minimal pixel shader that outlines text
// The terminal graphics as a texture
Texture2D shaderTexture;
SamplerState samplerState;
// Terminal settings such as the resolution of the texture
cbuffer PixelShaderSettings {
// The number of seconds since the pixel shader was enabled
float Time;
// UI Scale
float Scale;
// Resolution of the shaderTexture
float2 Resolution;
// Background color as rgba
float4 Background;
};
// A pixel shader is a program that given a texture coordinate (tex) produces a color.
// tex is an x,y tuple that ranges from 0,0 (top left) to 1,1 (bottom right).
// Just ignore the pos parameter.
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
{
// Read the color value at the current texture coordinate (tex)
// float4 is tuple of 4 floats, rgba
float4 color = shaderTexture.Sample(samplerState, tex);
// Read the color value at some offset, will be used as shadow. For the best
// effect, read the colors offset on the left, right, top, bottom of this
// fragment, as well as on the corners of this fragment.
//
// You could get away with fewer samples, but the resulting outlines will be
// blurrier.
//left, right, top, bottom:
float4 leftColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 1.0, 0.0)/Resolution.y);
float4 rightColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2(-1.0, 0.0)/Resolution.y);
float4 topColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 0.0, 1.0)/Resolution.y);
float4 bottomColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 0.0, -1.0)/Resolution.y);
// Corners
float4 topLeftColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 1.0, 1.0)/Resolution.y);
float4 topRightColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2(-1.0, 1.0)/Resolution.y);
float4 bottomLeftColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2( 1.0, -1.0)/Resolution.y);
float4 bottomRightColor = shaderTexture.Sample(samplerState, tex+1.0*Scale*float2(-1.0, -1.0)/Resolution.y);
// Now, if any of those adjacent cells has text in it, then the *color vec4
// will have a non-zero .w (which is used for alpha). Use that alpha value
// to add some black to the current fragment.
//
// This will result in only coloring fragments adjacent to text, but leaving
// background images (for example) untouched.
float3 outlineColor = float3(0, 0, 0);
float4 result = color;
result = result + float4(outlineColor, leftColor.w);
result = result + float4(outlineColor, rightColor.w);
result = result + float4(outlineColor, topColor.w);
result = result + float4(outlineColor, bottomColor.w);
result = result + float4(outlineColor, topLeftColor.w);
result = result + float4(outlineColor, topRightColor.w);
result = result + float4(outlineColor, bottomLeftColor.w);
result = result + float4(outlineColor, bottomRightColor.w);
return result;
}

34
src/Terminal.wprp Normal file
View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<WindowsPerformanceRecorder Version="1.0" Author="Microsoft Corporation" Copyright="Microsoft Corporation" Company="Microsoft Corporation">
<Profiles>
<EventCollector Id="EventCollector_Terminal" Name="Terminal">
<BufferSize Value="64" />
<Buffers Value="4" />
</EventCollector>
<EventProvider Id="EventProvider_TerminalControl" Name="28c82e50-57af-5a86-c25b-e39cd990032b" />
<EventProvider Id="EventProvider_TerminalConnection" Name="e912fe7b-eeb6-52a5-c628-abe388e5f792" />
<EventProvider Id="EventProvider_TerminalSettingsModel" Name="be579944-4d33-5202-e5d6-a7a57f1935cb" />
<EventProvider Id="EventProvider_TerminalApp" Name="24a1622f-7da7-5c77-3303-d850bd1ab2ed" />
<EventProvider Id="EventProvider_TerminalWin32Host" Name="56c06166-2e2e-5f4d-7ff3-74f4b78c87d6" />
<EventProvider Id="EventProvider_TerminalRemoting" Name="d6f04aad-629f-539a-77c1-73f5c3e4aa7b" />
<EventProvider Id="EventProvider_TerminalDirectX" Name="c93e739e-ae50-5a14-78e7-f171e947535d" />
<Profile Id="Terminal.Verbose.File" Name="Terminal" Description="Terminal" LoggingMode="File" DetailLevel="Verbose">
<Collectors>
<EventCollectorId Value="EventCollector_Terminal">
<EventProviders>
<EventProviderId Value="EventProvider_TerminalControl" />
<EventProviderId Value="EventProvider_TerminalConnection" />
<EventProviderId Value="EventProvider_TerminalSettingsModel" />
<EventProviderId Value="EventProvider_TerminalApp" />
<EventProviderId Value="EventProvider_TerminalWin32Host" />
<EventProviderId Value="EventProvider_TerminalRemoting" />
<EventProviderId Value="EventProvider_TerminalDirectX" />
</EventProviders>
</EventCollectorId>
</Collectors>
</Profile>
<Profile Id="Terminal.Light.File" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="File" DetailLevel="Light" />
<Profile Id="Terminal.Verbose.Memory" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="Memory" DetailLevel="Verbose" />
<Profile Id="Terminal.Light.Memory" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="Memory" DetailLevel="Light" />
</Profiles>
</WindowsPerformanceRecorder>

View File

@@ -70,6 +70,7 @@
<ItemGroup>
<ProjectReference Include="..\WindowsTerminal\WindowsTerminal.vcxproj" />
<ProjectReference Include="..\..\host\exe\Host.EXE.vcxproj" />
<ProjectReference Include="..\..\host\proxy\Host.Proxy.vcxproj" />
<ProjectReference Include="..\TerminalAzBridge\TerminalAzBridge.vcxproj" />
<ProjectReference Include="..\ShellExtension\WindowsTerminalShellExt.vcxproj" />
<ProjectReference Include="..\wt\wt.vcxproj" />

View File

@@ -73,9 +73,43 @@
<uap3:Name>com.microsoft.windows.terminal.settings</uap3:Name>
</uap3:AppExtensionHost>
</uap3:Extension>
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.console.host"
Id="OpenConsole-Dev"
DisplayName="OpenConsole Dev"
Description="Console host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>
<Clsid>{1F9F2BF5-5BC3-4F17-B0E6-912413F1F451}</Clsid>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.terminal.host"
Id="Terminal-Dev"
DisplayName="Windows Terminal Dev"
Description="Terminal host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>
<Clsid>{051F34EE-C1FD-4B19-AF75-9BA54648434C}</Clsid>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
<com:Extension Category="windows.comInterface">
<com:ComInterface>
<com:ProxyStub Id="DEC4804D-56D1-4F73-9FBE-6828E7C85C56" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="2B607BC1-43EB-40C3-95AE-2856ADDB7F23" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
<com:Interface Id="FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
</com:ComInterface>
</com:Extension>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer DisplayName="OpenConsole" Executable="OpenConsole.exe">
<com:Class Id="1F9F2BF5-5BC3-4F17-B0E6-912413F1F451"/>
</com:ExeServer>
<com:ExeServer DisplayName="WindowsTerminal" Executable="WindowsTerminal.exe">
<com:Class Id="051F34EE-C1FD-4B19-AF75-9BA54648434C"/>
</com:ExeServer>
<com:SurrogateServer DisplayName="WindowsTerminalShellExt">
<com:Class Id="52065414-e077-47ec-a3ac-1cc5455e1b54" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
</com:SurrogateServer>

View File

@@ -74,8 +74,45 @@
Enabled="false"
DisplayName="ms-resource:AppNamePre" />
</uap5:Extension>
<!-- DISABLED FOR 1.8
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.console.host"
Id="OpenConsole-Pre"
DisplayName="OpenConsole Preview"
Description="Console host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>
<Clsid>{06EC847C-C0A5-46B8-92CB-7C92F6E35CD5}</Clsid>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.terminal.host"
Id="Terminal-Pre"
DisplayName="Windows Terminal Preview"
Description="Terminal host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>
<Clsid>{86633F1F-6454-40EC-89CE-DA4EBA977EE2}</Clsid>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
-->
<com:Extension Category="windows.comInterface">
<com:ComInterface>
<com:ProxyStub Id="1833E661-CC81-4DD0-87C6-C2F74BD39EFA" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="2B607BC1-43EB-40C3-95AE-2856ADDB7F23" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
<com:Interface Id="FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
</com:ComInterface>
</com:Extension>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer DisplayName="OpenConsole" Executable="OpenConsole.exe">
<com:Class Id="06EC847C-C0A5-46B8-92CB-7C92F6E35CD5"/>
</com:ExeServer>
<com:ExeServer DisplayName="WindowsTerminal" Executable="WindowsTerminal.exe">
<com:Class Id="86633F1F-6454-40EC-89CE-DA4EBA977EE2"/>
</com:ExeServer>
<com:SurrogateServer DisplayName="WindowsTerminalShellExt">
<com:Class Id="02db545a-3e20-46de-83a5-1329b1e88b6b" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
</com:SurrogateServer>
@@ -105,8 +142,10 @@
<Extensions>
<uap7:Extension Category="windows.sharedFonts">
<uap7:SharedFonts>
<uap4:Font File="Cascadia.ttf" />
<uap4:Font File="CascadiaCode.ttf" />
<uap4:Font File="CascadiaCodeItalic.ttf" />
<uap4:Font File="CascadiaMono.ttf" />
<uap4:Font File="CascadiaMonoItalic.ttf" />
</uap7:SharedFonts>
</uap7:Extension>
</Extensions>

View File

@@ -74,9 +74,43 @@
Enabled="false"
DisplayName="ms-resource:AppName" />
</uap5:Extension>
<!-- <uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.console.host"
Id="OpenConsole"
DisplayName="OpenConsole"
Description="Console host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>
<Clsid>{2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69}</Clsid>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.terminal.host"
Id="Terminal"
DisplayName="Windows Terminal"
Description="Terminal host built from microsoft/terminal open source repository"
PublicFolder="Public">
<uap3:Properties>
<Clsid>{E12CFF52-A866-4C77-9A90-F570A7AA2C6B}</Clsid>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
<com:Extension Category="windows.comInterface">
<com:ComInterface>
<com:ProxyStub Id="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="2B607BC1-43EB-40C3-95AE-2856ADDB7F23" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
<com:Interface Id="FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
</com:ComInterface>
</com:Extension> -->
<com:Extension Category="windows.comServer">
<com:ComServer>
<!-- <com:ExeServer DisplayName="OpenConsole" Executable="OpenConsole.exe">
<com:Class Id="2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69"/>
</com:ExeServer>
<com:ExeServer DisplayName="WindowsTerminal" Executable="WindowsTerminal.exe">
<com:Class Id="E12CFF52-A866-4C77-9A90-F570A7AA2C6B"/>
</com:ExeServer> -->
<com:SurrogateServer DisplayName="WindowsTerminalShellExt">
<com:Class Id="9f156763-7844-4dc4-b2b1-901f640f5155" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
</com:SurrogateServer>
@@ -106,8 +140,10 @@
<Extensions>
<uap7:Extension Category="windows.sharedFonts">
<uap7:SharedFonts>
<uap4:Font File="Cascadia.ttf" />
<uap4:Font File="CascadiaCode.ttf" />
<uap4:Font File="CascadiaCodeItalic.ttf" />
<uap4:Font File="CascadiaMono.ttf" />
<uap4:Font File="CascadiaMonoItalic.ttf" />
</uap7:SharedFonts>
</uap7:Extension>
</Extensions>

View File

@@ -12,13 +12,9 @@
<Link>Images\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Content>
<!-- Fonts -->
<Content Include="$(OpenConsoleDir)res\Cascadia.ttf" Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
<Content Include="$(OpenConsoleDir)res\fonts\*.ttf" Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
<DeploymentContent>true</DeploymentContent>
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
</Content>
<Content Include="$(OpenConsoleDir)res\CascadiaMono.ttf" Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
<DeploymentContent>true</DeploymentContent>
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<Link>%(FileName)%(Extension)</Link>
</Content>
<!-- Profile Icons -->
<Content Include="$(OpenConsoleDir)src\cascadia\CascadiaPackage\ProfileIcons\**\*">

View File

@@ -338,34 +338,34 @@ namespace SettingsModelLocalTests
// verify profile defaults
Log::Comment(L"Profile Defaults");
VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().ColorSchemeName());
VERIFY_IS_TRUE(settings->ProfileDefaults().HasColorSchemeName());
VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().DefaultAppearance().ColorSchemeName());
VERIFY_IS_TRUE(settings->ProfileDefaults().DefaultAppearance().HasColorSchemeName());
// verify all other profiles
const auto& profiles{ settings->AllProfiles() };
{
const auto& prof{ profiles.GetAt(0) };
Log::Comment(prof.Name().c_str());
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
VERIFY_IS_TRUE(prof.HasColorSchemeName());
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(1) };
Log::Comment(prof.Name().c_str());
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
VERIFY_IS_TRUE(prof.HasColorSchemeName());
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(2) };
Log::Comment(prof.Name().c_str());
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
VERIFY_IS_FALSE(prof.HasColorSchemeName());
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
VERIFY_IS_FALSE(prof.DefaultAppearance().HasColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(3) };
Log::Comment(prof.Name().c_str());
VERIFY_ARE_EQUAL(L"Scheme 2", prof.ColorSchemeName());
VERIFY_IS_TRUE(prof.HasColorSchemeName());
VERIFY_ARE_EQUAL(L"Scheme 2", prof.DefaultAppearance().ColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
}
}
}

View File

@@ -9,7 +9,7 @@
using namespace Microsoft::Console;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Windows::Foundation::Collections;
using namespace WEX::Logging;
using namespace WEX::TestExecution;

View File

@@ -15,7 +15,7 @@ using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
namespace SettingsModelLocalTests
{
@@ -1311,9 +1311,9 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(3u, settings->_allProfiles.Size());
VERIFY_ARE_EQUAL(2u, settings->_globals->ColorSchemes().Size());
VERIFY_ARE_EQUAL(L"schemeOne", settings->_allProfiles.GetAt(0).ColorSchemeName());
VERIFY_ARE_EQUAL(L"InvalidSchemeName", settings->_allProfiles.GetAt(1).ColorSchemeName());
VERIFY_ARE_EQUAL(L"Campbell", settings->_allProfiles.GetAt(2).ColorSchemeName());
VERIFY_ARE_EQUAL(L"schemeOne", settings->_allProfiles.GetAt(0).DefaultAppearance().ColorSchemeName());
VERIFY_ARE_EQUAL(L"InvalidSchemeName", settings->_allProfiles.GetAt(1).DefaultAppearance().ColorSchemeName());
VERIFY_ARE_EQUAL(L"Campbell", settings->_allProfiles.GetAt(2).DefaultAppearance().ColorSchemeName());
settings->_ValidateAllSchemesExist();
@@ -1323,9 +1323,9 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(3u, settings->_allProfiles.Size());
VERIFY_ARE_EQUAL(2u, settings->_globals->ColorSchemes().Size());
VERIFY_ARE_EQUAL(L"schemeOne", settings->_allProfiles.GetAt(0).ColorSchemeName());
VERIFY_ARE_EQUAL(L"Campbell", settings->_allProfiles.GetAt(1).ColorSchemeName());
VERIFY_ARE_EQUAL(L"Campbell", settings->_allProfiles.GetAt(2).ColorSchemeName());
VERIFY_ARE_EQUAL(L"schemeOne", settings->_allProfiles.GetAt(0).DefaultAppearance().ColorSchemeName());
VERIFY_ARE_EQUAL(L"Campbell", settings->_allProfiles.GetAt(1).DefaultAppearance().ColorSchemeName());
VERIFY_ARE_EQUAL(L"Campbell", settings->_allProfiles.GetAt(2).DefaultAppearance().ColorSchemeName());
}
void DeserializationTests::ValidateColorSchemeInCommands()
@@ -1543,7 +1543,7 @@ namespace SettingsModelLocalTests
settings->_ParseJsonString(settingsJson, false);
settings->LayerJson(settings->_userSettings);
VERIFY_ARE_NOT_EQUAL(0u, settings->_allProfiles.Size());
VERIFY_ARE_EQUAL(expectedPath, settings->_allProfiles.GetAt(0).ExpandedBackgroundImagePath());
VERIFY_ARE_EQUAL(expectedPath, settings->_allProfiles.GetAt(0).DefaultAppearance().ExpandedBackgroundImagePath());
}
void DeserializationTests::TestProfileBackgroundImageWithDesktopWallpaper()
{
@@ -1564,8 +1564,8 @@ namespace SettingsModelLocalTests
auto settings = winrt::make_self<implementation::CascadiaSettings>();
settings->_ParseJsonString(settingsJson, false);
settings->LayerJson(settings->_userSettings);
VERIFY_ARE_EQUAL(expectedBackgroundImagePath, settings->_allProfiles.GetAt(0).BackgroundImagePath());
VERIFY_ARE_NOT_EQUAL(expectedBackgroundImagePath, settings->_allProfiles.GetAt(0).ExpandedBackgroundImagePath());
VERIFY_ARE_EQUAL(expectedBackgroundImagePath, settings->_allProfiles.GetAt(0).DefaultAppearance().BackgroundImagePath());
VERIFY_ARE_NOT_EQUAL(expectedBackgroundImagePath, settings->_allProfiles.GetAt(0).DefaultAppearance().ExpandedBackgroundImagePath());
}
void DeserializationTests::TestCloseOnExitParsing()
{

View File

@@ -11,7 +11,7 @@
using namespace Microsoft::Console;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;

View File

@@ -117,14 +117,14 @@ namespace SettingsModelLocalTests
const auto profile2Json = VerifyParseSucceeded(profile2String);
auto profile0 = implementation::Profile::FromJson(profile0Json);
VERIFY_IS_NOT_NULL(profile0->Foreground());
VERIFY_ARE_EQUAL(til::color(0, 0, 0), til::color{ profile0->Foreground().Value() });
VERIFY_IS_NOT_NULL(profile0->DefaultAppearance().Foreground());
VERIFY_ARE_EQUAL(til::color(0, 0, 0), til::color{ profile0->DefaultAppearance().Foreground().Value() });
VERIFY_IS_NOT_NULL(profile0->Background());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile0->Background().Value() });
VERIFY_IS_NOT_NULL(profile0->DefaultAppearance().Background());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile0->DefaultAppearance().Background().Value() });
VERIFY_IS_NOT_NULL(profile0->SelectionBackground());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile0->SelectionBackground().Value() });
VERIFY_IS_NOT_NULL(profile0->DefaultAppearance().SelectionBackground());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile0->DefaultAppearance().SelectionBackground().Value() });
VERIFY_ARE_EQUAL(L"profile0", profile0->Name());
@@ -135,14 +135,14 @@ namespace SettingsModelLocalTests
auto profile1{ profile0->CreateChild() };
profile1->LayerJson(profile1Json);
VERIFY_IS_NOT_NULL(profile1->Foreground());
VERIFY_ARE_EQUAL(til::color(2, 2, 2), til::color{ profile1->Foreground().Value() });
VERIFY_IS_NOT_NULL(profile1->DefaultAppearance().Foreground());
VERIFY_ARE_EQUAL(til::color(2, 2, 2), til::color{ profile1->DefaultAppearance().Foreground().Value() });
VERIFY_IS_NOT_NULL(profile1->Background());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile1->Background().Value() });
VERIFY_IS_NOT_NULL(profile1->DefaultAppearance().Background());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile1->DefaultAppearance().Background().Value() });
VERIFY_IS_NOT_NULL(profile1->Background());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile1->Background().Value() });
VERIFY_IS_NOT_NULL(profile1->DefaultAppearance().Background());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile1->DefaultAppearance().Background().Value() });
VERIFY_ARE_EQUAL(L"profile1", profile1->Name());
@@ -154,14 +154,14 @@ namespace SettingsModelLocalTests
auto profile2{ profile1->CreateChild() };
profile2->LayerJson(profile2Json);
VERIFY_IS_NOT_NULL(profile2->Foreground());
VERIFY_ARE_EQUAL(til::color(3, 3, 3), til::color{ profile2->Foreground().Value() });
VERIFY_IS_NOT_NULL(profile2->DefaultAppearance().Foreground());
VERIFY_ARE_EQUAL(til::color(3, 3, 3), til::color{ profile2->DefaultAppearance().Foreground().Value() });
VERIFY_IS_NOT_NULL(profile2->Background());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile2->Background().Value() });
VERIFY_IS_NOT_NULL(profile2->DefaultAppearance().Background());
VERIFY_ARE_EQUAL(til::color(1, 1, 1), til::color{ profile2->DefaultAppearance().Background().Value() });
VERIFY_IS_NOT_NULL(profile2->SelectionBackground());
VERIFY_ARE_EQUAL(til::color(2, 2, 2), til::color{ profile2->SelectionBackground().Value() });
VERIFY_IS_NOT_NULL(profile2->DefaultAppearance().SelectionBackground());
VERIFY_ARE_EQUAL(til::color(2, 2, 2), til::color{ profile2->DefaultAppearance().SelectionBackground().Value() });
VERIFY_ARE_EQUAL(L"profile2", profile2->Name());

View File

@@ -15,7 +15,7 @@ using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
namespace SettingsModelLocalTests
{

View File

@@ -40,6 +40,7 @@
<ClCompile Include="CommandTests.cpp" />
<ClCompile Include="DeserializationTests.cpp" />
<ClCompile Include="SerializationTests.cpp" />
<ClCompile Include="TerminalSettingsTests.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
@@ -57,7 +58,7 @@
<!-- If you don't reference these projects here, the
_ConsoleGenerateAdditionalWinmdManifests step won't gather the winmd's -->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)\src\cascadia\TerminalSettingsModel\dll\Microsoft.Terminal.Settings.Model.vcxproj" />
</ItemGroup>

View File

@@ -0,0 +1,556 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "../TerminalSettingsModel/CascadiaSettings.h"
#include "../TerminalSettingsModel/TerminalSettings.h"
#include "TestUtils.h"
using namespace Microsoft::Console;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::Control;
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class TerminalSettingsTests
{
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(TerminalSettingsTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(TryCreateWinRTType);
TEST_METHOD(TestTerminalArgsForBinding);
TEST_METHOD(MakeSettingsForProfileThatDoesntExist);
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
TEST_METHOD(TestLayerProfileOnColorScheme);
TEST_CLASS_SETUP(ClassSetup)
{
return true;
}
};
void TerminalSettingsTests::TryCreateWinRTType()
{
TerminalSettings settings;
VERIFY_IS_NOT_NULL(settings);
auto oldFontSize = settings.FontSize();
settings.FontSize(oldFontSize + 5);
auto newFontSize = settings.FontSize();
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
}
void TerminalSettingsTests::TestTerminalArgsForBinding()
{
const std::string settingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"historySize": 1,
"commandline": "cmd.exe"
},
{
"name": "profile1",
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
"historySize": 2,
"commandline": "pwsh.exe"
},
{
"name": "profile2",
"historySize": 3,
"commandline": "wsl.exe"
}
],
"keybindings": [
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
]
})" };
const winrt::guid guid0{ ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}") };
const winrt::guid guid1{ ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}") };
CascadiaSettings settings{ til::u8u16(settingsJson) };
auto keymap = settings.GlobalSettings().KeyMap();
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
const auto profile2Guid = settings.ActiveProfiles().GetAt(2).Guid();
VERIFY_ARE_NOT_EQUAL(winrt::guid{}, profile2Guid);
VERIFY_ARE_EQUAL(12u, keymap.Size());
{
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('B') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, guid);
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, guid);
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, guid);
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, guid);
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('H') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('I') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, guid);
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('J') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('K') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, guid);
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('L') };
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, guid);
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
}
}
void TerminalSettingsTests::MakeSettingsForProfileThatDoesntExist()
{
// Test that making settings throws when the GUID doesn't exist
const std::string settingsString{ R"(
{
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name" : "profile0",
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
"historySize": 1
},
{
"name" : "profile1",
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
"historySize": 2
}
]
})" };
CascadiaSettings settings{ til::u8u16(settingsString) };
const auto guid1 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
const auto guid2 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
const auto guid3 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
try
{
auto terminalSettings{ TerminalSettings::CreateWithProfileByID(settings, guid1, nullptr) };
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
VERIFY_ARE_EQUAL(1, terminalSettings.DefaultSettings().HistorySize());
}
catch (...)
{
VERIFY_IS_TRUE(false, L"This call to CreateWithProfileByID should succeed");
}
try
{
auto terminalSettings{ TerminalSettings::CreateWithProfileByID(settings, guid2, nullptr) };
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
VERIFY_ARE_EQUAL(2, terminalSettings.DefaultSettings().HistorySize());
}
catch (...)
{
VERIFY_IS_TRUE(false, L"This call to CreateWithProfileByID should succeed");
}
VERIFY_THROWS(auto terminalSettings = TerminalSettings::CreateWithProfileByID(settings, guid3, nullptr), wil::ResultException, L"This call to constructor should fail");
try
{
const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(settings, nullptr, nullptr) };
VERIFY_ARE_NOT_EQUAL(nullptr, termSettings);
VERIFY_ARE_EQUAL(1, termSettings.DefaultSettings().HistorySize());
}
catch (...)
{
VERIFY_IS_TRUE(false, L"This call to CreateWithNewTerminalArgs should succeed");
}
}
void TerminalSettingsTests::MakeSettingsForDefaultProfileThatDoesntExist()
{
// Test that MakeSettings _doesnt_ throw when we load settings with a
// defaultProfile that's not in the list, we validate the settings, and
// then call MakeSettings(nullopt). The validation should ensure that
// the default profile is something reasonable
const std::string settingsString{ R"(
{
"defaultProfile": "{6239a42c-3333-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name" : "profile0",
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
"historySize": 1
},
{
"name" : "profile1",
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
"historySize": 2
}
]
})" };
CascadiaSettings settings{ til::u8u16(settingsString) };
VERIFY_ARE_EQUAL(2u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(2u, settings.ActiveProfiles().Size());
VERIFY_ARE_EQUAL(settings.GlobalSettings().DefaultProfile(), settings.ActiveProfiles().GetAt(0).Guid());
try
{
const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(settings, nullptr, nullptr) };
VERIFY_ARE_NOT_EQUAL(nullptr, termSettings);
VERIFY_ARE_EQUAL(1, termSettings.DefaultSettings().HistorySize());
}
catch (...)
{
VERIFY_IS_TRUE(false, L"This call to CreateWithNewTerminalArgs should succeed");
}
}
void TerminalSettingsTests::TestLayerProfileOnColorScheme()
{
Log::Comment(NoThrowString().Format(
L"Ensure that setting (or not) a property in the profile that should override a property of the color scheme works correctly."));
const std::string settings0String{ R"(
{
"defaultProfile": "profile5",
"profiles": [
{
"name" : "profile0",
"colorScheme": "schemeWithCursorColor"
},
{
"name" : "profile1",
"colorScheme": "schemeWithoutCursorColor"
},
{
"name" : "profile2",
"colorScheme": "schemeWithCursorColor",
"cursorColor": "#234567"
},
{
"name" : "profile3",
"colorScheme": "schemeWithoutCursorColor",
"cursorColor": "#345678"
},
{
"name" : "profile4",
"cursorColor": "#456789"
},
{
"name" : "profile5"
}
],
"schemes": [
{
"name": "schemeWithCursorColor",
"cursorColor": "#123456"
},
{
"name": "schemeWithoutCursorColor"
}
]
})" };
CascadiaSettings settings{ til::u8u16(settings0String) };
VERIFY_ARE_EQUAL(6u, settings.ActiveProfiles().Size());
VERIFY_ARE_EQUAL(2u, settings.GlobalSettings().ColorSchemes().Size());
auto createTerminalSettings = [&](const auto& profile, const auto& schemes) {
auto terminalSettings{ winrt::make_self<implementation::TerminalSettings>() };
terminalSettings->_ApplyProfileSettings(profile);
terminalSettings->_ApplyAppearanceSettings(profile.DefaultAppearance(), schemes);
return terminalSettings;
};
auto terminalSettings0 = createTerminalSettings(settings.ActiveProfiles().GetAt(0), settings.GlobalSettings().ColorSchemes());
auto terminalSettings1 = createTerminalSettings(settings.ActiveProfiles().GetAt(1), settings.GlobalSettings().ColorSchemes());
auto terminalSettings2 = createTerminalSettings(settings.ActiveProfiles().GetAt(2), settings.GlobalSettings().ColorSchemes());
auto terminalSettings3 = createTerminalSettings(settings.ActiveProfiles().GetAt(3), settings.GlobalSettings().ColorSchemes());
auto terminalSettings4 = createTerminalSettings(settings.ActiveProfiles().GetAt(4), settings.GlobalSettings().ColorSchemes());
auto terminalSettings5 = createTerminalSettings(settings.ActiveProfiles().GetAt(5), settings.GlobalSettings().ColorSchemes());
VERIFY_ARE_EQUAL(ARGB(0, 0x12, 0x34, 0x56), terminalSettings0->CursorColor()); // from color scheme
VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings1->CursorColor()); // default
VERIFY_ARE_EQUAL(ARGB(0, 0x23, 0x45, 0x67), terminalSettings2->CursorColor()); // from profile (trumps color scheme)
VERIFY_ARE_EQUAL(ARGB(0, 0x34, 0x56, 0x78), terminalSettings3->CursorColor()); // from profile (not set in color scheme)
VERIFY_ARE_EQUAL(ARGB(0, 0x45, 0x67, 0x89), terminalSettings4->CursorColor()); // from profile (no color scheme)
VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings5->CursorColor()); // default
}
}

View File

@@ -24,18 +24,18 @@ public:
// Return Value:
// - The ActionAndArgs bound to the given key, or nullptr if nothing is bound to it.
static const winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs GetActionAndArgs(const winrt::Microsoft::Terminal::Settings::Model::KeyMapping& keymap,
const winrt::Microsoft::Terminal::TerminalControl::KeyChord& kc)
const winrt::Microsoft::Terminal::Control::KeyChord& kc)
{
std::wstring buffer{ L"" };
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::TerminalControl::KeyModifiers::Ctrl))
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Control::KeyModifiers::Ctrl))
{
buffer += L"Ctrl+";
}
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::TerminalControl::KeyModifiers::Shift))
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Control::KeyModifiers::Shift))
{
buffer += L"Shift+";
}
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::TerminalControl::KeyModifiers::Alt))
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Control::KeyModifiers::Alt))
{
buffer += L"Alt+";
}

View File

@@ -56,6 +56,8 @@ Author(s):
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.Terminal.Core.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View File

@@ -458,6 +458,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -479,6 +480,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"cmd", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -500,6 +502,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\Foo", myArgs.TerminalArgs().StartingDirectory());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -521,6 +524,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe", myArgs.TerminalArgs().Commandline());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -543,6 +547,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto myCommand = myArgs.TerminalArgs().Commandline();
VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg with spaces\"", myCommand);
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -565,6 +570,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto myCommand = myArgs.TerminalArgs().Commandline();
VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg with spaces\" another-arg \"more spaces in this one\"", myCommand);
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -586,6 +592,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"Windows PowerShell", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -606,6 +613,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -628,6 +636,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -651,6 +660,31 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(til::color(myArgs.TerminalArgs().TabColor().Value()), expectedColor);
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand, L"--colorScheme", L"Vintage" };
const winrt::hstring expectedScheme{ L"Vintage" };
_buildCommandlinesHelper(appArgs, 1u, rawCommands);
VERIFY_ARE_EQUAL(1u, appArgs._startupActions.size());
auto actionAndArgs = appArgs._startupActions.at(0);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_IS_FALSE(myArgs.TerminalArgs().ColorScheme().empty());
VERIFY_ARE_EQUAL(expectedScheme, myArgs.TerminalArgs().ColorScheme());
}
}
@@ -680,6 +714,7 @@ namespace TerminalAppLocalTests
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
}
{
@@ -699,6 +734,7 @@ namespace TerminalAppLocalTests
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitState::Horizontal, myArgs.SplitStyle());
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
}
{
@@ -720,6 +756,28 @@ namespace TerminalAppLocalTests
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitState::Vertical, myArgs.SplitStyle());
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
}
{
AppCommandlineArgs appArgs{};
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand, L"-D" };
auto commandlines = AppCommandlineArgs::BuildCommands(rawCommands);
VERIFY_ARE_EQUAL(1u, commandlines.size());
_buildCommandlinesHelper(appArgs, 1u, rawCommands);
VERIFY_ARE_EQUAL(2u, appArgs._startupActions.size());
// The first action is going to always be a new-tab action
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action());
// The one we actually want to test here is the SplitPane action we created
auto actionAndArgs = appArgs._startupActions.at(1);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitType::Duplicate, myArgs.SplitMode());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
}
{
@@ -749,6 +807,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -777,6 +836,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -805,6 +865,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine -H", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
}
}
@@ -1594,59 +1655,155 @@ namespace TerminalAppLocalTests
void CommandlineTest::TestFindTargetWindow()
{
{
Log::Comment(L"wt.exe with no args should always use the value from"
L" the settings (passed as the second argument).");
std::vector<winrt::hstring> args{ L"wt.exe" };
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew));
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseAnyExisting,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseAnyExisting, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
}
{
Log::Comment(L"-w -1 should always result in a new window");
std::vector<winrt::hstring> args{ L"wt.exe", L"-w", L"-1" };
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew));
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
}
{
Log::Comment(L"\"new\" should always result in a new window");
std::vector<winrt::hstring> args{ L"wt.exe", L"-w", L"new" };
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
}
{
Log::Comment(L"-w with a negative number should always result in a "
L"new window");
std::vector<winrt::hstring> args{ L"wt.exe", L"-w", L"-12345" };
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew));
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
}
{
Log::Comment(L"-w with a positive number should result in us trying"
L" to either make a new one or find an existing one "
L"with that ID, depending on the provided argument");
std::vector<winrt::hstring> args{ L"wt.exe", L"-w", L"12345" };
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(12345, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(12345, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(12345, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
}
{
Log::Comment(L"-w 0 should always use the \"current\" window");
std::vector<winrt::hstring> args{ L"wt.exe", L"-w", L"0" };
VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew));
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
}
{
Log::Comment(L"-w last should always use the most recent window on "
L"this desktop");
std::vector<winrt::hstring> args{ L"wt.exe", L"-w", L"last" };
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
}
{
Log::Comment(L"Make sure we follow the provided argument when a "
L"--window-id wasn't explicitly provided");
std::vector<winrt::hstring> args{ L"wt.exe", L"new-tab" };
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew));
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseAnyExisting,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseAnyExisting, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
}
{
Log::Comment(L"Even if someone uses a subcommand as a window name, "
L"that should work");
std::vector<winrt::hstring> args{ L"wt.exe", L"-w", L"new-tab" };
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseName, result.WindowId());
VERIFY_ARE_EQUAL(L"new-tab", result.WindowName());
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseName, result.WindowId());
VERIFY_ARE_EQUAL(L"new-tab", result.WindowName());
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseName, result.WindowId());
VERIFY_ARE_EQUAL(L"new-tab", result.WindowName());
}
}
@@ -1657,19 +1814,23 @@ namespace TerminalAppLocalTests
// This is a little helper to make sure that these args _always_ return
// UseNew, regardless of the windowing behavior.
auto testHelper = [](auto&& args) {
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew));
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
};
testHelper(std::vector<winrt::hstring>{ L"wt.exe", L"--help" });
testHelper(std::vector<winrt::hstring>{ L"wt.exe", L"new-tab", L"--help" });
testHelper(std::vector<winrt::hstring>{ L"wt.exe", L"-w", L"0", L"new-tab", L"--help" });
testHelper(std::vector<winrt::hstring>{ L"wt.exe", L"-w", L"foo", L"new-tab", L"--help" });
testHelper(std::vector<winrt::hstring>{ L"wt.exe", L"new-tab", L";", L"--help" });
}
@@ -1680,14 +1841,17 @@ namespace TerminalAppLocalTests
// This is a little helper to make sure that these args _always_ return
// UseNew, regardless of the windowing behavior.
auto testHelper = [](auto&& args) {
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew));
auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew,
appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting));
result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting);
VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId());
VERIFY_ARE_EQUAL(L"", result.WindowName());
};
testHelper(std::vector<winrt::hstring>{ L"wt.exe", L"--version" });

View File

@@ -11,7 +11,7 @@ using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
namespace TerminalAppLocalTests
{

View File

@@ -4,7 +4,6 @@
#include "pch.h"
#include "../TerminalApp/TerminalPage.h"
#include "../TerminalApp/TerminalSettings.h"
#include "../LocalTests_SettingsModel/TestUtils.h"
using namespace Microsoft::Console;
@@ -13,7 +12,7 @@ using namespace WEX::TestExecution;
using namespace WEX::Common;
using namespace winrt::TerminalApp;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
namespace TerminalAppLocalTests
{
@@ -34,15 +33,6 @@ namespace TerminalAppLocalTests
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(TryCreateWinRTType);
TEST_METHOD(TestTerminalArgsForBinding);
TEST_METHOD(MakeSettingsForProfileThatDoesntExist);
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
TEST_METHOD(TestLayerProfileOnColorScheme);
TEST_METHOD(TestIterateCommands);
TEST_METHOD(TestIterateOnGeneratedNamedCommands);
TEST_METHOD(TestIterateOnBadJson);
@@ -83,487 +73,6 @@ namespace TerminalAppLocalTests
}
};
void SettingsTests::TryCreateWinRTType()
{
TerminalSettings settings;
VERIFY_IS_NOT_NULL(settings);
auto oldFontSize = settings.FontSize();
settings.FontSize(oldFontSize + 5);
auto newFontSize = settings.FontSize();
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
}
void SettingsTests::TestTerminalArgsForBinding()
{
const std::string settingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"historySize": 1,
"commandline": "cmd.exe"
},
{
"name": "profile1",
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
"historySize": 2,
"commandline": "pwsh.exe"
},
{
"name": "profile2",
"historySize": 3,
"commandline": "wsl.exe"
}
],
"keybindings": [
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
]
})" };
const winrt::guid guid0{ ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}") };
const winrt::guid guid1{ ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}") };
CascadiaSettings settings{ til::u8u16(settingsJson) };
auto keymap = settings.GlobalSettings().KeyMap();
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
const auto profile2Guid = settings.ActiveProfiles().GetAt(2).Guid();
VERIFY_ARE_NOT_EQUAL(winrt::guid{}, profile2Guid);
VERIFY_ARE_EQUAL(12u, keymap.Size());
{
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('B') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}", realArgs.TerminalArgs().Profile());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid1, guid);
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid1, guid);
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(profile2Guid, guid);
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid1, guid);
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('H') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('I') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(profile2Guid, guid);
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('J') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid0, guid);
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('K') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(profile2Guid, guid);
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('L') };
auto actionAndArgs = TestUtils::GetActionAndArgs(keymap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, realArgs.TerminalArgs(), nullptr);
VERIFY_ARE_EQUAL(guid1, guid);
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
}
}
void SettingsTests::MakeSettingsForProfileThatDoesntExist()
{
// Test that MakeSettings throws when the GUID doesn't exist
const std::string settingsString{ R"(
{
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name" : "profile0",
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
"historySize": 1
},
{
"name" : "profile1",
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
"historySize": 2
}
]
})" };
CascadiaSettings settings{ til::u8u16(settingsString) };
const auto guid1 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
const auto guid2 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
const auto guid3 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
try
{
auto terminalSettings = winrt::make<winrt::TerminalApp::implementation::TerminalSettings>(settings, guid1, nullptr);
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
VERIFY_ARE_EQUAL(1, terminalSettings.HistorySize());
}
catch (...)
{
VERIFY_IS_TRUE(false, L"This call to BuildSettings should succeed");
}
try
{
auto terminalSettings = winrt::make<winrt::TerminalApp::implementation::TerminalSettings>(settings, guid2, nullptr);
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
VERIFY_ARE_EQUAL(2, terminalSettings.HistorySize());
}
catch (...)
{
VERIFY_IS_TRUE(false, L"This call to BuildSettings should succeed");
}
VERIFY_THROWS(auto terminalSettings = winrt::make<winrt::TerminalApp::implementation::TerminalSettings>(settings, guid3, nullptr), wil::ResultException, L"This call to BuildSettings should fail");
try
{
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, nullptr, nullptr);
VERIFY_ARE_NOT_EQUAL(nullptr, termSettings);
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
catch (...)
{
VERIFY_IS_TRUE(false, L"This call to BuildSettings should succeed");
}
}
void SettingsTests::MakeSettingsForDefaultProfileThatDoesntExist()
{
// Test that MakeSettings _doesnt_ throw when we load settings with a
// defaultProfile that's not in the list, we validate the settings, and
// then call MakeSettings(nullopt). The validation should ensure that
// the default profile is something reasonable
const std::string settingsString{ R"(
{
"defaultProfile": "{6239a42c-3333-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name" : "profile0",
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
"historySize": 1
},
{
"name" : "profile1",
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
"historySize": 2
}
]
})" };
CascadiaSettings settings{ til::u8u16(settingsString) };
VERIFY_ARE_EQUAL(2u, settings.Warnings().Size());
VERIFY_ARE_EQUAL(2u, settings.ActiveProfiles().Size());
VERIFY_ARE_EQUAL(settings.GlobalSettings().DefaultProfile(), settings.ActiveProfiles().GetAt(0).Guid());
try
{
const auto [guid, termSettings] = winrt::TerminalApp::implementation::TerminalSettings::BuildSettings(settings, nullptr, nullptr);
VERIFY_ARE_NOT_EQUAL(nullptr, termSettings);
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
}
catch (...)
{
VERIFY_IS_TRUE(false, L"This call to BuildSettings should succeed");
}
}
void SettingsTests::TestLayerProfileOnColorScheme()
{
Log::Comment(NoThrowString().Format(
L"Ensure that setting (or not) a property in the profile that should override a property of the color scheme works correctly."));
const std::string settings0String{ R"(
{
"defaultProfile": "profile5",
"profiles": [
{
"name" : "profile0",
"colorScheme": "schemeWithCursorColor"
},
{
"name" : "profile1",
"colorScheme": "schemeWithoutCursorColor"
},
{
"name" : "profile2",
"colorScheme": "schemeWithCursorColor",
"cursorColor": "#234567"
},
{
"name" : "profile3",
"colorScheme": "schemeWithoutCursorColor",
"cursorColor": "#345678"
},
{
"name" : "profile4",
"cursorColor": "#456789"
},
{
"name" : "profile5"
}
],
"schemes": [
{
"name": "schemeWithCursorColor",
"cursorColor": "#123456"
},
{
"name": "schemeWithoutCursorColor"
}
]
})" };
CascadiaSettings settings{ til::u8u16(settings0String) };
VERIFY_ARE_EQUAL(6u, settings.ActiveProfiles().Size());
VERIFY_ARE_EQUAL(2u, settings.GlobalSettings().ColorSchemes().Size());
auto createTerminalSettings = [&](const auto& profile, const auto& schemes) {
auto terminalSettings{ winrt::make_self<winrt::TerminalApp::implementation::TerminalSettings>() };
terminalSettings->_ApplyProfileSettings(profile, schemes);
return terminalSettings;
};
auto terminalSettings0 = createTerminalSettings(settings.ActiveProfiles().GetAt(0), settings.GlobalSettings().ColorSchemes());
auto terminalSettings1 = createTerminalSettings(settings.ActiveProfiles().GetAt(1), settings.GlobalSettings().ColorSchemes());
auto terminalSettings2 = createTerminalSettings(settings.ActiveProfiles().GetAt(2), settings.GlobalSettings().ColorSchemes());
auto terminalSettings3 = createTerminalSettings(settings.ActiveProfiles().GetAt(3), settings.GlobalSettings().ColorSchemes());
auto terminalSettings4 = createTerminalSettings(settings.ActiveProfiles().GetAt(4), settings.GlobalSettings().ColorSchemes());
auto terminalSettings5 = createTerminalSettings(settings.ActiveProfiles().GetAt(5), settings.GlobalSettings().ColorSchemes());
VERIFY_ARE_EQUAL(ARGB(0, 0x12, 0x34, 0x56), terminalSettings0->CursorColor()); // from color scheme
VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings1->CursorColor()); // default
VERIFY_ARE_EQUAL(ARGB(0, 0x23, 0x45, 0x67), terminalSettings2->CursorColor()); // from profile (trumps color scheme)
VERIFY_ARE_EQUAL(ARGB(0, 0x34, 0x56, 0x78), terminalSettings3->CursorColor()); // from profile (not set in color scheme)
VERIFY_ARE_EQUAL(ARGB(0, 0x45, 0x67, 0x89), terminalSettings4->CursorColor()); // from profile (no color scheme)
VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings5->CursorColor()); // default
}
void SettingsTests::TestIterateCommands()
{
// For this test, put an iterable command with a given `name`,

View File

@@ -85,6 +85,9 @@ namespace TerminalAppLocalTests
TEST_METHOD(NextMRUTab);
TEST_METHOD(VerifyCommandPaletteTabSwitcherOrder);
TEST_METHOD(TestWindowRenameSuccessful);
TEST_METHOD(TestWindowRenameFailure);
TEST_CLASS_SETUP(ClassSetup)
{
return true;
@@ -260,6 +263,15 @@ namespace TerminalAppLocalTests
page->Create();
Log::Comment(L"Create()'d the page successfully");
// Build a NewTab action, to make sure we start with one. The real
// Terminal will always get one from AppCommandlineArgs.
NewTerminalArgs newTerminalArgs{};
NewTabArgs args{ newTerminalArgs };
ActionAndArgs newTabAction{ ShortcutAction::NewTab, args };
// push the arg onto the front
page->_startupActions.Append(newTabAction);
Log::Comment(L"Added a single newTab action");
auto app = ::winrt::Windows::UI::Xaml::Application::Current();
winrt::TerminalApp::TerminalPage pp = *page;
@@ -276,8 +288,9 @@ namespace TerminalAppLocalTests
// In the real app, this isn't a problem, but doesn't happen
// reliably in the unit tests.
Log::Comment(L"Ensure we set the first tab as the selected one.");
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
page->_tabView.SelectedItem(tab->TabViewItem());
auto tab = page->_tabs.GetAt(0);
auto tabImpl = page->_GetTerminalTabImpl(tab);
page->_tabView.SelectedItem(tabImpl->TabViewItem());
page->_UpdatedSelectedTab(0);
});
VERIFY_SUCCEEDED(result);
@@ -330,7 +343,7 @@ namespace TerminalAppLocalTests
{
// * Create a tab with a profile with GUID 1
// * Reload the settings so that GUID 1 is no longer in the list of profiles
// * Try calling _DuplicateTabViewItem on tab 1
// * Try calling _DuplicateFocusedTab on tab 1
// * No new tab should be created (and more importantly, the app should not crash)
//
// Created to test GH#2455
@@ -392,7 +405,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Duplicate the first tab");
result = RunOnUIThread([&page]() {
page->_DuplicateTabViewItem();
page->_DuplicateFocusedTab();
VERIFY_ARE_EQUAL(2u, page->_tabs.Size());
});
VERIFY_SUCCEEDED(result);
@@ -407,7 +420,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Duplicate the tab, and don't crash");
result = RunOnUIThread([&page]() {
page->_DuplicateTabViewItem();
page->_DuplicateFocusedTab();
VERIFY_ARE_EQUAL(2u, page->_tabs.Size(), L"We should gracefully do nothing here - the profile no longer exists.");
});
VERIFY_SUCCEEDED(result);
@@ -601,7 +614,6 @@ namespace TerminalAppLocalTests
auto result = RunOnUIThread([&page]() {
SplitPaneArgs args{ SplitType::Duplicate };
ActionEventArgs eventArgs{ args };
// eventArgs.Args(args);
page->_HandleSplitPane(nullptr, eventArgs);
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
@@ -782,8 +794,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next MRU tab, which is the fourth tab");
TestOnUIThread([&page]() {
ActionEventArgs eventArgs{};
page->_HandleNextTab(nullptr, eventArgs);
page->_SelectNextTab(true, nullptr);
});
Log::Comment(L"Sleep to let events propagate");
@@ -804,8 +815,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next MRU tab, which is the second tab");
TestOnUIThread([&page]() {
ActionEventArgs eventArgs{};
page->_HandleNextTab(nullptr, eventArgs);
page->_SelectNextTab(true, nullptr);
});
Log::Comment(L"Sleep to let events propagate");
@@ -829,8 +839,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next in-order tab, which is the third tab");
TestOnUIThread([&page]() {
ActionEventArgs eventArgs{};
page->_HandleNextTab(nullptr, eventArgs);
page->_SelectNextTab(true, nullptr);
});
TestOnUIThread([&page]() {
uint32_t focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
@@ -842,8 +851,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next in-order tab, which is the fourth tab");
TestOnUIThread([&page]() {
ActionEventArgs eventArgs{};
page->_HandleNextTab(nullptr, eventArgs);
page->_SelectNextTab(true, nullptr);
});
TestOnUIThread([&page]() {
uint32_t focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
@@ -916,7 +924,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next MRU tab, which is the third tab");
RunOnUIThread([&page]() {
page->_SelectNextTab(true);
page->_SelectNextTab(true, nullptr);
// In the course of a single tick, the Command Palette will:
// * open
// * select the proper tab from the mru's list
@@ -943,4 +951,57 @@ namespace TerminalAppLocalTests
// will also dismiss itself immediately when that's called. So we can't
// really inspect the contents of the list in this test, unfortunately.
}
void TabTests::TestWindowRenameSuccessful()
{
auto page = _commonSetup();
page->RenameWindowRequested([&page](auto&&, const winrt::TerminalApp::RenameWindowRequestedArgs args) {
// In the real terminal, this would bounce up to the monarch and
// come back down. Instead, immediately call back and set the name.
page->WindowName(args.ProposedName());
});
bool windowNameChanged = false;
page->PropertyChanged([&page, &windowNameChanged](auto&&, const winrt::WUX::Data::PropertyChangedEventArgs& args) mutable {
if (args.PropertyName() == L"WindowNameForDisplay")
{
windowNameChanged = true;
}
});
TestOnUIThread([&page]() {
page->_RequestWindowRename(winrt::hstring{ L"Foo" });
});
TestOnUIThread([&]() {
VERIFY_ARE_EQUAL(L"Foo", page->_WindowName);
VERIFY_IS_TRUE(windowNameChanged,
L"The window name should have changed, and we should have raised a notification that WindowNameForDisplay changed");
});
}
void TabTests::TestWindowRenameFailure()
{
auto page = _commonSetup();
page->RenameWindowRequested([&page](auto&&, auto&&) {
// In the real terminal, this would bounce up to the monarch and
// come back down. Instead, immediately call back to tell the terminal it failed.
page->RenameFailed();
});
bool windowNameChanged = false;
page->PropertyChanged([&page, &windowNameChanged](auto&&, const winrt::WUX::Data::PropertyChangedEventArgs& args) mutable {
if (args.PropertyName() == L"WindowNameForDisplay")
{
windowNameChanged = true;
}
});
TestOnUIThread([&page]() {
page->_RequestWindowRename(winrt::hstring{ L"Foo" });
});
TestOnUIThread([&]() {
VERIFY_IS_FALSE(windowNameChanged,
L"The window name should not have changed, we should have rejected the change.");
});
}
}

View File

@@ -59,7 +59,7 @@
<!-- If you don't reference these projects here, the
_ConsoleGenerateAdditionalWinmdManifests step won't gather the winmd's -->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)\src\cascadia\TerminalApp\dll\TerminalApp.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)\src\cascadia\TerminalSettingsModel\dll\Microsoft.Terminal.Settings.Model.vcxproj" />

View File

@@ -97,7 +97,7 @@
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalApp\dll\TerminalApp.vcxproj">
<Project>{ca5cad1a-44bd-4ac7-ac72-f16e576fdd12}</Project>
@@ -117,7 +117,7 @@
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore">
<HintPath>$(OpenConsoleDir)\packages\Taef.Redist.Wlk.10.57.200731005-develop\lib\Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore.winmd</HintPath>
<HintPath>$(OpenConsoleDir)\packages\Microsoft.Taef.10.58.210305002\lib\Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<!-- This path is _relative to the .winmd_ -->

View File

@@ -1,8 +1,5 @@
<Application
x:Class="TestHostApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestHostApp"
RequestedTheme="Dark">
</Application>
<Application x:Class="TestHostApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestHostApp"
RequestedTheme="Dark" />

View File

@@ -45,6 +45,7 @@ Author(s):
#include <winrt/Windows.ui.input.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.input.h>
#include <winrt/Windows.UI.Xaml.Markup.h>

View File

@@ -798,7 +798,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
}
}
publicTerminal->_terminal->SetCursorStyle(theme.CursorStyle);
publicTerminal->_terminal->SetCursorStyle(static_cast<DispatchTypes::CursorStyle>(theme.CursorStyle));
publicTerminal->_desiredFont = { fontFamily, 0, DEFAULT_FONT_WEIGHT, { 0, fontSize }, CP_UTF8 };
publicTerminal->_UpdateFont(newDpi);

View File

@@ -19,7 +19,7 @@ typedef struct _TerminalTheme
COLORREF DefaultForeground;
COLORREF DefaultSelectionBackground;
float SelectionBackgroundAlpha;
DispatchTypes::CursorStyle CursorStyle;
uint32_t CursorStyle; // This will be converted to DispatchTypes::CursorStyle (size_t), but C# cannot marshal an enum type and have it fit in a size_t.
COLORREF ColorTable[16];
} TerminalTheme, *LPTerminalTheme;

View File

@@ -25,8 +25,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
struct FindTargetWindowArgs : public FindTargetWindowArgsT<FindTargetWindowArgs>
{
GETSET_PROPERTY(winrt::Microsoft::Terminal::Remoting::CommandlineArgs, Args, nullptr);
GETSET_PROPERTY(int, ResultTargetWindow, -1);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Remoting::CommandlineArgs, Args, nullptr);
WINRT_PROPERTY(int, ResultTargetWindow, -1);
WINRT_PROPERTY(winrt::hstring, ResultTargetWindowName);
public:
FindTargetWindowArgs(winrt::Microsoft::Terminal::Remoting::CommandlineArgs args) :

View File

@@ -25,6 +25,9 @@
<ClInclude Include="ProposeCommandlineResult.h">
<DependentUpon>Monarch.idl</DependentUpon>
</ClInclude>
<ClInclude Include="RenameRequestArgs.h">
<DependentUpon>Peasant.idl</DependentUpon>
</ClInclude>
<ClInclude Include="WindowActivatedArgs.h">
<DependentUpon>Peasant.idl</DependentUpon>
</ClInclude>
@@ -51,6 +54,9 @@
<ClCompile Include="ProposeCommandlineResult.cpp">
<DependentUpon>Monarch.idl</DependentUpon>
</ClCompile>
<ClCompile Include="RenameRequestArgs.cpp">
<DependentUpon>Peasant.idl</DependentUpon>
</ClCompile>
<ClCompile Include="WindowActivatedArgs.cpp">
<DependentUpon>Peasant.idl</DependentUpon>
</ClCompile>

View File

@@ -75,6 +75,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
auto newPeasantsId = peasant.GetID();
// Add an event listener to the peasant's WindowActivated event.
peasant.WindowActivated({ this, &Monarch::_peasantWindowActivated });
peasant.IdentifyWindowsRequested({ this, &Monarch::_identifyWindows });
peasant.RenameRequested({ this, &Monarch::_renameRequested });
_peasants[newPeasantsId] = peasant;
@@ -147,6 +149,59 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
}
}
// Method Description:
// - Find the ID of the peasant with the given name. If no such peasant
// exists, then we'll return 0. If we encounter any peasants who have died
// during this process, then we'll remove them from the set of _peasants
// Arguments:
// - name: The window name to look for
// Return Value:
// - 0 if we didn't find the given peasant, otherwise a positive number for
// the window's ID.
uint64_t Monarch::_lookupPeasantIdForName(std::wstring_view name)
{
if (name.empty())
{
return 0;
}
std::vector<uint64_t> peasantsToErase{};
uint64_t result = 0;
for (const auto& [id, p] : _peasants)
{
try
{
auto otherName = p.WindowName();
if (otherName == name)
{
result = id;
break;
}
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
// Normally, we'd just erase the peasant here. However, we can't
// erase from the map while we're iterating over it like this.
// Instead, pull a good ole Java and collect this id for removal
// later.
peasantsToErase.push_back(id);
}
}
// Remove the dead peasants we came across while iterating.
for (const auto& id : peasantsToErase)
{
// Remove the peasant from the list of peasants
_peasants.erase(id);
// Remove the peasant from the list of MRU windows. They're dead.
// They can't be the MRU anymore.
_clearOldMruEntries(id);
}
return result;
}
// Method Description:
// - Handler for the `Peasant::WindowActivated` event. We'll make a in-proc
// copy of the WindowActivatedArgs from the peasant. That way, we won't
@@ -400,6 +455,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// After the event was handled, ResultTargetWindow() will be filled with
// the parsed result.
const auto targetWindow = findWindowArgs->ResultTargetWindow();
const auto targetWindowName = findWindowArgs->ResultTargetWindowName();
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_ProposeCommandline",
@@ -410,6 +466,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// that goes with it. Alternatively, if we were given a magic windowing
// constant, we can use that to look up an appropriate peasant.
if (targetWindow >= 0 ||
targetWindow == WindowingBehaviorUseName ||
targetWindow == WindowingBehaviorUseExisting ||
targetWindow == WindowingBehaviorUseAnyExisting)
{
@@ -429,6 +486,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
case WindowingBehaviorUseAnyExisting:
windowID = _getMostRecentPeasantID(false);
break;
case WindowingBehaviorUseName:
windowID = _lookupPeasantIdForName(targetWindowName);
break;
default:
windowID = ::base::saturated_cast<uint64_t>(targetWindow);
break;
@@ -449,7 +509,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
if (auto targetPeasant{ _getPeasant(windowID) })
{
auto result{ winrt::make_self<Remoting::implementation::ProposeCommandlineResult>(false) };
try
{
// This will raise the peasant's ExecuteCommandlineRequested
@@ -463,6 +522,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// If we fail to propose the commandline to the peasant (it
// died?) then just tell this process to become a new window
// instead.
result->WindowName(targetWindowName);
result->ShouldCreateWindow(true);
// If this fails, it'll be logged in the following
@@ -497,6 +557,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
auto result{ winrt::make_self<Remoting::implementation::ProposeCommandlineResult>(true) };
result->Id(windowID);
result->WindowName(targetWindowName);
return *result;
}
}
@@ -508,6 +569,115 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
// In this case, no usable ID was provided. Return { true, nullopt }
return winrt::make<Remoting::implementation::ProposeCommandlineResult>(true);
auto result = winrt::make_self<Remoting::implementation::ProposeCommandlineResult>(true);
result->WindowName(targetWindowName);
return *result;
}
// Method Description:
// - Helper for doing something on each and every peasant, with no regard
// for if the peasant is living or dead.
// - We'll try calling callback on every peasant.
// - If any single peasant is dead, then we'll call errorCallback, and move on.
// - We're taking an errorCallback here, because the thing we usually want
// to do is TraceLog a message, but TraceLoggingWrite is actually a macro
// that _requires_ the second arg to be a string literal. It can't just be
// a variable.
// Arguments:
// - callback: The function to call on each peasant
// - errorCallback: The function to call if a peasant is dead.
// Return Value:
// - <none>
void Monarch::_forAllPeasantsIgnoringTheDead(std::function<void(const Remoting::IPeasant&, const uint64_t)> callback,
std::function<void(const uint64_t)> errorCallback)
{
for (const auto& [id, p] : _peasants)
{
try
{
callback(p, id);
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
// If this fails, we don't _really_ care. Just move on to the
// next one. Someone else will clean up the dead peasant.
errorCallback(id);
}
}
}
// Method Description:
// - This is an event handler for the IdentifyWindowsRequested event. A
// Peasant may raise that event if they want _all_ windows to identify
// themselves.
// - This will tell each and every peasant to identify themselves. This will
// eventually propagate down to TerminalPage::IdentifyWindow.
// Arguments:
// - <unused>
// Return Value:
// - <none>
void Monarch::_identifyWindows(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::Foundation::IInspectable& /*args*/)
{
// Notify all the peasants to display their ID.
auto callback = [](auto&& p, auto&& /*id*/) {
p.DisplayWindowId();
};
auto onError = [](auto&& id) {
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_identifyWindows_Failed",
TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not identify"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
};
_forAllPeasantsIgnoringTheDead(callback, onError);
}
// Method Description:
// - This is an event handler for the RenameRequested event. A
// Peasant may raise that event when they want to be renamed to something else.
// - We will check if there are any other windows with this name. If there
// are, then we'll reject the rename by setting args.Succeeded=false.
// - If there aren't any other windows with this name, then we'll set
// args.Succeeded=true, allowing the window to keep this name.
// Arguments:
// - args: Contains the requested window name and a boolean (Succeeded)
// indicating if the request was successful.
// Return Value:
// - <none>
void Monarch::_renameRequested(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args)
{
bool successfullyRenamed = false;
try
{
args.Succeeded(false);
const auto name{ args.NewName() };
// Try to find a peasant that currently has this name
const auto id = _lookupPeasantIdForName(name);
if (_getPeasant(id) == nullptr)
{
// If there is one, then oh no! The requestor is not allowed to
// be renamed.
args.Succeeded(true);
successfullyRenamed = true;
}
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_renameRequested",
TraceLoggingWideString(name.c_str(), "name", "The newly proposed name"),
TraceLoggingInt64(successfullyRenamed, "successfullyRenamed", "true if the peasant is allowed to rename themselves to that name."),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
// If this fails, we don't _really_ care. The peasant died, but
// they're the only one who cares about the result.
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_renameRequested_Failed",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
}
}
}

View File

@@ -67,12 +67,22 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
winrt::Microsoft::Terminal::Remoting::IPeasant _getPeasant(uint64_t peasantID);
uint64_t _getMostRecentPeasantID(bool limitToCurrentDesktop);
uint64_t _lookupPeasantIdForName(std::wstring_view name);
void _peasantWindowActivated(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs& args);
void _doHandleActivatePeasant(const winrt::com_ptr<winrt::Microsoft::Terminal::Remoting::implementation::WindowActivatedArgs>& args);
void _clearOldMruEntries(const uint64_t peasantID);
void _forAllPeasantsIgnoringTheDead(std::function<void(const winrt::Microsoft::Terminal::Remoting::IPeasant&, const uint64_t)> callback,
std::function<void(const uint64_t)> errorCallback);
void _identifyWindows(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
void _renameRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
friend class RemotingUnitTests::RemotingTests;
};
}

View File

@@ -9,11 +9,12 @@ namespace Microsoft.Terminal.Remoting
[default_interface] runtimeclass FindTargetWindowArgs {
CommandlineArgs Args { get; };
Int32 ResultTargetWindow;
String ResultTargetWindowName;
}
[default_interface] runtimeclass ProposeCommandlineResult {
Windows.Foundation.IReference<UInt64> Id { get; };
// TODO:projects/5 - also return the name here, if the name was set on the commandline
String WindowName { get; };
Boolean ShouldCreateWindow { get; }; // If you name this `CreateWindow`, the compiler will explode
}

View File

@@ -117,4 +117,81 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
return _lastActivatedArgs;
}
// Method Description:
// - Tell this window to display it's window ID. We'll raise a
// DisplayWindowIdRequested event, which will get handled in the AppHost,
// and used to tell the app to display the ID toast.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Peasant::DisplayWindowId()
{
// Not worried about try/catching this. The handler is in AppHost, which
// is in-proc for us.
_DisplayWindowIdRequestedHandlers(*this, nullptr);
}
// Method Description:
// - Raises an event to ask that all windows be identified. This will come
// back to us when the Monarch handles the event and calls our
// DisplayWindowId method.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Peasant::RequestIdentifyWindows()
{
bool successfullyNotified = false;
try
{
// Try/catch this, because the other side of this event is handled
// by the monarch. The monarch might have died. If they have, this
// will throw an exception. Just eat it, the election thread will
// handle hooking up the new one.
_IdentifyWindowsRequestedHandlers(*this, nullptr);
successfullyNotified = true;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
TraceLoggingWrite(g_hRemotingProvider,
"Peasant_RequestIdentifyWindows",
TraceLoggingUInt64(GetID(), "peasantID", "Our ID"),
TraceLoggingBoolean(successfullyNotified, "successfullyNotified", "true if we successfully notified the monarch"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
}
void Peasant::RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args)
{
bool successfullyNotified = false;
const auto oldName{ _WindowName };
try
{
// Try/catch this, because the other side of this event is handled
// by the monarch. The monarch might have died. If they have, this
// will throw an exception. Just eat it, the election thread will
// handle hooking up the new one.
_RenameRequestedHandlers(*this, args);
if (args.Succeeded())
{
_WindowName = args.NewName();
}
successfullyNotified = true;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
TraceLoggingWrite(g_hRemotingProvider,
"Peasant_RequestRename",
TraceLoggingUInt64(GetID(), "peasantID", "Our ID"),
TraceLoggingWideString(oldName.c_str(), "oldName", "Our old name"),
TraceLoggingWideString(args.NewName().c_str(), "newName", "The proposed name"),
TraceLoggingBoolean(args.Succeeded(), "succeeded", "true if the monarch ok'd this new name for us."),
TraceLoggingBoolean(successfullyNotified, "successfullyNotified", "true if we successfully notified the monarch"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
}
}

View File

@@ -5,6 +5,7 @@
#include "Peasant.g.h"
#include "../cascadia/inc/cppwinrt_utils.h"
#include "RenameRequestArgs.h"
namespace RemotingUnitTests
{
@@ -22,12 +23,20 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
bool ExecuteCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args);
void ActivateWindow(const winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs& args);
void RequestIdentifyWindows();
void DisplayWindowId();
void RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs GetLastActivatedArgs();
winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs();
WINRT_PROPERTY(winrt::hstring, WindowName);
TYPED_EVENT(WindowActivated, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs);
TYPED_EVENT(ExecuteCommandlineRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::CommandlineArgs);
TYPED_EVENT(IdentifyWindowsRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(DisplayWindowIdRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(RenameRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RenameRequestArgs);
private:
Peasant(const uint64_t testPID);

View File

@@ -13,6 +13,13 @@ namespace Microsoft.Terminal.Remoting
String CurrentDirectory();
};
runtimeclass RenameRequestArgs
{
RenameRequestArgs(String newName);
String NewName { get; };
Boolean Succeeded;
};
runtimeclass WindowActivatedArgs
{
WindowActivatedArgs(UInt64 peasantID, Guid desktopID, Windows.Foundation.DateTime activatedTime);
@@ -33,9 +40,17 @@ namespace Microsoft.Terminal.Remoting
Boolean ExecuteCommandline(CommandlineArgs args);
void ActivateWindow(WindowActivatedArgs args);
WindowActivatedArgs GetLastActivatedArgs();
String WindowName { get; };
void RequestIdentifyWindows(); // Tells us to raise a IdentifyWindowsRequested
void DisplayWindowId(); // Tells us to display its own ID (which causes a DisplayWindowIdRequested to be raised)
void RequestRename(RenameRequestArgs args); // Tells us to raise a RenameRequested
event Windows.Foundation.TypedEventHandler<Object, WindowActivatedArgs> WindowActivated;
event Windows.Foundation.TypedEventHandler<Object, CommandlineArgs> ExecuteCommandlineRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> DisplayWindowIdRequested;
event Windows.Foundation.TypedEventHandler<Object, RenameRequestArgs> RenameRequested;
};
[default_interface] runtimeclass Peasant : IPeasant

View File

@@ -26,8 +26,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
struct ProposeCommandlineResult : public ProposeCommandlineResultT<ProposeCommandlineResult>
{
public:
GETSET_PROPERTY(Windows::Foundation::IReference<uint64_t>, Id);
GETSET_PROPERTY(bool, ShouldCreateWindow, true);
WINRT_PROPERTY(Windows::Foundation::IReference<uint64_t>, Id);
WINRT_PROPERTY(winrt::hstring, WindowName);
WINRT_PROPERTY(bool, ShouldCreateWindow, true);
public:
ProposeCommandlineResult(bool shouldCreateWindow) :

View File

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

View File

@@ -0,0 +1,30 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Class Name:
- RenameRequestArgs.h
--*/
#pragma once
#include "RenameRequestArgs.g.h"
#include "../cascadia/inc/cppwinrt_utils.h"
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
struct RenameRequestArgs : public RenameRequestArgsT<RenameRequestArgs>
{
WINRT_PROPERTY(winrt::hstring, NewName);
WINRT_PROPERTY(bool, Succeeded, false);
public:
RenameRequestArgs(winrt::hstring newName) :
_NewName{ newName } {};
};
}
namespace winrt::Microsoft::Terminal::Remoting::factory_implementation
{
BASIC_FACTORY(RenameRequestArgs);
}

View File

@@ -27,10 +27,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
};
struct WindowActivatedArgs : public WindowActivatedArgsT<WindowActivatedArgs>
{
GETSET_PROPERTY(uint64_t, PeasantID, 0);
GETSET_PROPERTY(winrt::guid, DesktopID);
GETSET_PROPERTY(winrt::Windows::Foundation::DateTime, ActivatedTime, {});
GETSET_PROPERTY(uint64_t, Hwnd, 0);
WINRT_PROPERTY(uint64_t, PeasantID, 0);
WINRT_PROPERTY(winrt::guid, DesktopID);
WINRT_PROPERTY(winrt::Windows::Foundation::DateTime, ActivatedTime, {});
WINRT_PROPERTY(uint64_t, Hwnd, 0);
public:
WindowActivatedArgs(uint64_t peasantID,

View File

@@ -5,6 +5,8 @@
#include "WindowManager.h"
#include "MonarchFactory.h"
#include "CommandlineArgs.h"
#include "../inc/WindowingBehavior.h"
#include "FindTargetWindowArgs.h"
#include "WindowManager.g.cpp"
#include "../../types/inc/utils.hpp"
@@ -38,7 +40,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// stay in this jail until we do.
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_ExceptionInCtor",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
}
}
@@ -69,6 +72,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// Otherwise, the King will tell us if we should make a new window
_shouldCreateWindow = _isKing;
std::optional<uint64_t> givenID;
winrt::hstring givenName{};
if (!_isKing)
{
// The monarch may respond back "you should be a new
@@ -86,7 +90,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
givenID = result.Id().Value();
}
givenName = result.WindowName();
// TraceLogging doesn't have a good solution for logging an
// optional. So we have to repeat the calls here:
if (givenID)
@@ -95,7 +99,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
"WindowManager_ProposeCommandline",
TraceLoggingBoolean(_shouldCreateWindow, "CreateWindow", "true iff we should create a new window"),
TraceLoggingUInt64(givenID.value(), "Id", "The ID we should assign our peasant"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingWideString(givenName.c_str(), "Name", "The name we should assign this window"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
else
{
@@ -103,24 +109,72 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
"WindowManager_ProposeCommandline",
TraceLoggingBoolean(_shouldCreateWindow, "CreateWindow", "true iff we should create a new window"),
TraceLoggingPointer(nullptr, "Id", "No ID provided"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingWideString(givenName.c_str(), "Name", "The name we should assign this window"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
}
else
{
// We're the monarch, we don't need to propose anything. We're just
// going to do it.
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_ProposeCommandline_AsMonarch",
TraceLoggingBoolean(_shouldCreateWindow, "CreateWindow", "true iff we should create a new window"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
//
// However, we _do_ need to ask what our name should be. It's
// possible someone started the _first_ wt with something like `wt
// -w king` as the commandline - we want to make sure we set our
// name to "king".
//
// The FindTargetWindow event is the WindowManager's way of saying
// "I do not know how to figure out how to turn this list of args
// into a window ID/name. Whoever's listening to this event does, so
// I'll ask them". It's a convoluted way of hooking the
// WindowManager up to AppLogic without actually telling it anything
// about TerminalApp (or even WindowsTerminal)
auto findWindowArgs{ winrt::make_self<Remoting::implementation::FindTargetWindowArgs>(args) };
_raiseFindTargetWindowRequested(nullptr, *findWindowArgs);
const auto responseId = findWindowArgs->ResultTargetWindow();
if (responseId > 0)
{
givenID = ::base::saturated_cast<uint64_t>(responseId);
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_ProposeCommandline_AsMonarch",
TraceLoggingBoolean(_shouldCreateWindow, "CreateWindow", "true iff we should create a new window"),
TraceLoggingUInt64(givenID.value(), "Id", "The ID we should assign our peasant"),
TraceLoggingWideString(givenName.c_str(), "Name", "The name we should assign this window"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
else if (responseId == WindowingBehaviorUseName)
{
givenName = findWindowArgs->ResultTargetWindowName();
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_ProposeCommandline_AsMonarch",
TraceLoggingBoolean(_shouldCreateWindow, "CreateWindow", "true iff we should create a new window"),
TraceLoggingUInt64(0, "Id", "The ID we should assign our peasant"),
TraceLoggingWideString(givenName.c_str(), "Name", "The name we should assign this window"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
else
{
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_ProposeCommandline_AsMonarch",
TraceLoggingBoolean(_shouldCreateWindow, "CreateWindow", "true iff we should create a new window"),
TraceLoggingUInt64(0, "Id", "The ID we should assign our peasant"),
TraceLoggingWideString(L"", "Name", "The name we should assign this window"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
}
if (_shouldCreateWindow)
{
// If we should create a new window, then instantiate our Peasant
// instance, and tell that peasant to handle that commandline.
_createOurPeasant({ givenID });
_createOurPeasant({ givenID }, givenName);
// Spawn a thread to wait on the monarch, and handle the election
if (!_isKing)
@@ -180,7 +234,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
"WindowManager_ConnectedToMonarch",
TraceLoggingUInt64(_monarch.GetPID(), "monarchPID", "The PID of the new Monarch"),
TraceLoggingBoolean(_isKing, "isKing", "true if we are the new monarch"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
if (_peasant)
{
@@ -208,13 +263,17 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
return (ourPID == kingPID);
}
Remoting::IPeasant WindowManager::_createOurPeasant(std::optional<uint64_t> givenID)
Remoting::IPeasant WindowManager::_createOurPeasant(std::optional<uint64_t> givenID,
const winrt::hstring& givenName)
{
auto p = winrt::make_self<Remoting::implementation::Peasant>();
if (givenID)
{
p->AssignID(givenID.value());
}
// If the name wasn't specified, this will be an empty string.
p->WindowName(givenName);
_peasant = *p;
// Try to add us to the monarch. If that fails, try to find a monarch
@@ -242,7 +301,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_CreateOurPeasant",
TraceLoggingUInt64(_peasant.GetID(), "peasantID", "The ID of our new peasant"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
return _peasant;
}
@@ -317,7 +377,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
"WindowManager_FailedToOpenMonarch",
TraceLoggingUInt64(peasantID, "peasantID", "Our peasant ID"),
TraceLoggingUInt64(gle, "lastError", "The result of GetLastError"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
exitThreadRequested = _performElection();
continue;
@@ -333,7 +394,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_MonarchDied",
TraceLoggingUInt64(peasantID, "peasantID", "Our peasant ID"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
// Connect to the new monarch, which might be us!
// If we become the monarch, then we'll return true and exit this thread.
exitThreadRequested = _performElection();
@@ -344,7 +406,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_MonarchWaitInterrupted",
TraceLoggingUInt64(peasantID, "peasantID", "Our peasant ID"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
exitThreadRequested = true;
break;
@@ -353,7 +416,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_MonarchWaitTimeout",
TraceLoggingUInt64(peasantID, "peasantID", "Our peasant ID"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
exitThreadRequested = true;
break;
@@ -365,7 +429,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
"WindowManager_WaitFailed",
TraceLoggingUInt64(peasantID, "peasantID", "Our peasant ID"),
TraceLoggingUInt64(gle, "lastError", "The result of GetLastError"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
ExitProcess(0);
}
}
@@ -389,7 +454,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_ExceptionInWaitThread",
TraceLoggingUInt64(peasantID, "peasantID", "Our peasant ID"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
bool foundNewMonarch = false;
while (!foundNewMonarch)
{
@@ -409,7 +475,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingWrite(g_hRemotingProvider,
"WindowManager_ExceptionInNestedWaitThread",
TraceLoggingUInt64(peasantID, "peasantID", "Our peasant ID"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
}
}

View File

@@ -54,7 +54,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void _createMonarch();
void _createMonarchAndCallbacks();
bool _areWeTheKing();
winrt::Microsoft::Terminal::Remoting::IPeasant _createOurPeasant(std::optional<uint64_t> givenID);
winrt::Microsoft::Terminal::Remoting::IPeasant _createOurPeasant(std::optional<uint64_t> givenID,
const winrt::hstring& givenName);
bool _performElection();
void _createPeasantThread();

View File

@@ -33,7 +33,7 @@
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<None Include="packages.config" />
<None Include="Microsoft.Terminal.Remoting.def" />
<None Include="$(ProjectName).def" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>

View File

@@ -4,11 +4,11 @@
#include "pch.h"
#include "OpenTerminalHere.h"
#include "../WinRTUtils/inc/WtExeUtils.h"
#include "../WinRTUtils/inc/LibraryResources.h"
#include <winrt/Windows.ApplicationModel.Resources.Core.h>
#include <ShlObj.h>
// TODO GH#6112: Localize these strings
static constexpr std::wstring_view VerbDisplayName{ L"Open in Windows Terminal" };
static constexpr std::wstring_view VerbDevBuildDisplayName{ L"Open in Windows Terminal (Dev Build)" };
static constexpr std::wstring_view VerbName{ L"WindowsTerminalOpenHere" };
// This code is aggressively copied from
@@ -87,8 +87,15 @@ HRESULT OpenTerminalHere::GetTitle(IShellItemArray* /*psiItemArray*/,
{
// Change the string we return depending on if we're running from the dev
// build package or not.
const bool isDevBuild = IsDevBuild();
return SHStrDup(isDevBuild ? VerbDevBuildDisplayName.data() : VerbDisplayName.data(), ppszName);
const auto resource =
#if defined(WT_BRANDING_RELEASE)
RS_(L"ShellExtension_OpenInTerminalMenuItem");
#elif defined(WT_BRANDING_PREVIEW)
RS_(L"ShellExtension_OpenInTerminalMenuItem_Preview");
#else
RS_(L"ShellExtension_OpenInTerminalMenuItem_Dev");
#endif
return SHStrDup(resource.data(), ppszName);
}
HRESULT OpenTerminalHere::GetState(IShellItemArray* /*psiItemArray*/,

View File

@@ -31,7 +31,7 @@
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="WindowsTerminalShellExt.def" />
<None Include="$(ProjectName).def" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>

View File

@@ -4,6 +4,8 @@
#include "pch.h"
#include "OpenTerminalHere.h"
#include "../WinRTUtils/inc/LibraryResources.h"
using namespace Microsoft::WRL;
STDAPI DllCanUnloadNow()
@@ -30,3 +32,6 @@ DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*)
}
return TRUE;
}
// Usurp the TerminalApp's resource group.
UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"TerminalApp/Resources")

View File

@@ -14,7 +14,7 @@ namespace winrt::TerminalApp::implementation
ActionPaletteItem() = default;
ActionPaletteItem(Microsoft::Terminal::Settings::Model::Command const& command);
GETSET_PROPERTY(Microsoft::Terminal::Settings::Model::Command, Command, nullptr);
WINRT_PROPERTY(Microsoft::Terminal::Settings::Model::Command, Command, nullptr);
private:
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _commandChangedRevoker;

View File

@@ -1,52 +1,63 @@
<!-- 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="TerminalApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TerminalApp"
xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
xmlns:TA="using:TerminalApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
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 -->
<!--
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="TerminalApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TA="using:TerminalApp"
xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
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"/>
<!-- 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">
<!--
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}" />
<!--
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" />
<!-- 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" />
<!-- Define resources for Light mode here -->
<SolidColorBrush x:Key="TabViewBackground"
Color="#FFCCCCCC" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

View File

@@ -17,7 +17,7 @@ using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::System;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace ::TerminalApp;
@@ -39,7 +39,7 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleDuplicateTab(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
_DuplicateTabViewItem();
_DuplicateFocusedTab();
args.Handled(true);
}
@@ -89,15 +89,23 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleNextTab(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
_SelectNextTab(true);
args.Handled(true);
const auto& realArgs = args.ActionArgs().try_as<NextTabArgs>();
if (realArgs)
{
_SelectNextTab(true, realArgs.SwitcherMode());
args.Handled(true);
}
}
void TerminalPage::_HandlePrevTab(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
_SelectNextTab(false);
args.Handled(true);
const auto& realArgs = args.ActionArgs().try_as<PrevTabArgs>();
if (realArgs)
{
_SelectNextTab(false, realArgs.SwitcherMode());
args.Handled(true);
}
}
void TerminalPage::_HandleSendInput(const IInspectable& /*sender*/,
@@ -109,9 +117,11 @@ namespace winrt::TerminalApp::implementation
}
else if (const auto& realArgs = args.ActionArgs().try_as<SendInputArgs>())
{
const auto termControl = _GetActiveControl();
termControl.SendInput(realArgs.Input());
args.Handled(true);
if (const auto termControl{ _GetActiveControl() })
{
termControl.SendInput(realArgs.Input());
args.Handled(true);
}
}
}
@@ -300,9 +310,11 @@ namespace winrt::TerminalApp::implementation
{
if (const auto& realArgs = args.ActionArgs().try_as<AdjustFontSizeArgs>())
{
const auto termControl = _GetActiveControl();
termControl.AdjustFontSize(realArgs.Delta());
args.Handled(true);
if (const auto& termControl{ _GetActiveControl() })
{
termControl.AdjustFontSize(realArgs.Delta());
args.Handled(true);
}
}
}
@@ -316,17 +328,21 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleResetFontSize(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
const auto termControl = _GetActiveControl();
termControl.ResetFontSize();
args.Handled(true);
if (const auto& termControl{ _GetActiveControl() })
{
termControl.ResetFontSize();
args.Handled(true);
}
}
void TerminalPage::_HandleToggleShaderEffects(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
const auto termControl = _GetActiveControl();
termControl.ToggleShaderEffects();
args.Handled(true);
if (const auto& termControl{ _GetActiveControl() })
{
termControl.ToggleShaderEffects();
args.Handled(true);
}
}
void TerminalPage::_HandleToggleFocusMode(const IInspectable& /*sender*/,
@@ -376,7 +392,7 @@ namespace winrt::TerminalApp::implementation
if (const auto scheme = _settings.GlobalSettings().ColorSchemes().TryLookup(realArgs.SchemeName()))
{
auto controlSettings = activeControl.Settings().as<TerminalSettings>();
controlSettings->ApplyColorScheme(scheme);
controlSettings.ApplyColorScheme(scheme);
activeControl.UpdateSettings();
args.Handled(true);
}
@@ -490,7 +506,7 @@ namespace winrt::TerminalApp::implementation
return;
}
// Since _RemoveTab is asynchronous, create a snapshot of the tabs we want to remove
// Since _RemoveTabs is asynchronous, create a snapshot of the tabs we want to remove
std::vector<winrt::TerminalApp::TabBase> tabsToRemove;
if (index > 0)
{
@@ -529,7 +545,7 @@ namespace winrt::TerminalApp::implementation
return;
}
// Since _RemoveTab is asynchronous, create a snapshot of the tabs we want to remove
// Since _RemoveTabs is asynchronous, create a snapshot of the tabs we want to remove
std::vector<winrt::TerminalApp::TabBase> tabsToRemove;
std::copy(begin(_tabs) + index + 1, end(_tabs), std::back_inserter(tabsToRemove));
_RemoveTabs(tabsToRemove);
@@ -544,8 +560,8 @@ namespace winrt::TerminalApp::implementation
}
}
void TerminalPage::_HandleOpenTabSearch(const IInspectable& /*sender*/,
const ActionEventArgs& args)
void TerminalPage::_HandleTabSearch(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
CommandPalette().SetTabs(_tabs, _mruTabs);
CommandPalette().EnableTabSearchMode();
@@ -598,8 +614,8 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Important: Don't take the param by reference, since we'll be doing work
// on another thread.
fire_and_forget _OpenNewWindow(const bool elevate,
const NewTerminalArgs newTerminalArgs)
fire_and_forget TerminalPage::_OpenNewWindow(const bool elevate,
const NewTerminalArgs newTerminalArgs)
{
// Hop to the BG thread
co_await winrt::resume_background();
@@ -658,9 +674,8 @@ namespace winrt::TerminalApp::implementation
newTerminalArgs = NewTerminalArgs();
}
auto [profileGuid, settings] = TerminalSettings::BuildSettings(_settings,
newTerminalArgs,
*_bindings);
const auto profileGuid{ _settings.GetProfileForArgs(newTerminalArgs) };
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
// Manually fill in the evaluated profile.
newTerminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(profileGuid));
@@ -668,4 +683,81 @@ namespace winrt::TerminalApp::implementation
actionArgs.Handled(true);
}
// Method Description:
// - Raise a IdentifyWindowsRequested event. This will bubble up to the
// AppLogic, to the AppHost, to the Peasant, to the Monarch, then get
// distributed down to _all_ the Peasants, as to display info about the
// window in _every_ Peasant window.
// - This action is also buggy right now, because TeachingTips behave
// weird in XAML Islands. See microsoft-ui-xaml#4382
// Arguments:
// - <unused>
// Return Value:
// - <none>
void TerminalPage::_HandleIdentifyWindows(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
_IdentifyWindowsRequestedHandlers(*this, nullptr);
args.Handled(true);
}
// Method Description:
// - Display the "Toast" with the name and ID of this window.
// - Unlike _HandleIdentifyWindow**s**, this event just displays the window
// ID and name in the current window. It does not involve any bubbling
// up/down the page/logic/host/manager/peasant/monarch.
// Arguments:
// - <unused>
// Return Value:
// - <none>
void TerminalPage::_HandleIdentifyWindow(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
IdentifyWindow();
args.Handled(true);
}
void TerminalPage::_HandleRenameWindow(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
if (args)
{
if (const auto& realArgs = args.ActionArgs().try_as<RenameWindowArgs>())
{
const auto newName = realArgs.Name();
const auto request = winrt::make_self<implementation::RenameWindowRequestedArgs>(newName);
_RenameWindowRequestedHandlers(*this, *request);
args.Handled(true);
}
}
}
void TerminalPage::_HandleOpenWindowRenamer(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
if (WindowRenamer() == nullptr)
{
// We need to use FindName to lazy-load this object
if (MUX::Controls::TeachingTip tip{ FindName(L"WindowRenamer").try_as<MUX::Controls::TeachingTip>() })
{
tip.Closed({ get_weak(), &TerminalPage::_FocusActiveControl });
}
}
_UpdateTeachingTipTheme(WindowRenamer().try_as<winrt::Windows::UI::Xaml::FrameworkElement>());
WindowRenamer().IsOpen(true);
// PAIN: We can't immediately focus the textbox in the TeachingTip. It's
// not technically focusable until it is opened. However, it doesn't
// provide an event to tell us when it is opened. That's tracked in
// microsoft/microsoft-ui-xaml#1607. So for now, the user _needs_ to
// click on the text box manually.
//
// We're also not using a ContentDialog for this, because in Xaml
// Islands a text box in a ContentDialog won't receive _any_ keypresses.
// Fun!
// WindowRenamerTextBox().Focus(FocusState::Programmatic);
args.Handled(true);
}
}

View File

@@ -185,9 +185,9 @@ void AppCommandlineArgs::_buildParser()
maximized->excludes(fullscreen);
focus->excludes(fullscreen);
_app.add_option<std::optional<int>, int>("-w,--window",
_windowTarget,
RS_A(L"CmdWindowTargetArgDesc"));
_app.add_option("-w,--window",
_windowTarget,
RS_A(L"CmdWindowTargetArgDesc"));
// Subcommands
_buildNewTabParser();
@@ -255,6 +255,10 @@ void AppCommandlineArgs::_buildSplitPaneParser()
auto* sizeOpt = subcommand.subcommand->add_option("-s,--size",
_splitPaneSize,
RS_A(L"CmdSplitPaneSizeArgDesc"));
subcommand._duplicateOption = subcommand.subcommand->add_flag("-D,--duplicate",
_splitDuplicate,
RS_A(L"CmdSplitPaneDuplicateArgDesc"));
sizeOpt->check(CLI::Range(0.01f, 0.99f));
// When ParseCommand is called, if this subcommand was provided, this
@@ -283,7 +287,8 @@ void AppCommandlineArgs::_buildSplitPaneParser()
style = SplitState::Vertical;
}
}
SplitPaneArgs args{ style, _splitPaneSize, terminalArgs };
const auto splitMode{ subcommand._duplicateOption && _splitDuplicate ? SplitType::Duplicate : SplitType::Manual };
SplitPaneArgs args{ splitMode, style, _splitPaneSize, terminalArgs };
splitPaneActionAndArgs.Args(args);
_startupActions.push_back(splitPaneActionAndArgs);
});
@@ -417,6 +422,14 @@ void AppCommandlineArgs::_addNewTerminalArgs(AppCommandlineArgs::NewTerminalSubc
_startingTabColor,
RS_A(L"CmdTabColorArgDesc"));
subcommand.suppressApplicationTitleOption = subcommand.subcommand->add_flag(
"--suppressApplicationTitle,!--useApplicationTitle",
_suppressApplicationTitle,
RS_A(L"CmdSuppressApplicationTitleDesc"));
subcommand.colorSchemeOption = subcommand.subcommand->add_option("--colorScheme",
_startingColorScheme,
RS_A(L"CmdColorSchemeArgDesc"));
// Using positionals_at_end allows us to support "wt new-tab -d wsl -d Ubuntu"
// without CLI11 thinking that we've specified -d twice.
// There's an alternate construction where we make all subcommands "prefix commands",
@@ -480,8 +493,28 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT
if (*subcommand.tabColorOption)
{
const auto tabColor = Microsoft::Console::Utils::ColorFromHexString(_startingTabColor);
args.TabColor(static_cast<winrt::Windows::UI::Color>(tabColor));
try
{
// This is gonna throw whenever the string that's currently being parsed
// isn't a valid hex string. Let's just eat anything this throws because
// we should only lock in the TabColor arg when the user gives a valid hex
// str, and we shouldn't crash when the user gives us anything else.
const auto tabColor = Microsoft::Console::Utils::ColorFromHexString(_startingTabColor);
args.TabColor(static_cast<winrt::Windows::UI::Color>(tabColor));
}
catch (...)
{
}
}
if (*subcommand.suppressApplicationTitleOption)
{
args.SuppressApplicationTitle(_suppressApplicationTitle);
}
if (*subcommand.colorSchemeOption)
{
args.ColorScheme(winrt::to_hstring(_startingColorScheme));
}
return args;
@@ -522,10 +555,12 @@ void AppCommandlineArgs::_resetStateToDefault()
_startingTitle.clear();
_startingTabColor.clear();
_commandline.clear();
_suppressApplicationTitle = false;
_splitVertical = false;
_splitHorizontal = false;
_splitPaneSize = 0.5f;
_splitDuplicate = false;
_focusTabIndex = -1;
_focusNextTab = false;
@@ -673,6 +708,18 @@ std::vector<ActionAndArgs>& AppCommandlineArgs::GetStartupActions()
return _startupActions;
}
// Method Description:
// - Returns whether we should start listening for inbound PTY connections
// coming from the operating system default application feature.
// Arguments:
// - <none>
// Return Value:
// - True if the listener should be started. False otherwise.
bool AppCommandlineArgs::IsHandoffListener() const noexcept
{
return _isHandoffListener;
}
// Method Description:
// - Get the string of text that should be displayed to the user on exit. This
// is usually helpful for cases where the user entered some sort of invalid
@@ -715,17 +762,23 @@ bool AppCommandlineArgs::ShouldExitEarly() const noexcept
// - <none>
void AppCommandlineArgs::ValidateStartupCommands()
{
// If we parsed no commands, or the first command we've parsed is not a new
// tab action, prepend a new-tab command to the front of the list.
if (_startupActions.empty() ||
_startupActions.front().Action() != ShortcutAction::NewTab)
// Only check over the actions list for the potential to add a new-tab
// command if we are not starting for the purposes of receiving an inbound
// handoff connection from the operating system.
if (!_isHandoffListener)
{
// Build the NewTab action from the values we've parsed on the commandline.
NewTerminalArgs newTerminalArgs{};
NewTabArgs args{ newTerminalArgs };
ActionAndArgs newTabAction{ ShortcutAction::NewTab, args };
// push the arg onto the front
_startupActions.insert(_startupActions.begin(), 1, newTabAction);
// If we parsed no commands, or the first command we've parsed is not a new
// tab action, prepend a new-tab command to the front of the list.
if (_startupActions.empty() ||
_startupActions.front().Action() != ShortcutAction::NewTab)
{
// Build the NewTab action from the values we've parsed on the commandline.
NewTerminalArgs newTerminalArgs{};
NewTabArgs args{ newTerminalArgs };
ActionAndArgs newTabAction{ ShortcutAction::NewTab, args };
// push the arg onto the front
_startupActions.insert(_startupActions.begin(), 1, newTabAction);
}
}
}
@@ -749,6 +802,15 @@ std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> AppComman
// - 0 if the commandline was successfully parsed
int AppCommandlineArgs::ParseArgs(winrt::array_view<const winrt::hstring>& args)
{
for (const auto& arg : args)
{
if (arg == L"-Embedding")
{
_isHandoffListener = true;
return 0;
}
}
auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args);
for (auto& cmdBlob : commands)
@@ -853,17 +915,12 @@ void AppCommandlineArgs::FullResetState()
_startupActions.clear();
_exitMessage = "";
_shouldExitEarly = false;
_isHandoffListener = false;
_windowTarget = std::nullopt;
_windowTarget = {};
}
std::optional<int> AppCommandlineArgs::GetTargetWindow() const noexcept
std::string_view AppCommandlineArgs::GetTargetWindow() const noexcept
{
// If the user provides _any_ negative number, then treat it as -1, for "use a new window".
if (_windowTarget.has_value() && *_windowTarget < 0)
{
return { -1 };
}
return _windowTarget;
}

View File

@@ -35,6 +35,7 @@ public:
void ValidateStartupCommands();
std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs>& GetStartupActions();
bool IsHandoffListener() const noexcept;
const std::string& GetExitMessage();
bool ShouldExitEarly() const noexcept;
@@ -44,7 +45,7 @@ public:
void DisableHelpInExitMessage();
void FullResetState();
std::optional<int> GetTargetWindow() const noexcept;
std::string_view GetTargetWindow() const noexcept;
private:
static const std::wregex _commandDelimiterRegex;
@@ -61,12 +62,15 @@ private:
CLI::Option* startingDirectoryOption;
CLI::Option* titleOption;
CLI::Option* tabColorOption;
CLI::Option* suppressApplicationTitleOption;
CLI::Option* colorSchemeOption;
};
struct NewPaneSubcommand : public NewTerminalSubcommand
{
CLI::Option* _horizontalOption;
CLI::Option* _verticalOption;
CLI::Option* _duplicateOption;
};
// --- Subcommands ---
@@ -85,6 +89,8 @@ private:
std::string _startingDirectory;
std::string _startingTitle;
std::string _startingTabColor;
std::string _startingColorScheme;
bool _suppressApplicationTitle{ false };
winrt::Microsoft::Terminal::Settings::Model::FocusDirection _moveFocusDirection{ winrt::Microsoft::Terminal::Settings::Model::FocusDirection::None };
@@ -93,6 +99,7 @@ private:
bool _splitVertical{ false };
bool _splitHorizontal{ false };
bool _splitDuplicate{ false };
float _splitPaneSize{ 0.5f };
int _focusTabIndex{ -1 };
@@ -102,11 +109,12 @@ private:
const Commandline* _currentCommandline{ nullptr };
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> _launchMode{ std::nullopt };
bool _isHandoffListener{ false };
std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs> _startupActions;
std::string _exitMessage;
bool _shouldExitEarly{ false };
std::optional<int> _windowTarget{ std::nullopt };
std::string _windowTarget{};
// Are you adding more args or attributes here? If they are not reset in _resetStateToDefault, make sure to reset them in FullResetState
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs _getNewTerminalArgs(NewTerminalSubcommand& subcommand);

View File

@@ -8,7 +8,7 @@
using namespace winrt::Microsoft::Terminal;
using namespace winrt::TerminalApp;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
namespace winrt::TerminalApp::implementation
{

View File

@@ -19,7 +19,7 @@ namespace winrt::TerminalApp::implementation
{
AppKeyBindings() = default;
bool TryKeyChord(winrt::Microsoft::Terminal::TerminalControl::KeyChord const& kc);
bool TryKeyChord(winrt::Microsoft::Terminal::Control::KeyChord const& kc);
void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch);
void SetKeyMapping(const Microsoft::Terminal::Settings::Model::KeyMapping& keymap);

View File

@@ -4,7 +4,7 @@ import "ShortcutActionDispatch.idl";
namespace TerminalApp
{
[default_interface] runtimeclass AppKeyBindings : Microsoft.Terminal.TerminalControl.IKeyBindings
[default_interface] runtimeclass AppKeyBindings : Microsoft.Terminal.Control.IKeyBindings
{
AppKeyBindings();

View File

@@ -5,6 +5,7 @@
#include "AppLogic.h"
#include "../inc/WindowingBehavior.h"
#include "AppLogic.g.cpp"
#include "FindTargetWindowResult.g.cpp"
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
#include <LibraryResources.h>
@@ -16,7 +17,7 @@ using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::System;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace ::TerminalApp;
@@ -576,9 +577,9 @@ namespace winrt::TerminalApp::implementation
}
// Use the default profile to determine how big of a window we need.
const auto [_, settings] = TerminalSettings::BuildSettings(_settings, nullptr, nullptr);
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, nullptr, nullptr) };
auto proposedSize = TermControl::GetProposedDimensions(settings, dpi);
auto proposedSize = TermControl::GetProposedDimensions(settings.DefaultSettings(), dpi);
const float scale = static_cast<float>(dpi) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
@@ -1035,7 +1036,7 @@ namespace winrt::TerminalApp::implementation
void AppLogic::_ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme)
{
// Propagate the event to the host layer, so it can update its own UI
_requestedThemeChangedHandlers(*this, newTheme);
_RequestedThemeChangedHandlers(*this, newTheme);
}
UIElement AppLogic::GetRoot() noexcept
@@ -1185,6 +1186,17 @@ namespace winrt::TerminalApp::implementation
_hasCommandLineArguments = args.size() > 1;
_appArgs.ValidateStartupCommands();
_root->SetStartupActions(_appArgs.GetStartupActions());
// Check if we were started as a COM server for inbound connections of console sessions
// coming out of the operating system default application feature. If so,
// tell TerminalPage to start the listener as we have to make sure it has the chance
// to register a handler to hear about the requests first and is all ready to receive
// them before the COM server registers itself. Otherwise, the request might come
// in and be routed to an event with no handlers or a non-ready Page.
if (_appArgs.IsHandoffListener())
{
_root->SetInboundListener();
}
}
return result;
@@ -1239,14 +1251,20 @@ namespace winrt::TerminalApp::implementation
// - WindowingBehaviorUseAnyExisting: We should handle the args "in the current
// window ON ANY DESKTOP"
// - anything else: We should handle the commandline in the window with the given ID.
int32_t AppLogic::FindTargetWindow(array_view<const winrt::hstring> args)
TerminalApp::FindTargetWindowResult AppLogic::FindTargetWindow(array_view<const winrt::hstring> args)
{
if (!_loadedInitialSettings)
{
// Load settings if we haven't already
LoadSettings();
}
return AppLogic::_doFindTargetWindow(args, _settings.GlobalSettings().WindowingBehavior());
}
// The main body of this function is a static helper, to facilitate unit-testing
int32_t AppLogic::_doFindTargetWindow(array_view<const winrt::hstring> args,
const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior)
TerminalApp::FindTargetWindowResult AppLogic::_doFindTargetWindow(array_view<const winrt::hstring> args,
const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior)
{
::TerminalApp::AppCommandlineArgs appArgs;
const auto result = appArgs.ParseArgs(args);
@@ -1254,31 +1272,70 @@ namespace winrt::TerminalApp::implementation
{
if (!appArgs.GetExitMessage().empty())
{
return WindowingBehaviorUseNew;
return winrt::make<FindTargetWindowResult>(WindowingBehaviorUseNew);
}
const auto parsedTarget = appArgs.GetTargetWindow();
if (parsedTarget.has_value())
const std::string parsedTarget{ appArgs.GetTargetWindow() };
// If the user did not provide any value on the commandline,
// then lookup our windowing behavior to determine what to do
// now.
if (parsedTarget.empty())
{
// parsedTarget might be -1, if the user explicitly requested -1
// (or any other negative number) on the commandline. So the set
// of possible values here is {-1, 0, +}
return *parsedTarget;
}
else
{
// If the user did not provide any value on the commandline,
// then lookup our windowing behavior to determine what to do
// now.
int32_t windowId = WindowingBehaviorUseNew;
switch (windowingBehavior)
{
case WindowingMode::UseExisting:
return WindowingBehaviorUseExisting;
case WindowingMode::UseAnyExisting:
return WindowingBehaviorUseAnyExisting;
case WindowingMode::UseNew:
default:
return WindowingBehaviorUseNew;
windowId = WindowingBehaviorUseNew;
break;
case WindowingMode::UseExisting:
windowId = WindowingBehaviorUseExisting;
break;
case WindowingMode::UseAnyExisting:
windowId = WindowingBehaviorUseAnyExisting;
break;
}
return winrt::make<FindTargetWindowResult>(windowId);
}
// Here, the user _has_ provided a window-id on the commandline.
// What is it? Let's start by checking if it's an int, for the
// window's ID:
try
{
int32_t windowId = ::base::saturated_cast<int32_t>(std::stoi(parsedTarget));
// If the user provides _any_ negative number, then treat it as
// -1, for "use a new window".
if (windowId < 0)
{
windowId = -1;
}
// Hooray! This is a valid integer. The set of possible values
// here is {-1, 0, +}. Let's return that window ID.
return winrt::make<FindTargetWindowResult>(windowId);
}
catch (...)
{
// Value was not a valid int. It could be any other string to
// use as a title though!
//
// First, check the reserved keywords:
if (parsedTarget == "new")
{
return winrt::make<FindTargetWindowResult>(WindowingBehaviorUseNew);
}
else if (parsedTarget == "last")
{
return winrt::make<FindTargetWindowResult>(WindowingBehaviorUseExisting);
}
else
{
// The string they provided wasn't an int, it wasn't "new"
// or "last", so whatever it is, that's the name they get.
winrt::hstring winrtName{ til::u8u16(parsedTarget) };
return winrt::make<FindTargetWindowResult>(WindowingBehaviorUseName, winrtName);
}
}
}
@@ -1294,7 +1351,7 @@ namespace winrt::TerminalApp::implementation
// create a new window. Then, in that new window, we'll try to set the
// StartupActions, which will again fail, returning the correct error
// message.
return WindowingBehaviorUseNew;
return winrt::make<FindTargetWindowResult>(WindowingBehaviorUseNew);
}
// Method Description:
@@ -1343,8 +1400,43 @@ namespace winrt::TerminalApp::implementation
return _root ? _root->AlwaysOnTop() : false;
}
// -------------------------------- WinRT Events ---------------------------------
// Winrt events need a method for adding a callback to the event and removing the callback.
// These macros will define them both for you.
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(AppLogic, RequestedThemeChanged, _requestedThemeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
void AppLogic::IdentifyWindow()
{
if (_root)
{
_root->IdentifyWindow();
}
}
winrt::hstring AppLogic::WindowName()
{
return _root ? _root->WindowName() : L"";
}
void AppLogic::WindowName(const winrt::hstring& name)
{
if (_root)
{
_root->WindowName(name);
}
}
uint64_t AppLogic::WindowId()
{
return _root ? _root->WindowId() : 0;
}
void AppLogic::WindowId(const uint64_t& id)
{
if (_root)
{
_root->WindowId(id);
}
}
void AppLogic::RenameFailed()
{
if (_root)
{
_root->RenameFailed();
}
}
}

View File

@@ -4,6 +4,7 @@
#pragma once
#include "AppLogic.g.h"
#include "FindTargetWindowResult.g.h"
#include "TerminalPage.h"
#include "Jumplist.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
@@ -18,6 +19,19 @@ namespace TerminalAppLocalTests
namespace winrt::TerminalApp::implementation
{
struct FindTargetWindowResult : FindTargetWindowResultT<FindTargetWindowResult>
{
WINRT_PROPERTY(int32_t, WindowId, -1);
WINRT_PROPERTY(winrt::hstring, WindowName, L"");
public:
FindTargetWindowResult(const int32_t id, const winrt::hstring& name) :
_WindowId{ id }, _WindowName{ name } {};
FindTargetWindowResult(const int32_t id) :
FindTargetWindowResult(id, L""){};
};
struct AppLogic : AppLogicT<AppLogic, IInitializeWithWindow>
{
public:
@@ -38,7 +52,7 @@ namespace winrt::TerminalApp::implementation
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions, const winrt::hstring& cwd);
int32_t FindTargetWindow(array_view<const winrt::hstring> actions);
TerminalApp::FindTargetWindowResult FindTargetWindow(array_view<const winrt::hstring> actions);
winrt::hstring ParseCommandlineMessage();
bool ShouldExitEarly();
@@ -46,6 +60,13 @@ namespace winrt::TerminalApp::implementation
bool Fullscreen() const;
bool AlwaysOnTop() const;
void IdentifyWindow();
void RenameFailed();
winrt::hstring WindowName();
void WindowName(const winrt::hstring& name);
uint64_t WindowId();
void WindowId(const uint64_t& id);
Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
bool CenterOnLaunch();
TerminalApp::InitialPosition GetInitialPosition(int64_t defaultInitialX, int64_t defaultInitialY);
@@ -69,7 +90,7 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
// -------------------------------- WinRT Events ---------------------------------
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RequestedThemeChanged, _requestedThemeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
private:
bool _isUwp{ false };
@@ -98,8 +119,8 @@ namespace winrt::TerminalApp::implementation
::TerminalApp::AppCommandlineArgs _appArgs;
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
int _ParseArgs(winrt::array_view<const hstring>& args);
static int32_t _doFindTargetWindow(winrt::array_view<const hstring> args,
const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior);
static TerminalApp::FindTargetWindowResult _doFindTargetWindow(winrt::array_view<const hstring> args,
const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior);
void _ShowLoadErrorsDialog(const winrt::hstring& titleKey, const winrt::hstring& contentKey, HRESULT settingsLoadedResult);
void _ShowLoadWarningsDialog();
@@ -135,6 +156,8 @@ namespace winrt::TerminalApp::implementation
FORWARDED_TYPED_EVENT(AlwaysOnTopChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, AlwaysOnTopChanged);
FORWARDED_TYPED_EVENT(RaiseVisualBell, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, RaiseVisualBell);
FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress);
FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested);
FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested);
#ifdef UNIT_TESTING
friend class TerminalAppLocalTests::CommandlineTest;

View File

@@ -13,6 +13,12 @@ namespace TerminalApp
Int64 Y;
};
[default_interface] runtimeclass FindTargetWindowResult
{
Int32 WindowId { get; };
String WindowName { get; };
};
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter
{
AppLogic();
@@ -42,6 +48,11 @@ namespace TerminalApp
Boolean Fullscreen { get; };
Boolean AlwaysOnTop { get; };
void IdentifyWindow();
String WindowName;
UInt64 WindowId;
void RenameFailed();
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
Boolean CenterOnLaunch { get; };
@@ -57,7 +68,7 @@ namespace TerminalApp
UInt64 GetLastActiveControlTaskbarState();
UInt64 GetLastActiveControlTaskbarProgress();
Int32 FindTargetWindow(String[] args);
FindTargetWindowResult FindTargetWindow(String[] args);
// See IDialogPresenter and TerminalPage's DialogPresenter for more
// information.
@@ -72,5 +83,7 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<Object, Object> AlwaysOnTopChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> RaiseVisualBell;
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
}
}

View File

@@ -1,146 +1,193 @@
<Flyout
x:Class="TerminalApp.ColorPickupFlyout"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TerminalApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Flyout x:Class="TerminalApp.ColorPickupFlyout"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Flyout.FlyoutPresenterStyle>
<Style TargetType="FlyoutPresenter">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinWidth" Value="0" />
</Style>
</Flyout.FlyoutPresenterStyle>
<StackPanel Orientation="Horizontal">
<StackPanel XYFocusKeyboardNavigation="Enabled">
<VariableSizedWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="4" HorizontalAlignment="Center" Margin="0, 3, 0, 0">
<VariableSizedWrapGrid Margin="0,3,0,0"
HorizontalAlignment="Center"
MaximumRowsOrColumns="4"
Orientation="Horizontal">
<VariableSizedWrapGrid.Resources>
<Style TargetType="Rectangle">
<Setter Property="Width" Value="30"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Width" Value="30" />
<Setter Property="Height" Value="30" />
</Style>
<Style TargetType="Button">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="2" />
</Style>
</VariableSizedWrapGrid.Resources>
<Button Click="ColorButton_Click" AutomationProperties.Name="Crimson" x:Uid="CrimsonColorButton">
<Button x:Uid="CrimsonColorButton"
AutomationProperties.Name="Crimson"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="Crimson"/>
<Rectangle Fill="Crimson" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="SteelBlue" x:Uid="SteelBlueColorButton">
<Button x:Uid="SteelBlueColorButton"
AutomationProperties.Name="SteelBlue"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="SteelBlue"/>
<Rectangle Fill="SteelBlue" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="MediumSeaGreen" x:Uid="MediumSeaGreenColorButton">
<Button x:Uid="MediumSeaGreenColorButton"
AutomationProperties.Name="MediumSeaGreen"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="MediumSeaGreen"/>
<Rectangle Fill="MediumSeaGreen" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="DarkOrange" x:Uid="DarkOrangeColorButton">
<Button x:Uid="DarkOrangeColorButton"
AutomationProperties.Name="DarkOrange"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="DarkOrange"/>
<Rectangle Fill="DarkOrange" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="MediumVioletRed" x:Uid="MediumVioletRedColorButton">
<Button x:Uid="MediumVioletRedColorButton"
AutomationProperties.Name="MediumVioletRed"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="MediumVioletRed"/>
<Rectangle Fill="MediumVioletRed" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="DodgerBlue" x:Uid="DodgerBlueColorButton">
<Button x:Uid="DodgerBlueColorButton"
AutomationProperties.Name="DodgerBlue"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="DodgerBlue"/>
<Rectangle Fill="DodgerBlue" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="LimeGreen" x:Uid="LimeGreenColorButton">
<Button x:Uid="LimeGreenColorButton"
AutomationProperties.Name="LimeGreen"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="LimeGreen"/>
<Rectangle Fill="LimeGreen" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="Yellow" x:Uid="YellowColorButton">
<Button x:Uid="YellowColorButton"
AutomationProperties.Name="Yellow"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="Yellow"/>
<Rectangle Fill="Yellow" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="BlueViolet" x:Uid="BlueVioletColorButton">
<Button x:Uid="BlueVioletColorButton"
AutomationProperties.Name="BlueViolet"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="BlueViolet"/>
<Rectangle Fill="BlueViolet" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="SlateBlue" x:Uid="SlateBlueColorButton">
<Button x:Uid="SlateBlueColorButton"
AutomationProperties.Name="SlateBlue"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="SlateBlue"/>
<Rectangle Fill="SlateBlue" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="Lime" x:Uid="LimeColorButton">
<Button x:Uid="LimeColorButton"
AutomationProperties.Name="Lime"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="Lime"/>
<Rectangle Fill="Lime" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="Tan" x:Uid="TanColorButton">
<Button x:Uid="TanColorButton"
AutomationProperties.Name="Tan"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="Tan"/>
<Rectangle Fill="Tan" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="Magenta" x:Uid="MagentaColorButton">
<Button x:Uid="MagentaColorButton"
AutomationProperties.Name="Magenta"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="Magenta"/>
<Rectangle Fill="Magenta" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="Cyan" x:Uid="CyanColorButton">
<Button x:Uid="CyanColorButton"
AutomationProperties.Name="Cyan"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="Cyan"/>
<Rectangle Fill="Cyan" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="SkyBlue" x:Uid="SkyBlueColorButton">
<Button x:Uid="SkyBlueColorButton"
AutomationProperties.Name="SkyBlue"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="SkyBlue"/>
<Rectangle Fill="SkyBlue" />
</Button.Content>
</Button>
<Button Click="ColorButton_Click" AutomationProperties.Name="DarkGray" x:Uid="DarkGrayColorButton">
<Button x:Uid="DarkGrayColorButton"
AutomationProperties.Name="DarkGray"
Click="ColorButton_Click">
<Button.Content>
<Rectangle Fill="DarkGray"/>
<Rectangle Fill="DarkGray" />
</Button.Content>
</Button>
</VariableSizedWrapGrid>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<StackPanel HorizontalAlignment="Center"
Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="2" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
</StackPanel.Resources>
<Button Padding="5"
Click="ClearColorButton_Click"
x:Name="ClearColorButton" x:Uid="TabColorClearButton" CornerRadius="2" Content="Reset">
</Button>
<Button Padding="5"
Click="ShowColorPickerButton_Click"
x:Name="CustomColorButton" x:Uid="TabColorCustomButton" CornerRadius="2" Content="Custom...">
</Button>
<Button x:Name="ClearColorButton"
x:Uid="TabColorClearButton"
Padding="5"
Click="ClearColorButton_Click"
Content="Reset"
CornerRadius="2" />
<Button x:Name="CustomColorButton"
x:Uid="TabColorCustomButton"
Padding="5"
Click="ShowColorPickerButton_Click"
Content="Custom..."
CornerRadius="2" />
</StackPanel>
</StackPanel>
<Grid Visibility="Collapsed" x:Name="customColorPanel" Margin="5">
<Grid x:Name="customColorPanel"
Margin="5"
Visibility="Collapsed">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ColorPicker x:Name="customColorPicker"
IsMoreButtonVisible="True"
IsColorSliderVisible="True"
IsColorChannelTextInputVisible="True"
IsHexInputVisible="True"
IsAlphaEnabled="False"
IsAlphaSliderVisible="False"
IsAlphaTextInputVisible="False"
FontSize="10"
Grid.Row="0"
ColorChanged="ColorPicker_ColorChanged"
>
</ColorPicker>
<Button x:Name="OkButton" Click="CustomColorButton_Click" Grid.Row="1" HorizontalAlignment="Center" MinWidth="130" MinHeight="12" Margin="0, 5, 0, 0" x:Uid="OkButton" Content="**OK**"/>
Grid.Row="0"
ColorChanged="ColorPicker_ColorChanged"
FontSize="10"
IsAlphaEnabled="False"
IsAlphaSliderVisible="False"
IsAlphaTextInputVisible="False"
IsColorChannelTextInputVisible="True"
IsColorSliderVisible="True"
IsHexInputVisible="True"
IsMoreButtonVisible="True" />
<Button x:Name="OkButton"
x:Uid="OkButton"
Grid.Row="1"
MinWidth="130"
MinHeight="12"
Margin="0,5,0,0"
HorizontalAlignment="Center"
Click="CustomColorButton_Click"
Content="**OK**" />
</Grid>
</StackPanel>
</Flyout>

View File

@@ -14,7 +14,7 @@ namespace winrt::TerminalApp::implementation
CommandLinePaletteItem() = default;
CommandLinePaletteItem(winrt::hstring const& commandLine);
GETSET_PROPERTY(winrt::hstring, CommandLine);
WINRT_PROPERTY(winrt::hstring, CommandLine);
};
}

View File

@@ -14,6 +14,7 @@ using namespace winrt;
using namespace winrt::TerminalApp;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::System;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
@@ -256,7 +257,7 @@ namespace winrt::TerminalApp::implementation
// a really widely used keyboard navigation key.
if (_currentMode == CommandPaletteMode::TabSwitchMode && _keymap)
{
winrt::Microsoft::Terminal::TerminalControl::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
const auto action = _keymap.TryLookup(kc);
if (action)
{
@@ -311,6 +312,13 @@ namespace winrt::TerminalApp::implementation
}
else if (key == VirtualKey::Enter)
{
if (const auto& button = e.OriginalSource().try_as<Button>())
{
// Let the button handle the Enter key so an eventually attached click handler will be called
e.Handled(false);
return;
}
const auto selectedCommand = _filteredActionsView().SelectedItem();
const auto filteredCommand = selectedCommand.try_as<winrt::TerminalApp::FilteredCommand>();
_dispatchCommand(filteredCommand);
@@ -503,6 +511,7 @@ namespace winrt::TerminalApp::implementation
void CommandPalette::_moveBackButtonClicked(Windows::Foundation::IInspectable const& /*sender*/,
Windows::UI::Xaml::RoutedEventArgs const&)
{
_PreviewActionHandlers(*this, nullptr);
_nestedActionStack.Clear();
ParentCommandName(L"");
_currentNestedCommands.Clear();
@@ -629,7 +638,13 @@ namespace winrt::TerminalApp::implementation
// palette like the Tab Switcher will be able to have the last laugh.
_close();
_DispatchCommandRequestedHandlers(*this, actionPaletteItem.Command());
// But make an exception for the Toggle Command Palette action: we don't want the dispatch
// make the command palette - that was just closed - visible again.
// All other actions can just be dispatched.
if (actionPaletteItem.Command().ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
{
_DispatchCommandRequestedHandlers(*this, actionPaletteItem.Command());
}
TraceLoggingWrite(
g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
@@ -927,6 +942,10 @@ namespace winrt::TerminalApp::implementation
ParsedCommandLineText(L"");
_searchBox().Text(L"");
_searchBox().Select(_searchBox().Text().size(), 0);
_nestedActionStack.Clear();
ParentCommandName(L"");
_currentNestedCommands.Clear();
// Leaving this block of code outside the above if-statement
// guarantees that the correct text is shown for the mode
// whenever _switchToMode is called.

View File

@@ -48,12 +48,12 @@ namespace winrt::TerminalApp::implementation
void EnableTabSearchMode();
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, PrefixCharacter, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ControlName, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ParentCommandName, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ParsedCommandLineText, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, PrefixCharacter, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ControlName, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ParentCommandName, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ParsedCommandLineText, _PropertyChangedHandlers);
TYPED_EVENT(SwitchToTabRequested, winrt::TerminalApp::CommandPalette, winrt::TerminalApp::TabBase);
TYPED_EVENT(CommandLineExecutionRequested, winrt::TerminalApp::CommandPalette, winrt::hstring);

View File

@@ -1,490 +1,500 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information. -->
<UserControl
x:Class="TerminalApp.CommandPalette"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TerminalApp"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Windows10version1903="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 8)"
xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model"
TabNavigation="Cycle"
IsTabStop="True"
AllowFocusOnInteraction="True"
PointerPressed="_rootPointerPressed"
PreviewKeyDown="_previewKeyDownHandler"
PreviewKeyUp="_keyUpHandler"
LostFocus="_lostFocusHandler"
mc:Ignorable="d"
AutomationProperties.Name="{x:Bind ControlName, Mode=OneWay}">
<UserControl.Resources>
<ResourceDictionary>
<!-- ThemeShadow is only on 18362. This "Windows10version1903" bit
adds it conditionally -->
<Windows10version1903:ThemeShadow x:Name="CommandPaletteShadow" />
<!-- This creates an instance of our CommandKeyChordVisibilityConverter we can reference below -->
<local:EmptyStringVisibilityConverter x:Key="CommandKeyChordVisibilityConverter"/>
<local:EmptyStringVisibilityConverter x:Key="ParsedCommandLineTextVisibilityConverter"/>
<local:EmptyStringVisibilityConverter x:Key="ParentCommandVisibilityConverter"/>
<model:IconPathConverter x:Key="IconSourceConverter"/>
<DataTemplate x:Key="ListItemTemplate" x:DataType="local:FilteredCommand">
<ListViewItem HorizontalContentAlignment="Stretch"
AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}"
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}"/>
</DataTemplate>
<DataTemplate x:Key="GeneralItemTemplate" x:DataType="local:FilteredCommand">
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<!-- icon -->
<ColumnDefinition Width="Auto"/>
<!-- command label -->
<ColumnDefinition Width="*"/>
<!-- key chord -->
<ColumnDefinition Width="16"/>
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<IconSourceElement
Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind Item.Icon,
Mode=OneWay,
Converter={StaticResource IconSourceConverter}}"/>
<local:HighlightedTextControl
Grid.Column="1"
HorizontalAlignment="Left"
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
<!-- The block for the key chord is only visible
when there's actual text set as the label. See
CommandKeyChordVisibilityConverter for details.
We're setting the accessibility view on the
border and text block to Raw because otherwise,
Narrator will read out the key chord. Problem is,
it already did that because it was the list item's
"AcceleratorKey". It's redundant. -->
<Border
Grid.Column="2"
Visibility="{x:Bind Item.KeyChordText,
Mode=OneWay,
Converter={StaticResource CommandKeyChordVisibilityConverter}}"
Style="{ThemeResource KeyChordBorderStyle}"
Padding="2,0,2,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw">
<TextBlock
Style="{ThemeResource KeyChordTextBlockStyle}"
FontSize="12"
Text="{x:Bind Item.KeyChordText, Mode=OneWay}"
AutomationProperties.AccessibilityView="Raw" />
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="NestedItemTemplate" x:DataType="local:FilteredCommand">
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<!-- icon -->
<ColumnDefinition Width="Auto"/>
<!-- command label -->
<ColumnDefinition Width="*"/>
<!-- key chord -->
<ColumnDefinition Width="16"/>
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<IconSourceElement
Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind Item.Icon,
Mode=OneWay,
Converter={StaticResource IconSourceConverter}}"/>
<local:HighlightedTextControl
Grid.Column="1"
HorizontalAlignment="Left"
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
<!-- The block for the key chord is only visible
when there's actual text set as the label. See
CommandKeyChordVisibilityConverter for details.
We're setting the accessibility view on the
border and text block to Raw because otherwise,
Narrator will read out the key chord. Problem is,
it already did that because it was the list item's
"AcceleratorKey". It's redundant. -->
<Border
Grid.Column="2"
Visibility="{x:Bind Item.KeyChordText,
Mode=OneWay,
Converter={StaticResource CommandKeyChordVisibilityConverter}}"
Style="{ThemeResource KeyChordBorderStyle}"
Padding="2,0,2,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw">
<TextBlock
Style="{ThemeResource KeyChordTextBlockStyle}"
FontSize="12"
Text="{x:Bind Item.KeyChordText, Mode=OneWay}"
AutomationProperties.AccessibilityView="Raw" />
</Border>
<!-- xE70E is ChevronUp. Rotated 90 degrees, it's _ChevronRight_ -->
<FontIcon
FontFamily="Segoe MDL2 Assets"
Glyph="&#xE70E;"
HorizontalAlignment="Right"
Grid.Column="2">
<FontIcon.RenderTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="90"/>
</FontIcon.RenderTransform>
</FontIcon>
</Grid>
</DataTemplate>
<DataTemplate x:Key="TabItemTemplate" x:DataType="local:FilteredCommand">
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8" AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<!-- icon / progress -->
<ColumnDefinition Width="Auto"/>
<!-- command label -->
<ColumnDefinition Width="*"/>
<!-- gutter for indicators -->
<ColumnDefinition Width="Auto"/>
<!-- Indicators -->
<ColumnDefinition Width="16"/>
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<mux:ProgressRing
Grid.Column="0"
IsActive="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingActive, Mode=OneWay}"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingActive, Mode=OneWay}"
IsIndeterminate="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingIndeterminate, Mode=OneWay}"
Value="{x:Bind Item.(local:TabPaletteItem.TabStatus).ProgressValue, Mode=OneWay}"
MinHeight="0"
MinWidth="0"
Height="15"
Width="15"/>
<IconSourceElement
Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind Item.Icon,
Mode=OneWay,
Converter={StaticResource IconSourceConverter}}"/>
<local:HighlightedTextControl
Grid.Column="1"
HorizontalAlignment="Left"
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
<StackPanel
Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Orientation="Horizontal">
<FontIcon
FontFamily="Segoe MDL2 Assets"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).BellIndicator, Mode=OneWay}"
Glyph="&#xEA8F;"
FontSize="12"
Margin="0,0,8,0"/>
<FontIcon
FontFamily="Segoe MDL2 Assets"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsPaneZoomed, Mode=OneWay}"
Glyph="&#xE8A3;"
FontSize="12"
Margin="0,0,8,0"/>
<FontIcon x:Name="HeaderLockIcon"
FontFamily="Segoe MDL2 Assets"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsReadOnlyActive, Mode=OneWay}"
Glyph="&#xE72E;"
FontSize="12"
Margin="0,0,8,0"/>
</StackPanel>
</Grid>
</DataTemplate>
<local:PaletteItemTemplateSelector x:Key="PaletteItemTemplateSelector"
TabItemTemplate="{StaticResource TabItemTemplate}"
GeneralItemTemplate="{StaticResource GeneralItemTemplate}"
NestedItemTemplate="{StaticResource NestedItemTemplate}"/>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<Style x:Key="CommandPaletteBackground" TargetType="Grid">
<Setter Property="Background" Value="#333333" />
</Style>
<!-- TextBox colors !-->
<SolidColorBrush x:Key="TextControlBackground" Color="#333333"/>
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush" Color="#B5B5B5"/>
<SolidColorBrush x:Key="TextControlForeground" Color="#B5B5B5"/>
<SolidColorBrush x:Key="TextControlBorderBrush" Color="#404040"/>
<SolidColorBrush x:Key="TextControlButtonForeground" Color="#B5B5B5"/>
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="#404040"/>
<SolidColorBrush x:Key="TextControlForegroundPointerOver" Color="#FFFFFF"/>
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver" Color="#404040"/>
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver" Color="#FF4343"/>
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="#333333"/>
<SolidColorBrush x:Key="TextControlForegroundFocused" Color="#FFFFFF"/>
<SolidColorBrush x:Key="TextControlBorderBrushFocused" Color="#404040"/>
<SolidColorBrush x:Key="TextControlButtonForegroundPressed" Color="#FFFFFF"/>
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed" Color="#FF4343"/>
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle" TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle" TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="ParsedCommandLineTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<Style x:Key="CommandPaletteBackground" TargetType="Grid">
<Setter Property="Background" Value="#CCCCCC" />
</Style>
<!-- TextBox colors !-->
<SolidColorBrush x:Key="TextControlBackground" Color="#CCCCCC"/>
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush" Color="#636363"/>
<SolidColorBrush x:Key="TextControlBorderBrush" Color="#636363"/>
<SolidColorBrush x:Key="TextControlButtonForeground" Color="#636363"/>
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="#DADADA"/>
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver" Color="#636363"/>
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver" Color="#FF4343"/>
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="#CCCCCC"/>
<SolidColorBrush x:Key="TextControlBorderBrushFocused" Color="#636363"/>
<SolidColorBrush x:Key="TextControlButtonForegroundPressed" Color="#FFFFFF"/>
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed" Color="#FF4343"/>
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle" TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle" TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="ParsedCommandLineTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<Style x:Key="CommandPaletteBackground" TargetType="Grid">
<Setter Property="Background" Value="{ThemeResource SystemColorWindowColor}" />
</Style>
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="KeyChordBorderStyle" TargetType="Border"/>
<Style x:Key="KeyChordTextBlockStyle" TargetType="TextBlock"/>
<!-- ParsedCommandLineText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="ParsedCommandLineBorderStyle" TargetType="Border"/>
<Style x:Key="ParsedCommandLineTextBlockStyle" TargetType="TextBlock"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="6*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="8*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<!-- Setting the row/col span of this shadow backdrop is a bit of a hack. In
order to receive pointer events, an element needs to be _not_ transparent.
However, we want to be able to eat all the clicks outside the immediate
bounds of the command palette, and we don't want a semi-transparent overlay
over all of the UI. Fortunately, if we make this _shadowBackdrop the size of
the entire page, then it can be mostly transparent, and cause the root grid
to receive clicks _anywhere_ in its bounds. -->
<Grid
x:Name="_shadowBackdrop"
Background="Transparent"
Grid.Column="0"
Grid.Row="0"
Grid.ColumnSpan="3"
Grid.RowSpan="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
</Grid>
<Grid
x:Name="_backdrop"
Style="{ThemeResource CommandPaletteBackground}"
CornerRadius="{ThemeResource ControlCornerRadius}"
PointerPressed="_backdropPointerPressed"
Margin="8"
Grid.Column="1"
Grid.Row="0"
Windows10version1903:Shadow="{StaticResource CommandPaletteShadow}"
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox
Grid.Row="0"
x:Name="_searchBox"
Margin="8"
Padding="18,8,8,8"
IsSpellCheckEnabled="False"
TextChanged="_filterTextChanged"
PlaceholderText="{x:Bind SearchBoxPlaceholderText, Mode=OneWay}"
Text="">
</TextBox>
<TextBlock
Grid.Row="0"
x:Name="_prefixCharacter"
Margin="16,16,0,-8"
FontSize="14"
HorizontalAlignment="Left"
Visibility="{x:Bind PrefixCharacter,
Mode=OneWay,
Converter={StaticResource ParentCommandVisibilityConverter}}"
Text="{x:Bind PrefixCharacter, Mode=OneWay}"
>
</TextBlock>
<StackPanel Orientation="Horizontal"
Padding="16, 0, 16, 4"
Grid.Row="1"
Visibility="{x:Bind ParentCommandName,
Mode=OneWay,
Converter={StaticResource ParentCommandVisibilityConverter}}">
<Button
Background="Transparent"
x:Name="_parentCommandBackButton"
x:Uid="ParentCommandBackButton"
Click="_moveBackButtonClicked"
ClickMode="Press"
VerticalAlignment="Center">
<FontIcon
FontSize="12"
FontFamily="Segoe MDL2 Assets"
Glyph="&#xE76b;">
</FontIcon>
</Button>
<TextBlock
Padding="16, 0, 16, 4"
x:Name="_parentCommandText"
FontStyle="Italic"
Grid.Row="1"
Text="{x:Bind ParentCommandName, Mode=OneWay}"
VerticalAlignment="Center">
</TextBlock>
</StackPanel>
<TextBlock
Padding="16"
x:Name="_noMatchesText"
FontStyle="Italic"
Visibility="Collapsed"
Grid.Row="1"
Text="{x:Bind NoMatchesText, Mode=OneWay}">
</TextBlock>
<Border
Grid.Row="1"
Visibility="{x:Bind ParsedCommandLineText, Mode=OneWay, Converter={StaticResource ParsedCommandLineTextVisibilityConverter}}"
Style="{ThemeResource ParsedCommandLineBorderStyle}"
Padding="16"
HorizontalAlignment="Stretch"
VerticalAlignment="Center">
<ScrollViewer MaxHeight="200" VerticalScrollBarVisibility="Auto">
<TextBlock
FontStyle="Italic"
TextWrapping="Wrap"
Text="{x:Bind ParsedCommandLineText, Mode=OneWay}"/>
</ScrollViewer>
</Border>
<ListView
Grid.Row="2"
x:Name="_filteredActionsView"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
SelectionMode="Single"
CanReorderItems="False"
AllowDrop="False"
IsItemClickEnabled="True"
ItemClick="_listItemClicked"
ChoosingItemContainer="_choosingItemContainer"
ContainerContentChanging="_containerContentChanging"
ItemsSource="{x:Bind FilteredActions}">
</ListView>
</Grid>
</Grid>
</UserControl>
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<UserControl x:Class="TerminalApp.CommandPalette"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model"
xmlns:Windows10version1903="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 8)"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
AllowFocusOnInteraction="True"
AutomationProperties.Name="{x:Bind ControlName, Mode=OneWay}"
IsTabStop="True"
LostFocus="_lostFocusHandler"
PointerPressed="_rootPointerPressed"
PreviewKeyDown="_previewKeyDownHandler"
PreviewKeyUp="_keyUpHandler"
TabNavigation="Cycle"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<!--
ThemeShadow is only on 18362. This "Windows10version1903" bit
adds it conditionally
-->
<Windows10version1903:ThemeShadow x:Name="CommandPaletteShadow" />
<!-- This creates an instance of our CommandKeyChordVisibilityConverter we can reference below -->
<local:EmptyStringVisibilityConverter x:Key="CommandKeyChordVisibilityConverter" />
<local:EmptyStringVisibilityConverter x:Key="ParsedCommandLineTextVisibilityConverter" />
<local:EmptyStringVisibilityConverter x:Key="ParentCommandVisibilityConverter" />
<model:IconPathConverter x:Key="IconSourceConverter" />
<DataTemplate x:Key="ListItemTemplate"
x:DataType="local:FilteredCommand">
<ListViewItem HorizontalContentAlignment="Stretch"
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}"
AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}" />
</DataTemplate>
<DataTemplate x:Key="GeneralItemTemplate"
x:DataType="local:FilteredCommand">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<!-- icon -->
<ColumnDefinition Width="Auto" />
<!-- command label -->
<ColumnDefinition Width="*" />
<!-- key chord -->
<ColumnDefinition Width="16" />
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<IconSourceElement Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind Item.Icon, Mode=OneWay, Converter={StaticResource IconSourceConverter}}" />
<local:HighlightedTextControl Grid.Column="1"
HorizontalAlignment="Left"
Text="{x:Bind HighlightedName, Mode=OneWay}" />
<!--
The block for the key chord is only visible
when there's actual text set as the label. See
CommandKeyChordVisibilityConverter for details.
We're setting the accessibility view on the
border and text block to Raw because otherwise,
Narrator will read out the key chord. Problem is,
it already did that because it was the list item's
"AcceleratorKey". It's redundant.
-->
<Border Grid.Column="2"
Padding="2,0,2,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Style="{ThemeResource KeyChordBorderStyle}"
Visibility="{x:Bind Item.KeyChordText, Mode=OneWay, Converter={StaticResource CommandKeyChordVisibilityConverter}}">
<TextBlock AutomationProperties.AccessibilityView="Raw"
FontSize="12"
Style="{ThemeResource KeyChordTextBlockStyle}"
Text="{x:Bind Item.KeyChordText, Mode=OneWay}" />
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="NestedItemTemplate"
x:DataType="local:FilteredCommand">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<!-- icon -->
<ColumnDefinition Width="Auto" />
<!-- command label -->
<ColumnDefinition Width="*" />
<!-- key chord -->
<ColumnDefinition Width="16" />
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<IconSourceElement Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind Item.Icon, Mode=OneWay, Converter={StaticResource IconSourceConverter}}" />
<local:HighlightedTextControl Grid.Column="1"
HorizontalAlignment="Left"
Text="{x:Bind HighlightedName, Mode=OneWay}" />
<!--
The block for the key chord is only visible
when there's actual text set as the label. See
CommandKeyChordVisibilityConverter for details.
We're setting the accessibility view on the
border and text block to Raw because otherwise,
Narrator will read out the key chord. Problem is,
it already did that because it was the list item's
"AcceleratorKey". It's redundant.
-->
<Border Grid.Column="2"
Padding="2,0,2,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Style="{ThemeResource KeyChordBorderStyle}"
Visibility="{x:Bind Item.KeyChordText, Mode=OneWay, Converter={StaticResource CommandKeyChordVisibilityConverter}}">
<TextBlock AutomationProperties.AccessibilityView="Raw"
FontSize="12"
Style="{ThemeResource KeyChordTextBlockStyle}"
Text="{x:Bind Item.KeyChordText, Mode=OneWay}" />
</Border>
<!-- xE70E is ChevronUp. Rotated 90 degrees, it's _ChevronRight_ -->
<FontIcon Grid.Column="2"
HorizontalAlignment="Right"
FontFamily="Segoe MDL2 Assets"
Glyph="&#xE70E;">
<FontIcon.RenderTransform>
<RotateTransform Angle="90" CenterX="0.5" CenterY="0.5" />
</FontIcon.RenderTransform>
</FontIcon>
</Grid>
</DataTemplate>
<DataTemplate x:Key="TabItemTemplate"
x:DataType="local:FilteredCommand">
<Grid HorizontalAlignment="Stretch"
AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<!-- icon / progress -->
<ColumnDefinition Width="Auto" />
<!-- command label -->
<ColumnDefinition Width="*" />
<!-- gutter for indicators -->
<ColumnDefinition Width="Auto" />
<!-- Indicators -->
<ColumnDefinition Width="16" />
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<mux:ProgressRing Grid.Column="0"
Width="15"
Height="15"
MinWidth="0"
MinHeight="0"
IsActive="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingActive, Mode=OneWay}"
IsIndeterminate="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingIndeterminate, Mode=OneWay}"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingActive, Mode=OneWay}"
Value="{x:Bind Item.(local:TabPaletteItem.TabStatus).ProgressValue, Mode=OneWay}" />
<IconSourceElement Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind Item.Icon, Mode=OneWay, Converter={StaticResource IconSourceConverter}}" />
<local:HighlightedTextControl Grid.Column="1"
HorizontalAlignment="Left"
Text="{x:Bind HighlightedName, Mode=OneWay}" />
<StackPanel Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Orientation="Horizontal">
<FontIcon Margin="0,0,8,0"
FontFamily="Segoe MDL2 Assets"
FontSize="12"
Glyph="&#xEA8F;"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).BellIndicator, Mode=OneWay}" />
<FontIcon Margin="0,0,8,0"
FontFamily="Segoe MDL2 Assets"
FontSize="12"
Glyph="&#xE8A3;"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsPaneZoomed, Mode=OneWay}" />
<FontIcon x:Name="HeaderLockIcon"
Margin="0,0,8,0"
FontFamily="Segoe MDL2 Assets"
FontSize="12"
Glyph="&#xE72E;"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsReadOnlyActive, Mode=OneWay}" />
</StackPanel>
</Grid>
</DataTemplate>
<local:PaletteItemTemplateSelector x:Key="PaletteItemTemplateSelector"
GeneralItemTemplate="{StaticResource GeneralItemTemplate}"
NestedItemTemplate="{StaticResource NestedItemTemplate}"
TabItemTemplate="{StaticResource TabItemTemplate}" />
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<Style x:Key="CommandPaletteBackground"
TargetType="Grid">
<Setter Property="Background" Value="#333333" />
</Style>
<!-- TextBox colors ! -->
<SolidColorBrush x:Key="TextControlBackground"
Color="#333333" />
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush"
Color="#B5B5B5" />
<SolidColorBrush x:Key="TextControlForeground"
Color="#B5B5B5" />
<SolidColorBrush x:Key="TextControlBorderBrush"
Color="#404040" />
<SolidColorBrush x:Key="TextControlButtonForeground"
Color="#B5B5B5" />
<SolidColorBrush x:Key="TextControlBackgroundPointerOver"
Color="#404040" />
<SolidColorBrush x:Key="TextControlForegroundPointerOver"
Color="#FFFFFF" />
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver"
Color="#404040" />
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver"
Color="#FF4343" />
<SolidColorBrush x:Key="TextControlBackgroundFocused"
Color="#333333" />
<SolidColorBrush x:Key="TextControlForegroundFocused"
Color="#FFFFFF" />
<SolidColorBrush x:Key="TextControlBorderBrushFocused"
Color="#404040" />
<SolidColorBrush x:Key="TextControlButtonForegroundPressed"
Color="#FFFFFF" />
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed"
Color="#FF4343" />
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<Style x:Key="CommandPaletteBackground"
TargetType="Grid">
<Setter Property="Background" Value="#CCCCCC" />
</Style>
<!-- TextBox colors ! -->
<SolidColorBrush x:Key="TextControlBackground"
Color="#CCCCCC" />
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush"
Color="#636363" />
<SolidColorBrush x:Key="TextControlBorderBrush"
Color="#636363" />
<SolidColorBrush x:Key="TextControlButtonForeground"
Color="#636363" />
<SolidColorBrush x:Key="TextControlBackgroundPointerOver"
Color="#DADADA" />
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver"
Color="#636363" />
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver"
Color="#FF4343" />
<SolidColorBrush x:Key="TextControlBackgroundFocused"
Color="#CCCCCC" />
<SolidColorBrush x:Key="TextControlBorderBrushFocused"
Color="#636363" />
<SolidColorBrush x:Key="TextControlButtonForegroundPressed"
Color="#FFFFFF" />
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed"
Color="#FF4343" />
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<Style x:Key="CommandPaletteBackground"
TargetType="Grid">
<Setter Property="Background" Value="{ThemeResource SystemColorWindowColor}" />
</Style>
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border" />
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock" />
<!-- ParsedCommandLineText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border" />
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="6*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<!--
Setting the row/col span of this shadow backdrop is a bit of a hack. In
order to receive pointer events, an element needs to be _not_ transparent.
However, we want to be able to eat all the clicks outside the immediate
bounds of the command palette, and we don't want a semi-transparent overlay
over all of the UI. Fortunately, if we make this _shadowBackdrop the size of
the entire page, then it can be mostly transparent, and cause the root grid
to receive clicks _anywhere_ in its bounds.
-->
<Grid x:Name="_shadowBackdrop"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
Grid.ColumnSpan="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent" />
<Grid x:Name="_backdrop"
Grid.Row="0"
Grid.Column="1"
Margin="8"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Windows10version1903:Shadow="{StaticResource CommandPaletteShadow}"
CornerRadius="{ThemeResource ControlCornerRadius}"
PointerPressed="_backdropPointerPressed"
Style="{ThemeResource CommandPaletteBackground}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox x:Name="_searchBox"
Grid.Row="0"
Margin="8"
Padding="18,8,8,8"
IsSpellCheckEnabled="False"
PlaceholderText="{x:Bind SearchBoxPlaceholderText, Mode=OneWay}"
Text=""
TextChanged="_filterTextChanged" />
<TextBlock x:Name="_prefixCharacter"
Grid.Row="0"
Margin="16,16,0,-8"
HorizontalAlignment="Left"
FontSize="14"
Text="{x:Bind PrefixCharacter, Mode=OneWay}"
Visibility="{x:Bind PrefixCharacter, Mode=OneWay, Converter={StaticResource ParentCommandVisibilityConverter}}" />
<StackPanel Grid.Row="1"
Padding="16,0,16,4"
Orientation="Horizontal"
Visibility="{x:Bind ParentCommandName, Mode=OneWay, Converter={StaticResource ParentCommandVisibilityConverter}}">
<Button x:Name="_parentCommandBackButton"
x:Uid="ParentCommandBackButton"
VerticalAlignment="Center"
Background="Transparent"
Click="_moveBackButtonClicked"
ClickMode="Press">
<FontIcon FontFamily="Segoe MDL2 Assets"
FontSize="12"
Glyph="&#xE76b;" />
</Button>
<TextBlock x:Name="_parentCommandText"
Grid.Row="1"
Padding="16,0,16,4"
VerticalAlignment="Center"
FontStyle="Italic"
Text="{x:Bind ParentCommandName, Mode=OneWay}" />
</StackPanel>
<TextBlock x:Name="_noMatchesText"
Grid.Row="1"
Padding="16"
FontStyle="Italic"
Text="{x:Bind NoMatchesText, Mode=OneWay}"
Visibility="Collapsed" />
<Border Grid.Row="1"
Padding="16"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Style="{ThemeResource ParsedCommandLineBorderStyle}"
Visibility="{x:Bind ParsedCommandLineText, Mode=OneWay, Converter={StaticResource ParsedCommandLineTextVisibilityConverter}}">
<ScrollViewer MaxHeight="200"
VerticalScrollBarVisibility="Auto">
<TextBlock FontStyle="Italic"
Text="{x:Bind ParsedCommandLineText, Mode=OneWay}"
TextWrapping="Wrap" />
</ScrollViewer>
</Border>
<ListView x:Name="_filteredActionsView"
Grid.Row="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AllowDrop="False"
CanReorderItems="False"
ChoosingItemContainer="_choosingItemContainer"
ContainerContentChanging="_containerContentChanging"
IsItemClickEnabled="True"
ItemClick="_listItemClicked"
ItemsSource="{x:Bind FilteredActions}"
SelectionMode="Single" />
</Grid>
</Grid>
</UserControl>

View File

@@ -25,10 +25,10 @@ namespace winrt::TerminalApp::implementation
static int Compare(winrt::TerminalApp::FilteredCommand const& first, winrt::TerminalApp::FilteredCommand const& second);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
OBSERVABLE_GETSET_PROPERTY(winrt::TerminalApp::PaletteItem, Item, _PropertyChangedHandlers, nullptr);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Filter, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(winrt::TerminalApp::HighlightedText, HighlightedName, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(int, Weight, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::PaletteItem, Item, _PropertyChangedHandlers, nullptr);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Filter, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::HighlightedText, HighlightedName, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(int, Weight, _PropertyChangedHandlers);
private:
winrt::TerminalApp::HighlightedText _computeHighlightedName();

View File

@@ -17,8 +17,8 @@ namespace winrt::TerminalApp::implementation
HighlightedTextSegment(winrt::hstring const& text, bool isHighlighted);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, TextSegment, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(bool, IsHighlighted, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, TextSegment, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(bool, IsHighlighted, _PropertyChangedHandlers);
};
struct HighlightedText : HighlightedTextT<HighlightedText>
@@ -27,7 +27,7 @@ namespace winrt::TerminalApp::implementation
HighlightedText(Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment> const& segments);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
OBSERVABLE_GETSET_PROPERTY(Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment>, Segments, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment>, Segments, _PropertyChangedHandlers);
};
}

View File

@@ -1,13 +1,11 @@
<UserControl
x:Class="TerminalApp.HighlightedTextControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TerminalApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="Transparent">
<UserControl x:Class="TerminalApp.HighlightedTextControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="Transparent"
mc:Ignorable="d">
<TextBlock
x:Name="_textView"/>
<TextBlock x:Name="_textView" />
</UserControl>

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