Compare commits

...

45 commits

Author SHA1 Message Date
Dustin L. Howett 258a3f32ad Migrate spelling-0.0.19 changes from main 2021-07-13 10:55:36 -05:00
Dustin Howett 596586d911
Disable default terminal dropdown on Stable (oops!) 2021-07-13 10:55:36 -05:00
Dustin Howett afb0cac3e3 [STABLE ONLY] Combined revert of Environment Block Changes
Revert "Fix environment block creation (#7401)"

This reverts commit 7886f16714.

(cherry picked from commit e46ba65665)

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

This reverts commit 849243af99.

References #7418

(cherry picked from commit 4204d2535c)
(cherry picked from commit f8e8572c23)
(cherry picked from commit cb4c4f7b73)
2021-07-12 18:13:38 -05:00
Dustin L. Howett bae1793de4 Update Xaml Toolkit App Host to 6.1.3 (#10640)
This is required for some inbox compliance tasks regarding symbol availability.

(cherry picked from commit e37fd5e546)
2021-07-12 18:13:19 -05:00
Mike Griese fd4af02ff3
Update the quakeMode action name (#10641)
As in #10210. This string was already in the resources (so it should already be localized!)

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

![image](https://user-images.githubusercontent.com/18356694/125360281-45ddd280-e331-11eb-9798-6f087f33af2f.png)

(cherry picked from commit 59166faa27)
2021-07-12 18:13:12 -05:00
Mim van den Bos d5ff31cdfd
Encapsulate settings main frame to prevent overflow (#10619)
When navigating the settings (or saving/discarding) the animation of the main content overflows the bar with the save and discard buttons. If the main content is encapsulated in a ScrollView the issue goes away.

Fixes one of the issues in #10609

## Validation Steps Performed
Clicked around a whole bunch and have not seen the overflow happen again. Verified that on tabs where scroll is necessary it can still be scrolled, and reflow of elements still functions.

(cherry picked from commit 19f8b9c3ca)
2021-07-12 18:13:12 -05:00
PankajBhojwani 889ffe9934
Update RIS to reset mouse mode and encoding (#10602)
## Summary of the Pull Request

RIS resets mouse mode and encoding

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

## Validation Steps Performed

(cherry picked from commit 1d33429673)
2021-07-12 18:13:12 -05:00
Mim van den Bos dc77f8cbce
Include profile nav menu items to consider for retaining position (#10618)
## Summary of the Pull Request

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

## References

Issue introduced by #10390

## PR Checklist

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

## Detailed Description of the Pull Request / Additional comments

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

## Validation Steps Performed

Spam discard and save buttons

(cherry picked from commit ef8ba20bee)
2021-07-12 18:13:12 -05:00
PankajBhojwani 0480f20d20
Fix all fragments not loading when one is badly formed (#10601)
Adds try-catch blocks to the parts where we layer a fragment onto a profile and create a new profile from a fragment. This allows us to continue looping over the remaining fragments after failing to use a badly-formed one, instead of aborting prematurely.

## PR Checklist
* [x] Closes #10590

## Validation Steps Performed
Non-badly formed fragments get loaded even if there is a badly formed one somewhere

(cherry picked from commit a89746a869)
2021-07-12 18:13:11 -05:00
Ian O'Neill 5c93e4bf12
Set working directory when invoked from shell extension (#10546)
Sets the working directory of the terminal when invoked from the shell extension. This ensures that new tabs opened with a starting directory of `.` open in the directory that the terminal was invoked from.

Closes #8933

## Validation Steps Performed
Manually tested - default PowerShell profile set to use home directory, Windows PowerShell profile set to use current directory. Launched via the shell extension and the default profile opened in the explorer directory, as did a new Windows PowerShell tab.

(cherry picked from commit f152573058)
2021-07-12 18:13:11 -05:00
Michael Niksa d3db8f8480
Skip accessibility notifier and all event calculations when we're in PTY mode (#10569)
Change accessibility notifier creation so we do not create one when we're in PTY mode. (Guard all call sites to skip math/event work when the notifier is null.) MSAA events are legacy events that are registered for globally and used by some screen readers to find content in the conhost window. The PTY mode is not responsible for hosting the display content or input window, so it makes sense for it to not broadcast these events and delegate the accessibility requirement to the connected terminal.

## References
- #10537

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

(cherry picked from commit 91b454ac95)
2021-07-12 18:13:11 -05:00
PankajBhojwani 91d599b830
Fix the cursor blink VT sequence being ignored (#10589)
Ensure that the cursor blink VT sequence gets flushed to terminal when conhost is attached to a pty

Closes #10543

(cherry picked from commit 6409ab91fa)
2021-07-12 18:13:11 -05:00
Carlos Zamora 89b420c572 Introduce feature flag for editable actions page (#10581)
Adds a feature flag `Feature_EditableActionsPage` that controls whether the Actions page in the Settings UI is read-only vs editable. The editable version is disabled for `Release` builds and enabled everywhere else (i.e. Dev, Preview, etc...).

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

Closes #10578

(cherry picked from commit f03cacfa5b)
2021-07-12 18:13:09 -05:00
Michael Niksa e9d8b53e7c
Delay load call SetThreadDescription to restore WPF renderer on Win7 (#10582)
Delay load call SetThreadDescription to restore WPF renderer on Win7

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

## Detailed Description of the Pull Request / Additional comments

I keep forgetting that anything in the WPF control needs to keep working on Win7. Or more specifically... I remember this fact for the DX renderer, but not for the render thread base. Oops. Turns out this particular convenience method to set thread descriptions for visibility inside the debugger (to make my life easier) only works down to 1607 (see https://docs.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription). Since it's just a debugging convenience... skipping it entirely when the procedure is not found should be fine. Also I don't try to load `kernel32.dll` and just get the handle of the existing module (which per the remarks at https://docs.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlew will not increment the module reference count) because `kernel32.dll` pretty much has to be there or we're already in hot water.

(cherry picked from commit 1374396f10)
2021-07-08 10:23:35 -05:00
PankajBhojwani 50acd89814
Cleanup from bell flash PR (#10307)
Just come cleanup I did not manage to get to before #9270 merged.

Specifically:

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

## Validation Steps Performed
It still works

(cherry picked from commit 2fed4c4255)
2021-07-07 13:18:46 -05:00
Michael Niksa d49d045bd9
Lock for writing in ControlCore::SetBackgroundOpacity (#10357)
## PR Checklist
* [x] Closes random crash that @lhecker sent me on Teams
* [x] I work here.

## Detailed Description of the Pull Request / Additional comments
- Any change to the renderer engine has to be done under lock. Leonard gave me a crash where the dirty rectangles changed out from under the renderer thread. By inspection, only one spot in `ControlCore` is modifying the engine outside of lock.... here. The dump is too far along to definitively prove the issue and it's sort of a race so its difficult to repro. But the theory is sound that all writes to the dirty regions must be done under lock. So here's a fix.

(cherry picked from commit 94d39b7580)
2021-07-07 13:18:12 -05:00
Leonard Hecker dbe688dcd9
Fix SUI race conditions when reloading settings (#10390)
## Summary of the Pull Request

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

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

## Validation Steps Performed

* Settings UI reloads without crashing ✔️

(cherry picked from commit b034fc9ae5)

# Conflicts:
#	src/cascadia/TerminalApp/AppLogic.cpp
#	src/cascadia/TerminalApp/AppLogic.h
2021-07-07 13:16:53 -05:00
kovdu 39f3f23da8
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:51 -05:00
Michael Niksa 8c5f676533
Summon, not toggle visibility, window on command line dispatch (#10396)
Summon, not toggle visibility, window on command line dispatch

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

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

## Validation Steps Performed
- Opened a window. Dispatched the `wt -w 0 - p <profile>` and watched it join/summon instead of minimize the active WT.

(cherry picked from commit 0f42ee189d)
2021-07-07 13:12:49 -05:00
kovdu 6c60f2be82
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:24 -05:00
Chester Liu f9ba77f186
Prefer FMT_COMPILE for string formatting in VtRenderer (#10426)
Kill `WriteFormattedString` and replace it with `fmt::format_to` to avoid expensive string operations in VtRenderer.

This saves ~8% of the CPU time.

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

Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
(cherry picked from commit 4f0b57ec8e)
2021-07-07 13:10:44 -05:00
Dustin L. Howett 9a2a9db5e9
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)

# Conflicts:
#	src/cascadia/TerminalApp/Resources/en-US/Resources.resw
2021-07-07 13:09:48 -05:00
Chester Liu 079cadeb18
Defer _run substr operation in StateMachine::ProcessString (#10471)
Do not eagerly create run by substring to reduce the unnecessary overhead.

Switching from `.substr` to offset/length tracking saves us 7% CPU time.

(cherry picked from commit 6a37818c07)
2021-07-07 13:07:20 -05:00
Leonard Hecker cf859053a1
Improve parser performance by reducing tracing overhead (#10533)
Passing structures larger than the register size is very expensive
due to Microsoft's x64 calling convention. We could reduce the
overhead by passing the string-view by reference, but this forces us
to allocate the parameters as static string-views on the data
segment of our binary. I've found that passing them as classic
C-strings is more ergonomic instead and fits the need for
high performance in this particular code.
This improves performance for VT-heavy output by 15-20%.

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

(cherry picked from commit ee3259847a)
2021-07-07 13:07:07 -05:00
Chester Liu cd6ec2d625
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:57 -05:00
Dustin L. Howett bf6fd9d67f
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:59 -05:00
Leonard Hecker e77ab2b036
Fix racy access to _tsfTryRedrawCanvas in TermControl (#10549)
Previously `TermControl::Close` destroyed all `ThrottledFunc`s to ensure they're not scheduling any callbacks on the UI thread, as the call to `Close` signals the point at which the `TermControl` isn't part of the UI thread anymore. `_CursorPositionChanged` tried to prevent access to the potentially deallocated `_tsfTryRedrawCanvas` by checking the `std::shared_ptr` for nullability, but since the deallocation happens on the UI thread and the nullability check on a background thread, this check introduced a race condition.

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

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

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

## Validation Steps Performed

* Opening and closing tabs doesn't crash ✔️
* Printing long text doesn't crash ✔️
* Manual scrolling doesn't crash ✔️
* ^G / the audible bell doesn't crash ✔️

(cherry picked from commit 83c6bce73d)
2021-07-07 13:04:08 -05:00
Leonard Hecker 1b996e7416
Introduce til/latch.h, til/mutex.h and til/throttled_func.h (#10403)
This commit introduce three new `til` features:
* "til/latch.h": A std::latch clone, until we're on C++20.
* "til/mutex.h": A safe mutex wrapper, which only allows you access to the protected data after locking it. No more forgetting to lock mutexes!
* "til/throttled_func.h": Function invocation throttling used to be available as the `ThrottledFunc` class already. But this class is vastly more efficient and doesn't rely on any WinRT types.

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

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

Closes #10393

(cherry picked from commit 0d9a357373)
2021-07-07 13:03:51 -05:00
Carlos Zamora 8a73c69567
[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 13:00:27 -05:00
WSLUser 44e99f4976
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 13:00:27 -05:00
Dustin L. Howett a7f2a8badd
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 13:00:27 -05:00
Carlos Zamora ee058551c5
Ensure equality when hashing default args and no args in actions (#10341)
## Summary of the Pull Request
#10297 found a bug in `ActionMap` where the `ToggleCommandPalette` key chord could not be found using `GetKeyBindingForAction`.

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

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

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

## Validation Steps Performed
- Added a test.
- Tested this on #10297's branch and this does fix the bug

(cherry picked from commit b3b648496e)
2021-07-07 13:00:26 -05:00
Carlos Zamora febbf083e4
Fix edit button color in light theme (#10412)
## Summary of the Pull Request
Fixes a bug where the edit button in the actions page would have white text when in light theme. Now, we just fallback to XAML's built-in value (black in light theme and white in dark theme).

## References
#6900 - Epic
Closes #10406

(cherry picked from commit 1fcfb618ad)
2021-07-07 13:00:26 -05:00
Carlos Zamora 658e6e6ee2
Bugfix: serialize iterable commands (#10373)
## Summary of the Pull Request
Fixes a bug where top-level iterable commands were not serialized.

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

## Detailed Description of the Pull Request / Additional comments
- `Command::ToJson`:
   - iterable commands deserve the same treatment as nested commands
- `ActionMap`:
   - Similar to how we store nested commands, iterable commands need to be handled separately from standard commands. Then, when generating the name map, we make sure we export the iterable commands at the same time we export the nested commands.

(cherry picked from commit 9294ecc8e5)
2021-07-07 13:00:26 -05:00
Luan Vitor Simião Oliveira 3fd8ebf319
profile.schema: add missing actions and commands keys (#10384)
Add missing keys to the schema:
- globalSummon (and args: desktop, monitor, name, dropdownDuration, toggleVisibility)
- quakeMode
- iterateOn
- commands

Also enforces required keys for commands and deprecates "keybindings"

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

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

## Validation Steps Performed
Changed the `"$schema"` value in my settings.json to point to the edited one.

(cherry picked from commit 8157605058)
2021-07-07 13:00:26 -05:00
Michael Niksa 1a4e2e65d7
Activate window only (no toggle) when inbound connection arrives (#10389)
Activate window only (no toggle) when inbound connection arrives

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

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

## Validation Steps Performed
- Made the change. Launched Terminal as default as active window. Runbox'd another command. It didn't hide itself like it used to. Stays visible.

(cherry picked from commit 3c81b51b78)
2021-07-07 13:00:25 -05:00
Marcel Wagner 33774d23d6
Add percentage sign to opacity slider values (#10369)
This PR adds a new PercentageSignConverter that appends the percentage sign to a number. The new converter is being used by the Acrylic opacity slider label and the Background image opacity slider label.

* [x] Closes #10289

(cherry picked from commit becc254f67)
2021-07-07 13:00:25 -05:00
Dustin L. Howett f284843afd
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:30:04 -05:00
Dustin L. Howett fd06b0ce60
Work around an ARM64 compiler crash by splitting a coroutine up (#10306)
Built and tested in PackageES
2021-06-01 11:56:28 -05:00
Mike Griese c8ac63e78e
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:27:17 -05:00
Michael Niksa 414adf16a9
Switch FAIL_FAST to LOG for starting inbound connection server on monarch startup (#10261)
Stop startup crash by logging when monarch fails to register inbound connections, but still crash when COM attempted to start us

## References
- See also #10243

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

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

## Validation Steps Performed
- I basically have to guess at this one based on the crash dump and Watson logs because it happens sporadically when the platform messes up on us.

(cherry picked from commit d8647e01c1)
2021-05-28 17:27:17 -05:00
Dustin L. Howett 3533aa2661
Ignore closeOnExit when a conn. moves from Connecting to Failed (#10263)
ConptyConnection has two different failure modes:

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

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

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

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

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

Closes #10225.

(cherry picked from commit 31d78dceb5)
2021-05-28 17:27:16 -05:00
Michael Niksa fbc59b7a3b
Prevent crashes in Settings UI launch on OS versions before package management extensions (#10238)
Prevent crashes in Settings UI launch on OS versions before package management extensions

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

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

## Validation Steps Performed
- Simulated no items returned from list and nullptr returned to XAML on Current() method of Model. Validated XAML will happily select no item from list (and is fine with an empty list of items... that is it doesn't crash).
- Simulated downlevel OS returning package management errors in lookup catalog functions after the hardcoded default is added to the list. Ensured that this error is only logged, the remainder of the package identification functions make the hardcoded default package, and it is presented as your one and only option in the XAML.

(cherry picked from commit b2c2a4c159)
2021-05-28 17:27:15 -05:00
Michael Niksa 30f1c64e08
Summon this window when it receives an inbound connection (#10217)
Summon the listening window when it receives an inbound connection

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

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

## Validation Steps Performed
- Opened the Terminal with it registered as DefTerm. Activated some other windows to the foreground. Start > Run > Cmd. Tab connects and opens in existing Terminal and it is brought to foreground.
- With no running Terminal and registered as DefTerm, do Start > Run > Cmd. New Terminal is spawned and it is brought to foreground

(cherry picked from commit e694f36ad2)
2021-05-28 17:27:15 -05:00
Michael Niksa d9c93430a0
Correct Default Application Selector styles for high contrast and to change with OS theme dark/light toggle (#10185)
Correct Default Application Selector styles for high contrast and to change with OS theme dark/light toggle

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

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

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

## Validation Steps Performed
- Loaded in light mode. Flipped to dark. Watched it change live. Checked both unselected and rollover/selected to ensure it was fine.
- Loaded in dark mode. Flipped to light. Watched it change live. Checked both unselected and rollover/selected to ensure it was fine.
- Flipped to HC. Watched it change live. Confirmed that unselected is black/white contrast and the roll over has the cyan/black. (No longer uses special second-line brush for HC, matches the controls I modeled this one on from OS Settings).

(cherry picked from commit 43d5713a02)
2021-05-28 17:27:06 -05:00
141 changed files with 2897 additions and 930 deletions

View file

@ -1,10 +1,15 @@
Apc
apc
calt
ccmp
changelog
cybersecurity
Apc
clickable
clig
copyable
dalet
Dcs
dcs
Dcs
dialytika
dje
downside
@ -12,7 +17,10 @@ downsides
dze
dzhe
Enum'd
Fitt
formattings
ftp
fvar
geeksforgeeks
ghe
gje
@ -24,9 +32,17 @@ hyperlinks
img
It'd
kje
liga
lje
locl
lorem
Llast
Lmid
Lorigin
maxed
mkmk
mru
noreply
nje
ogonek
ok'd
@ -34,18 +50,26 @@ overlined
postmodern
ptys
qof
qps
rclt
reimplementation
reserialization
reserialize
reserializes
rlig
runtimes
shcha
slnt
Sos
timestamped
TLDR
tokenizes
tonos
tshe
uiatextrange
UIs
und
unregister
versioned
We'd
wildcards

View file

@ -2,15 +2,20 @@ ACCEPTFILES
ACCESSDENIED
alignas
alignof
APPLYTOSUBMENUS
bitfield
bitfields
BUILDBRANCH
BUILDMSG
BUILDNUMBER
BYPOSITION
charconv
CLASSNOTAVAILABLE
cmdletbinding
COLORPROPERTY
colspan
COMDLG
comparand
cstdint
CXICON
CYICON
@ -20,9 +25,11 @@ DERR
dlldata
DONTADDTORECENT
DWORDLONG
enumset
environstrings
EXPCMDFLAGS
EXPCMDSTATE
filetime
FILTERSPEC
FORCEFILESYSTEM
FORCEMINIMIZE
@ -45,6 +52,7 @@ IBind
IBox
IClass
IComparable
IComparer
IConnection
ICustom
IDialog
@ -58,6 +66,8 @@ IObject
iosfwd
IPackage
IPeasant
isspace
ISetup
IStorage
istream
IStringable
@ -65,26 +75,40 @@ ITab
ITaskbar
IUri
IVirtual
KEYSELECT
LCID
llabs
llu
localtime
lround
LSHIFT
MENUCOMMAND
MENUDATA
MENUINFO
memicmp
mptt
mov
msappx
MULTIPLEUSE
NCHITTEST
NCLBUTTONDBLCLK
NCRBUTTONDBLCLK
NIF
NIN
NOAGGREGATION
NOASYNC
NOCHANGEDIR
NOPROGRESS
NOREDIRECTIONBITMAP
NOREPEAT
NOTIFYBYPOS
NOTIFYICON
NOTIFYICONDATA
ntprivapi
oaidl
ocidl
ODR
offsetof
osver
OSVERSIONINFOEXW
otms
@ -93,6 +117,7 @@ overridable
PAGESCROLL
PICKFOLDERS
pmr
rcx
REGCLS
RETURNCMD
rfind
@ -101,41 +126,54 @@ RSHIFT
schandle
semver
serializer
SETVERSION
SHELLEXECUTEINFOW
shobjidl
SHOWMINIMIZED
SHOWTIP
SINGLEUSE
SIZENS
smoothstep
snprintf
spsc
sregex
SRWLOC
SRWLOCK
STDCPP
STDMETHOD
strchr
strcpy
streambuf
strtoul
Stubless
Subheader
Subpage
syscall
TASKBARCREATED
TBPF
THEMECHANGED
tlg
tmp
tolower
toupper
TTask
TVal
UChar
UPDATEINIFILE
userenv
wcsstr
wcstoui
winmain
wmemcmp
wpc
wsregex
wwinmain
xchg
XDocument
XElement
xfacet
xhash
XIcon
xiosbase
xlocale
xlocbuf
@ -144,9 +182,13 @@ xlocmes
xlocmon
xlocnum
xloctime
XMax
xmemory
XParse
xpath
xstddef
xstring
xtree
xutility
YIcon
YMax

View file

@ -7,3 +7,4 @@ Iosevka
MDL
Monofur
Segoe
wght

View file

@ -1,3 +1,11 @@
atan
CPrime
HBar
HPrime
isnan
LPrime
LStep
powf
RSub
sqrtf
ULP

View file

@ -1,5 +1,6 @@
ACLs
ADMINS
advapi
altform
altforms
appendwttlogging
@ -7,6 +8,7 @@ appx
appxbundle
appxerror
appxmanifest
ATL
backplating
bitmaps
BOMs
@ -14,6 +16,7 @@ CPLs
cpptools
cppvsdbg
CPRs
cryptbase
DACL
DACLs
diffs
@ -23,14 +26,20 @@ DTDs
DWINRT
enablewttlogging
Intelli
IVisual
LKG
LOCKFILE
Lxss
mfcribbon
microsoft
microsoftonline
MSAA
msixbundle
MSVC
muxc
netcore
osgvsowi
PFILETIME
pgc
pgo
pgosweep
@ -38,10 +47,14 @@ powerrename
powershell
propkey
pscustomobject
QWORD
regedit
robocopy
SACLs
sdkddkver
Shobjidl
Skype
SRW
sxs
Sysinternals
sysnative
@ -56,6 +69,7 @@ Virtualization
visualstudio
vscode
VSTHRD
winsdkver
wlk
wslpath
wtl

View file

@ -31,6 +31,7 @@ Kourosh
kowalczyk
leonmsft
Lepilleur
lhecker
lukesampson
Manandhar
mbadolato
@ -52,6 +53,7 @@ oldnewthing
opengl
osgwiki
pabhojwa
panos
paulcam
pauldotknopf
PGP
@ -66,6 +68,7 @@ sonpham
stakx
thereses
Walisch
Wellons
Wirt
Wojciech
zadjii

View file

@ -2,10 +2,7 @@ AAAa
AAAAA
AAAAAAAAAAAAA
AAAAAABBBBBBCCC
AAAAABBBBBBBCCC
AAAAABBBBBBCCC
AAAAABCCCCCCCCC
AAAAADCCCCCCCCC
abcd
abcd
abcde

View file

@ -14,7 +14,6 @@ ACTIVEBORDER
ACTIVECAPTION
adaa
ADDALIAS
ADDB
ADDREF
addressof
ADDSTRING
@ -50,6 +49,7 @@ APARTMENTTHREADED
APCs
api
APIENTRY
apimswincoresynchl
apiset
APPBARDATA
appconsult
@ -105,6 +105,7 @@ autoscrolling
Autowrap
AVerify
AVI
AVX
awch
azuredevopspodcast
azzle
@ -114,6 +115,7 @@ Backgrounder
backgrounding
backport
backstory
barbaz
Batang
baz
Bazz
@ -163,9 +165,11 @@ BPBF
bpp
BPPF
branchconfig
brandings
BRK
Browsable
bsearch
Bspace
bstr
BTNFACE
buf
@ -183,12 +187,13 @@ bytebuffer
cac
cacafire
callee
cang
capslock
CARETBLINKINGENABLED
carlos
CARRIAGERETURN
cascadia
cassert
castsi
catid
cazamor
CBash
@ -267,9 +272,12 @@ cmder
CMDEXT
Cmdlet
cmdline
cmh
CMOUSEBUTTONS
cmp
cmpeq
cmt
cmw
cmyk
CNL
cnt
@ -379,6 +387,7 @@ cplusplus
cpp
CPPCORECHECK
cppcorecheckrules
cppm
cpprest
cpprestsdk
cppwinrt
@ -401,11 +410,13 @@ csbiex
csharp
CSHORT
CSIDL
Cspace
csproj
Csr
csrmsg
CSRSS
csrutil
css
cstdarg
cstddef
cstdio
@ -496,7 +507,6 @@ DEADCHAR
dealloc
Debian
debolden
debounce
debugtype
DECALN
DECANM
@ -505,6 +515,8 @@ DECAWM
DECCKM
DECCOLM
DECDHL
decdld
DECDLD
DECDWL
DECEKBD
DECID
@ -525,6 +537,7 @@ DECRC
DECREQTPARM
DECRLM
DECRQM
DECRQSS
DECRST
DECSASD
DECSC
@ -545,6 +558,7 @@ DECSTR
DECSWL
DECTCEM
Dedupe
deduplicate
deduplicated
DEFAPP
DEFAULTBACKGROUND
@ -654,6 +668,7 @@ dwriteglyphrundescriptionclustermap
dxgi
dxgidwm
dxinterop
dxsm
dxttbmp
eachother
eae
@ -757,7 +772,6 @@ filepath
FILESUBTYPE
FILESYSPATH
filesystem
FILETIME
FILETYPE
fileurl
FILEW
@ -773,11 +787,13 @@ FINDSTRINGEXACT
FINDUP
FIter
FIXEDCONVERTED
FIXEDFILEINFO
Flg
flyout
fmodern
fmtarg
fmtid
FNV
FOLDERID
FONTCHANGE
fontdlg
@ -786,6 +802,7 @@ FONTENUMPROC
FONTFACE
FONTFAMILY
FONTHEIGHT
FONTINFO
fontlist
FONTOK
FONTSIZE
@ -795,6 +812,7 @@ FONTTYPE
FONTWEIGHT
FONTWIDTH
FONTWINDOW
fooo
forceinline
FORCEOFFFEEDBACK
FORCEONFEEDBACK
@ -898,6 +916,7 @@ github
gitlab
gle
globals
GLYPHENTRY
gmail
GMEM
GNUC
@ -946,6 +965,7 @@ hdrstop
HEIGHTSCROLL
hfile
hfont
hfontresource
hglobal
hhh
HHmm
@ -981,7 +1001,7 @@ hostlib
Hostx
HPA
HPAINTBUFFER
hpcon
HPCON
hpj
hpp
HPR
@ -1020,6 +1040,7 @@ IAction
IApi
IApplication
IBase
ICache
icacls
iccex
icch
@ -1113,6 +1134,7 @@ interop
interoperability
inthread
intptr
intrin
intsafe
INVALIDARG
INVALIDATERECT
@ -1165,6 +1187,7 @@ IWin
IWindow
IXaml
IXMP
ixx
jconcpp
JOBOBJECT
JOBOBJECTINFOCLASS
@ -1209,6 +1232,7 @@ KLF
KLMNO
KLMNOPQRST
KLMNOPQRSTQQQQQ
KPRIORITY
KVM
langid
LANGUAGELIST
@ -1257,6 +1281,7 @@ lnkd
lnkfile
LNM
LOADONCALL
loadu
LOBYTE
localappdata
localhost
@ -1264,6 +1289,7 @@ locsrc
locstudio
Loewen
LOGFONT
LOGFONTA
LOGFONTW
logissue
lowercased
@ -1368,7 +1394,6 @@ MEASUREITEM
megamix
memallocator
memcmp
memcopy
memcpy
memmove
memset
@ -1418,6 +1443,7 @@ MOUSEFIRST
MOUSEHWHEEL
MOUSEMOVE
mousewheel
movemask
MOVESTART
msb
msbuild
@ -1444,11 +1470,13 @@ MSVCRTD
MSVS
msys
msysgit
MTSM
mui
Mul
multiline
munged
munges
murmurhash
mutex
mutexes
muxes
@ -1499,6 +1527,7 @@ nfe
nlength
Nls
NLSMODE
nnn
NOACTIVATE
NOAPPLYNOW
NOCLIP
@ -1579,6 +1608,7 @@ NTVDM
ntverp
NTWIN
nuget
nullability
nullness
nullonfailure
nullopt
@ -1613,6 +1643,7 @@ onecoreuapuuid
onecoreuuid
ONECOREWINDOWS
onehalf
oneseq
ONLCR
openbash
opencode
@ -1643,6 +1674,7 @@ oss
ostream
ostringstream
ouicompat
OUnter
outdir
outfile
Outof
@ -1653,6 +1685,7 @@ Outptr
OVERLAPPEDWINDOW
OWNDC
OWNERDRAWFIXED
packagename
packageuwp
PACKCOORD
PACKVERSION
@ -1677,6 +1710,7 @@ pcch
PCCHAR
PCCONSOLE
PCD
pcg
pch
PCHAR
PCIDLIST
@ -1772,6 +1806,7 @@ POSX
POSXSCROLL
POSYSCROLL
ppci
PPEB
ppf
ppguid
ppidl
@ -1922,6 +1957,7 @@ realloc
reamapping
rects
redef
redefinable
Redir
redirector
redist
@ -1943,7 +1979,7 @@ REGSTR
reingest
Relayout
RELBINPATH
Remoting
remoting
renamer
renderengine
rendersize
@ -1964,11 +2000,12 @@ resx
retval
rfa
rfc
rfid
rftp
rgb
rgba
RGBCOLOR
rgbi
rgch
rgci
rgfae
rgfte
@ -1985,9 +2022,11 @@ rhs
RIGHTALIGN
RIGHTBUTTON
riid
Rike
RIPMSG
RIS
RMENU
rng
roadmap
robomac
roundtrip
@ -2033,7 +2072,6 @@ scanline
schemename
SCL
scm
scprintf
SCRBUF
SCRBUFSIZE
screenbuffer
@ -2044,8 +2082,6 @@ scriptload
Scrollable
scrollback
scrollbar
Scrolldown
Scrolldownpage
Scroller
SCROLLFORWARD
SCROLLINFO
@ -2053,8 +2089,6 @@ scrolllock
scrolloffset
SCROLLSCALE
SCROLLSCREENBUFFER
Scrollup
Scrolluppage
scursor
sddl
sdeleted
@ -2069,8 +2103,7 @@ selectany
SELECTEDFONT
SELECTSTRING
Selfhosters
serializer
serializers
SERIALIZERS
SERVERDLL
SETACTIVE
SETBUDDYINT
@ -2142,6 +2175,7 @@ SIGDN
SINGLEFLAG
SINGLETHREADED
siup
sixel
SIZEBOX
sizeof
SIZESCROLL
@ -2213,6 +2247,7 @@ stoi
stol
stoul
stoutapot
Stri
strikethrough
stringstream
STRINGTABLE
@ -2245,6 +2280,7 @@ SWMR
SWP
swprintf
SYMED
symlink
SYNCPAINT
sys
syscalls
@ -2311,7 +2347,6 @@ testmddefinition
testmode
testname
testnameprefix
testnetv
TESTNULL
testpass
testpasses
@ -2347,7 +2382,6 @@ TITLEISLINKNAME
TJson
TLambda
TLEN
Tlg
Tlgdata
TMAE
TMPF
@ -2422,7 +2456,6 @@ uapadmin
UAX
ubuntu
ucd
ucd
ucdxml
uch
UCHAR
@ -2531,6 +2564,7 @@ vcvarsall
vcxitems
vcxproj
vec
vectorized
VERCTRL
versioning
VERTBAR
@ -2548,13 +2582,13 @@ VMs
VPA
VPATH
VPR
VPrintf
VProc
VRaw
VREDRAW
vsc
vscprintf
VSCROLL
vsdevshell
vsinfo
vsnprintf
vso
@ -2663,6 +2697,7 @@ WINDOWPOSCHANGING
windowproc
windowrect
windowsapp
windowsdeveloper
windowsinternalstring
WINDOWSIZE
windowsx
@ -2694,6 +2729,7 @@ wixproj
wline
wlinestream
wmain
wmemory
WMSZ
wnd
WNDALLOC
@ -2749,6 +2785,7 @@ WTo
wtof
wtoi
WTs
WTSOFTFONT
wtw
wtypes
Wubi
@ -2775,10 +2812,10 @@ XCount
xdy
XEncoding
xes
Xes
xff
XFile
XFORM
xIcon
XManifest
XMath
XMFLOAT
@ -2786,8 +2823,6 @@ xml
xmlns
xor
xorg
xorg
Xpath
XPosition
XResource
xsd
@ -2813,6 +2848,7 @@ YCast
YCENTER
YCount
YDPI
yIcon
yml
YOffset
YPosition
@ -2820,6 +2856,7 @@ YSize
YSubstantial
YVIRTUALSCREEN
YWalk
zamora
ZCmd
ZCtrl
zsh

View file

@ -1,5 +1,7 @@
http
www
easyrgb
php
ecma
rapidtables
WCAG
@ -11,6 +13,7 @@ leonerd
fixterms
winui
appshellintegration
mdtauk
cppreference
gfycat
Guake

View file

@ -23,3 +23,5 @@ VERIFY_ARE_EQUAL\(L"[^"]+"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
std::memory_order_[\w]+
D2DERR_SHADER_COMPILE_FAILED
TIL_FEATURE_[0-9A-Z_]+
vcvars\w*

View file

@ -1,19 +1,20 @@
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
name: Spell checking
on:
pull_request_target:
push:
jobs:
build:
spelling:
name: Spell checking
runs-on: ubuntu-latest
steps:
- name: checkout-merge
if: "contains(github.event_name, 'pull_request')"
uses: actions/checkout@v2.0.0
uses: actions/checkout@v2
with:
ref: refs/pull/${{github.event.pull_request.number}}/merge
- name: checkout
if: "!contains(github.event_name, 'pull_request')"
uses: actions/checkout@v2.0.0
- uses: check-spelling/check-spelling@v0.0.18
uses: actions/checkout@v2
- uses: check-spelling/check-spelling@v0.0.19

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

@ -19,6 +19,7 @@
"/.github/",
"/samples/",
"/res/terminal/",
"/res/fonts/",
"/doc/specs/",
"/doc/cascadia/",
"/doc/user-docs/",

View file

@ -191,6 +191,7 @@
"find",
"findMatch",
"focusPane",
"globalSummon",
"identifyWindow",
"identifyWindows",
"moveFocus",
@ -206,6 +207,7 @@
"prevTab",
"renameTab",
"openTabRenamer",
"quakeMode",
"resetFontSize",
"resizePane",
"renameWindow",
@ -544,12 +546,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"
]
}
}
@ -817,6 +821,63 @@
}
]
},
"GlobalSummonAction": {
"description": "This is a special action that works globally in the OS, rather than only in the context of the terminal window. When pressed, this action will summon the terminal window.",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "globalSummon" },
"desktop": {
"type": "string",
"default": "toCurrent",
"description": "This controls how the terminal should interact with virtual desktops.\n- \"any\": Leave the window on whichever desktop it's already on - will switch to that desktop as the window is activated.\n- \"toCurrent\" (default): Move the window to the current virtual desktop.\n- \"onCurrent\": Only summon the window if it's already on the current virtual desktop. ",
"enum": [
"any",
"toCurrent",
"onCurrent"
]
},
"monitor": {
"type": "string",
"default": "toMouse",
"description": "This controls the monitor that the window will be summoned from/to.\n- \"any\": Summon the most recently used window, regardless of which monitor it's currently on.\n- \"toCurrent\": Summon the most recently used window to the monitor with the current foreground window.\n- \"toMouse\" (default): Summon the most recently used window to the monitor where the mouse cursor is.",
"enum": [
"any",
"toCurrent",
"toMouse"
]
},
"name": {
"type": "string",
"description": "When provided, summon the window whose name or ID matches the given name value. If no such window exists, then create a new window with that name."
},
"dropdownDuration": {
"type": "number",
"minimum": 0,
"default": 0,
"description": "When provided with a positive number, \"slide\" the window in from the top of the screen using an animation that lasts dropdownDuration milliseconds."
},
"toggleVisibility": {
"type": "boolean",
"default": true,
"description": "When true, pressing the assigned keys for this action will dismiss (minimize) the window when the window is currently the foreground window."
}
}
}
]
},
"QuakeModeAction": {
"description": "This action is a special variation of the globalSummon action. It specifically summons a window called \"_quake\". If you would like to change the behavior of the quakeMode action, we recommended creating a new globalSummon entry.",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "quakeMode" }
}
}
]
},
"Keybinding": {
"additionalProperties": false,
"properties": {
@ -848,6 +909,8 @@
{ "$ref": "#/definitions/RenameTabAction" },
{ "$ref": "#/definitions/RenameWindowAction" },
{ "$ref": "#/definitions/FocusPaneAction" },
{ "$ref": "#/definitions/GlobalSummonAction" },
{ "$ref": "#/definitions/QuakeModeAction" },
{ "type": "null" }
]
},
@ -868,16 +931,38 @@
},
"icon": { "$ref": "#/definitions/Icon" },
"name": {
"description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.",
"description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.\nIf name is a string, it will be the name of the command.\nIf name is a object, the key property of the object will be used to lookup a localized string resource for the command",
"properties": {
"key": {
"type": "string"
}
},
"type": [
"string",
"object",
"null"
]
},
"iterateOn": {
"type": "string",
"description": "Used to create iterable commands based on other objects in your settings. Possible values:\n- \"profiles\" \n- \"schemes\"",
"enum": [
"profiles",
"schemes"
]
},
"commands": {
"description": "List of commands to execute",
"items": {
"$ref": "#/definitions/Keybinding/properties/command"
},
"minItems": 1,
"type": "array"
}
},
"required": [
"command",
"keys"
"anyOf": [
{"required": ["name","commands"]},
{"required": ["command"]}
],
"type": "object"
},
@ -1011,8 +1096,16 @@
"type": [ "integer", "string" ],
"deprecated": true
},
"actions": {
"description": "Properties are specific to each custom action.",
"items": {
"$ref": "#/definitions/Keybinding"
},
"type": "array"
},
"keybindings": {
"description": "Properties are specific to each custom key binding.",
"description": "[deprecated] Use actions instead.",
"deprecated": true,
"items": {
"$ref": "#/definitions/Keybinding"
},

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

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

@ -140,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

@ -140,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

@ -647,10 +647,12 @@ namespace SettingsModelLocalTests
const std::string bindings0String{ R"([ { "command": "closeWindow", "keys": "ctrl+a" } ])" };
const std::string bindings1String{ R"([ { "command": { "action": "copy", "singleLine": true }, "keys": "ctrl+b" } ])" };
const std::string bindings2String{ R"([ { "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+c" } ])" };
const std::string bindings3String{ R"([ { "command": "commandPalette", "keys": "ctrl+shift+p" } ])" };
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
const auto bindings1Json = VerifyParseSucceeded(bindings1String);
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
const auto bindings3Json = VerifyParseSucceeded(bindings3String);
auto VerifyKeyChordEquality = [](const KeyChord& expected, const KeyChord& actual) {
if (expected)
@ -699,5 +701,13 @@ namespace SettingsModelLocalTests
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::NewTab, *args) };
VerifyKeyChordEquality({ KeyModifiers::Ctrl, static_cast<int32_t>('C') }, kbd);
}
{
Log::Comment(L"command with hidden args");
actionMap->LayerJson(bindings3Json);
VERIFY_ARE_EQUAL(4u, actionMap->_KeyMap.size());
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::ToggleCommandPalette) };
VerifyKeyChordEquality({ KeyModifiers::Ctrl | KeyModifiers::Shift, static_cast<int32_t>('P') }, kbd);
}
}
}

View file

@ -229,10 +229,12 @@ namespace SettingsModelLocalTests
void SerializationTests::Actions()
{
// simple command
const std::string actionsString1{ R"([
{ "command": "paste" }
])" };
// complex command
const std::string actionsString2A{ R"([
{ "command": { "action": "setTabColor" } }
])" };
@ -244,29 +246,35 @@ namespace SettingsModelLocalTests
{ "command": { "action": "copy", "singleLine": true, "copyFormatting": "html" } }
])" };
// simple command with key chords
const std::string actionsString3{ R"([
{ "command": "toggleAlwaysOnTop", "keys": "ctrl+a" },
{ "command": "toggleAlwaysOnTop", "keys": "ctrl+b" }
])" };
// complex command with key chords
const std::string actionsString4{ R"([
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+c" },
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+d" }
])" };
// command with name and icon and multiple key chords
const std::string actionsString5{ R"([
{ "icon": "image.png", "name": "Scroll To Top Name", "command": "scrollToTop", "keys": "ctrl+e" },
{ "command": "scrollToTop", "keys": "ctrl+f" }
])" };
// complex command with new terminal args
const std::string actionsString6{ R"([
{ "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+g" },
])" };
// complex command with meaningful null arg
const std::string actionsString7{ R"([
{ "command": { "action": "renameWindow", "name": null }, "keys": "ctrl+h" }
])" };
// nested command
const std::string actionsString8{ R"([
{
"name": "Change font size...",
@ -278,6 +286,7 @@ namespace SettingsModelLocalTests
}
])" };
// iterable command
const std::string actionsString9A{ R"([
{
"name": "New tab",
@ -330,7 +339,20 @@ namespace SettingsModelLocalTests
"name": "Send Input (Evil) ..."
}
])"" };
const std::string actionsString9D{ R""([
{
"command":
{
"action": "newTab",
"profile": "${profile.name}"
},
"icon": "${profile.icon}",
"iterateOn": "profiles",
"name": "${profile.name}: New tab"
}
])"" };
// unbound command
const std::string actionsString10{ R"([
{ "command": "unbound", "keys": "ctrl+c" }
])" };
@ -365,6 +387,7 @@ namespace SettingsModelLocalTests
RoundtripTest<implementation::ActionMap>(actionsString9A);
RoundtripTest<implementation::ActionMap>(actionsString9B);
RoundtripTest<implementation::ActionMap>(actionsString9C);
RoundtripTest<implementation::ActionMap>(actionsString9D);
Log::Comment(L"unbound command");
RoundtripTest<implementation::ActionMap>(actionsString10);

View file

@ -97,6 +97,6 @@
<!-- We actually can just straight up reference MUX here, it's fine -->
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
</Project>

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

@ -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
@ -56,16 +56,17 @@ HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
// Append a "\." to the given path, so that this will work in "C:\"
auto cmdline{ wil::str_printf<std::wstring>(LR"-("%s" -d "%s\.")-", GetWtExePath().c_str(), pszName.get()) };
auto path{ wil::str_printf<std::wstring>(LR"-(%s\.)-", pszName.get()) };
auto cmdline{ wil::str_printf<std::wstring>(LR"-("%s" -d "%s")-", GetWtExePath().c_str(), path.c_str()) };
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
nullptr,
nullptr, // lpApplicationName
cmdline.data(),
nullptr, // lpProcessAttributes
nullptr, // lpThreadAttributes
false, // bInheritHandles
EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
nullptr, // lpEnvironment
nullptr,
path.data(),
&siEx.StartupInfo, // lpStartupInfo
&_piClient // lpProcessInformation
));
@ -87,8 +88,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

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

@ -306,7 +306,7 @@ namespace winrt::TerminalApp::implementation
});
_root->Create();
_ApplyTheme(_settings.GlobalSettings().Theme());
_RefreshThemeRoutine();
_ApplyStartupTaskStateChange();
TraceLoggingWrite(
@ -895,36 +895,25 @@ namespace winrt::TerminalApp::implementation
// this stops us from reloading too many times or too quickly.
fire_and_forget AppLogic::_DispatchReloadSettings()
{
static constexpr auto FileActivityQuiesceTime{ std::chrono::milliseconds(50) };
if (!_settingsReloadQueued.exchange(true))
if (_settingsReloadQueued.exchange(true))
{
co_return;
}
auto weakSelf = get_weak();
co_await winrt::resume_after(std::chrono::milliseconds(100));
co_await winrt::resume_foreground(_root->Dispatcher());
if (auto self{ weakSelf.get() })
{
co_await winrt::resume_after(FileActivityQuiesceTime);
_ReloadSettings();
_settingsReloadQueued.store(false);
}
}
fire_and_forget AppLogic::_LoadErrorsDialogRoutine()
void AppLogic::_RefreshThemeRoutine()
{
co_await winrt::resume_foreground(_root->Dispatcher());
const winrt::hstring titleKey = USES_RESOURCE(L"ReloadJsonParseErrorTitle");
const winrt::hstring textKey = USES_RESOURCE(L"ReloadJsonParseErrorText");
_ShowLoadErrorsDialog(titleKey, textKey, _settingsLoadedResult);
}
fire_and_forget AppLogic::_ShowLoadWarningsDialogRoutine()
{
co_await winrt::resume_foreground(_root->Dispatcher());
_ShowLoadWarningsDialog();
}
fire_and_forget AppLogic::_RefreshThemeRoutine()
{
co_await winrt::resume_foreground(_root->Dispatcher());
// Refresh the UI theme
_ApplyTheme(_settings.GlobalSettings().Theme());
}
@ -959,39 +948,26 @@ namespace winrt::TerminalApp::implementation
return;
}
auto weakThis{ get_weak() };
co_await winrt::resume_foreground(_root->Dispatcher(), CoreDispatcherPriority::Normal);
if (auto page{ weakThis.get() })
{
StartupTaskState state;
bool tryEnableStartupTask = _settings.GlobalSettings().StartOnUserLogin();
StartupTask task = co_await StartupTask::GetAsync(StartupTaskName);
const auto tryEnableStartupTask = _settings.GlobalSettings().StartOnUserLogin();
const auto task = co_await StartupTask::GetAsync(StartupTaskName);
state = task.State();
switch (state)
switch (task.State())
{
case StartupTaskState::Disabled:
if (tryEnableStartupTask)
{
case StartupTaskState::Disabled:
co_await task.RequestEnableAsync();
}
break;
case StartupTaskState::DisabledByUser:
// TODO: GH#6254: define UX for other StartupTaskStates
break;
case StartupTaskState::Enabled:
if (!tryEnableStartupTask)
{
if (tryEnableStartupTask)
{
co_await task.RequestEnableAsync();
}
break;
}
case StartupTaskState::DisabledByUser:
{
// TODO: GH#6254: define UX for other StartupTaskStates
break;
}
case StartupTaskState::Enabled:
{
if (!tryEnableStartupTask)
{
task.Disable();
}
break;
}
task.Disable();
}
break;
}
}
CATCH_LOG();
@ -1009,12 +985,15 @@ namespace winrt::TerminalApp::implementation
if (FAILED(_settingsLoadedResult))
{
_LoadErrorsDialogRoutine();
const winrt::hstring titleKey = USES_RESOURCE(L"ReloadJsonParseErrorTitle");
const winrt::hstring textKey = USES_RESOURCE(L"ReloadJsonParseErrorText");
_ShowLoadErrorsDialog(titleKey, textKey, _settingsLoadedResult);
return;
}
else if (_settingsLoadedResult == S_FALSE)
if (_settingsLoadedResult == S_FALSE)
{
_ShowLoadWarningsDialogRoutine();
_ShowLoadWarningsDialog();
}
// Here, we successfully reloaded the settings, and created a new
@ -1206,7 +1185,7 @@ namespace winrt::TerminalApp::implementation
// in and be routed to an event with no handlers or a non-ready Page.
if (_appArgs.IsHandoffListener())
{
SetInboundListener();
_root->SetInboundListener(true);
}
}
@ -1222,7 +1201,7 @@ namespace winrt::TerminalApp::implementation
// - <none>
void AppLogic::SetInboundListener()
{
_root->SetInboundListener();
_root->SetInboundListener(false);
}
// Method Description:

View file

@ -124,18 +124,14 @@ namespace winrt::TerminalApp::implementation
::TerminalApp::AppCommandlineArgs _appArgs;
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
int _ParseArgs(winrt::array_view<const hstring>& args);
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();
bool _IsKeyboardServiceEnabled();
void _ShowKeyboardServiceDisabledDialog();
fire_and_forget _LoadErrorsDialogRoutine();
fire_and_forget _ShowLoadWarningsDialogRoutine();
fire_and_forget _RefreshThemeRoutine();
void _RefreshThemeRoutine();
fire_and_forget _ApplyStartupTaskStateChange();
void _OnLoaded(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
@ -165,6 +161,7 @@ namespace winrt::TerminalApp::implementation
FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested);
FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested);
FORWARDED_TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IsQuakeWindowChanged);
FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested);
#ifdef UNIT_TESTING
friend class TerminalAppLocalTests::CommandlineTest;

View file

@ -92,5 +92,6 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> SettingsChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
}
}

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;
@ -317,6 +318,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);
@ -509,6 +517,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();
@ -635,7 +644,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

View file

@ -329,6 +329,7 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
}
const auto newConnectionState = _control.ConnectionState();
const auto previousConnectionState = std::exchange(_connectionState, newConnectionState);
if (newConnectionState < ConnectionState::Closed)
{
@ -336,6 +337,14 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
return;
}
if (previousConnectionState < ConnectionState::Connected && newConnectionState >= ConnectionState::Failed)
{
// A failure to complete the connection (before it has _connected_) is not covered by "closeOnExit".
// This is to prevent a misconfiguration (closeOnExit: always, startingDirectory: garbage) resulting
// in Terminal flashing open and immediately closed.
return;
}
const auto settings{ winrt::TerminalApp::implementation::AppLogic::CurrentAppSettings() };
auto paneProfile = settings.FindProfile(_profile.value());
if (paneProfile)
@ -709,6 +718,7 @@ void Pane::_CloseChild(const bool closeFirst)
// take the control, profile and id of the pane that _wasn't_ closed.
_control = remainingChild->_control;
_connectionState = remainingChild->_connectionState;
_profile = remainingChild->_profile;
_id = remainingChild->Id();
@ -1476,6 +1486,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
// Move our control, guid into the first one.
// Move the new guid, control into the second.
_firstChild = std::make_shared<Pane>(_profile.value(), _control);
_firstChild->_connectionState = std::exchange(_connectionState, ConnectionState::NotConnected);
_profile = std::nullopt;
_control = { nullptr };
_secondChild = std::make_shared<Pane>(profile, control);

View file

@ -95,6 +95,7 @@ private:
winrt::Windows::UI::Xaml::Controls::Grid _root{};
winrt::Windows::UI::Xaml::Controls::Border _border{};
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_focusedBorderBrush;
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_unfocusedBorderBrush;

View file

@ -634,4 +634,16 @@
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Restore Down</value>
</data>
</root>
<data name="ShellExtension_OpenInTerminalMenuItem_Dev" xml:space="preserve">
<value>Open in Windows Terminal (Dev)</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Preview" xml:space="preserve">
<value>Open in Windows Terminal Preview</value>
<comment>{Locked="Windows"} This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem" xml:space="preserve">
<value>Open in Windows Terminal</value>
<comment>{Locked="Windows"} This is a menu item that will be displayed in the Windows File Explorer that launches the non-preview version of Windows Terminal</comment>
</data>
</root>

View file

@ -19,7 +19,7 @@
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<ItemDefinitionGroup>
<ClCompile>
@ -372,13 +372,13 @@
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
<!--

View file

@ -92,31 +92,26 @@ namespace winrt::TerminalApp::implementation
}
}
winrt::fire_and_forget TerminalPage::SetSettings(CascadiaSettings settings, bool needRefreshUI)
void TerminalPage::SetSettings(CascadiaSettings settings, bool needRefreshUI)
{
_settings = settings;
auto weakThis{ get_weak() };
co_await winrt::resume_foreground(Dispatcher());
if (auto page{ weakThis.get() })
// Make sure to _UpdateCommandsForPalette before
// _RefreshUIForSettingsReload. _UpdateCommandsForPalette will make
// sure the KeyChordText of Commands is updated, which needs to
// happen before the Settings UI is reloaded and tries to re-read
// those values.
_UpdateCommandsForPalette();
CommandPalette().SetActionMap(_settings.ActionMap());
if (needRefreshUI)
{
// Make sure to _UpdateCommandsForPalette before
// _RefreshUIForSettingsReload. _UpdateCommandsForPalette will make
// sure the KeyChordText of Commands is updated, which needs to
// happen before the Settings UI is reloaded and tries to re-read
// those values.
_UpdateCommandsForPalette();
CommandPalette().SetActionMap(_settings.ActionMap());
if (needRefreshUI)
{
_RefreshUIForSettingsReload();
}
// Upon settings update we reload the system settings for scrolling as well.
// TODO: consider reloading this value periodically.
_systemRowsToScroll = _ReadSystemRowsToScroll();
_RefreshUIForSettingsReload();
}
// Upon settings update we reload the system settings for scrolling as well.
// TODO: consider reloading this value periodically.
_systemRowsToScroll = _ReadSystemRowsToScroll();
}
void TerminalPage::Create()
@ -356,7 +351,27 @@ namespace winrt::TerminalApp::implementation
// we would be left with an empty terminal frame with no tabs.
// Instead, crash out so COM sees the server die and things unwind
// without a weird empty frame window.
CATCH_FAIL_FAST()
catch (...)
{
// However, we cannot always fail fast because of MSFT:33501832. Sometimes the COM catalog
// tears the state between old and new versions and fails here for that reason.
// As we're always becoming an inbound server in the monarch, even when COM didn't strictly
// ask us yet...we might just crash always.
// Instead... we're going to differentiate. If COM started us... we will fail fast
// so it sees the process die and falls back.
// If we were just starting normally as a Monarch and opportunistically listening for
// inbound connections... then we'll just log the failure and move on assuming
// the version state is torn and will fix itself whenever the packaging upgrade
// tasks decide to clean up.
if (_isEmbeddingInboundListener)
{
FAIL_FAST_CAUGHT_EXCEPTION();
}
else
{
LOG_CAUGHT_EXCEPTION();
}
}
}
}
@ -1810,7 +1825,7 @@ namespace winrt::TerminalApp::implementation
// This includes update the settings of all the tabs according
// to their profiles, update the title and icon of each tab, and
// finally create the tab flyout
winrt::fire_and_forget TerminalPage::_RefreshUIForSettingsReload()
void TerminalPage::_RefreshUIForSettingsReload()
{
// Re-wire the keybindings to their handlers, as we'll have created a
// new AppKeyBindings object.
@ -1865,17 +1880,10 @@ namespace winrt::TerminalApp::implementation
tabImpl->SetActionMap(_settings.ActionMap());
}
auto weakThis{ get_weak() };
co_await winrt::resume_foreground(Dispatcher());
// repopulate the new tab button's flyout with entries for each
// profile, which might have changed
if (auto page{ weakThis.get() })
{
_UpdateTabWidthMode();
_CreateNewTabFlyout();
}
_UpdateTabWidthMode();
_CreateNewTabFlyout();
// Reload the current value of alwaysOnTop from the settings file. This
// will let the user hot-reload this setting, but any runtime changes to
@ -1981,12 +1989,13 @@ namespace winrt::TerminalApp::implementation
// listener for command-line tools attempting to join this Terminal
// through the default application channel.
// Arguments:
// - <none> - Implicitly sets to true. Default page state is false.
// - isEmbedding - True if COM started us to be a server. False if we're doing it of our own accord.
// Return Value:
// - <none>
void TerminalPage::SetInboundListener()
void TerminalPage::SetInboundListener(bool isEmbedding)
{
_shouldStartInboundListener = true;
_isEmbeddingInboundListener = isEmbedding;
// If the page has already passed the NotInitialized state,
// then it is ready-enough for us to just start this immediately.
@ -2319,6 +2328,9 @@ namespace winrt::TerminalApp::implementation
{
// TODO: GH 9458 will give us more context so we can try to choose a better profile.
_OpenNewTab(nullptr, connection);
// Request a summon of this window to the foreground
_SummonWindowRequestedHandlers(*this, nullptr);
}
// Method Description:

View file

@ -54,7 +54,7 @@ namespace winrt::TerminalApp::implementation
// put it in our inheritance graph. https://github.com/microsoft/microsoft-ui-xaml/issues/3331
STDMETHODIMP Initialize(HWND hwnd);
winrt::fire_and_forget SetSettings(Microsoft::Terminal::Settings::Model::CascadiaSettings settings, bool needRefreshUI);
void SetSettings(Microsoft::Terminal::Settings::Model::CascadiaSettings settings, bool needRefreshUI);
void Create();
@ -67,8 +67,6 @@ namespace winrt::TerminalApp::implementation
winrt::hstring ApplicationDisplayName();
winrt::hstring ApplicationVersion();
winrt::hstring ThirdPartyNoticesLink();
winrt::fire_and_forget CloseWindow();
void ToggleFocusMode();
@ -79,7 +77,7 @@ namespace winrt::TerminalApp::implementation
bool AlwaysOnTop() const;
void SetStartupActions(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>& actions);
void SetInboundListener();
void SetInboundListener(bool isEmbedding);
static std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> ConvertExecuteCommandlineToActions(const Microsoft::Terminal::Settings::Model::ExecuteCommandlineArgs& args);
winrt::TerminalApp::IDialogPresenter DialogPresenter() const;
@ -124,6 +122,7 @@ namespace winrt::TerminalApp::implementation
TYPED_EVENT(IdentifyWindowsRequested, IInspectable, IInspectable);
TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs);
TYPED_EVENT(IsQuakeWindowChanged, IInspectable, IInspectable);
TYPED_EVENT(SummonWindowRequested, IInspectable, IInspectable);
private:
friend struct TerminalPageT<TerminalPage>; // for Xaml to bind events
@ -174,6 +173,7 @@ namespace winrt::TerminalApp::implementation
Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> _startupActions;
bool _shouldStartInboundListener{ false };
bool _isEmbeddingInboundListener{ false };
std::shared_ptr<Toast> _windowIdToast{ nullptr };
std::shared_ptr<Toast> _windowRenameFailedToast{ nullptr };
@ -294,7 +294,7 @@ namespace winrt::TerminalApp::implementation
winrt::Microsoft::Terminal::Control::TermControl _InitControl(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection);
winrt::fire_and_forget _RefreshUIForSettingsReload();
void _RefreshUIForSettingsReload();
void _SetNonClientAreaColors(const Windows::UI::Color& selectedTabColor);
void _ClearNonClientAreaColors();

View file

@ -56,5 +56,6 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
}
}

View file

@ -14,7 +14,7 @@
</PropertyGroup>
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- DON'T PUT XAML FILES HERE! Put them in TerminalAppLib.vcxproj -->
@ -90,13 +90,13 @@
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
<ItemDefinitionGroup>

View file

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

View file

@ -6,7 +6,6 @@
#include "ConptyConnection.h"
#include <windows.h>
#include <userenv.h>
#include "ConptyConnection.g.cpp"
#include "CTerminalHandoff.h"
@ -95,11 +94,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
environment.clear();
});
{
const auto newEnvironmentBlock{ Utils::CreateEnvironmentBlock() };
// Populate the environment map with the current environment.
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment, newEnvironmentBlock.get()));
}
// Populate the environment map with the current environment.
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment));
{
// Convert connection Guid to string and ignore the enclosing '{}'.
@ -251,6 +247,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void ConptyConnection::Start()
try
{
_transitionToState(ConnectionState::Connecting);
if (!_inPipe)
{
const COORD dimensions{ gsl::narrow_cast<SHORT>(_initialCols), gsl::narrow_cast<SHORT>(_initialRows) };

View file

@ -1126,6 +1126,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
if (_renderEngine)
{
auto lock = _terminal->LockForWriting();
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(opacity));
}
}

View file

@ -23,7 +23,6 @@
#include "../../cascadia/TerminalCore/Terminal.hpp"
#include "../buffer/out/search.h"
#include "cppwinrt_utils.h"
#include "ThrottledFunc.h"
namespace ControlUnitTests
{

View file

@ -48,9 +48,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
TermControl::TermControl(IControlSettings settings,
TerminalConnection::ITerminalConnection connection) :
_initializedTerminal{ false },
_settings{ settings },
_closing{ false },
_isInternalScrollBarUpdate{ false },
_autoScrollVelocity{ 0 },
_autoScrollingPointerPoint{ std::nullopt },
@ -58,8 +56,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_lastAutoScrollUpdateTime{ std::nullopt },
_cursorTimer{},
_blinkTimer{},
_searchBox{ nullptr },
_bellLightAnimation{ Window::Current().Compositor().CreateScalarKeyFrameAnimation() }
_searchBox{ nullptr }
{
InitializeComponent();
@ -111,11 +108,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Core eventually won't have access to. When we get to
// https://github.com/microsoft/terminal/projects/5#card-50760282
// then we'll move the applicable ones.
//
// These four throttled functions are triggered by terminal output and interact with the UI.
// Since Close() is the point after which we are removed from the UI, but before the
// destructor has run, we MUST check control->_IsClosing() before actually doing anything.
_tsfTryRedrawCanvas = std::make_shared<ThrottledFuncTrailing<>>(
Dispatcher(),
TsfRedrawInterval,
[weakThis = get_weak()]() {
if (auto control{ weakThis.get() })
if (auto control{ weakThis.get() }; !control->_IsClosing())
{
control->TSFInputControl().TryRedrawCanvas();
}
@ -125,7 +126,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Dispatcher(),
UpdatePatternLocationsInterval,
[weakThis = get_weak()]() {
if (auto control{ weakThis.get() })
if (auto control{ weakThis.get() }; !control->_IsClosing())
{
control->_core->UpdatePatternLocations();
}
@ -135,7 +136,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Dispatcher(),
TerminalWarningBellInterval,
[weakThis = get_weak()]() {
if (auto control{ weakThis.get() })
if (auto control{ weakThis.get() }; !control->_IsClosing())
{
control->_WarningBellHandlers(*control, nullptr);
}
@ -145,14 +146,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Dispatcher(),
ScrollBarUpdateInterval,
[weakThis = get_weak()](const auto& update) {
if (auto control{ weakThis.get() })
if (auto control{ weakThis.get() }; !control->_IsClosing())
{
control->_isInternalScrollBarUpdate = true;
auto scrollBar = control->ScrollBar();
if (update.newValue.has_value())
if (update.newValue)
{
scrollBar.Value(update.newValue.value());
scrollBar.Value(*update.newValue);
}
scrollBar.Maximum(update.newMaximum);
scrollBar.Minimum(update.newMinimum);
@ -168,11 +169,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
_autoScrollTimer.Tick({ this, &TermControl::_UpdateAutoScroll });
// Add key frames and a duration to our bell light animation
_bellLightAnimation.InsertKeyFrame(0.0, 2.0);
_bellLightAnimation.InsertKeyFrame(1.0, 1.0);
_bellLightAnimation.Duration(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(TerminalWarningBellInterval)));
_ApplyUISettings(_settings);
}
@ -211,7 +207,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::SearchMatch(const bool goForward)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -302,7 +298,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - newSettings: the new settings to set
void TermControl::_UpdateSettingsFromUIThread(IControlSettings newSettings)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -320,7 +316,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - newAppearance: the new appearance to set
void TermControl::_UpdateAppearanceFromUIThread(IControlAppearance newAppearance)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -533,7 +529,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Windows::UI::Xaml::Automation::Peers::AutomationPeer TermControl::OnCreateAutomationPeer()
try
{
if (_initializedTerminal && !_closing) // only set up the automation peer if we're ready to go live
if (_initializedTerminal && !_IsClosing()) // only set up the automation peer if we're ready to go live
{
// create a custom automation peer with this code pattern:
// (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers)
@ -753,7 +749,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_CharacterHandler(winrt::Windows::Foundation::IInspectable const& /*sender*/,
Input::CharacterReceivedRoutedEventArgs const& e)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -851,7 +847,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// win32-input-mode, then we'll send all these keystrokes to the
// terminal - it's smart enough to ignore the keys it doesn't care
// about.
if (_closing ||
if (_IsClosing() ||
e.OriginalKey() == VirtualKey::LeftWindows ||
e.OriginalKey() == VirtualKey::RightWindows)
@ -1003,12 +999,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
keyDown) :
true;
if (_cursorTimer.has_value())
if (_cursorTimer)
{
// Manually show the cursor when a key is pressed. Restarting
// the timer prevents flickering.
_core->CursorOn(true);
_cursorTimer.value().Start();
_cursorTimer->Start();
}
return handled;
@ -1033,7 +1029,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_PointerPressedHandler(Windows::Foundation::IInspectable const& sender,
Input::PointerRoutedEventArgs const& args)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -1084,7 +1080,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_PointerMovedHandler(Windows::Foundation::IInspectable const& /*sender*/,
Input::PointerRoutedEventArgs const& args)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -1157,7 +1153,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_PointerReleasedHandler(Windows::Foundation::IInspectable const& sender,
Input::PointerRoutedEventArgs const& args)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -1199,7 +1195,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_MouseWheelHandler(Windows::Foundation::IInspectable const& /*sender*/,
Input::PointerRoutedEventArgs const& args)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -1301,7 +1297,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_ScrollbarChangeHandler(Windows::Foundation::IInspectable const& /*sender*/,
Controls::Primitives::RangeBaseValueChangedEventArgs const& args)
{
if (_isInternalScrollBarUpdate || _closing)
if (_isInternalScrollBarUpdate || _IsClosing())
{
// The update comes from ourselves, more specifically from the
// terminal. So we don't have to update the terminal because it
@ -1367,15 +1363,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_TryStartAutoScroll(Windows::UI::Input::PointerPoint const& pointerPoint, const double scrollVelocity)
{
// Allow only one pointer at the time
if (!_autoScrollingPointerPoint.has_value() ||
_autoScrollingPointerPoint.value().PointerId() == pointerPoint.PointerId())
if (!_autoScrollingPointerPoint ||
_autoScrollingPointerPoint->PointerId() == pointerPoint.PointerId())
{
_autoScrollingPointerPoint = pointerPoint;
_autoScrollVelocity = scrollVelocity;
// If this is first time the auto scroll update is about to be called,
// kick-start it by initializing its time delta as if it started now
if (!_lastAutoScrollUpdateTime.has_value())
if (!_lastAutoScrollUpdateTime)
{
_lastAutoScrollUpdateTime = std::chrono::high_resolution_clock::now();
}
@ -1394,8 +1390,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - pointerId: id of pointer for which to stop auto scroll
void TermControl::_TryStopAutoScroll(const uint32_t pointerId)
{
if (_autoScrollingPointerPoint.has_value() &&
pointerId == _autoScrollingPointerPoint.value().PointerId())
if (_autoScrollingPointerPoint &&
pointerId == _autoScrollingPointerPoint->PointerId())
{
_autoScrollingPointerPoint = std::nullopt;
_autoScrollVelocity = 0;
@ -1421,15 +1417,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
const auto timeNow = std::chrono::high_resolution_clock::now();
if (_lastAutoScrollUpdateTime.has_value())
if (_lastAutoScrollUpdateTime)
{
static constexpr double microSecPerSec = 1000000.0;
const double deltaTime = std::chrono::duration_cast<std::chrono::microseconds>(timeNow - _lastAutoScrollUpdateTime.value()).count() / microSecPerSec;
const double deltaTime = std::chrono::duration_cast<std::chrono::microseconds>(timeNow - *_lastAutoScrollUpdateTime).count() / microSecPerSec;
ScrollBar().Value(ScrollBar().Value() + _autoScrollVelocity * deltaTime);
if (_autoScrollingPointerPoint.has_value())
if (_autoScrollingPointerPoint)
{
_SetEndSelectionPointAtCursor(_autoScrollingPointerPoint.value().Position());
_SetEndSelectionPointAtCursor(_autoScrollingPointerPoint->Position());
}
}
@ -1445,7 +1441,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_GotFocusHandler(Windows::Foundation::IInspectable const& /* sender */,
RoutedEventArgs const& /* args */)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -1474,16 +1470,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TSFInputControl().NotifyFocusEnter();
}
if (_cursorTimer.has_value())
if (_cursorTimer)
{
// When the terminal focuses, show the cursor immediately
_core->CursorOn(true);
_cursorTimer.value().Start();
_cursorTimer->Start();
}
if (_blinkTimer.has_value())
if (_blinkTimer)
{
_blinkTimer.value().Start();
_blinkTimer->Start();
}
_interactivity->GainFocus();
@ -1504,7 +1500,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_LostFocusHandler(Windows::Foundation::IInspectable const& /* sender */,
RoutedEventArgs const& /* args */)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -1523,15 +1519,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TSFInputControl().NotifyFocusLeave();
}
if (_cursorTimer.has_value())
if (_cursorTimer)
{
_cursorTimer.value().Stop();
_cursorTimer->Stop();
_core->CursorOn(false);
}
if (_blinkTimer.has_value())
if (_blinkTimer)
{
_blinkTimer.value().Stop();
_blinkTimer->Stop();
}
// Check if there is an unfocused config we should set the appearance to
@ -1550,7 +1546,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_SwapChainSizeChanged(winrt::Windows::Foundation::IInspectable const& /*sender*/,
SizeChangedEventArgs const& e)
{
if (!_initializedTerminal || _closing)
if (!_initializedTerminal || _IsClosing())
{
return;
}
@ -1602,7 +1598,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_CursorTimerTick(Windows::Foundation::IInspectable const& /* sender */,
Windows::Foundation::IInspectable const& /* e */)
{
if (!_closing)
if (!_IsClosing())
{
_core->BlinkCursor();
}
@ -1616,7 +1612,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_BlinkTimerTick(Windows::Foundation::IInspectable const& /* sender */,
Windows::Foundation::IInspectable const& /* e */)
{
if (!_closing)
if (!_IsClosing())
{
_core->BlinkAttributeTick();
}
@ -1644,13 +1640,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_ScrollPositionChanged(const IInspectable& /*sender*/,
const Control::ScrollPositionChangedArgs& args)
{
// Since this callback fires from non-UI thread, we might be already
// closed/closing.
if (_closing.load())
{
return;
}
ScrollBarUpdate update;
const auto hiddenContent = args.BufferSize() - args.ViewHeight();
update.newMaximum = hiddenContent;
@ -1670,10 +1659,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_CursorPositionChanged(const IInspectable& /*sender*/,
const IInspectable& /*args*/)
{
if (_tsfTryRedrawCanvas)
{
_tsfTryRedrawCanvas->Run();
}
_tsfTryRedrawCanvas->Run();
}
hstring TermControl::Title()
@ -1706,7 +1692,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// if we should defer which formats are copied to the global setting
bool TermControl::CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference<CopyFormat>& formats)
{
if (_closing)
if (_IsClosing())
{
return false;
}
@ -1723,21 +1709,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::Close()
{
if (!_closing.exchange(true))
if (!_IsClosing())
{
_closing = true;
_core->ReceivedOutput(_coreOutputEventToken);
_RestorePointerCursorHandlers(*this, nullptr);
// These four throttled functions are triggered by terminal output and interact with the UI.
// Since Close() is the point after which we are removed from the UI, but before the destructor
// has run, we should disconnect them *right now*. If we don't, they may fire between the
// throttle delay (from the final output) and the dtor.
_tsfTryRedrawCanvas.reset();
_updatePatternLocations.reset();
_updateScrollBar.reset();
_playWarningBell.reset();
// Disconnect the TSF input control so it doesn't receive EditContext events.
TSFInputControl().Close();
_autoScrollTimer.Stop();
@ -1845,9 +1822,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// will take up.
// TODO: MSFT:21254947 - use a static function to do this instead of
// instantiating a DxEngine
// GH#10211 - UNDER NO CIRCUMSTANCE should this fail. If it does, the
// whole app will crash instantaneously on launch, which is no good.
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
THROW_IF_FAILED(dxEngine->UpdateDpi(dpi));
THROW_IF_FAILED(dxEngine->UpdateFont(desiredFont, actualFont));
LOG_IF_FAILED(dxEngine->UpdateDpi(dpi));
LOG_IF_FAILED(dxEngine->UpdateFont(desiredFont, actualFont));
const auto scale = dxEngine->GetScaling();
const auto fontSize = actualFont.GetSize();
@ -2101,7 +2080,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <none>
void TermControl::_CompositionCompleted(winrt::hstring text)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -2178,7 +2157,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::fire_and_forget TermControl::_DragDropHandler(Windows::Foundation::IInspectable /*sender*/,
DragEventArgs e)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -2265,7 +2244,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_DragOverHandler(Windows::Foundation::IInspectable const& /*sender*/,
DragEventArgs const& e)
{
if (_closing)
if (_IsClosing())
{
return;
}
@ -2384,17 +2363,33 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::BellLightOn()
{
// Initialize the animation if it does not exist
// We only initialize here instead of in the ctor because depending on the bell style setting,
// we may never need this animation
if (!_bellLightAnimation)
{
_bellLightAnimation = Window::Current().Compositor().CreateScalarKeyFrameAnimation();
// Add key frames and a duration to our bell light animation
_bellLightAnimation.InsertKeyFrame(0.0, 2.0);
_bellLightAnimation.InsertKeyFrame(1.0, 1.0);
_bellLightAnimation.Duration(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(TerminalWarningBellInterval)));
}
// Similar to the animation, only initialize the timer here
if (!_bellLightTimer)
{
_bellLightTimer = {};
_bellLightTimer.Interval(std::chrono::milliseconds(TerminalWarningBellInterval));
_bellLightTimer.Tick({ get_weak(), &TermControl::_BellLightOff });
}
Windows::Foundation::Numerics::float2 zeroSize{ 0, 0 };
// If the grid has 0 size or if the bell timer is
// already active, do nothing
if (RootGrid().ActualSize() != zeroSize && !_bellLightTimer)
if (RootGrid().ActualSize() != zeroSize && !_bellLightTimer.IsEnabled())
{
// Start the timer, when the timer ticks we switch off the light
DispatcherTimer invertTimer;
invertTimer.Interval(std::chrono::milliseconds(TerminalWarningBellInterval));
invertTimer.Tick({ get_weak(), &TermControl::_BellLightOff });
invertTimer.Start();
_bellLightTimer.emplace(std::move(invertTimer));
_bellLightTimer.Start();
// Switch on the light and animate the intensity to fade out
VisualBellLight::SetIsTarget(RootGrid(), true);
@ -2408,10 +2403,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_bellLightTimer)
{
// Stop the timer and switch off the light
_bellLightTimer->Stop();
_bellLightTimer.reset();
_bellLightTimer.Stop();
if (!_closing)
if (!_IsClosing())
{
VisualBellLight::SetIsTarget(RootGrid(), false);
}
@ -2454,7 +2448,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (auto self{ weakThis.get() })
{
auto lastHoveredCell = _core->GetHoveredCell();
if (lastHoveredCell.has_value())
if (lastHoveredCell)
{
const auto uriText = _core->GetHoveredUriText();
if (!uriText.empty())

View file

@ -13,7 +13,6 @@
#include "../buffer/out/search.h"
#include "cppwinrt_utils.h"
#include "SearchBoxControl.h"
#include "ThrottledFunc.h"
#include "ControlInteractivity.h"
@ -150,9 +149,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::com_ptr<SearchBoxControl> _searchBox;
IControlSettings _settings;
std::atomic<bool> _closing;
bool _focused;
bool _initializedTerminal;
bool _closing{ false };
bool _focused{ false };
bool _initializedTerminal{ false };
std::shared_ptr<ThrottledFuncTrailing<>> _tsfTryRedrawCanvas;
std::shared_ptr<ThrottledFuncTrailing<>> _updatePatternLocations;
@ -174,16 +173,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Windows::UI::Xaml::DispatcherTimer _autoScrollTimer;
std::optional<std::chrono::high_resolution_clock::time_point> _lastAutoScrollUpdateTime;
winrt::Windows::UI::Composition::ScalarKeyFrameAnimation _bellLightAnimation;
winrt::Windows::UI::Composition::ScalarKeyFrameAnimation _bellLightAnimation{ nullptr };
Windows::UI::Xaml::DispatcherTimer _bellLightTimer{ nullptr };
std::optional<Windows::UI::Xaml::DispatcherTimer> _cursorTimer;
std::optional<Windows::UI::Xaml::DispatcherTimer> _blinkTimer;
std::optional<Windows::UI::Xaml::DispatcherTimer> _bellLightTimer;
event_token _coreOutputEventToken;
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
inline bool _IsClosing() const noexcept
{
// _closing isn't atomic and may only be accessed from the main thread.
assert(Dispatcher().HasThreadAccess());
return _closing;
}
void _UpdateSettingsFromUIThread(IControlSettings newSettings);
void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance);
void _ApplyUISettings(const IControlSettings&);

View file

@ -52,7 +52,6 @@
<ClInclude Include="TermControlAutomationPeer.h">
<DependentUpon>TermControlAutomationPeer.idl</DependentUpon>
</ClInclude>
<ClInclude Include="ThrottledFunc.h" />
<ClInclude Include="TSFInputControl.h">
<DependentUpon>TSFInputControl.xaml</DependentUpon>
</ClInclude>

View file

@ -1,186 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- ThrottledFunc.h
--*/
#pragma once
#include "pch.h"
template<typename... Args>
class ThrottledFuncStorage
{
public:
template<typename... MakeArgs>
bool Emplace(MakeArgs&&... args)
{
std::scoped_lock guard{ _lock };
const bool hadValue = _pendingRunArgs.has_value();
_pendingRunArgs.emplace(std::forward<MakeArgs>(args)...);
return hadValue;
}
template<typename F>
void ModifyPending(F f)
{
std::scoped_lock guard{ _lock };
if (_pendingRunArgs.has_value())
{
std::apply(f, _pendingRunArgs.value());
}
}
std::tuple<Args...> Extract()
{
decltype(_pendingRunArgs) args;
std::scoped_lock guard{ _lock };
_pendingRunArgs.swap(args);
return args.value();
}
private:
std::mutex _lock;
std::optional<std::tuple<Args...>> _pendingRunArgs;
};
template<>
class ThrottledFuncStorage<>
{
public:
bool Emplace()
{
return _isRunPending.test_and_set(std::memory_order_relaxed);
}
std::tuple<> Extract()
{
Reset();
return {};
}
void Reset()
{
_isRunPending.clear(std::memory_order_relaxed);
}
private:
std::atomic_flag _isRunPending;
};
// Class Description:
// - Represents a function that takes arguments and whose invocation is
// delayed by a specified duration and rate-limited such that if the code
// tries to run the function while a call to the function is already
// pending, then the previous call with the previous arguments will be
// cancelled and the call will be made with the new arguments instead.
// - The function will be run on the the specified dispatcher.
template<bool leading, typename... Args>
class ThrottledFunc : public std::enable_shared_from_this<ThrottledFunc<leading, Args...>>
{
public:
using Func = std::function<void(Args...)>;
ThrottledFunc(winrt::Windows::UI::Core::CoreDispatcher dispatcher, winrt::Windows::Foundation::TimeSpan delay, Func func) :
_dispatcher{ std::move(dispatcher) },
_delay{ std::move(delay) },
_func{ std::move(func) }
{
}
// Method Description:
// - Runs the function later with the specified arguments, except if `Run`
// is called again before with new arguments, in which case the new
// arguments will be used instead.
// - For more information, read the class' documentation.
// - This method is always thread-safe. It can be called multiple times on
// different threads.
// Arguments:
// - args: the arguments to pass to the function
// Return Value:
// - <none>
template<typename... MakeArgs>
void Run(MakeArgs&&... args)
{
if (!_storage.Emplace(std::forward<MakeArgs>(args)...))
{
_Fire();
}
}
// Method Description:
// - Modifies the pending arguments for the next function invocation, if
// there is one pending currently.
// - Let's say that you just called the `Run` method with some arguments.
// After the delay specified in the constructor, the function specified
// in the constructor will be called with these arguments.
// - By using this method, you can modify the arguments before the function
// is called.
// - You pass a function to this method which will take references to
// the arguments (one argument corresponds to one reference to an
// argument) and will modify them.
// - When there is no pending invocation of the function, this method will
// not do anything.
// - This method is always thread-safe. It can be called multiple times on
// different threads.
// Arguments:
// - f: the function to call with references to the arguments
// Return Value:
// - <none>
template<typename F>
void ModifyPending(F f)
{
_storage.ModifyPending(f);
}
private:
winrt::fire_and_forget _Fire()
{
const auto dispatcher = _dispatcher;
auto weakSelf = this->weak_from_this();
if constexpr (leading)
{
co_await winrt::resume_foreground(dispatcher);
if (auto self{ weakSelf.lock() })
{
self->_func();
}
else
{
co_return;
}
co_await winrt::resume_after(_delay);
if (auto self{ weakSelf.lock() })
{
self->_storage.Reset();
}
}
else
{
co_await winrt::resume_after(_delay);
co_await winrt::resume_foreground(dispatcher);
if (auto self{ weakSelf.lock() })
{
std::apply(self->_func, self->_storage.Extract());
}
}
}
winrt::Windows::UI::Core::CoreDispatcher _dispatcher;
winrt::Windows::Foundation::TimeSpan _delay;
Func _func;
ThrottledFuncStorage<Args...> _storage;
};
template<typename... Args>
using ThrottledFuncTrailing = ThrottledFunc<false, Args...>;
using ThrottledFuncLeading = ThrottledFunc<true>;

View file

@ -58,3 +58,5 @@ TRACELOGGING_DECLARE_PROVIDER(g_hTerminalControlProvider);
#include <telemetry/ProjectTelemetry.h>
#include "til.h"
#include "ThrottledFunc.h"

View file

@ -733,6 +733,10 @@ bool TerminalDispatch::HardReset() noexcept
// Cursor to 1,1 - the Soft Reset guarantees this is absolute
success = CursorPosition(1, 1) && success;
// Reset the mouse mode
success = EnableSGRExtendedMouseMode(false);
success = EnableAnyEventMouseMode(false);
// Delete all current tab stops and reapply
_ResetTabStops();

View file

@ -241,16 +241,12 @@
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ButtonForeground"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="{StaticResource SystemAccentColor}" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="{StaticResource SystemAccentColor}" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="ButtonForeground"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="{StaticResource SystemAccentColor}" />
<SolidColorBrush x:Key="ButtonForegroundPressed"

View file

@ -11,6 +11,26 @@
<ResourceDictionary Source="SettingContainerStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<Style x:Key="SecondaryTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemBaseMediumColor}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<Style x:Key="SecondaryTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemBaseMediumColor}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<Style x:Key="SecondaryTextBlockStyle"
TargetType="TextBlock" />
<!-- Do not mess with the foreground color for High Contrast. Let it ride as is. -->
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<x:Double x:Key="StandardIconSize">14.0</x:Double>
<Thickness x:Key="StandardIndentMargin">13,0,0,0</Thickness>
<Thickness x:Key="StandardControlMargin">0,24,0,0</Thickness>

View file

@ -39,6 +39,11 @@ namespace Microsoft.Terminal.Settings.Editor
PercentageConverter();
};
runtimeclass PercentageSignConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
PercentageSignConverter();
};
runtimeclass StringIsEmptyConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
StringIsEmptyConverter();

View file

@ -20,6 +20,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
INITIALIZE_BINDABLE_ENUM_SETTING(LaunchMode, LaunchMode, LaunchMode, L"Globals_LaunchMode", L"Content");
INITIALIZE_BINDABLE_ENUM_SETTING(WindowingBehavior, WindowingMode, WindowingMode, L"Globals_WindowingBehavior", L"Content");
#if 0
// BODGY
// Xaml code generator for x:Bind to this will fail to find UnloadObject() on Launch class.
// To work around, check it ourselves on construction and FindName to force load.
@ -28,6 +29,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
FindName(L"DefaultTerminalDropdown");
}
#endif
}
void Launch::OnNavigatedTo(const NavigationEventArgs& e)

View file

@ -114,12 +114,12 @@
<TextBlock Grid.Row="1"
Grid.Column="1"
Foreground="{StaticResource SystemBaseMediumColor}"
Style="{ThemeResource SecondaryTextBlockStyle}"
Text="{x:Bind Author}" />
<TextBlock Grid.Row="1"
Grid.Column="2"
Foreground="{StaticResource SystemBaseMediumColor}"
Style="{ThemeResource SecondaryTextBlockStyle}"
Text="{x:Bind Version}" />
</Grid>

View file

@ -8,6 +8,7 @@
#include "Interaction.h"
#include "Rendering.h"
#include "Actions.h"
#include "ReadOnlyActions.h"
#include "Profiles.h"
#include "GlobalAppearance.h"
#include "ColorSchemes.h"
@ -65,13 +66,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// - settings - the new settings source
// Return value:
// - <none>
fire_and_forget MainPage::UpdateSettings(Model::CascadiaSettings settings)
void MainPage::UpdateSettings(const Model::CascadiaSettings& settings)
{
_settingsSource = settings;
_settingsClone = settings.Copy();
co_await winrt::resume_foreground(Dispatcher());
// Deduce information about the currently selected item
IInspectable selectedItemTag;
auto menuItems{ SettingsNav().MenuItems() };
@ -83,34 +82,43 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
// remove all profile-related NavViewItems by populating a std::vector
// with the ones we want to keep.
// NOTE: menuItems.Remove() causes an out-of-bounds crash. Using ReplaceAll()
// gets around this crash.
std::vector<IInspectable> menuItemsSTL;
for (const auto& item : menuItems)
{
if (const auto& navViewItem{ item.try_as<MUX::Controls::NavigationViewItem>() })
{
if (const auto& tag{ navViewItem.Tag() })
{
if (tag.try_as<Editor::ProfileViewModel>())
// We'll remove a bunch of items and iterate over it twice.
// --> Copy it into an STL vector to simplify our code and reduce COM overhead.
std::vector<IInspectable> menuItemsSTL(menuItems.Size(), nullptr);
menuItems.GetMany(0, menuItemsSTL);
// We want to refresh the list of profiles in the NavigationView.
// In order to add profiles we can use _InitializeProfilesList();
// But before we can do that we have to remove existing profiles first of course.
// This "erase-remove" idiom will achieve just that.
menuItemsSTL.erase(
std::remove_if(
menuItemsSTL.begin(),
menuItemsSTL.end(),
[](const auto& item) -> bool {
if (const auto& navViewItem{ item.try_as<MUX::Controls::NavigationViewItem>() })
{
// don't add NavViewItem pointing to a Profile
continue;
}
else if (const auto& stringTag{ tag.try_as<hstring>() })
{
if (stringTag == addProfileTag)
if (const auto& tag{ navViewItem.Tag() })
{
// don't add the "Add Profile" item
continue;
if (tag.try_as<Editor::ProfileViewModel>())
{
// remove NavViewItem pointing to a Profile
return true;
}
if (const auto& stringTag{ tag.try_as<hstring>() })
{
if (stringTag == addProfileTag)
{
// remove the "Add Profile" item
return true;
}
}
}
}
}
}
menuItemsSTL.emplace_back(item);
}
return false;
}),
menuItemsSTL.end());
menuItems.ReplaceAll(menuItemsSTL);
// Repopulate profile-related menu items
@ -138,7 +146,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// found the one that was selected before the refresh
SettingsNav().SelectedItem(item);
_Navigate(*stringTag);
co_return;
return;
}
}
}
@ -151,7 +159,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// found the one that was selected before the refresh
SettingsNav().SelectedItem(item);
_Navigate(*profileTag);
co_return;
return;
}
}
}
@ -160,14 +168,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
// couldn't find the selected item,
// fallback to first menu item
const auto& firstItem{ menuItems.GetAt(0) };
// Couldn't find the selected item, fallback to first menu item
// This happens when the selected item was a profile which doesn't exist in the new configuration
// We can use menuItemsSTL here because the only things they miss are profile entries.
const auto& firstItem{ menuItemsSTL.at(0).as<MUX::Controls::NavigationViewItem>() };
SettingsNav().SelectedItem(firstItem);
if (const auto& tag{ SettingsNav().SelectedItem().try_as<MUX::Controls::NavigationViewItem>().Tag() })
{
_Navigate(unbox_value<hstring>(tag));
}
_Navigate(unbox_value<hstring>(firstItem.Tag()));
}
void MainPage::SetHostingWindow(uint64_t hostingWindow) noexcept
@ -286,7 +292,21 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
else if (clickedItemTag == actionsTag)
{
contentFrame().Navigate(xaml_typename<Editor::Actions>(), winrt::make<ActionsPageNavigationState>(_settingsClone));
if constexpr (Feature_EditableActionsPage::IsEnabled())
{
contentFrame().Navigate(xaml_typename<Editor::Actions>(), winrt::make<ActionsPageNavigationState>(_settingsClone));
}
else
{
auto actionsState{ winrt::make<ReadOnlyActionsPageNavigationState>(_settingsClone) };
actionsState.OpenJson([weakThis = get_weak()](auto&&, auto&& arg) {
if (auto self{ weakThis.get() })
{
self->_OpenJsonHandlers(nullptr, arg);
}
});
contentFrame().Navigate(xaml_typename<Editor::ReadOnlyActions>(), actionsState);
}
}
else if (clickedItemTag == colorSchemesTag)
{

View file

@ -13,7 +13,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
MainPage() = delete;
MainPage(const Model::CascadiaSettings& settings);
fire_and_forget UpdateSettings(Model::CascadiaSettings settings);
void UpdateSettings(const Model::CascadiaSettings& settings);
void OpenJsonKeyDown(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& args);
void OpenJsonTapped(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& args);

View file

@ -107,8 +107,9 @@
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Frame x:Name="contentFrame"
Grid.Row="0" />
<ScrollViewer Grid.Row="0">
<Frame x:Name="contentFrame" />
</ScrollViewer>
<Grid Grid.Row="1"
Height="100"
BorderBrush="{ThemeResource SystemBaseLowColor}"

View file

@ -60,6 +60,9 @@
<ClInclude Include="InvertedBooleanToVisibilityConverter.h">
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="PercentageSignConverter.h">
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="StringIsEmptyConverter.h">
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
@ -96,6 +99,9 @@
<DependentUpon>Profiles.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="ReadOnlyActions.h">
<DependentUpon>ReadOnlyActions.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="Rendering.h">
<DependentUpon>Rendering.xaml</DependentUpon>
</ClInclude>
@ -134,6 +140,9 @@
<Page Include="Profiles.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="ReadOnlyActions.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Rendering.xaml">
<SubType>Designer</SubType>
</Page>
@ -167,6 +176,9 @@
<ClCompile Include="InvertedBooleanToVisibilityConverter.cpp">
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="PercentageSignConverter.cpp">
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="StringIsEmptyConverter.cpp">
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
@ -203,6 +215,9 @@
<DependentUpon>Profiles.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="ReadOnlyActions.cpp">
<DependentUpon>ReadOnlyActions.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="Rendering.cpp">
<DependentUpon>Rendering.xaml</DependentUpon>
</ClCompile>
@ -242,6 +257,10 @@
<DependentUpon>Interaction.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="ReadOnlyActions.idl">
<DependentUpon>ReadOnlyActions.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="Rendering.idl">
<DependentUpon>Rendering.xaml</DependentUpon>
<SubType>Code</SubType>

View file

@ -10,10 +10,16 @@
<ClCompile Include="pch.cpp" />
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="Utils.cpp" />
<ClCompile Include="PercentageSignConverter.cpp">
<Filter>Converters</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="Utils.h" />
<ClInclude Include="PercentageSignConverter.h">
<Filter>Converters</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Midl Include="EnumEntry.idl" />
@ -43,4 +49,4 @@
<UniqueIdentifier>{00f725c8-41b4-40a8-995e-8ee2e49a4a4c}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View file

@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "PercentageSignConverter.h"
#include "PercentageSignConverter.g.cpp"
using namespace winrt::Windows;
using namespace winrt::Windows::UI::Xaml;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Foundation::IInspectable PercentageSignConverter::Convert(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /* parameter */,
hstring const& /* language */)
{
const auto number{ winrt::unbox_value<double>(value) };
return winrt::box_value(to_hstring((int)number) + L"%");
}
Foundation::IInspectable PercentageSignConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /*parameter*/,
hstring const& /* language */)
{
throw hresult_not_implemented();
}
}

View file

@ -0,0 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "PercentageSignConverter.g.h"
#include "Utils.h"
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, PercentageSignConverter);

View file

@ -35,6 +35,7 @@
</DataTemplate>
<local:ColorToBrushConverter x:Key="ColorToBrushConverter" />
<local:PercentageConverter x:Key="PercentageConverter" />
<local:PercentageSignConverter x:Key="PercentageSignConverter" />
<local:FontWeightConverter x:Key="FontWeightConverter" />
<local:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter" />
<local:StringIsEmptyConverter x:Key="StringIsEmptyConverter" />
@ -626,7 +627,7 @@
Value="{x:Bind State.Profile.BackgroundImageOpacity, Converter={StaticResource PercentageConverter}, Mode=TwoWay}" />
<TextBlock Grid.Column="1"
Style="{StaticResource SliderValueLabelStyle}"
Text="{Binding ElementName=BIOpacitySlider, Path=Value, Mode=OneWay}" />
Text="{Binding ElementName=BIOpacitySlider, Path=Value, Mode=OneWay, Converter={StaticResource PercentageSignConverter}}" />
</Grid>
</local:SettingContainer>
</StackPanel>
@ -664,7 +665,7 @@
Value="{x:Bind State.Profile.AcrylicOpacity, Converter={StaticResource PercentageConverter}, Mode=TwoWay}" />
<TextBlock Grid.Column="1"
Style="{StaticResource SliderValueLabelStyle}"
Text="{Binding ElementName=AcrylicOpacitySlider, Path=Value, Mode=OneWay}" />
Text="{Binding ElementName=AcrylicOpacitySlider, Path=Value, Mode=OneWay, Converter={StaticResource PercentageSignConverter}}" />
</Grid>
</StackPanel>
</local:SettingContainer>

View file

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

View file

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

View file

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

View file

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

View file

@ -587,6 +587,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
winrt::hstring GlobalSummonArgs::GenerateName() const
{
// GH#10210 - Is this action literally the same thing as the `quakeMode`
// action? That has a special name.
static const auto quakeModeArgs{ std::get<0>(GlobalSummonArgs::QuakeModeFromJson(Json::Value::null)) };
if (quakeModeArgs.Equals(*this))
{
return RS_(L"QuakeModeCommandKey");
}
std::wstringstream ss;
ss << std::wstring_view(RS_(L"GlobalSummonCommandKey"));

View file

@ -68,6 +68,15 @@ constexpr size_t Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(c
return gsl::narrow_cast<size_t>(args.Hash());
}
// Retrieves the hash value for an empty-constructed object.
template<typename T>
static size_t EmptyHash()
{
// cache the value of the empty hash
static const size_t cachedHash = winrt::make_self<T>()->Hash();
return cachedHash;
}
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
using namespace ::Microsoft::Terminal::Settings::Model;

View file

@ -2,6 +2,7 @@
// Licensed under the MIT license.
#include "pch.h"
#include "AllShortcutActions.h"
#include "ActionMap.h"
#include "ActionMap.g.cpp"
@ -18,18 +19,36 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
size_t hashedArgs{};
if (const auto& args{ actionAndArgs.Args() })
{
// Args are defined, so hash them
hashedArgs = gsl::narrow_cast<size_t>(args.Hash());
}
else
{
std::hash<IActionArgs> argsHash;
hashedArgs = argsHash(nullptr);
// Args are not defined.
// Check if the ShortcutAction supports args.
switch (actionAndArgs.Action())
{
#define ON_ALL_ACTIONS_WITH_ARGS(action) \
case ShortcutAction::action: \
/* If it does, hash the default values for the args.*/ \
hashedArgs = EmptyHash<implementation::action##Args>(); \
break;
ALL_SHORTCUT_ACTIONS_WITH_ARGS
#undef ON_ALL_ACTIONS_WITH_ARGS
default:
{
// Otherwise, hash nullptr.
std::hash<IActionArgs> argsHash;
hashedArgs = argsHash(nullptr);
}
}
}
return hashedAction ^ hashedArgs;
}
ActionMap::ActionMap() :
_NestedCommands{ single_threaded_map<hstring, Model::Command>() }
_NestedCommands{ single_threaded_map<hstring, Model::Command>() },
_IterableCommands{ single_threaded_vector<Model::Command>() }
{
}
@ -87,7 +106,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
// populate _NameMapCache
std::unordered_map<hstring, Model::Command> nameMap{};
_PopulateNameMapWithNestedCommands(nameMap);
_PopulateNameMapWithSpecialCommands(nameMap);
_PopulateNameMapWithStandardCommands(nameMap);
_NameMapCache = single_threaded_map<hstring, Model::Command>(std::move(nameMap));
@ -96,18 +115,19 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
}
// Method Description:
// - Populates the provided nameMap with all of our nested commands and our parents nested commands
// - Performs a top-down approach by going to the root first, then recursively adding the nested commands layer-by-layer
// - Populates the provided nameMap with all of our special commands and our parent's special commands.
// - Special commands include nested and iterable commands.
// - Performs a top-down approach by going to the root first, then recursively adding the nested commands layer-by-layer.
// Arguments:
// - nameMap: the nameMap we're populating. This maps the name (hstring) of a command to the command itself.
void ActionMap::_PopulateNameMapWithNestedCommands(std::unordered_map<hstring, Model::Command>& nameMap) const
void ActionMap::_PopulateNameMapWithSpecialCommands(std::unordered_map<hstring, Model::Command>& nameMap) const
{
// Update NameMap with our parents.
// Starting with this means we're doing a top-down approach.
FAIL_FAST_IF(_parents.size() > 1);
for (const auto& parent : _parents)
{
parent->_PopulateNameMapWithNestedCommands(nameMap);
parent->_PopulateNameMapWithSpecialCommands(nameMap);
}
// Add NestedCommands to NameMap _after_ we handle our parents.
@ -125,6 +145,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
nameMap.erase(name);
}
}
// Add IterableCommands to NameMap
for (const auto& cmd : _IterableCommands)
{
nameMap.insert_or_assign(cmd.Name(), cmd);
}
}
// Method Description:
@ -291,6 +317,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
actionMap->_NestedCommands.Insert(name, *(get_self<Command>(cmd)->Copy()));
}
// copy _IterableCommands
for (const auto& cmd : _IterableCommands)
{
actionMap->_IterableCommands.Append(*(get_self<Command>(cmd)->Copy()));
}
// repeat this for each of our parents
FAIL_FAST_IF(_parents.size() > 1);
for (const auto& parent : _parents)
@ -331,6 +363,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return;
}
// Handle iterable commands
if (cmdImpl->IterateOn() != ExpandCommandType::None)
{
_IterableCommands.Append(cmd);
return;
}
// General Case:
// Add the new command to the KeyMap.
// This map directs you to an entry in the ActionMap.

View file

@ -81,7 +81,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
std::optional<Model::Command> _GetActionByID(const InternalActionID actionID) const;
std::optional<Model::Command> _GetActionByKeyChordInternal(Control::KeyChord const& keys) const;
void _PopulateNameMapWithNestedCommands(std::unordered_map<hstring, Model::Command>& nameMap) const;
void _PopulateNameMapWithSpecialCommands(std::unordered_map<hstring, Model::Command>& nameMap) const;
void _PopulateNameMapWithStandardCommands(std::unordered_map<hstring, Model::Command>& nameMap) const;
void _PopulateKeyBindingMapWithStandardCommands(std::unordered_map<Control::KeyChord, Model::Command, KeyChordHash, KeyChordEquality>& keyBindingsMap, std::unordered_set<Control::KeyChord, KeyChordHash, KeyChordEquality>& unboundKeys) const;
std::vector<Model::Command> _GetCumulativeActions() const noexcept;
@ -94,6 +94,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Windows::Foundation::Collections::IMap<Control::KeyChord, Model::Command> _GlobalHotkeysCache{ nullptr };
Windows::Foundation::Collections::IMap<Control::KeyChord, Model::Command> _KeyBindingMapCache{ nullptr };
Windows::Foundation::Collections::IMap<hstring, Model::Command> _NestedCommands{ nullptr };
Windows::Foundation::Collections::IVector<Model::Command> _IterableCommands{ nullptr };
std::unordered_map<Control::KeyChord, InternalActionID, KeyChordHash, KeyChordEquality> _KeyMap;
std::unordered_map<InternalActionID, Model::Command> _ActionMap;

View file

@ -60,34 +60,40 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
Json::Value actionList{ Json::ValueType::arrayValue };
// Serialize all standard Command objects in the current layer
for (const auto& [_, cmd] : _ActionMap)
{
// Command serializes to an array of JSON objects.
// This is because a Command may have multiple key chords associated with it.
// The name and icon are only serialized in the first object.
// Example:
// { "name": "Custom Copy", "command": "copy", "keys": "ctrl+c" }
// { "command": "copy", "keys": "ctrl+shift+c" }
// { "command": "copy", "keys": "ctrl+ins" }
// Command serializes to an array of JSON objects.
// This is because a Command may have multiple key chords associated with it.
// The name and icon are only serialized in the first object.
// Example:
// { "name": "Custom Copy", "command": "copy", "keys": "ctrl+c" }
// { "command": "copy", "keys": "ctrl+shift+c" }
// { "command": "copy", "keys": "ctrl+ins" }
auto toJson = [&actionList](const Model::Command& cmd) {
const auto cmdImpl{ winrt::get_self<implementation::Command>(cmd) };
const auto& cmdJsonArray{ cmdImpl->ToJson() };
for (const auto& cmdJson : cmdJsonArray)
{
actionList.append(cmdJson);
}
};
// Serialize all standard Command objects in the current layer
for (const auto& [_, cmd] : _ActionMap)
{
toJson(cmd);
}
// Serialize all nested Command objects added in the current layer
for (const auto& [_, cmd] : _NestedCommands)
{
const auto cmdImpl{ winrt::get_self<implementation::Command>(cmd) };
const auto& cmdJsonArray{ cmdImpl->ToJson() };
for (const auto& cmdJson : cmdJsonArray)
{
actionList.append(cmdJson);
}
toJson(cmd);
}
// Serialize all iterable Command objects added in the current layer
for (const auto& cmd : _IterableCommands)
{
toJson(cmd);
}
return actionList;
}

View file

@ -545,14 +545,20 @@ void CascadiaSettings::_ParseAndLayerFragmentFiles(const std::unordered_set<std:
auto matchingProfile = _FindMatchingProfile(profileStub);
if (matchingProfile)
{
// We found a matching profile, create a child of it and put the modifications there
// (we add a new inheritance layer)
auto childImpl{ matchingProfile->CreateChild() };
childImpl->LayerJson(profileStub);
childImpl->Origin(OriginTag::Fragment);
try
{
// We found a matching profile, create a child of it and put the modifications there
// (we add a new inheritance layer)
auto childImpl{ matchingProfile->CreateChild() };
childImpl->LayerJson(profileStub);
childImpl->Origin(OriginTag::Fragment);
// replace parent in _profiles with child
_allProfiles.SetAt(_FindMatchingProfileIndex(matchingProfile->ToJson()).value(), *childImpl);
// replace parent in _profiles with child
_allProfiles.SetAt(_FindMatchingProfileIndex(matchingProfile->ToJson()).value(), *childImpl);
}
catch (...)
{
}
}
}
else
@ -561,13 +567,19 @@ void CascadiaSettings::_ParseAndLayerFragmentFiles(const std::unordered_set<std:
// (it must have at least a name)
if (profileStub.isMember(JsonKey(NameKey)))
{
auto newProfile = Profile::FromJson(profileStub);
// Make sure to give the new profile a source, then we add it to our list of profiles
// We don't make modifications to the user's settings file yet, that will happen when
// _AppendDynamicProfilesToUserSettings() is called later
newProfile->Source(source);
newProfile->Origin(OriginTag::Fragment);
_allProfiles.Append(*newProfile);
try
{
auto newProfile = Profile::FromJson(profileStub);
// Make sure to give the new profile a source, then we add it to our list of profiles
// We don't make modifications to the user's settings file yet, that will happen when
// _AppendDynamicProfilesToUserSettings() is called later
newProfile->Source(source);
newProfile->Origin(OriginTag::Fragment);
_allProfiles.Append(*newProfile);
}
catch (...)
{
}
}
}
}

View file

@ -394,10 +394,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
Json::Value cmdList{ Json::ValueType::arrayValue };
if (_nestedCommand)
if (_nestedCommand || _IterateOn != ExpandCommandType::None)
{
// handle nested command
// For nested commands, we can trust _originalJson to be correct.
// handle special commands
// For these, we can trust _originalJson to be correct.
// In fact, we _need_ to use it here because we don't actually deserialize `iterateOn`
// until we expand the command.
cmdList.append(_originalJson);

View file

@ -11,7 +11,7 @@ using namespace winrt::Microsoft::Terminal::Settings;
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
winrt::Windows::Foundation::Collections::IVector<Model::DefaultTerminal> DefaultTerminal::_available = winrt::single_threaded_vector<Model::DefaultTerminal>();
std::optional<Model::DefaultTerminal> DefaultTerminal::_current;
Model::DefaultTerminal DefaultTerminal::_current = nullptr;
DefaultTerminal::DefaultTerminal(DelegationConfig::DelegationPackage pkg) :
_pkg(pkg)
@ -81,7 +81,10 @@ Model::DefaultTerminal DefaultTerminal::Current()
{
Refresh();
}
return _current.value();
// The potential of returning nullptr feels weird, but XAML can handle that appropriately
// and will select nothing as current in the dropdown.
return _current;
}
void DefaultTerminal::Current(const Model::DefaultTerminal& term)

View file

@ -42,7 +42,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
private:
DelegationConfig::DelegationPackage _pkg;
static Windows::Foundation::Collections::IVector<Model::DefaultTerminal> _available;
static std::optional<Model::DefaultTerminal> _current;
static Model::DefaultTerminal _current;
};
}

View file

@ -17,6 +17,7 @@
<ClInclude Include="pch.h" />
<ClInclude Include="ScopedResourceLoader.h" />
<ClInclude Include="inc\LibraryResources.h" />
<ClInclude Include="inc\ThrottledFunc.h" />
<ClInclude Include="inc\Utils.h" />
<ClInclude Include="inc\WtExeUtils.h" />
</ItemGroup>

View file

@ -12,6 +12,7 @@
<ClInclude Include="pch.h" />
<ClInclude Include="ScopedResourceLoader.h" />
<ClInclude Include="inc\LibraryResources.h" />
<ClInclude Include="inc\ThrottledFunc.h" />
<ClInclude Include="inc\Utils.h" />
<ClInclude Include="inc\WtExeUtils.h" />
</ItemGroup>

View file

@ -0,0 +1,141 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "til/throttled_func.h"
// ThrottledFunc is a copy of til::throttled_func,
// specialized for the use with a WinRT Dispatcher.
template<bool leading, typename... Args>
class ThrottledFunc : public std::enable_shared_from_this<ThrottledFunc<leading, Args...>>
{
public:
using filetime_duration = std::chrono::duration<int64_t, std::ratio<1, 10000000>>;
using function = std::function<void(Args...)>;
// Throttles invocations to the given `func` to not occur more often than `delay`.
//
// If this is a:
// * ThrottledFuncLeading: `func` will be invoked immediately and
// further invocations prevented until `delay` time has passed.
// * ThrottledFuncTrailing: On the first invocation a timer of `delay` time will
// be started. After the timer has expired `func` will be invoked just once.
//
// After `func` was invoked the state is reset and this cycle is repeated again.
ThrottledFunc(
winrt::Windows::UI::Core::CoreDispatcher dispatcher,
filetime_duration delay,
function func) :
_dispatcher{ std::move(dispatcher) },
_func{ std::move(func) },
_timer{ _create_timer() }
{
const auto d = -delay.count();
if (d >= 0)
{
throw std::invalid_argument("non-positive delay specified");
}
memcpy(&_delay, &d, sizeof(d));
}
// ThrottledFunc uses its `this` pointer when creating _timer.
// Since the timer cannot be recreated, instances cannot be moved either.
ThrottledFunc(const ThrottledFunc&) = delete;
ThrottledFunc& operator=(const ThrottledFunc&) = delete;
ThrottledFunc(ThrottledFunc&&) = delete;
ThrottledFunc& operator=(ThrottledFunc&&) = delete;
// Throttles the invocation of the function passed to the constructor.
// If this is a trailing_throttled_func:
// If you call this function again before the underlying
// timer has expired, the new arguments will be used.
template<typename... MakeArgs>
void Run(MakeArgs&&... args)
{
if (!_storage.emplace(std::forward<MakeArgs>(args)...))
{
_leading_edge();
}
}
// Modifies the pending arguments for the next function
// invocation, if there is one pending currently.
//
// `func` will be invoked as func(Args...). Make sure to bind any
// arguments in `func` by reference if you'd like to modify them.
template<typename F>
void ModifyPending(F func)
{
_storage.modify_pending(func);
}
private:
static void __stdcall _timer_callback(PTP_CALLBACK_INSTANCE /*instance*/, PVOID context, PTP_TIMER /*timer*/) noexcept
{
static_cast<ThrottledFunc*>(context)->_trailing_edge();
}
void _leading_edge()
{
if constexpr (leading)
{
_dispatcher.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [weakSelf = this->weak_from_this()]() {
if (auto self{ weakSelf.lock() })
{
try
{
self->_func();
}
CATCH_LOG();
SetThreadpoolTimerEx(self->_timer.get(), &self->_delay, 0, 0);
}
});
}
else
{
SetThreadpoolTimerEx(_timer.get(), &_delay, 0, 0);
}
}
void _trailing_edge()
{
if constexpr (leading)
{
_storage.reset();
}
else
{
_dispatcher.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [weakSelf = this->weak_from_this()]() {
if (auto self{ weakSelf.lock() })
{
try
{
std::apply(self->_func, self->_storage.take());
}
CATCH_LOG();
}
});
}
}
inline wil::unique_threadpool_timer _create_timer()
{
wil::unique_threadpool_timer timer{ CreateThreadpoolTimer(&_timer_callback, this, nullptr) };
THROW_LAST_ERROR_IF(!timer);
return timer;
}
FILETIME _delay;
winrt::Windows::UI::Core::CoreDispatcher _dispatcher;
function _func;
wil::unique_threadpool_timer _timer;
til::details::throttled_func_storage<Args...> _storage;
};
template<typename... Args>
using ThrottledFuncTrailing = ThrottledFunc<false, Args...>;
using ThrottledFuncLeading = ThrottledFunc<true>;

View file

@ -266,6 +266,7 @@ void AppHost::Initialize()
_logic.RenameWindowRequested({ this, &AppHost::_RenameWindowRequested });
_logic.SettingsChanged({ this, &AppHost::_HandleSettingsChanged });
_logic.IsQuakeWindowChanged({ this, &AppHost::_IsQuakeWindowChanged });
_logic.SummonWindowRequested({ this, &AppHost::_SummonWindowRequested });
_window->UpdateTitle(_logic.Title());
@ -586,16 +587,17 @@ bool AppHost::HasWindow()
// - args: the bundle of a commandline and working directory to use for this invocation.
// Return Value:
// - <none>
void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable /*sender*/,
void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable sender,
Remoting::CommandlineArgs args)
{
const Remoting::SummonWindowBehavior summonArgs{};
summonArgs.MoveToCurrentDesktop(false);
summonArgs.DropdownDuration(0);
summonArgs.ToMonitor(Remoting::MonitorBehavior::InPlace);
summonArgs.ToggleVisibility(false); // Do not toggle, just make visible.
// Summon the window whenever we dispatch a commandline to it. This will
// make it obvious when a new tab/pane is created in a window.
_window->SummonWindow(summonArgs);
_HandleSummon(sender, summonArgs);
_logic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory());
}
@ -925,3 +927,15 @@ void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectab
{
_window->IsQuakeWindow(_logic.IsQuakeWindow());
}
void AppHost::_SummonWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable&)
{
const Remoting::SummonWindowBehavior summonArgs{};
summonArgs.MoveToCurrentDesktop(false);
summonArgs.DropdownDuration(0);
summonArgs.ToMonitor(Remoting::MonitorBehavior::InPlace);
summonArgs.ToggleVisibility(false); // Do not toggle, just make visible.
_HandleSummon(sender, summonArgs);
}

View file

@ -82,4 +82,7 @@ private:
void _IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
void _SummonWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
};

View file

@ -1023,7 +1023,15 @@ winrt::fire_and_forget IslandWindow::SummonWindow(Remoting::SummonWindowBehavior
{
// On the foreground thread:
co_await winrt::resume_foreground(_rootGrid.Dispatcher());
_summonWindowRoutineBody(args);
}
// Method Description:
// - As above.
// BODGY: ARM64 BUILD FAILED WITH fatal error C1001: Internal compiler error
// when this was part of the coroutine body.
void IslandWindow::_summonWindowRoutineBody(Remoting::SummonWindowBehavior args)
{
uint32_t actualDropdownDuration = args.DropdownDuration();
// If the user requested an animation, let's check if animations are enabled in the OS.
if (args.DropdownDuration() > 0)

View file

@ -111,6 +111,8 @@ protected:
bool _isQuakeWindow{ false };
void _enterQuakeMode();
void _summonWindowRoutineBody(winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior args);
private:
// This minimum width allows for width the tabs fit
static constexpr long minimumWidth = 460L;

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<PropertyGroup Label="Globals">
<ProjectGuid>{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}</ProjectGuid>
@ -111,15 +111,15 @@
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.3.210521003\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.3.210521003\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets'))" />
</Target>

View file

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

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<PropertyGroup Label="Globals">
@ -88,15 +88,15 @@
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />

View file

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

View file

@ -96,6 +96,8 @@ namespace WpfTerminalTestNetCore
{
DefaultBackground = 0x0c0c0c,
DefaultForeground = 0xcccccc,
DefaultSelectionBackground = 0xcccccc,
SelectionBackgroundAlpha = 0.5f,
CursorStyle = CursorStyle.BlinkingBar,
// This is Campbell.
ColorTable = new uint[] { 0x0C0C0C, 0x1F0FC5, 0x0EA113, 0x009CC1, 0xDA3700, 0x981788, 0xDD963A, 0xCCCCCC, 0x767676, 0x5648E7, 0x0CC616, 0xA5F1F9, 0xFF783B, 0x9E00B4, 0xD6D661, 0xF2F2F2 },

View file

@ -64,4 +64,21 @@
<Touch Files="@(_PCHFileToCleanWithTimestamp)" Time="%(LastWriteTime)" AlwaysCreate="true" />
<Message Text="PCH and Precomp object @(_PCHFileToCleanWithTimestamp) has been deleted for $(ProjectName)." />
</Target>
<PropertyGroup>
<BuildDependsOn>
OCCallFeatureFlagGenerator;
$(BuildDependsOn)
</BuildDependsOn>
</PropertyGroup>
<Target Name="OCCallFeatureFlagGenerator">
<MSBuild Projects="$(SolutionDir)\build\rules\GenerateFeatureFlags.proj" />
</Target>
<ItemDefinitionGroup>
<ClCompile>
<ForcedIncludeFiles>$(SolutionDir)\bin\$(Configuration)\inc\TilFeatureStaging.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
</ClCompile>
</ItemDefinitionGroup>
</Project>

10
src/features.xml Normal file
View file

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<featureStaging xmlns="http://microsoft.com/TilFeatureStaging-Schema.xsd">
<!-- See doc/feature_flags.md for more info. -->
<feature>
<name>Feature_EditableActionsPage</name>
<description>The Actions page in the settings UI should allow users to edit actions.</description>
<stage>AlwaysEnabled</stage>
<alwaysDisabledReleaseTokens/>
</feature>
</featureStaging>

View file

@ -70,7 +70,7 @@ void CursorBlinker::TimerRoutine(SCREEN_INFORMATION& ScreenInfo)
auto& buffer = ScreenInfo.GetTextBuffer();
auto& cursor = buffer.GetCursor();
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
auto* const _pAccessibilityNotifier = ServiceLocator::LocateAccessibilityNotifier();
auto* const pAccessibilityNotifier = ServiceLocator::LocateAccessibilityNotifier();
if (!WI_IsFlagSet(gci.Flags, CONSOLE_HAS_FOCUS))
{
@ -78,7 +78,8 @@ void CursorBlinker::TimerRoutine(SCREEN_INFORMATION& ScreenInfo)
}
// Update the cursor pos in USER so accessibility will work.
if (cursor.HasMoved())
// Don't do all this work or send events if we don't have a notifier target.
if (pAccessibilityNotifier && cursor.HasMoved())
{
// Convert the buffer position to the equivalent screen coordinates
// required by the notifier, taking line rendition into account.
@ -93,7 +94,7 @@ void CursorBlinker::TimerRoutine(SCREEN_INFORMATION& ScreenInfo)
rc.right = rc.left + fontSize.X;
rc.bottom = rc.top + fontSize.Y;
_pAccessibilityNotifier->NotifyConsoleCaretEvent(rc);
pAccessibilityNotifier->NotifyConsoleCaretEvent(rc);
// Send accessibility information
{
@ -109,7 +110,7 @@ void CursorBlinker::TimerRoutine(SCREEN_INFORMATION& ScreenInfo)
flags = IAccessibilityNotifier::ConsoleCaretEventFlags::CaretVisible;
}
_pAccessibilityNotifier->NotifyConsoleCaretEvent(flags, MAKELONG(position.X, position.Y));
pAccessibilityNotifier->NotifyConsoleCaretEvent(flags, MAKELONG(position.X, position.Y));
}
}

View file

@ -224,10 +224,13 @@ void WriteToScreen(SCREEN_INFORMATION& screenInfo, const Viewport& region)
cellsModified = done.GetCellDistance(it);
// Notify accessibility
auto endingCoordinate = startingCoordinate;
bufferSize.MoveInBounds(cellsModified, endingCoordinate);
screenBuffer.NotifyAccessibilityEventing(startingCoordinate.X, startingCoordinate.Y, endingCoordinate.X, endingCoordinate.Y);
if (screenBuffer.HasAccessibilityEventing())
{
// Notify accessibility
auto endingCoordinate = startingCoordinate;
bufferSize.MoveInBounds(cellsModified, endingCoordinate);
screenBuffer.NotifyAccessibilityEventing(startingCoordinate.X, startingCoordinate.Y, endingCoordinate.X, endingCoordinate.Y);
}
}
CATCH_RETURN();
@ -284,9 +287,12 @@ void WriteToScreen(SCREEN_INFORMATION& screenInfo, const Viewport& region)
cellsModified = done.GetInputDistance(it);
// Notify accessibility
auto endingCoordinate = startingCoordinate;
bufferSize.MoveInBounds(cellsModified, endingCoordinate);
screenInfo.NotifyAccessibilityEventing(startingCoordinate.X, startingCoordinate.Y, endingCoordinate.X, endingCoordinate.Y);
if (screenInfo.HasAccessibilityEventing())
{
auto endingCoordinate = startingCoordinate;
bufferSize.MoveInBounds(cellsModified, endingCoordinate);
screenInfo.NotifyAccessibilityEventing(startingCoordinate.X, startingCoordinate.Y, endingCoordinate.X, endingCoordinate.Y);
}
// GH#3126 - This is a shim for powershell's `Clear-Host` function. In
// the vintage console, `Clear-Host` is supposed to clear the entire

View file

@ -557,7 +557,10 @@ constexpr unsigned int LOCAL_BUFFER_SIZE = 100;
const auto itEnd = screenInfo.Write(it);
// Notify accessibility
screenInfo.NotifyAccessibilityEventing(CursorPosition.X, CursorPosition.Y, CursorPosition.X + gsl::narrow<SHORT>(i - 1), CursorPosition.Y);
if (screenInfo.HasAccessibilityEventing())
{
screenInfo.NotifyAccessibilityEventing(CursorPosition.X, CursorPosition.Y, CursorPosition.X + gsl::narrow<SHORT>(i - 1), CursorPosition.Y);
}
// The number of "spaces" or "cells" we have consumed needs to be reported and stored for later
// when/if we need to erase the command line.

View file

@ -376,7 +376,10 @@ std::vector<OutputCell>::const_iterator ConsoleImeInfo::_WriteConversionArea(con
area.Paint();
// Notify accessibility that we have updated the text in this display region within the viewport.
screenInfo.NotifyAccessibilityEventing(insertionPos.X, insertionPos.Y, gsl::narrow<SHORT>(insertionPos.X + lineVec.size() - 1), insertionPos.Y);
if (screenInfo.HasAccessibilityEventing())
{
screenInfo.NotifyAccessibilityEventing(insertionPos.X, insertionPos.Y, gsl::narrow<SHORT>(insertionPos.X + lineVec.size() - 1), insertionPos.Y);
}
// Hand back the iterator representing the end of what we used to be fed into the beginning of the next call.
return lineEnd;

View file

@ -2210,10 +2210,14 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo)
screenInfo.Write(fillData, startPosition, false);
// Notify accessibility
auto endPosition = startPosition;
const auto bufferSize = screenInfo.GetBufferSize();
bufferSize.MoveInBounds(fillLength - 1, endPosition);
screenInfo.NotifyAccessibilityEventing(startPosition.X, startPosition.Y, endPosition.X, endPosition.Y);
if (screenInfo.HasAccessibilityEventing())
{
auto endPosition = startPosition;
const auto bufferSize = screenInfo.GetBufferSize();
bufferSize.MoveInBounds(fillLength - 1, endPosition);
screenInfo.NotifyAccessibilityEventing(startPosition.X, startPosition.Y, endPosition.X, endPosition.Y);
}
return S_OK;
}
CATCH_RETURN();

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