2019-07-09 23:47:30 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "TerminalPage.h"
|
2019-11-22 00:09:50 +01:00
|
|
|
#include "ActionAndArgs.h"
|
2019-09-04 23:34:06 +02:00
|
|
|
#include "Utils.h"
|
2020-04-07 20:35:05 +02:00
|
|
|
#include "AppLogic.h"
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
#include "../../types/inc/utils.hpp"
|
2019-07-09 23:47:30 +02:00
|
|
|
|
2019-11-01 23:47:05 +01:00
|
|
|
#include <LibraryResources.h>
|
|
|
|
|
2019-07-09 23:47:30 +02:00
|
|
|
#include "TerminalPage.g.cpp"
|
2019-09-04 23:34:06 +02:00
|
|
|
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
2019-07-09 23:47:30 +02:00
|
|
|
|
Add Dynamic Profile Generators (#2603)
_**This PR targets the #2515 PR**_. It does that for the sake of diffing. When this PR and #2515 are both ready, I'll merge #2515 first, then change the target of this branch, and merge this one.
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR adds support for "dynamic profiles", in accordance with the [Cascading Settings Spec](https://github.com/microsoft/terminal/blob/master/doc/cascadia/Cascading-Default-Settings.md#dynamic-profiles). Currently, we have three types of default profiles that fit the category of dynamic profile generators. These are profiles that we want to create on behalf of the user, but require runtime information to be able to create correctly. Because they require runtime information, we can't ship a static version of these profiles as a part of `defaults.json`. These three profile generators are:
* The Powershell Core generator
* The WSL Distro generator
* The Azure Cloud Shell generator
<!-- 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 #754
* [x] I work here
* [x] look at all these **Tests**
* [x] Requires documentation to be updated - This is done as part of the parent PR
<!-- 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
We want to be able to enable the user to edit dynamic profiles that are generated from DPGs. When dynamic profiles are added, we'll add entries for them to the user's `profiles.json`. We do this _without re-serializing_ the settings. Instead, we insert a partial serialization for the profile into the user's settings.
### Remaining TODOs:
* Make sure that dynamic profiles appear in the right place in the order of profiles -> #2722
* [x] don't serialize the `colorTable` key for dynamic profiles.
* [x] re-parse the user settings string if we've changed it.
* Handle changing the default profile to pwsh if it exists on first launch, or file a follow-up issue -> #2721
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
<hr>
* Create profiles by layering them
* Update test to layer multiple times on the same profile
* Add support for layering an array of profiles, but break a couple tests
* Add a defaults.json to the package
* Layer colorschemes
* Moves tests into individual classes
* adds support for layering a colorscheme on top of another
* Layer an array of color schemes
* oh no, this was missed with #2481
must have committed without staging this change, uh oh. Not like those tests actually work so nbd
* Layer keybindings
* Read settings from defaults.json + profiles.json, layer appropriately
This is like 80% of #754. Needs tests.
* Add tests for keybindings
* add support to unbind a key with `null` or `"unbound"` or `"garbage"`
* Layer or clear optional properties
* Add a helper to get an optional variable for a bunch of different types
In the end, I think we need to ask _was this worth it_
* Do this with the stretch mode too
* Add back in the GUID check for profiles
* Add some tests for global settings layering
* M A D W I T H P O W E R
Add a MsBuild target to auto-generate a header with the defaults.json as a
string in the file. That way, we can _always_ load the defaults. Literally impossible to not.
* When the user's profile.json doesn't exist, create it from a template
* Re-order profiles to match the order set in the user's profiles.json
* Add tests for re-ordering profiles to match user ordering
* Add support for hiding profiles using `"hidden": true`
* Use the hardcoded defaults.json for the exception->"use defaults" case
* Somehow I messed up the git submodules?
* woo documentation
* Fix a Terminal.App.Unit.Tests failure
* signed/unsigned is hard
* Use Alt+Settings button to open the default settings
* Missed a signed/unsigned
* Start dynamically creating profiles
* Give the inbox generators a namespace
and generally hack this a lot less
* Some very preliminary PR feedback
* More PR feedback
Use the wil helper for the exe path
Move jsonutils into their own file
kill some dead code
* Add templates to these bois
* remove some code for generating defaults, reorder defaults.json a tad
* Make guid a std::optional
* Large block of PR feedback
* Remove some dead code
* add some comments
* tag some todos
* stl is love, stl is life
* Serialize the source key
* Make the Azure cloud shell a dynamic profile
* Make the built-in namespaces public
* Add a mechanism for quick-diffing a profile
This will be used to generate the json snippets for dynamically generated profiles.
* Generate partial serializations of dynamic profiles _not_ in the user settings
* Start writing tests for generating dyn profiles
* dyn profiles generate GUIDs based on _source
* we won't run DPGs when they'd disabled?
* Add more DPG tests - TestDontRunDisabledGenerators
* Don't layer profiles with a source that's also different
* Add another test, DoLayerUserProfilesOnDynamicsWhenSourceMatches
* Actually insert new dynamic profiles into the file
* Minor cleanup of `Profile::ShouldBeLayered`
* Migrate legacy profiles gracefully
* using namespace winrt::Windows::UI::Xaml;
* _Only_ layer dynamic profiles from user settings, never create
* Write a test for migrating dynamic profiles
* Comments for dayssssss
* add `-noprofile`
* Fix the crash that dustin found
* -Encoding ASCII
* Set a profile's default scheme to Campbell
* Fix the tests I regressed
* Update UsingJsonSetting.md to reflect that changes from these PRs
* Change how GenerateGuidForProfile works
* Make AppKeyBindings do its own serialization
* Remove leftover dead code from the previous commit
* Fix up an enormous number of PR nits
* Don't layer a profile if the json doesn't have a GUID
* Fix a test I unfixed
* get rid of extraneous bois{};
* Piles of PR feedback
* Collection of PR nits
* PR nits
* Fix a typo; Update the defaults to match #2378
* Tiny nits
* In-den-taition!
* Some typos, PR nits
* Fix this broken defaults case
* Apply suggestions from code review
Co-Authored-By: Carlos Zamora <carlos.zamora@microsoft.com>
* PR nits
2019-09-16 22:34:27 +02:00
|
|
|
#include "AzureCloudShellGenerator.h" // For AzureConnectionType
|
2019-12-09 20:07:08 +01:00
|
|
|
#include "TelnetGenerator.h" // For TelnetConnectionType
|
2019-10-15 07:41:43 +02:00
|
|
|
#include "TabRowControl.h"
|
2020-05-04 22:57:12 +02:00
|
|
|
#include "ColorHelper.h"
|
2020-03-26 23:33:47 +01:00
|
|
|
#include "DebugTapConnection.h"
|
Add Dynamic Profile Generators (#2603)
_**This PR targets the #2515 PR**_. It does that for the sake of diffing. When this PR and #2515 are both ready, I'll merge #2515 first, then change the target of this branch, and merge this one.
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR adds support for "dynamic profiles", in accordance with the [Cascading Settings Spec](https://github.com/microsoft/terminal/blob/master/doc/cascadia/Cascading-Default-Settings.md#dynamic-profiles). Currently, we have three types of default profiles that fit the category of dynamic profile generators. These are profiles that we want to create on behalf of the user, but require runtime information to be able to create correctly. Because they require runtime information, we can't ship a static version of these profiles as a part of `defaults.json`. These three profile generators are:
* The Powershell Core generator
* The WSL Distro generator
* The Azure Cloud Shell generator
<!-- 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 #754
* [x] I work here
* [x] look at all these **Tests**
* [x] Requires documentation to be updated - This is done as part of the parent PR
<!-- 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
We want to be able to enable the user to edit dynamic profiles that are generated from DPGs. When dynamic profiles are added, we'll add entries for them to the user's `profiles.json`. We do this _without re-serializing_ the settings. Instead, we insert a partial serialization for the profile into the user's settings.
### Remaining TODOs:
* Make sure that dynamic profiles appear in the right place in the order of profiles -> #2722
* [x] don't serialize the `colorTable` key for dynamic profiles.
* [x] re-parse the user settings string if we've changed it.
* Handle changing the default profile to pwsh if it exists on first launch, or file a follow-up issue -> #2721
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
<hr>
* Create profiles by layering them
* Update test to layer multiple times on the same profile
* Add support for layering an array of profiles, but break a couple tests
* Add a defaults.json to the package
* Layer colorschemes
* Moves tests into individual classes
* adds support for layering a colorscheme on top of another
* Layer an array of color schemes
* oh no, this was missed with #2481
must have committed without staging this change, uh oh. Not like those tests actually work so nbd
* Layer keybindings
* Read settings from defaults.json + profiles.json, layer appropriately
This is like 80% of #754. Needs tests.
* Add tests for keybindings
* add support to unbind a key with `null` or `"unbound"` or `"garbage"`
* Layer or clear optional properties
* Add a helper to get an optional variable for a bunch of different types
In the end, I think we need to ask _was this worth it_
* Do this with the stretch mode too
* Add back in the GUID check for profiles
* Add some tests for global settings layering
* M A D W I T H P O W E R
Add a MsBuild target to auto-generate a header with the defaults.json as a
string in the file. That way, we can _always_ load the defaults. Literally impossible to not.
* When the user's profile.json doesn't exist, create it from a template
* Re-order profiles to match the order set in the user's profiles.json
* Add tests for re-ordering profiles to match user ordering
* Add support for hiding profiles using `"hidden": true`
* Use the hardcoded defaults.json for the exception->"use defaults" case
* Somehow I messed up the git submodules?
* woo documentation
* Fix a Terminal.App.Unit.Tests failure
* signed/unsigned is hard
* Use Alt+Settings button to open the default settings
* Missed a signed/unsigned
* Start dynamically creating profiles
* Give the inbox generators a namespace
and generally hack this a lot less
* Some very preliminary PR feedback
* More PR feedback
Use the wil helper for the exe path
Move jsonutils into their own file
kill some dead code
* Add templates to these bois
* remove some code for generating defaults, reorder defaults.json a tad
* Make guid a std::optional
* Large block of PR feedback
* Remove some dead code
* add some comments
* tag some todos
* stl is love, stl is life
* Serialize the source key
* Make the Azure cloud shell a dynamic profile
* Make the built-in namespaces public
* Add a mechanism for quick-diffing a profile
This will be used to generate the json snippets for dynamically generated profiles.
* Generate partial serializations of dynamic profiles _not_ in the user settings
* Start writing tests for generating dyn profiles
* dyn profiles generate GUIDs based on _source
* we won't run DPGs when they'd disabled?
* Add more DPG tests - TestDontRunDisabledGenerators
* Don't layer profiles with a source that's also different
* Add another test, DoLayerUserProfilesOnDynamicsWhenSourceMatches
* Actually insert new dynamic profiles into the file
* Minor cleanup of `Profile::ShouldBeLayered`
* Migrate legacy profiles gracefully
* using namespace winrt::Windows::UI::Xaml;
* _Only_ layer dynamic profiles from user settings, never create
* Write a test for migrating dynamic profiles
* Comments for dayssssss
* add `-noprofile`
* Fix the crash that dustin found
* -Encoding ASCII
* Set a profile's default scheme to Campbell
* Fix the tests I regressed
* Update UsingJsonSetting.md to reflect that changes from these PRs
* Change how GenerateGuidForProfile works
* Make AppKeyBindings do its own serialization
* Remove leftover dead code from the previous commit
* Fix up an enormous number of PR nits
* Don't layer a profile if the json doesn't have a GUID
* Fix a test I unfixed
* get rid of extraneous bois{};
* Piles of PR feedback
* Collection of PR nits
* PR nits
* Fix a typo; Update the defaults to match #2378
* Tiny nits
* In-den-taition!
* Some typos, PR nits
* Fix this broken defaults case
* Apply suggestions from code review
Co-Authored-By: Carlos Zamora <carlos.zamora@microsoft.com>
* PR nits
2019-09-16 22:34:27 +02:00
|
|
|
|
2019-07-09 23:47:30 +02:00
|
|
|
using namespace winrt;
|
2020-04-17 19:15:20 +02:00
|
|
|
using namespace winrt::Windows::Foundation::Collections;
|
2019-09-04 23:34:06 +02:00
|
|
|
using namespace winrt::Windows::UI::Xaml;
|
|
|
|
using namespace winrt::Windows::UI::Core;
|
|
|
|
using namespace winrt::Windows::System;
|
|
|
|
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
|
|
|
using namespace winrt::Windows::UI::Text;
|
|
|
|
using namespace winrt::Microsoft::Terminal;
|
|
|
|
using namespace winrt::Microsoft::Terminal::TerminalControl;
|
|
|
|
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
|
|
|
using namespace winrt::Microsoft::Terminal::Settings;
|
|
|
|
using namespace ::TerminalApp;
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
using namespace ::Microsoft::Console;
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
namespace winrt
|
|
|
|
{
|
|
|
|
namespace MUX = Microsoft::UI::Xaml;
|
2019-10-15 07:41:43 +02:00
|
|
|
namespace WUX = Windows::UI::Xaml;
|
2019-09-04 23:34:06 +02:00
|
|
|
using IInspectable = Windows::Foundation::IInspectable;
|
|
|
|
}
|
2019-07-09 23:47:30 +02:00
|
|
|
|
|
|
|
namespace winrt::TerminalApp::implementation
|
|
|
|
{
|
2019-11-01 23:47:05 +01:00
|
|
|
TerminalPage::TerminalPage() :
|
2020-02-04 22:51:11 +01:00
|
|
|
_tabs{ winrt::single_threaded_observable_vector<TerminalApp::Tab>() }
|
2019-07-09 23:47:30 +02:00
|
|
|
{
|
2019-07-13 00:21:45 +02:00
|
|
|
InitializeComponent();
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void TerminalPage::SetSettings(std::shared_ptr<::TerminalApp::CascadiaSettings> settings, bool needRefreshUI)
|
|
|
|
{
|
|
|
|
_settings = settings;
|
|
|
|
if (needRefreshUI)
|
|
|
|
{
|
|
|
|
_RefreshUIForSettingsReload();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TerminalPage::Create()
|
|
|
|
{
|
|
|
|
// Hookup the key bindings
|
|
|
|
_HookupKeyBindings(_settings->GetKeybindings());
|
|
|
|
|
|
|
|
_tabContent = this->TabContent();
|
|
|
|
_tabRow = this->TabRow();
|
|
|
|
_tabView = _tabRow.TabView();
|
2019-11-08 18:27:20 +01:00
|
|
|
_rearranging = false;
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// GH#2455 - Make sure to try/catch calls to Application::Current,
|
|
|
|
// because that _won't_ be an instance of TerminalApp::App in the
|
|
|
|
// LocalTests
|
|
|
|
auto isElevated = false;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// GH#3581 - There's a platform limitation that causes us to crash when we rearrange tabs.
|
|
|
|
// Xaml tries to send a drag visual (to wit: a screenshot) to the drag hosting process,
|
|
|
|
// but that process is running at a different IL than us.
|
|
|
|
// For now, we're disabling elevated drag.
|
2020-04-27 18:17:19 +02:00
|
|
|
isElevated = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated();
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
}
|
|
|
|
CATCH_LOG();
|
|
|
|
|
2020-03-11 16:52:09 +01:00
|
|
|
_tabView.CanReorderTabs(!isElevated);
|
|
|
|
_tabView.CanDragTabs(!isElevated);
|
|
|
|
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
_tabView.TabDragStarting([weakThis{ get_weak() }](auto&& /*o*/, auto&& /*a*/) {
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
if (auto page{ weakThis.get() })
|
2019-11-08 18:27:20 +01:00
|
|
|
{
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
page->_rearranging = true;
|
|
|
|
page->_rearrangeFrom = std::nullopt;
|
|
|
|
page->_rearrangeTo = std::nullopt;
|
2019-11-08 18:27:20 +01:00
|
|
|
}
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
});
|
|
|
|
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
_tabView.TabDragCompleted([weakThis{ get_weak() }](auto&& /*o*/, auto&& /*a*/) {
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
if (auto page{ weakThis.get() })
|
|
|
|
{
|
|
|
|
auto& from{ page->_rearrangeFrom };
|
|
|
|
auto& to{ page->_rearrangeTo };
|
2019-11-08 18:27:20 +01:00
|
|
|
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
if (from.has_value() && to.has_value() && to != from)
|
|
|
|
{
|
|
|
|
auto& tabs{ page->_tabs };
|
2020-02-04 22:51:11 +01:00
|
|
|
auto tab = tabs.GetAt(from.value());
|
|
|
|
tabs.RemoveAt(from.value());
|
|
|
|
tabs.InsertAt(to.value(), tab);
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
page->_rearranging = false;
|
|
|
|
from = std::nullopt;
|
|
|
|
to = std::nullopt;
|
|
|
|
}
|
2019-11-08 18:27:20 +01:00
|
|
|
});
|
2019-10-15 07:41:43 +02:00
|
|
|
|
|
|
|
auto tabRowImpl = winrt::get_self<implementation::TabRowControl>(_tabRow);
|
|
|
|
_newTabButton = tabRowImpl->NewTabButton();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
if (_settings->GlobalSettings().GetShowTabsInTitlebar())
|
|
|
|
{
|
|
|
|
// Remove the TabView from the page. We'll hang on to it, we need to
|
|
|
|
// put it in the titlebar.
|
|
|
|
uint32_t index = 0;
|
|
|
|
if (this->Root().Children().IndexOf(_tabRow, index))
|
|
|
|
{
|
|
|
|
this->Root().Children().RemoveAt(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Inform the host that our titlebar content has changed.
|
|
|
|
_setTitleBarContentHandlers(*this, _tabRow);
|
|
|
|
}
|
|
|
|
|
2019-11-27 22:51:38 +01:00
|
|
|
// Hookup our event handlers to the ShortcutActionDispatch
|
|
|
|
_RegisterActionCallbacks();
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
//Event Bindings (Early)
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
_newTabButton.Click([weakThis{ get_weak() }](auto&&, auto&&) {
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
if (auto page{ weakThis.get() })
|
|
|
|
{
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
page->_OpenNewTab(nullptr);
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
});
|
|
|
|
_tabView.SelectionChanged({ this, &TerminalPage::_OnTabSelectionChanged });
|
2019-10-15 07:41:43 +02:00
|
|
|
_tabView.TabCloseRequested({ this, &TerminalPage::_OnTabCloseRequested });
|
|
|
|
_tabView.TabItemsChanged({ this, &TerminalPage::_OnTabItemsChanged });
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
_CreateNewTabFlyout();
|
2020-01-27 16:34:12 +01:00
|
|
|
|
2020-01-10 01:16:54 +01:00
|
|
|
_UpdateTabWidthMode();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
_tabContent.SizeChanged({ this, &TerminalPage::_OnContentSizeChanged });
|
2020-01-27 16:34:12 +01:00
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// Once the page is actually laid out on the screen, trigger all our
|
|
|
|
// startup actions. Things like Panes need to know at least how big the
|
|
|
|
// window will be, so they can subdivide that space.
|
|
|
|
//
|
|
|
|
// _OnFirstLayout will remove this handler so it doesn't get called more than once.
|
|
|
|
_layoutUpdatedRevoker = _tabContent.LayoutUpdated(winrt::auto_revoke, { this, &TerminalPage::_OnFirstLayout });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - This method is called once on startup, on the first LayoutUpdated event.
|
|
|
|
// We'll use this event to know that we have an ActualWidth and
|
|
|
|
// ActualHeight, so we can now attempt to process our list of startup
|
|
|
|
// actions.
|
|
|
|
// - We'll remove this event handler when the event is first handled.
|
|
|
|
// - If there are no startup actions, we'll open a single tab with the
|
|
|
|
// default profile.
|
|
|
|
// Arguments:
|
|
|
|
// - <unused>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_OnFirstLayout(const IInspectable& /*sender*/, const IInspectable& /*eventArgs*/)
|
|
|
|
{
|
|
|
|
// Only let this succeed once.
|
|
|
|
_layoutUpdatedRevoker.revoke();
|
|
|
|
|
|
|
|
// This event fires every time the layout changes, but it is always the
|
|
|
|
// last one to fire in any layout change chain. That gives us great
|
|
|
|
// flexibility in finding the right point at which to initialize our
|
|
|
|
// renderer (and our terminal). Any earlier than the last layout update
|
|
|
|
// and we may not know the terminal's starting size.
|
|
|
|
if (_startupState == StartupState::NotInitialized)
|
2020-01-27 16:34:12 +01:00
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
_startupState = StartupState::InStartup;
|
2020-01-27 16:34:12 +01:00
|
|
|
_appArgs.ValidateStartupCommands();
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
if (_appArgs.GetStartupActions().empty())
|
|
|
|
{
|
|
|
|
_OpenNewTab(nullptr);
|
|
|
|
_startupState = StartupState::Initialized;
|
|
|
|
_InitializedHandlers(*this, nullptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_ProcessStartupActions();
|
|
|
|
}
|
2020-01-27 16:34:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// - Process all the startup actions in our list of startup actions. We'll
|
|
|
|
// do this all at once here.
|
2020-01-27 16:34:12 +01:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
winrt::fire_and_forget TerminalPage::_ProcessStartupActions()
|
2020-01-27 16:34:12 +01:00
|
|
|
{
|
|
|
|
// If there are no actions left, do nothing.
|
|
|
|
if (_appArgs.GetStartupActions().empty())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto weakThis{ get_weak() };
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// Handle it on a subsequent pass of the UI thread.
|
|
|
|
co_await winrt::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal);
|
2020-01-27 16:34:12 +01:00
|
|
|
if (auto page{ weakThis.get() })
|
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
for (const auto& action : _appArgs.GetStartupActions())
|
|
|
|
{
|
|
|
|
_actionDispatch->DoAction(action);
|
|
|
|
}
|
|
|
|
_startupState = StartupState::Initialized;
|
|
|
|
_InitializedHandlers(*this, nullptr);
|
2020-01-27 16:34:12 +01:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2020-03-27 22:00:32 +01:00
|
|
|
// - Show a dialog with "About" information. Displays the app's Display
|
|
|
|
// Name, version, getting started link, documentation link, release
|
|
|
|
// Notes link, and privacy policy link.
|
|
|
|
void TerminalPage::_ShowAboutDialog()
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-03-27 22:00:32 +01:00
|
|
|
_showDialogHandlers(*this, FindName(L"AboutDialog").try_as<WUX::Controls::ContentDialog>());
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2020-03-27 22:00:32 +01:00
|
|
|
winrt::hstring TerminalPage::ApplicationDisplayName()
|
|
|
|
{
|
2020-04-07 20:35:05 +02:00
|
|
|
if (const auto appLogic{ implementation::AppLogic::Current() })
|
2020-03-27 22:00:32 +01:00
|
|
|
{
|
2020-04-07 20:35:05 +02:00
|
|
|
return appLogic->ApplicationDisplayName();
|
2020-03-27 22:00:32 +01:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2020-04-07 20:35:05 +02:00
|
|
|
return RS_(L"ApplicationDisplayNameUnpackaged");
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
2020-03-27 22:00:32 +01:00
|
|
|
winrt::hstring TerminalPage::ApplicationVersion()
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-04-07 20:35:05 +02:00
|
|
|
if (const auto appLogic{ implementation::AppLogic::Current() })
|
2020-03-27 22:00:32 +01:00
|
|
|
{
|
2020-04-07 20:35:05 +02:00
|
|
|
return appLogic->ApplicationVersion();
|
2020-03-27 22:00:32 +01:00
|
|
|
}
|
|
|
|
|
2020-04-07 20:35:05 +02:00
|
|
|
return RS_(L"ApplicationVersionUnknown");
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
2020-05-01 00:06:13 +02:00
|
|
|
void TerminalPage::_ThirdPartyNoticesOnClick(const IInspectable& /*sender*/, const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/)
|
2020-04-28 22:22:44 +02:00
|
|
|
{
|
2020-05-01 00:06:13 +02:00
|
|
|
std::filesystem::path currentPath{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
|
|
|
|
currentPath.replace_filename(L"NOTICE.html");
|
|
|
|
ShellExecute(nullptr, nullptr, currentPath.c_str(), nullptr, nullptr, SW_SHOW);
|
2020-04-28 22:22:44 +02:00
|
|
|
}
|
|
|
|
|
2019-09-17 07:43:27 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Displays a dialog for warnings found while closing the terminal app using
|
|
|
|
// key binding with multiple tabs opened. Display messages to warn user
|
2020-02-10 21:40:01 +01:00
|
|
|
// that more than 1 tab is opened, and once the user clicks the OK button, remove
|
2019-09-17 07:43:27 +02:00
|
|
|
// all the tabs and shut down and app. If cancel is clicked, the dialog will close
|
|
|
|
// - Only one dialog can be visible at a time. If another dialog is visible
|
|
|
|
// when this is called, nothing happens. See _ShowDialog for details
|
|
|
|
void TerminalPage::_ShowCloseWarningDialog()
|
|
|
|
{
|
2020-03-27 22:00:32 +01:00
|
|
|
_showDialogHandlers(*this, FindName(L"CloseAllDialog").try_as<WUX::Controls::ContentDialog>());
|
2019-09-17 07:43:27 +02:00
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Builds the flyout (dropdown) attached to the new tab button, and
|
|
|
|
// attaches it to the button. Populates the flyout with one entry per
|
|
|
|
// Profile, displaying the profile's name. Clicking each flyout item will
|
|
|
|
// open a new tab with that profile.
|
|
|
|
// Below the profiles are the static menu items: settings, feedback
|
|
|
|
void TerminalPage::_CreateNewTabFlyout()
|
|
|
|
{
|
2019-10-15 07:41:43 +02:00
|
|
|
auto newTabFlyout = WUX::Controls::MenuFlyout{};
|
2019-09-04 23:34:06 +02:00
|
|
|
auto keyBindings = _settings->GetKeybindings();
|
|
|
|
|
|
|
|
const GUID defaultProfileGuid = _settings->GlobalSettings().GetDefaultProfile();
|
|
|
|
// the number of profiles should not change in the loop for this to work
|
|
|
|
auto const profileCount = gsl::narrow_cast<int>(_settings->GetProfiles().size());
|
|
|
|
for (int profileIndex = 0; profileIndex < profileCount; profileIndex++)
|
|
|
|
{
|
|
|
|
const auto& profile = _settings->GetProfiles()[profileIndex];
|
2019-10-15 07:41:43 +02:00
|
|
|
auto profileMenuItem = WUX::Controls::MenuFlyoutItem{};
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
// add the keyboard shortcuts for the first 9 profiles
|
|
|
|
if (profileIndex < 9)
|
|
|
|
{
|
2020-03-31 22:58:28 +02:00
|
|
|
// Look for a keychord that is bound to the equivalent
|
|
|
|
// NewTab(ProfileIndex=N) action
|
|
|
|
auto actionAndArgs = winrt::make_self<winrt::TerminalApp::implementation::ActionAndArgs>();
|
|
|
|
actionAndArgs->Action(ShortcutAction::NewTab);
|
|
|
|
auto newTabArgs = winrt::make_self<winrt::TerminalApp::implementation::NewTabArgs>();
|
|
|
|
auto newTerminalArgs = winrt::make_self<winrt::TerminalApp::implementation::NewTerminalArgs>();
|
|
|
|
newTerminalArgs->ProfileIndex(profileIndex);
|
|
|
|
newTabArgs->TerminalArgs(*newTerminalArgs);
|
|
|
|
actionAndArgs->Args(*newTabArgs);
|
|
|
|
auto profileKeyChord{ keyBindings.GetKeyBindingForActionWithArgs(*actionAndArgs) };
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
// make sure we find one to display
|
|
|
|
if (profileKeyChord)
|
|
|
|
{
|
|
|
|
_SetAcceleratorForMenuItem(profileMenuItem, profileKeyChord);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto profileName = profile.GetName();
|
|
|
|
winrt::hstring hName{ profileName };
|
|
|
|
profileMenuItem.Text(hName);
|
|
|
|
|
|
|
|
// If there's an icon set for this profile, set it as the icon for
|
|
|
|
// this flyout item.
|
|
|
|
if (profile.HasIcon())
|
|
|
|
{
|
2019-10-15 07:41:43 +02:00
|
|
|
auto iconSource = GetColoredIcon<WUX::Controls::IconSource>(profile.GetExpandedIconPath());
|
|
|
|
|
|
|
|
WUX::Controls::IconSourceElement iconElement;
|
|
|
|
iconElement.IconSource(iconSource);
|
|
|
|
profileMenuItem.Icon(iconElement);
|
2020-03-05 23:32:46 +01:00
|
|
|
Automation::AutomationProperties::SetAccessibilityView(iconElement, Automation::Peers::AccessibilityView::Raw);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (profile.GetGuid() == defaultProfileGuid)
|
|
|
|
{
|
|
|
|
// Contrast the default profile with others in font weight.
|
|
|
|
profileMenuItem.FontWeight(FontWeights::Bold());
|
|
|
|
}
|
|
|
|
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
profileMenuItem.Click([profileIndex, weakThis{ get_weak() }](auto&&, auto&&) {
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
if (auto page{ weakThis.get() })
|
|
|
|
{
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
auto newTerminalArgs = winrt::make_self<winrt::TerminalApp::implementation::NewTerminalArgs>();
|
|
|
|
newTerminalArgs->ProfileIndex(profileIndex);
|
|
|
|
page->_OpenNewTab(*newTerminalArgs);
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
});
|
|
|
|
newTabFlyout.Items().Append(profileMenuItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
// add menu separator
|
2019-10-15 07:41:43 +02:00
|
|
|
auto separatorItem = WUX::Controls::MenuFlyoutSeparator{};
|
2019-09-04 23:34:06 +02:00
|
|
|
newTabFlyout.Items().Append(separatorItem);
|
|
|
|
|
|
|
|
// add static items
|
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// GH#2455 - Make sure to try/catch calls to Application::Current,
|
|
|
|
// because that _won't_ be an instance of TerminalApp::App in the
|
|
|
|
// LocalTests
|
|
|
|
auto isUwp = false;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
isUwp = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsUwp();
|
|
|
|
}
|
|
|
|
CATCH_LOG();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2019-12-09 20:07:08 +01:00
|
|
|
if (!isUwp)
|
|
|
|
{
|
|
|
|
// Create the settings button.
|
|
|
|
auto settingsItem = WUX::Controls::MenuFlyoutItem{};
|
|
|
|
settingsItem.Text(RS_(L"SettingsMenuItem"));
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2019-12-09 20:07:08 +01:00
|
|
|
WUX::Controls::SymbolIcon ico{};
|
|
|
|
ico.Symbol(WUX::Controls::Symbol::Setting);
|
|
|
|
settingsItem.Icon(ico);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2019-12-09 20:07:08 +01:00
|
|
|
settingsItem.Click({ this, &TerminalPage::_SettingsButtonOnClick });
|
|
|
|
newTabFlyout.Items().Append(settingsItem);
|
|
|
|
|
|
|
|
auto settingsKeyChord = keyBindings.GetKeyBindingForAction(ShortcutAction::OpenSettings);
|
|
|
|
if (settingsKeyChord)
|
|
|
|
{
|
|
|
|
_SetAcceleratorForMenuItem(settingsItem, settingsKeyChord);
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2019-12-09 20:07:08 +01:00
|
|
|
// Create the feedback button.
|
|
|
|
auto feedbackFlyout = WUX::Controls::MenuFlyoutItem{};
|
|
|
|
feedbackFlyout.Text(RS_(L"FeedbackMenuItem"));
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2019-12-09 20:07:08 +01:00
|
|
|
WUX::Controls::FontIcon feedbackIcon{};
|
|
|
|
feedbackIcon.Glyph(L"\xE939");
|
|
|
|
feedbackIcon.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" });
|
|
|
|
feedbackFlyout.Icon(feedbackIcon);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2019-12-09 20:07:08 +01:00
|
|
|
feedbackFlyout.Click({ this, &TerminalPage::_FeedbackButtonOnClick });
|
|
|
|
newTabFlyout.Items().Append(feedbackFlyout);
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
// Create the about button.
|
2019-10-15 07:41:43 +02:00
|
|
|
auto aboutFlyout = WUX::Controls::MenuFlyoutItem{};
|
2019-11-01 23:47:05 +01:00
|
|
|
aboutFlyout.Text(RS_(L"AboutMenuItem"));
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2019-10-15 07:41:43 +02:00
|
|
|
WUX::Controls::SymbolIcon aboutIcon{};
|
|
|
|
aboutIcon.Symbol(WUX::Controls::Symbol::Help);
|
|
|
|
aboutFlyout.Icon(aboutIcon);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
aboutFlyout.Click({ this, &TerminalPage::_AboutButtonOnClick });
|
|
|
|
newTabFlyout.Items().Append(aboutFlyout);
|
|
|
|
}
|
|
|
|
|
|
|
|
_newTabButton.Flyout(newTabFlyout);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function Description:
|
|
|
|
// Called when the openNewTabDropdown keybinding is used.
|
|
|
|
// Adds the flyout show option to left-align the dropdown with the split button.
|
|
|
|
// Shows the dropdown flyout.
|
|
|
|
void TerminalPage::_OpenNewTabDropdown()
|
|
|
|
{
|
2019-10-15 07:41:43 +02:00
|
|
|
WUX::Controls::Primitives::FlyoutShowOptions options{};
|
|
|
|
options.Placement(WUX::Controls::Primitives::FlyoutPlacementMode::BottomEdgeAlignedLeft);
|
2019-09-04 23:34:06 +02:00
|
|
|
_newTabButton.Flyout().ShowAt(_newTabButton, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Open a new tab. This will create the TerminalControl hosting the
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
// terminal, and add a new Tab to our list of tabs. The method can
|
|
|
|
// optionally be provided a NewTerminalArgs, which will be used to create
|
|
|
|
// a tab using the values in that object.
|
2019-09-04 23:34:06 +02:00
|
|
|
// Arguments:
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
// - newTerminalArgs: An object that may contain a blob of parameters to
|
|
|
|
// control which profile is created and with possible other
|
|
|
|
// configurations. See CascadiaSettings::BuildSettings for more details.
|
|
|
|
void TerminalPage::_OpenNewTab(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs)
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
try
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
const auto [profileGuid, settings] = _settings->BuildSettings(newTerminalArgs);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
_CreateNewTabFromSettings(profileGuid, settings);
|
|
|
|
|
2020-02-04 22:51:11 +01:00
|
|
|
const uint32_t tabCount = _tabs.Size();
|
2019-12-11 03:04:33 +01:00
|
|
|
const bool usedManualProfile = (newTerminalArgs != nullptr) &&
|
|
|
|
(newTerminalArgs.ProfileIndex() != nullptr ||
|
|
|
|
newTerminalArgs.Profile().empty());
|
2019-09-04 23:34:06 +02:00
|
|
|
TraceLoggingWrite(
|
|
|
|
g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
|
|
|
|
"TabInformation",
|
|
|
|
TraceLoggingDescription("Event emitted upon new tab creation in TerminalApp"),
|
2020-02-12 21:02:48 +01:00
|
|
|
TraceLoggingUInt32(1u, "EventVer", "Version of this event"),
|
2020-02-10 21:40:01 +01:00
|
|
|
TraceLoggingUInt32(tabCount, "TabCount", "Count of tabs currently opened in TerminalApp"),
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"),
|
2019-09-04 23:34:06 +02:00
|
|
|
TraceLoggingGuid(profileGuid, "ProfileGuid", "The GUID of the profile spawned in the new tab"),
|
2020-02-12 21:02:48 +01:00
|
|
|
TraceLoggingBool(settings.UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"),
|
|
|
|
TraceLoggingFloat64(settings.TintOpacity(), "TintOpacity", "Opacity preference from the settings"),
|
|
|
|
TraceLoggingWideString(settings.FontFace().c_str(), "FontFace", "Font face chosen in the settings"),
|
2019-09-04 23:34:06 +02:00
|
|
|
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
|
|
|
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
|
|
|
}
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
CATCH_LOG();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
winrt::fire_and_forget TerminalPage::_RemoveOnCloseRoutine(Microsoft::UI::Xaml::Controls::TabViewItem tabViewItem, winrt::com_ptr<TerminalPage> page)
|
|
|
|
{
|
|
|
|
co_await winrt::resume_foreground(page->_tabView.Dispatcher());
|
|
|
|
|
|
|
|
page->_RemoveTabViewItem(tabViewItem);
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Creates a new tab with the given settings. If the tab bar is not being
|
|
|
|
// currently displayed, it will be shown.
|
|
|
|
// Arguments:
|
|
|
|
// - settings: the TerminalSettings object to use to create the TerminalControl with.
|
|
|
|
void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings)
|
|
|
|
{
|
|
|
|
// Initialize the new tab
|
|
|
|
|
|
|
|
// Create a connection based on the values in our settings object.
|
2020-03-26 23:33:47 +01:00
|
|
|
auto connection = _CreateConnectionFromSettings(profileGuid, settings);
|
|
|
|
|
|
|
|
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
|
|
|
|
if (_settings->GlobalSettings().DebugFeaturesEnabled())
|
|
|
|
{
|
|
|
|
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
|
|
|
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
|
|
|
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
|
|
|
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
|
|
|
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
|
|
|
if (bothAltsPressed)
|
|
|
|
{
|
|
|
|
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
TermControl term{ settings, connection };
|
|
|
|
|
|
|
|
// Add the new tab to the list of our tabs.
|
2020-02-04 22:51:11 +01:00
|
|
|
auto newTabImpl = winrt::make_self<Tab>(profileGuid, term);
|
|
|
|
_tabs.Append(*newTabImpl);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
// Hookup our event handlers to the new terminal
|
2020-02-04 22:51:11 +01:00
|
|
|
_RegisterTerminalEvents(term, *newTabImpl);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// Don't capture a strong ref to the tab. If the tab is removed as this
|
|
|
|
// is called, we don't really care anymore about handling the event.
|
2020-02-04 22:51:11 +01:00
|
|
|
auto weakTab = make_weak(newTabImpl);
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// When the tab's active pane changes, we'll want to lookup a new icon
|
2020-02-10 21:40:01 +01:00
|
|
|
// for it, and possibly propagate the title up to the window.
|
2020-02-04 22:51:11 +01:00
|
|
|
newTabImpl->ActivePaneChanged([weakTab, weakThis{ get_weak() }]() {
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
auto page{ weakThis.get() };
|
2020-02-04 22:51:11 +01:00
|
|
|
auto tab{ weakTab.get() };
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
|
|
|
|
if (page && tab)
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
{
|
|
|
|
// Possibly update the icon of the tab.
|
2020-02-04 22:51:11 +01:00
|
|
|
page->_UpdateTabIcon(*tab);
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// Possibly update the title of the tab, window to match the newly
|
|
|
|
// focused pane.
|
2020-02-04 22:51:11 +01:00
|
|
|
page->_UpdateTitle(*tab);
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-02-04 22:51:11 +01:00
|
|
|
auto tabViewItem = newTabImpl->GetTabViewItem();
|
2019-10-15 07:41:43 +02:00
|
|
|
_tabView.TabItems().Append(tabViewItem);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// Set this tab's icon to the icon from the user's profile
|
|
|
|
const auto* const profile = _settings->FindProfile(profileGuid);
|
2019-09-04 23:34:06 +02:00
|
|
|
if (profile != nullptr && profile->HasIcon())
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
newTabImpl->UpdateIcon(profile->GetExpandedIconPath());
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
tabViewItem.PointerPressed({ this, &TerminalPage::_OnTabClick });
|
|
|
|
|
|
|
|
// When the tab is closed, remove it from our list of tabs.
|
2020-02-04 22:51:11 +01:00
|
|
|
newTabImpl->Closed([tabViewItem, weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) {
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
if (auto page{ weakThis.get() })
|
|
|
|
{
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
page->_RemoveOnCloseRoutine(tabViewItem, page);
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
});
|
|
|
|
|
2020-03-26 23:33:47 +01:00
|
|
|
if (debugConnection) // this will only be set if global debugging is on and tap is active
|
|
|
|
{
|
|
|
|
TermControl newControl{ settings, debugConnection };
|
|
|
|
_RegisterTerminalEvents(newControl, *newTabImpl);
|
|
|
|
// Split (auto) with the debug tap.
|
|
|
|
newTabImpl->SplitPane(SplitState::Automatic, profileGuid, newControl);
|
|
|
|
}
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// This kicks off TabView::SelectionChanged, in response to which
|
|
|
|
// we'll attach the terminal's Xaml control to the Xaml root.
|
|
|
|
_tabView.SelectedItem(tabViewItem);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Creates a new connection based on the profile settings
|
|
|
|
// Arguments:
|
|
|
|
// - the profile GUID we want the settings from
|
|
|
|
// - the terminal settings
|
|
|
|
// Return value:
|
|
|
|
// - the desired connection
|
|
|
|
TerminalConnection::ITerminalConnection TerminalPage::_CreateConnectionFromSettings(GUID profileGuid,
|
|
|
|
winrt::Microsoft::Terminal::Settings::TerminalSettings settings)
|
|
|
|
{
|
|
|
|
const auto* const profile = _settings->FindProfile(profileGuid);
|
|
|
|
|
|
|
|
TerminalConnection::ITerminalConnection connection{ nullptr };
|
|
|
|
|
|
|
|
GUID connectionType{ 0 };
|
2019-09-05 22:38:42 +02:00
|
|
|
GUID sessionGuid{ 0 };
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
if (profile->HasConnectionType())
|
|
|
|
{
|
|
|
|
connectionType = profile->GetConnectionType();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (profile->HasConnectionType() &&
|
|
|
|
profile->GetConnectionType() == AzureConnectionType &&
|
|
|
|
TerminalConnection::AzureConnection::IsAzureConnectionAvailable())
|
|
|
|
{
|
2020-02-21 01:21:05 +01:00
|
|
|
// TODO GH#4661: Replace this with directly using the AzCon when our VT is better
|
|
|
|
std::filesystem::path azBridgePath{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
|
|
|
|
azBridgePath.replace_filename(L"TerminalAzBridge.exe");
|
2020-04-17 19:15:20 +02:00
|
|
|
connection = TerminalConnection::ConptyConnection(azBridgePath.wstring(),
|
|
|
|
L".",
|
|
|
|
L"Azure",
|
|
|
|
nullptr,
|
|
|
|
settings.InitialRows(),
|
|
|
|
settings.InitialCols(),
|
|
|
|
winrt::guid());
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
2019-12-09 20:07:08 +01:00
|
|
|
else if (profile->HasConnectionType() &&
|
|
|
|
profile->GetConnectionType() == TelnetConnectionType)
|
|
|
|
{
|
|
|
|
connection = TerminalConnection::TelnetConnection(settings.Commandline());
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
else
|
|
|
|
{
|
2020-04-17 19:15:20 +02:00
|
|
|
std::wstring guidWString = Utils::GuidToString(profileGuid);
|
|
|
|
|
|
|
|
StringMap envMap{};
|
|
|
|
envMap.Insert(L"WT_PROFILE_ID", guidWString);
|
|
|
|
envMap.Insert(L"WSLENV", L"WT_PROFILE_ID");
|
|
|
|
|
|
|
|
auto conhostConn = TerminalConnection::ConptyConnection(
|
|
|
|
settings.Commandline(),
|
|
|
|
settings.StartingDirectory(),
|
|
|
|
settings.StartingTitle(),
|
|
|
|
envMap.GetView(),
|
|
|
|
settings.InitialRows(),
|
|
|
|
settings.InitialCols(),
|
|
|
|
winrt::guid());
|
|
|
|
|
2019-09-05 22:38:42 +02:00
|
|
|
sessionGuid = conhostConn.Guid();
|
|
|
|
connection = conhostConn;
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TraceLoggingWrite(
|
|
|
|
g_hTerminalAppProvider,
|
|
|
|
"ConnectionCreated",
|
|
|
|
TraceLoggingDescription("Event emitted upon the creation of a connection"),
|
|
|
|
TraceLoggingGuid(connectionType, "ConnectionTypeGuid", "The type of the connection"),
|
2019-09-05 22:38:42 +02:00
|
|
|
TraceLoggingGuid(profileGuid, "ProfileGuid", "The profile's GUID"),
|
|
|
|
TraceLoggingGuid(sessionGuid, "SessionGuid", "The WT_SESSION's GUID"),
|
2019-09-04 23:34:06 +02:00
|
|
|
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
|
|
|
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
|
|
|
|
|
|
|
return connection;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when the settings button is clicked. Launches a background
|
|
|
|
// thread to open the settings file in the default JSON editor.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_SettingsButtonOnClick(const IInspectable&,
|
|
|
|
const RoutedEventArgs&)
|
|
|
|
{
|
Add Cascading User + Default Settings (#2515)
This PR represents the start of the work on Cascading User + default settings, #754.
Cascading settings will be done in two parts:
* [ ] Layered Default+User settings (this PR)
* [ ] Dynamic Profile Generation (#2603).
Until _both_ are done, _neither are going in. The dynamic profiles PR will target this PR when it's ready, but will go in as a separate commit into master.
This PR covers adding one primary feature: the settings are now in two separate files:
* a static `defaults.json` that ships with the package (the "default settings")
* a `profiles.json` with the user's customizations (the "user settings)
User settings are _layered_ upon the settings in the defaults settings.
## References
Other things that might be related here:
* #1378 - This seems like it's definitely fixed. The default keybindings are _much_ cleaner, and without the save-on-load behavior, the user's keybindings will be left in a good state
* #1398 - This might have honestly been solved by #2475
## PR Checklist
* [x] Closes #754
* [x] Closes #1378
* [x] Closes #2566
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated - it **ABSOLUTELY DOES**
## Detailed Description of the Pull Request / Additional comments
1. We start by taking all of the `FromJson` functions in Profile, ColorScheme, Globals, etc, and converting them to `LayerJson` methods. These are effectively the same, with the change that instead of building a new object, they are simply layering the values on top of `this` object.
2. Next, we add tests for layering properties like that.
3. Now, we add a `defaults.json` to the package. This is the file the users can refer to as our default settings.
4. We then take that `defaults.json` and stamp it into an auto generated `.h` file, so we can use it's data without having to worry about reading it from disk.
5. We then change the `LoadAll` function in `CascadiaSettings`. Now, the function does two loads - one from the defaults, and then a second load from the `profiles.json` file, layering the settings from each source upon the previous values.
6. If the `profiles.json` file doesn't exist, we'll create it from a hardcoded `userDefaults.json`, which is stamped in similar to how `defaults.json` is.
7. We also add support for _unbinding_ keybindings that might exist in the `defaults.json`, but the user doesn't want to be bound to anything.
8. We add support for _hiding_ a profile, which is useful if a user doesn't want one of the default profiles to appear in the list of profiles.
## TODO:
* [x] Still need to make Alt+Click work on the settings button
* [x] Need to write some user documentation on how the new settings model works
* [x] Fix the pair of tests I broke (re: Duplicate profiles)
<hr>
* Create profiles by layering them
* Update test to layer multiple times on the same profile
* Add support for layering an array of profiles, but break a couple tests
* Add a defaults.json to the package
* Layer colorschemes
* Moves tests into individual classes
* adds support for layering a colorscheme on top of another
* Layer an array of color schemes
* oh no, this was missed with #2481
must have committed without staging this change, uh oh. Not like those tests actually work so nbd
* Layer keybindings
* Read settings from defaults.json + profiles.json, layer appropriately
This is like 80% of #754. Needs tests.
* Add tests for keybindings
* add support to unbind a key with `null` or `"unbound"` or `"garbage"`
* Layer or clear optional properties
* Add a helper to get an optional variable for a bunch of different types
In the end, I think we need to ask _was this worth it_
* Do this with the stretch mode too
* Add back in the GUID check for profiles
* Add some tests for global settings layering
* M A D W I T H P O W E R
Add a MsBuild target to auto-generate a header with the defaults.json as a
string in the file. That way, we can _always_ load the defaults. Literally impossible to not.
* When the user's profile.json doesn't exist, create it from a template
* Re-order profiles to match the order set in the user's profiles.json
* Add tests for re-ordering profiles to match user ordering
* Add support for hiding profiles using `"hidden": true`
* Use the hardcoded defaults.json for the exception->"use defaults" case
* Somehow I messed up the git submodules?
* woo documentation
* Fix a Terminal.App.Unit.Tests failure
* signed/unsigned is hard
* Use Alt+Settings button to open the default settings
* Missed a signed/unsigned
* Some very preliminary PR feedback
* More PR feedback
Use the wil helper for the exe path
Move jsonutils into their own file
kill some dead code
* Add templates to these bois
* remove some code for generating defaults, reorder defaults.json a tad
* Make guid a std::optional
* Large block of PR feedback
* Remove some dead code
* add some comments
* tag some todos
* stl is love, stl is life
* add `-noprofile`
* Fix the crash that dustin found
* -Encoding ASCII
* Set a profile's default scheme to Campbell
* Fix the tests I regressed
* Update UsingJsonSetting.md to reflect that changes from these PRs
* Change how GenerateGuidForProfile works
* Make AppKeyBindings do its own serialization
* Remove leftover dead code from the previous commit
* Fix up an enormous number of PR nits
* Fix a typo; Update the defaults to match #2378
* Tiny nits
* Some typos, PR nits
* Fix this broken defaults case
2019-09-16 21:57:10 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
_LaunchSettings(altPressed);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when the feedback button is clicked. Launches github in your
|
|
|
|
// default browser, navigated to the "issues" page of the Terminal repo.
|
|
|
|
void TerminalPage::_FeedbackButtonOnClick(const IInspectable&,
|
|
|
|
const RoutedEventArgs&)
|
|
|
|
{
|
2019-11-01 23:47:05 +01:00
|
|
|
const auto feedbackUriValue = RS_(L"FeedbackUriValue");
|
2020-03-23 18:15:24 +01:00
|
|
|
winrt::Windows::Foundation::Uri feedbackUri{ feedbackUriValue };
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2020-03-23 18:15:24 +01:00
|
|
|
winrt::Windows::System::Launcher::LaunchUriAsync(feedbackUri);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when the about button is clicked. See _ShowAboutDialog for more info.
|
|
|
|
// Arguments:
|
|
|
|
// - <unused>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_AboutButtonOnClick(const IInspectable&,
|
|
|
|
const RoutedEventArgs&)
|
|
|
|
{
|
|
|
|
_ShowAboutDialog();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2019-11-27 22:51:38 +01:00
|
|
|
// - Configure the AppKeyBindings to use our ShortcutActionDispatch as the
|
|
|
|
// object to handle dispatching ShortcutAction events.
|
2019-09-04 23:34:06 +02:00
|
|
|
// Arguments:
|
|
|
|
// - bindings: A AppKeyBindings object to wire up with our event handlers
|
|
|
|
void TerminalPage::_HookupKeyBindings(TerminalApp::AppKeyBindings bindings) noexcept
|
|
|
|
{
|
2019-12-11 03:04:33 +01:00
|
|
|
bindings.SetDispatch(*_actionDispatch);
|
2019-11-27 22:51:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Register our event handlers with our ShortcutActionDispatch. The
|
|
|
|
// ShortcutActionDispatch is responsible for raising the appropriate
|
|
|
|
// events for an ActionAndArgs. WE'll handle each possible event in our
|
|
|
|
// own way.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_RegisterActionCallbacks()
|
|
|
|
{
|
|
|
|
// Hook up the ShortcutActionDispatch object's events to our handlers.
|
2019-09-04 23:34:06 +02:00
|
|
|
// They should all be hooked up here, regardless of whether or not
|
|
|
|
// there's an actual keychord for them.
|
2019-12-11 03:04:33 +01:00
|
|
|
_actionDispatch->OpenNewTabDropdown({ this, &TerminalPage::_HandleOpenNewTabDropdown });
|
|
|
|
_actionDispatch->DuplicateTab({ this, &TerminalPage::_HandleDuplicateTab });
|
|
|
|
_actionDispatch->CloseTab({ this, &TerminalPage::_HandleCloseTab });
|
|
|
|
_actionDispatch->ClosePane({ this, &TerminalPage::_HandleClosePane });
|
|
|
|
_actionDispatch->CloseWindow({ this, &TerminalPage::_HandleCloseWindow });
|
|
|
|
_actionDispatch->ScrollUp({ this, &TerminalPage::_HandleScrollUp });
|
|
|
|
_actionDispatch->ScrollDown({ this, &TerminalPage::_HandleScrollDown });
|
|
|
|
_actionDispatch->NextTab({ this, &TerminalPage::_HandleNextTab });
|
|
|
|
_actionDispatch->PrevTab({ this, &TerminalPage::_HandlePrevTab });
|
|
|
|
_actionDispatch->SplitPane({ this, &TerminalPage::_HandleSplitPane });
|
|
|
|
_actionDispatch->ScrollUpPage({ this, &TerminalPage::_HandleScrollUpPage });
|
|
|
|
_actionDispatch->ScrollDownPage({ this, &TerminalPage::_HandleScrollDownPage });
|
|
|
|
_actionDispatch->OpenSettings({ this, &TerminalPage::_HandleOpenSettings });
|
|
|
|
_actionDispatch->PasteText({ this, &TerminalPage::_HandlePasteText });
|
|
|
|
_actionDispatch->NewTab({ this, &TerminalPage::_HandleNewTab });
|
|
|
|
_actionDispatch->SwitchToTab({ this, &TerminalPage::_HandleSwitchToTab });
|
|
|
|
_actionDispatch->ResizePane({ this, &TerminalPage::_HandleResizePane });
|
|
|
|
_actionDispatch->MoveFocus({ this, &TerminalPage::_HandleMoveFocus });
|
|
|
|
_actionDispatch->CopyText({ this, &TerminalPage::_HandleCopyText });
|
|
|
|
_actionDispatch->AdjustFontSize({ this, &TerminalPage::_HandleAdjustFontSize });
|
Search - add search box control and implement search experience (#3590)
<!-- 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)? -->
This is the PR for feature Search: #605
This PR includes the newly introduced SearchBoxControl in TermControl dir, which is the search bar for the search experience. And the codes that enable Search in Windows Terminal.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
The PR that migrates the Conhost search module: https://github.com/microsoft/terminal/pull/3279
Spec (still actively updating): https://github.com/microsoft/terminal/pull/3299
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #605
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be 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 -->
These functionalities are included in the search experience.
1. Search in Terminal text buffer.
2. Automatic wrap-around.
3. Search up or down switch by clicking different buttons.
4. Search case sensitively/insensitively by clicking a button. S. Move the search box to the top/bottom by clicking a button.
6. Close by clicking 'X'.
7. Open search by ctrl + F.
When the searchbox is open, the user could still interact with the terminal by clicking the terminal input area.
While I already have the search functionalities, currently there are still some known to-do works and I will keep updating my PR:
1. Optimize the search box UI, this includes:
1) Theme adaptation. The search box background and font color
should change according to the theme,
2) Add background. Currently the elements in search box are all
transparent. However, we need a background.
3) Move button should be highlighted once clicked.
2. Accessibility: search process should be able to performed without mouse. Once the search box is focused, the user should be able to navigate between all interactive elements on the searchbox using keyboard.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
To test:
1. checkout this branch.
2. Build the project.
3. Start Windows Terminal and press Ctrl+F
4. The search box should appear on the top right corner.
2019-12-17 16:52:37 +01:00
|
|
|
_actionDispatch->Find({ this, &TerminalPage::_HandleFind });
|
2019-12-11 03:04:33 +01:00
|
|
|
_actionDispatch->ResetFontSize({ this, &TerminalPage::_HandleResetFontSize });
|
|
|
|
_actionDispatch->ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen });
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// - Get the title of the currently focused terminal control. If this tab is
|
|
|
|
// the focused tab, then also bubble this title to any listeners of our
|
|
|
|
// TitleChanged event.
|
2019-09-04 23:34:06 +02:00
|
|
|
// Arguments:
|
|
|
|
// - tab: the Tab to update the title for.
|
2020-02-04 22:51:11 +01:00
|
|
|
void TerminalPage::_UpdateTitle(const Tab& tab)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
auto newTabTitle = tab.GetActiveTitle();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
if (_settings->GlobalSettings().GetShowTitleInTitlebar() &&
|
2020-02-04 22:51:11 +01:00
|
|
|
tab.IsFocused())
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
_titleChangeHandlers(*this, newTabTitle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Get the icon of the currently focused terminal control, and set its
|
|
|
|
// tab's icon to that icon.
|
|
|
|
// Arguments:
|
|
|
|
// - tab: the Tab to update the title for.
|
2020-02-04 22:51:11 +01:00
|
|
|
void TerminalPage::_UpdateTabIcon(Tab& tab)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
const auto lastFocusedProfileOpt = tab.GetFocusedProfile();
|
2019-09-04 23:34:06 +02:00
|
|
|
if (lastFocusedProfileOpt.has_value())
|
|
|
|
{
|
|
|
|
const auto lastFocusedProfile = lastFocusedProfileOpt.value();
|
|
|
|
const auto* const matchingProfile = _settings->FindProfile(lastFocusedProfile);
|
|
|
|
if (matchingProfile)
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
tab.UpdateIcon(matchingProfile->GetExpandedIconPath());
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
tab.UpdateIcon({});
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 01:16:54 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Handle changes to the tab width set by the user
|
|
|
|
void TerminalPage::_UpdateTabWidthMode()
|
|
|
|
{
|
|
|
|
_tabView.TabWidthMode(_settings->GlobalSettings().GetTabWidthMode());
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Handle changes in tab layout.
|
|
|
|
void TerminalPage::_UpdateTabView()
|
|
|
|
{
|
Enable fullscreen mode (#3408)
## Summary of the Pull Request
Enables the `toggleFullscreen` action to be able to enter fullscreen mode, bound by default to <kbd>alt+enter</kbd>.
The action is bubbled up to the WindowsTerminal (Win32) layer, where the window resizes itself to take the entire size of the monitor.
This largely reuses code from conhost. Conhost already had a fullscreen mode, so I figured I might as well re-use that.
## References
Unfortunately there are still very thin borders around the window when the NonClientIslandWindow is fullscreened. I think I know where the problem is. However, that area of code is about to get a massive overhaul with #3064, so I didn't want to necessarily make it worse right now.
A follow up should be filed to add support for "Always show / reveal / never show tabs in fullscreen mode". Currently, the only mode is "never show tabs".
Additionally, some of this code (particularily re:drawing the nonclient area) could be re-used for #2238.
## PR Checklist
* [x] Closes #531, #3411
* [x] I work here
* [n/a] Tests added/passed 😭
* [x] Requires documentation to be updated
## Validation Steps Performed
* Manually tested both the NonClientIslandWindow and the IslandWindow.
* Cherry-pick commit 8e56bfe
* Don't draw the tab strip when maximized
(cherry picked from commit bac4be7c0f3ed1cdcd4f9ae8980fc98103538613)
* Fix the vista window flash for the NCIW
(cherry picked from commit 7d3a18a893c02bd2ed75026f2aac52e20321a1cf)
* Some code cleanup for review
(cherry picked from commit 9e22b7730bba426adcbfd9e7025f192dbf8efb32)
* A tad bit more notes and cleanup
* Update schema, docs
* Most of the PR comments
* I'm not sure this actually works, so I'm committing it to revert it and check
* Update some comments that were lost.
* Fix a build break?
* oh no
2019-11-05 20:40:29 +01:00
|
|
|
// Never show the tab row when we're fullscreen. Otherwise:
|
2019-09-04 23:34:06 +02:00
|
|
|
// Show tabs when there's more than 1, or the user has chosen to always
|
|
|
|
// show the tab bar.
|
Enable fullscreen mode (#3408)
## Summary of the Pull Request
Enables the `toggleFullscreen` action to be able to enter fullscreen mode, bound by default to <kbd>alt+enter</kbd>.
The action is bubbled up to the WindowsTerminal (Win32) layer, where the window resizes itself to take the entire size of the monitor.
This largely reuses code from conhost. Conhost already had a fullscreen mode, so I figured I might as well re-use that.
## References
Unfortunately there are still very thin borders around the window when the NonClientIslandWindow is fullscreened. I think I know where the problem is. However, that area of code is about to get a massive overhaul with #3064, so I didn't want to necessarily make it worse right now.
A follow up should be filed to add support for "Always show / reveal / never show tabs in fullscreen mode". Currently, the only mode is "never show tabs".
Additionally, some of this code (particularily re:drawing the nonclient area) could be re-used for #2238.
## PR Checklist
* [x] Closes #531, #3411
* [x] I work here
* [n/a] Tests added/passed 😭
* [x] Requires documentation to be updated
## Validation Steps Performed
* Manually tested both the NonClientIslandWindow and the IslandWindow.
* Cherry-pick commit 8e56bfe
* Don't draw the tab strip when maximized
(cherry picked from commit bac4be7c0f3ed1cdcd4f9ae8980fc98103538613)
* Fix the vista window flash for the NCIW
(cherry picked from commit 7d3a18a893c02bd2ed75026f2aac52e20321a1cf)
* Some code cleanup for review
(cherry picked from commit 9e22b7730bba426adcbfd9e7025f192dbf8efb32)
* A tad bit more notes and cleanup
* Update schema, docs
* Most of the PR comments
* I'm not sure this actually works, so I'm committing it to revert it and check
* Update some comments that were lost.
* Fix a build break?
* oh no
2019-11-05 20:40:29 +01:00
|
|
|
const bool isVisible = (!_isFullscreen) &&
|
|
|
|
(_settings->GlobalSettings().GetShowTabsInTitlebar() ||
|
2020-02-04 22:51:11 +01:00
|
|
|
(_tabs.Size() > 1) ||
|
Enable fullscreen mode (#3408)
## Summary of the Pull Request
Enables the `toggleFullscreen` action to be able to enter fullscreen mode, bound by default to <kbd>alt+enter</kbd>.
The action is bubbled up to the WindowsTerminal (Win32) layer, where the window resizes itself to take the entire size of the monitor.
This largely reuses code from conhost. Conhost already had a fullscreen mode, so I figured I might as well re-use that.
## References
Unfortunately there are still very thin borders around the window when the NonClientIslandWindow is fullscreened. I think I know where the problem is. However, that area of code is about to get a massive overhaul with #3064, so I didn't want to necessarily make it worse right now.
A follow up should be filed to add support for "Always show / reveal / never show tabs in fullscreen mode". Currently, the only mode is "never show tabs".
Additionally, some of this code (particularily re:drawing the nonclient area) could be re-used for #2238.
## PR Checklist
* [x] Closes #531, #3411
* [x] I work here
* [n/a] Tests added/passed 😭
* [x] Requires documentation to be updated
## Validation Steps Performed
* Manually tested both the NonClientIslandWindow and the IslandWindow.
* Cherry-pick commit 8e56bfe
* Don't draw the tab strip when maximized
(cherry picked from commit bac4be7c0f3ed1cdcd4f9ae8980fc98103538613)
* Fix the vista window flash for the NCIW
(cherry picked from commit 7d3a18a893c02bd2ed75026f2aac52e20321a1cf)
* Some code cleanup for review
(cherry picked from commit 9e22b7730bba426adcbfd9e7025f192dbf8efb32)
* A tad bit more notes and cleanup
* Update schema, docs
* Most of the PR comments
* I'm not sure this actually works, so I'm committing it to revert it and check
* Update some comments that were lost.
* Fix a build break?
* oh no
2019-11-05 20:40:29 +01:00
|
|
|
_settings->GlobalSettings().GetAlwaysShowTabs());
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
// collapse/show the tabs themselves
|
|
|
|
_tabView.Visibility(isVisible ? Visibility::Visible : Visibility::Collapsed);
|
|
|
|
|
|
|
|
// collapse/show the row that the tabs are in.
|
|
|
|
// NaN is the special value XAML uses for "Auto" sizing.
|
|
|
|
_tabRow.Height(isVisible ? NAN : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Duplicates the current focused tab
|
|
|
|
void TerminalPage::_DuplicateTabViewItem()
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
try
|
2020-02-04 22:51:11 +01:00
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
auto focusedTab = _GetStrongTabImpl(*index);
|
|
|
|
// TODO: GH#5047 - In the future, we should get the Profile of
|
|
|
|
// the focused pane, and use that to build a new instance of the
|
|
|
|
// settings so we can duplicate this tab/pane.
|
|
|
|
//
|
|
|
|
// Currently, if the profile doesn't exist anymore in our
|
|
|
|
// settings, we'll silently do nothing.
|
|
|
|
//
|
|
|
|
// In the future, it will be preferable to just duplicate the
|
|
|
|
// current control's settings, but we can't do that currently,
|
|
|
|
// because we won't be able to create a new instance of the
|
|
|
|
// connection without keeping an instance of the original Profile
|
|
|
|
// object around.
|
|
|
|
|
|
|
|
const auto& profileGuid = focusedTab->GetFocusedProfile();
|
|
|
|
if (profileGuid.has_value())
|
|
|
|
{
|
|
|
|
const auto settings = _settings->BuildSettings(profileGuid.value());
|
|
|
|
_CreateNewTabFromSettings(profileGuid.value(), settings);
|
|
|
|
}
|
2020-02-04 22:51:11 +01:00
|
|
|
}
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
CATCH_LOG();
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2019-09-17 07:43:27 +02:00
|
|
|
// - Look for the index of the input tabView in the tabs vector,
|
|
|
|
// and call _RemoveTabViewItemByIndex
|
2019-09-04 23:34:06 +02:00
|
|
|
// Arguments:
|
|
|
|
// - tabViewItem: the TabViewItem in the TabView that is being removed.
|
2019-10-15 07:41:43 +02:00
|
|
|
void TerminalPage::_RemoveTabViewItem(const MUX::Controls::TabViewItem& tabViewItem)
|
2019-09-17 07:43:27 +02:00
|
|
|
{
|
|
|
|
uint32_t tabIndexFromControl = 0;
|
2020-05-05 18:16:09 +02:00
|
|
|
if (_tabView.TabItems().IndexOf(tabViewItem, tabIndexFromControl))
|
|
|
|
{
|
|
|
|
// If IndexOf returns true, we've actually got an index
|
|
|
|
_RemoveTabViewItemByIndex(tabIndexFromControl);
|
|
|
|
}
|
2019-09-17 07:43:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Removes the tab (both TerminalControl and XAML)
|
|
|
|
// Arguments:
|
|
|
|
// - tabIndex: the index of the tab to be removed
|
|
|
|
void TerminalPage::_RemoveTabViewItemByIndex(uint32_t tabIndex)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-01-23 23:12:20 +01:00
|
|
|
// Removing the tab from the collection should destroy its control and disconnect its connection,
|
|
|
|
// but it doesn't always do so. The UI tree may still be holding the control and preventing its destruction.
|
2020-02-04 22:51:11 +01:00
|
|
|
auto tab{ _GetStrongTabImpl(tabIndex) };
|
|
|
|
tab->Shutdown();
|
2020-01-23 23:12:20 +01:00
|
|
|
|
2020-02-04 22:51:11 +01:00
|
|
|
_tabs.RemoveAt(tabIndex);
|
2020-01-23 23:12:20 +01:00
|
|
|
_tabView.TabItems().RemoveAt(tabIndex);
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// To close the window here, we need to close the hosting window.
|
2020-02-04 22:51:11 +01:00
|
|
|
if (_tabs.Size() == 0)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
_lastTabClosedHandlers(*this, nullptr);
|
|
|
|
}
|
Manually select a new tab when we're in fullscreen mode (#5809)
If we're fullscreen, the TabView isn't `Visible`. If it's not `Visible`,
it's _not_ going to raise a `SelectionChanged` event, which is what we
usually use to focus another tab. Instead, we'll have to do it manually
here.
So, what we're going to try to do is move the focus to the tab to the
left, within the bounds of how many tabs we have.
EX: we have 4 tabs: [A, B, C, D]. If we close:
* A (`tabIndex=0`): We'll want to focus tab B (now in index 0)
* B (`tabIndex=1`): We'll want to focus tab A (now in index 0)
* C (`tabIndex=2`): We'll want to focus tab B (now in index 1)
* D (`tabIndex=3`): We'll want to focus tab C (now in index 2)
`_UpdatedSelectedTab` will do the work of setting up the new tab as the
focused one, and unfocusing all the others.
Also, we need to _manually_ set the SelectedItem of the tabView here. If
we don't, then the TabView will technically not have a selected item at
all, which can make things like ClosePane not work correctly.
## PR Checklist
* [x] Closes #5799
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Played with it a bunch
2020-05-08 20:53:34 +02:00
|
|
|
else if (_isFullscreen)
|
|
|
|
{
|
|
|
|
// GH#5799 - If we're fullscreen, the TabView isn't visible. If it's
|
|
|
|
// not Visible, it's _not_ going to raise a SelectionChanged event,
|
|
|
|
// which is what we usually use to focus another tab. Instead, we'll
|
|
|
|
// have to do it manually here.
|
|
|
|
//
|
|
|
|
// We can't use
|
|
|
|
// auto selectedIndex = _tabView.SelectedIndex();
|
|
|
|
// Because this will always return -1 in this scenario unfortunately.
|
|
|
|
//
|
|
|
|
// So, what we're going to try to do is move the focus to the tab
|
|
|
|
// to the left, within the bounds of how many tabs we have.
|
|
|
|
//
|
|
|
|
// EX: we have 4 tabs: [A, B, C, D]. If we close:
|
|
|
|
// * A (tabIndex=0): We'll want to focus tab B (now in index 0)
|
|
|
|
// * B (tabIndex=1): We'll want to focus tab A (now in index 0)
|
|
|
|
// * C (tabIndex=2): We'll want to focus tab B (now in index 1)
|
|
|
|
// * D (tabIndex=3): We'll want to focus tab C (now in index 2)
|
|
|
|
const auto newSelectedIndex = std::clamp<int32_t>(tabIndex - 1, 0, _tabs.Size());
|
|
|
|
// _UpdatedSelectedTab will do the work of setting up the new tab as
|
|
|
|
// the focused one, and unfocusing all the others.
|
|
|
|
_UpdatedSelectedTab(newSelectedIndex);
|
|
|
|
|
|
|
|
// Also, we need to _manually_ set the SelectedItem of the tabView
|
|
|
|
// here. If we don't, then the TabView will technically not have a
|
|
|
|
// selected item at all, which can make things like ClosePane not
|
|
|
|
// work correctly.
|
|
|
|
auto newSelectedTab{ _GetStrongTabImpl(newSelectedIndex) };
|
|
|
|
_tabView.SelectedItem(newSelectedTab->GetTabViewItem());
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Connects event handlers to the TermControl for events that we want to
|
|
|
|
// handle. This includes:
|
|
|
|
// * the Copy and Paste events, for setting and retrieving clipboard data
|
|
|
|
// on the right thread
|
2019-11-25 21:23:08 +01:00
|
|
|
// * the TitleChanged event, for changing the text of the tab
|
2019-09-04 23:34:06 +02:00
|
|
|
// Arguments:
|
|
|
|
// - term: The newly created TermControl to connect the events for
|
|
|
|
// - hostingTab: The Tab that's hosting this TermControl instance
|
2020-02-04 22:51:11 +01:00
|
|
|
void TerminalPage::_RegisterTerminalEvents(TermControl term, Tab& hostingTab)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
// Add an event handler when the terminal's selection wants to be copied.
|
|
|
|
// When the text buffer data is retrieved, we'll copy the data into the Clipboard
|
|
|
|
term.CopyToClipboard({ this, &TerminalPage::_CopyToClipboardHandler });
|
|
|
|
|
|
|
|
// Add an event handler when the terminal wants to paste data from the Clipboard.
|
|
|
|
term.PasteFromClipboard({ this, &TerminalPage::_PasteFromClipboardHandler });
|
2019-11-25 21:23:08 +01:00
|
|
|
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
// Bind Tab events to the TermControl and the Tab's Pane
|
2020-05-04 22:57:12 +02:00
|
|
|
hostingTab.Initialize(term);
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
|
2019-11-25 21:23:08 +01:00
|
|
|
// Don't capture a strong ref to the tab. If the tab is removed as this
|
|
|
|
// is called, we don't really care anymore about handling the event.
|
2020-02-04 22:51:11 +01:00
|
|
|
term.TitleChanged([weakTab{ hostingTab.get_weak() }, weakThis{ get_weak() }](auto newTitle) {
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
auto page{ weakThis.get() };
|
2020-02-04 22:51:11 +01:00
|
|
|
auto tab{ weakTab.get() };
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
|
|
|
|
if (page && tab)
|
2019-11-25 21:23:08 +01:00
|
|
|
{
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
// The title of the control changed, but not necessarily the title
|
|
|
|
// of the tab. Get the title of the focused pane of the tab, and set
|
|
|
|
// the tab's text to the focused panes' text.
|
2020-02-04 22:51:11 +01:00
|
|
|
page->_UpdateTitle(*tab);
|
2019-11-25 21:23:08 +01:00
|
|
|
}
|
|
|
|
});
|
2020-05-04 22:57:12 +02:00
|
|
|
|
|
|
|
// react on color changed events
|
|
|
|
hostingTab.ColorSelected([weakTab{ hostingTab.get_weak() }, weakThis{ get_weak() }](auto&& color) {
|
|
|
|
auto page{ weakThis.get() };
|
|
|
|
auto tab{ weakTab.get() };
|
|
|
|
|
|
|
|
if (page && tab && tab->IsFocused())
|
|
|
|
{
|
|
|
|
page->_SetNonClientAreaColors(color);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
hostingTab.ColorCleared([weakTab{ hostingTab.get_weak() }, weakThis{ get_weak() }]() {
|
|
|
|
auto page{ weakThis.get() };
|
|
|
|
auto tab{ weakTab.get() };
|
|
|
|
|
|
|
|
if (page && tab && tab->IsFocused())
|
|
|
|
{
|
|
|
|
page->_ClearNonClientAreaColors();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-05-05 22:33:07 +02:00
|
|
|
// TODO GH#3327: Once we support colorizing the NewTab button based on
|
|
|
|
// the color of the tab, we'll want to make sure to call
|
|
|
|
// _ClearNewTabButtonColor here, to reset it to the default (for the
|
|
|
|
// newly created tab).
|
2020-05-04 22:57:12 +02:00
|
|
|
// remove any colors left by other colored tabs
|
2020-05-05 22:33:07 +02:00
|
|
|
// _ClearNewTabButtonColor();
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Sets focus to the tab to the right or left the currently selected tab.
|
|
|
|
void TerminalPage::_SelectNextTab(const bool bMoveRight)
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
|
|
|
{
|
|
|
|
uint32_t tabCount = _tabs.Size();
|
|
|
|
// Wraparound math. By adding tabCount and then calculating modulo tabCount,
|
|
|
|
// we clamp the values to the range [0, tabCount) while still supporting moving
|
|
|
|
// leftward from 0 to tabCount - 1.
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
const auto newTabIndex = ((tabCount + *index + (bMoveRight ? 1 : -1)) % tabCount);
|
|
|
|
_SelectTab(newTabIndex);
|
2020-02-04 22:51:11 +01:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Sets focus to the desired tab. Returns false if the provided tabIndex
|
|
|
|
// is greater than the number of tabs we have.
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// - During startup, we'll immediately set the selected tab as focused.
|
|
|
|
// - After startup, we'll dispatch an async method to set the the selected
|
|
|
|
// item of the TabView, which will then also trigger a
|
|
|
|
// TabView::SelectionChanged, handled in
|
|
|
|
// TerminalPage::_OnTabSelectionChanged
|
2019-09-04 23:34:06 +02:00
|
|
|
// Return Value:
|
|
|
|
// true iff we were able to select that tab index, false otherwise
|
2020-02-04 22:51:11 +01:00
|
|
|
bool TerminalPage::_SelectTab(const uint32_t tabIndex)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (tabIndex >= 0 && tabIndex < _tabs.Size())
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
if (_startupState == StartupState::InStartup)
|
|
|
|
{
|
|
|
|
auto tab{ _GetStrongTabImpl(tabIndex) };
|
|
|
|
_tabView.SelectedItem(tab->GetTabViewItem());
|
|
|
|
_UpdatedSelectedTab(tabIndex);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_SetFocusedTabIndex(tabIndex);
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Attempt to move focus between panes, as to focus the child on
|
|
|
|
// the other side of the separator. See Pane::NavigateFocus for details.
|
|
|
|
// - Moves the focus of the currently focused tab.
|
|
|
|
// Arguments:
|
|
|
|
// - direction: The direction to move the focus in.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_MoveFocus(const Direction& direction)
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
|
|
|
{
|
|
|
|
auto focusedTab{ _GetStrongTabImpl(*index) };
|
|
|
|
focusedTab->NavigateFocus(direction);
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
winrt::Microsoft::Terminal::TerminalControl::TermControl TerminalPage::_GetActiveControl()
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
|
|
|
{
|
|
|
|
auto focusedTab{ _GetStrongTabImpl(*index) };
|
|
|
|
return focusedTab->GetActiveTerminalControl();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Returns the index in our list of tabs of the currently focused tab. If
|
|
|
|
// no tab is currently selected, returns -1.
|
|
|
|
// Return Value:
|
|
|
|
// - the index of the currently focused tab if there is one, else -1
|
2020-02-04 22:51:11 +01:00
|
|
|
std::optional<uint32_t> TerminalPage::_GetFocusedTabIndex() const noexcept
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
// GH#1117: This is a workaround because _tabView.SelectedIndex()
|
|
|
|
// sometimes return incorrect result after removing some tabs
|
|
|
|
uint32_t focusedIndex;
|
2019-10-15 07:41:43 +02:00
|
|
|
if (_tabView.TabItems().IndexOf(_tabView.SelectedItem(), focusedIndex))
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
return focusedIndex;
|
|
|
|
}
|
2020-02-04 22:51:11 +01:00
|
|
|
return std::nullopt;
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// Method Description:
|
|
|
|
// - An async method for changing the focused tab on the UI thread. This
|
|
|
|
// method will _only_ set the selected item of the TabView, which will
|
|
|
|
// then also trigger a TabView::SelectionChanged event, which we'll handle
|
|
|
|
// in TerminalPage::_OnTabSelectionChanged, where we'll mark the new tab
|
|
|
|
// as focused.
|
|
|
|
// Arguments:
|
|
|
|
// - tabIndex: the index in the list of tabs to focus.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2020-02-04 22:51:11 +01:00
|
|
|
winrt::fire_and_forget TerminalPage::_SetFocusedTabIndex(const uint32_t tabIndex)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
// GH#1117: This is a workaround because _tabView.SelectedIndex(tabIndex)
|
|
|
|
// sometimes set focus to an incorrect tab after removing some tabs
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
auto weakThis{ get_weak() };
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
|
|
|
|
co_await winrt::resume_foreground(_tabView.Dispatcher());
|
|
|
|
|
|
|
|
if (auto page{ weakThis.get() })
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
auto tab{ _GetStrongTabImpl(tabIndex) };
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
_tabView.SelectedItem(tab->GetTabViewItem());
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Close the currently focused tab. Focus will move to the left, if possible.
|
|
|
|
void TerminalPage::_CloseFocusedTab()
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
|
|
|
{
|
|
|
|
_RemoveTabViewItemByIndex(*index);
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Close the currently focused pane. If the pane is the last pane in the
|
|
|
|
// tab, the tab will also be closed. This will happen when we handle the
|
|
|
|
// tab's Closed event.
|
|
|
|
void TerminalPage::_CloseFocusedPane()
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
|
|
|
{
|
|
|
|
auto focusedTab{ _GetStrongTabImpl(*index) };
|
|
|
|
focusedTab->ClosePane();
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
2019-09-17 07:43:27 +02:00
|
|
|
// Method Description:
|
2019-10-11 02:09:07 +02:00
|
|
|
// - Close the terminal app. If there is more
|
2019-09-17 07:43:27 +02:00
|
|
|
// than one tab opened, show a warning dialog.
|
2019-10-11 02:09:07 +02:00
|
|
|
void TerminalPage::CloseWindow()
|
2019-09-17 07:43:27 +02:00
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (_tabs.Size() > 1 && _settings->GlobalSettings().GetConfirmCloseAllTabs())
|
2019-09-17 07:43:27 +02:00
|
|
|
{
|
|
|
|
_ShowCloseWarningDialog();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_CloseAllTabs();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Remove all the tabs opened and the terminal will terminate
|
|
|
|
// on its own when the last tab is closed.
|
|
|
|
void TerminalPage::_CloseAllTabs()
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
while (_tabs.Size() != 0)
|
2019-09-17 07:43:27 +02:00
|
|
|
{
|
|
|
|
_RemoveTabViewItemByIndex(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Move the viewport of the terminal of the currently focused tab up or
|
|
|
|
// down a number of lines. Negative values of `delta` will move the
|
|
|
|
// view up, and positive values will move the viewport down.
|
|
|
|
// Arguments:
|
|
|
|
// - delta: a number of lines to move the viewport relative to the current viewport.
|
|
|
|
void TerminalPage::_Scroll(int delta)
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
|
|
|
{
|
|
|
|
auto focusedTab{ _GetStrongTabImpl(*index) };
|
|
|
|
focusedTab->Scroll(delta);
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Split the focused pane either horizontally or vertically, and place the
|
|
|
|
// given TermControl into the newly created pane.
|
|
|
|
// - If splitType == SplitState::None, this method does nothing.
|
|
|
|
// Arguments:
|
2019-11-28 14:42:15 +01:00
|
|
|
// - splitType: one value from the TerminalApp::SplitState enum, indicating how the
|
2019-09-04 23:34:06 +02:00
|
|
|
// new pane should be split from its parent.
|
2020-03-07 00:15:45 +01:00
|
|
|
// - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
// - newTerminalArgs: An object that may contain a blob of parameters to
|
|
|
|
// control which profile is created and with possible other
|
|
|
|
// configurations. See CascadiaSettings::BuildSettings for more details.
|
|
|
|
void TerminalPage::_SplitPane(const TerminalApp::SplitState splitType,
|
2020-03-07 00:15:45 +01:00
|
|
|
const TerminalApp::SplitType splitMode,
|
Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request
This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`
`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.
`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.
With this PR, you can make bindings like the following:
```json
{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```
## References
This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.
## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated
## Validation Steps Performed
There are tests 🎉
Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
|
|
|
const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
// Do nothing if we're requesting no split.
|
2019-11-28 14:42:15 +01:00
|
|
|
if (splitType == TerminalApp::SplitState::None)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-04 22:51:11 +01:00
|
|
|
auto indexOpt = _GetFocusedTabIndex();
|
|
|
|
|
|
|
|
// Do nothing if for some reason, there's no tab in focus. We don't want to crash.
|
|
|
|
if (!indexOpt)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
try
|
2020-03-07 00:15:45 +01:00
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
auto focusedTab = _GetStrongTabImpl(*indexOpt);
|
|
|
|
winrt::Microsoft::Terminal::Settings::TerminalSettings controlSettings;
|
|
|
|
GUID realGuid;
|
|
|
|
bool profileFound = false;
|
|
|
|
|
|
|
|
if (splitMode == TerminalApp::SplitType::Duplicate)
|
2020-03-07 00:15:45 +01:00
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
std::optional<GUID> current_guid = focusedTab->GetFocusedProfile();
|
|
|
|
if (current_guid)
|
|
|
|
{
|
|
|
|
profileFound = true;
|
|
|
|
controlSettings = _settings->BuildSettings(current_guid.value());
|
|
|
|
realGuid = current_guid.value();
|
|
|
|
}
|
|
|
|
// TODO: GH#5047 - In the future, we should get the Profile of
|
|
|
|
// the focused pane, and use that to build a new instance of the
|
|
|
|
// settings so we can duplicate this tab/pane.
|
|
|
|
//
|
|
|
|
// Currently, if the profile doesn't exist anymore in our
|
|
|
|
// settings, we'll silently do nothing.
|
|
|
|
//
|
|
|
|
// In the future, it will be preferable to just duplicate the
|
|
|
|
// current control's settings, but we can't do that currently,
|
|
|
|
// because we won't be able to create a new instance of the
|
|
|
|
// connection without keeping an instance of the original Profile
|
|
|
|
// object around.
|
|
|
|
}
|
|
|
|
if (!profileFound)
|
|
|
|
{
|
|
|
|
std::tie(realGuid, controlSettings) = _settings->BuildSettings(newTerminalArgs);
|
2020-03-07 00:15:45 +01:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
const auto controlConnection = _CreateConnectionFromSettings(realGuid, controlSettings);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
const auto canSplit = focusedTab->CanSplitPane(splitType);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
if (!canSplit && _startupState == StartupState::Initialized)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
auto realSplitType = splitType;
|
|
|
|
if (realSplitType == SplitState::Automatic && _startupState < StartupState::Initialized)
|
|
|
|
{
|
|
|
|
float contentWidth = gsl::narrow_cast<float>(_tabContent.ActualWidth());
|
|
|
|
float contentHeight = gsl::narrow_cast<float>(_tabContent.ActualHeight());
|
|
|
|
realSplitType = focusedTab->PreCalculateAutoSplit({ contentWidth, contentHeight });
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
TermControl newControl{ controlSettings, controlConnection };
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// Hookup our event handlers to the new terminal
|
|
|
|
_RegisterTerminalEvents(newControl, *focusedTab);
|
|
|
|
|
|
|
|
focusedTab->SplitPane(realSplitType, realGuid, newControl);
|
|
|
|
}
|
|
|
|
CATCH_LOG();
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Attempt to move a separator between panes, as to resize each child on
|
|
|
|
// either size of the separator. See Pane::ResizePane for details.
|
|
|
|
// - Moves a separator on the currently focused tab.
|
|
|
|
// Arguments:
|
|
|
|
// - direction: The direction to move the separator in.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_ResizePane(const Direction& direction)
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
|
|
|
{
|
|
|
|
auto focusedTab{ _GetStrongTabImpl(*index) };
|
|
|
|
focusedTab->ResizePane(direction);
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Move the viewport of the terminal of the currently focused tab up or
|
|
|
|
// down a page. The page length will be dependent on the terminal view height.
|
|
|
|
// Negative values of `delta` will move the view up by one page, and positive values
|
|
|
|
// will move the viewport down by one page.
|
|
|
|
// Arguments:
|
|
|
|
// - delta: The direction to move the view relative to the current viewport(it
|
|
|
|
// is clamped between -1 and 1)
|
|
|
|
void TerminalPage::_ScrollPage(int delta)
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
auto indexOpt = _GetFocusedTabIndex();
|
|
|
|
// Do nothing if for some reason, there's no tab in focus. We don't want to crash.
|
|
|
|
if (!indexOpt)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
delta = std::clamp(delta, -1, 1);
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
const auto control = _GetActiveControl();
|
2019-09-04 23:34:06 +02:00
|
|
|
const auto termHeight = control.GetViewHeight();
|
2020-02-04 22:51:11 +01:00
|
|
|
auto focusedTab{ _GetStrongTabImpl(*indexOpt) };
|
|
|
|
focusedTab->Scroll(termHeight * delta);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Gets the title of the currently focused terminal control. If there
|
|
|
|
// isn't a control selected for any reason, returns "Windows Terminal"
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - the title of the focused control if there is one, else "Windows Terminal"
|
|
|
|
hstring TerminalPage::Title()
|
|
|
|
{
|
|
|
|
if (_settings->GlobalSettings().GetShowTitleInTitlebar())
|
|
|
|
{
|
|
|
|
auto selectedIndex = _tabView.SelectedIndex();
|
|
|
|
if (selectedIndex >= 0)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
if (auto focusedControl{ _GetActiveControl() })
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
return focusedControl.Title();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CATCH_LOG();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return { L"Windows Terminal" };
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Handles the special case of providing a text override for the UI shortcut due to VK_OEM issue.
|
|
|
|
// Looks at the flags from the KeyChord modifiers and provides a concatenated string value of all
|
|
|
|
// in the same order that XAML would put them as well.
|
|
|
|
// Return Value:
|
|
|
|
// - a string representation of the key modifiers for the shortcut
|
|
|
|
//NOTE: This needs to be localized with https://github.com/microsoft/terminal/issues/794 if XAML framework issue not resolved before then
|
|
|
|
static std::wstring _FormatOverrideShortcutText(Settings::KeyModifiers modifiers)
|
|
|
|
{
|
|
|
|
std::wstring buffer{ L"" };
|
|
|
|
|
|
|
|
if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Ctrl))
|
|
|
|
{
|
|
|
|
buffer += L"Ctrl+";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Shift))
|
|
|
|
{
|
|
|
|
buffer += L"Shift+";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Alt))
|
|
|
|
{
|
|
|
|
buffer += L"Alt+";
|
|
|
|
}
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Takes a MenuFlyoutItem and a corresponding KeyChord value and creates the accelerator for UI display.
|
|
|
|
// Takes into account a special case for an error condition for a comma
|
|
|
|
// Arguments:
|
|
|
|
// - MenuFlyoutItem that will be displayed, and a KeyChord to map an accelerator
|
2019-10-15 07:41:43 +02:00
|
|
|
void TerminalPage::_SetAcceleratorForMenuItem(WUX::Controls::MenuFlyoutItem& menuItem,
|
2019-09-04 23:34:06 +02:00
|
|
|
const winrt::Microsoft::Terminal::Settings::KeyChord& keyChord)
|
|
|
|
{
|
|
|
|
#ifdef DEP_MICROSOFT_UI_XAML_708_FIXED
|
|
|
|
// work around https://github.com/microsoft/microsoft-ui-xaml/issues/708 in case of VK_OEM_COMMA
|
|
|
|
if (keyChord.Vkey() != VK_OEM_COMMA)
|
|
|
|
{
|
|
|
|
// use the XAML shortcut to give us the automatic capabilities
|
|
|
|
auto menuShortcut = Windows::UI::Xaml::Input::KeyboardAccelerator{};
|
|
|
|
|
|
|
|
// TODO: Modify this when https://github.com/microsoft/terminal/issues/877 is resolved
|
|
|
|
menuShortcut.Key(static_cast<Windows::System::VirtualKey>(keyChord.Vkey()));
|
|
|
|
|
|
|
|
// inspect the modifiers from the KeyChord and set the flags int he XAML value
|
|
|
|
auto modifiers = AppKeyBindings::ConvertVKModifiers(keyChord.Modifiers());
|
|
|
|
|
|
|
|
// add the modifiers to the shortcut
|
|
|
|
menuShortcut.Modifiers(modifiers);
|
|
|
|
|
|
|
|
// add to the menu
|
|
|
|
menuItem.KeyboardAccelerators().Append(menuShortcut);
|
|
|
|
}
|
|
|
|
else // we've got a comma, so need to just use the alternate method
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// extract the modifier and key to a nice format
|
|
|
|
auto overrideString = _FormatOverrideShortcutText(keyChord.Modifiers());
|
|
|
|
auto mappedCh = MapVirtualKeyW(keyChord.Vkey(), MAPVK_VK_TO_CHAR);
|
|
|
|
if (mappedCh != 0)
|
|
|
|
{
|
|
|
|
menuItem.KeyboardAcceleratorTextOverride(overrideString + gsl::narrow_cast<wchar_t>(mappedCh));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
// Method Description:
|
2020-02-10 21:40:01 +01:00
|
|
|
// - Calculates the appropriate size to snap to in the given direction, for
|
2020-01-09 18:19:21 +01:00
|
|
|
// the given dimension. If the global setting `snapToGridOnResize` is set
|
|
|
|
// to `false`, this will just immediately return the provided dimension,
|
|
|
|
// effectively disabling snapping.
|
2020-01-08 22:19:23 +01:00
|
|
|
// - See Pane::CalcSnappedDimension
|
|
|
|
float TerminalPage::CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
|
|
|
|
{
|
2020-01-09 18:19:21 +01:00
|
|
|
if (_settings->GlobalSettings().SnapToGridOnResize())
|
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
if (auto index{ _GetFocusedTabIndex() })
|
|
|
|
{
|
|
|
|
auto focusedTab{ _GetStrongTabImpl(*index) };
|
|
|
|
return focusedTab->CalcSnappedDimension(widthOrHeight, dimension);
|
|
|
|
}
|
2020-01-09 18:19:21 +01:00
|
|
|
}
|
2020-02-04 22:51:11 +01:00
|
|
|
return dimension;
|
2020-01-08 22:19:23 +01:00
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Place `copiedData` into the clipboard as text. Triggered when a
|
|
|
|
// terminal control raises it's CopyToClipboard event.
|
|
|
|
// Arguments:
|
|
|
|
// - copiedData: the new string content to place on the clipboard.
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
winrt::fire_and_forget TerminalPage::_CopyToClipboardHandler(const IInspectable /*sender*/,
|
|
|
|
const winrt::Microsoft::Terminal::TerminalControl::CopyToClipboardEventArgs copiedData)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
co_await winrt::resume_foreground(Dispatcher(), CoreDispatcherPriority::High);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
DataPackage dataPack = DataPackage();
|
|
|
|
dataPack.RequestedOperation(DataPackageOperation::Copy);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
// copy text to dataPack
|
|
|
|
dataPack.SetText(copiedData.Text());
|
2019-09-04 23:34:06 +02:00
|
|
|
|
2020-04-10 01:32:38 +02:00
|
|
|
if (_settings->GlobalSettings().GetCopyFormatting())
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
{
|
2020-04-10 01:32:38 +02:00
|
|
|
// copy html to dataPack
|
|
|
|
const auto htmlData = copiedData.Html();
|
|
|
|
if (!htmlData.empty())
|
|
|
|
{
|
|
|
|
dataPack.SetHtmlFormat(htmlData);
|
|
|
|
}
|
2019-11-13 21:13:22 +01:00
|
|
|
|
2020-04-10 01:32:38 +02:00
|
|
|
// copy rtf data to dataPack
|
|
|
|
const auto rtfData = copiedData.Rtf();
|
|
|
|
if (!rtfData.empty())
|
|
|
|
{
|
|
|
|
dataPack.SetRtf(rtfData);
|
|
|
|
}
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Clipboard::SetContent(dataPack);
|
|
|
|
Clipboard::Flush();
|
|
|
|
}
|
|
|
|
CATCH_LOG();
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Fires an async event to get data from the clipboard, and paste it to
|
|
|
|
// the terminal. Triggered when the Terminal Control requests clipboard
|
|
|
|
// data with it's PasteFromClipboard event.
|
|
|
|
// Arguments:
|
|
|
|
// - eventArgs: the PasteFromClipboard event sent from the TermControl
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
winrt::fire_and_forget TerminalPage::_PasteFromClipboardHandler(const IInspectable /*sender*/,
|
|
|
|
const PasteFromClipboardEventArgs eventArgs)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
co_await winrt::resume_foreground(Dispatcher(), CoreDispatcherPriority::High);
|
|
|
|
|
|
|
|
TerminalPage::PasteFromClipboard(eventArgs);
|
2019-07-09 23:47:30 +02:00
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
// Function Description:
|
|
|
|
// - Copies and processes the text data from the Windows Clipboard.
|
|
|
|
// Does some of this in a background thread, as to not hang/crash the UI thread.
|
|
|
|
// Arguments:
|
|
|
|
// - eventArgs: the PasteFromClipboard event sent from the TermControl
|
|
|
|
fire_and_forget TerminalPage::PasteFromClipboard(PasteFromClipboardEventArgs eventArgs)
|
|
|
|
{
|
|
|
|
const DataPackageView data = Clipboard::GetContent();
|
|
|
|
|
|
|
|
// This will switch the execution of the function to a background (not
|
|
|
|
// UI) thread. This is IMPORTANT, because the getting the clipboard data
|
|
|
|
// will crash on the UI thread, because the main thread is a STA.
|
|
|
|
co_await winrt::resume_background();
|
|
|
|
|
|
|
|
hstring text = L"";
|
|
|
|
if (data.Contains(StandardDataFormats::Text()))
|
|
|
|
{
|
|
|
|
text = co_await data.GetTextAsync();
|
|
|
|
}
|
|
|
|
eventArgs.HandleClipboardData(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Copy text from the focused terminal to the Windows Clipboard
|
|
|
|
// Arguments:
|
2020-04-03 01:10:28 +02:00
|
|
|
// - singleLine: if enabled, copy contents as a single line of text
|
2019-09-04 23:34:06 +02:00
|
|
|
// Return Value:
|
|
|
|
// - true iff we we able to copy text (if a selection was active)
|
2020-04-03 01:10:28 +02:00
|
|
|
bool TerminalPage::_CopyText(const bool singleLine)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
const auto control = _GetActiveControl();
|
2020-04-03 01:10:28 +02:00
|
|
|
return control.CopySelectionToClipboard(singleLine);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Paste text from the Windows Clipboard to the focused terminal
|
|
|
|
void TerminalPage::_PasteText()
|
|
|
|
{
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
const auto control = _GetActiveControl();
|
2019-09-04 23:34:06 +02:00
|
|
|
control.PasteTextFromClipboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function Description:
|
|
|
|
// - Called when the settings button is clicked. ShellExecutes the settings
|
|
|
|
// file, as to open it in the default editor for .json files. Does this in
|
|
|
|
// a background thread, as to not hang/crash the UI thread.
|
Add Cascading User + Default Settings (#2515)
This PR represents the start of the work on Cascading User + default settings, #754.
Cascading settings will be done in two parts:
* [ ] Layered Default+User settings (this PR)
* [ ] Dynamic Profile Generation (#2603).
Until _both_ are done, _neither are going in. The dynamic profiles PR will target this PR when it's ready, but will go in as a separate commit into master.
This PR covers adding one primary feature: the settings are now in two separate files:
* a static `defaults.json` that ships with the package (the "default settings")
* a `profiles.json` with the user's customizations (the "user settings)
User settings are _layered_ upon the settings in the defaults settings.
## References
Other things that might be related here:
* #1378 - This seems like it's definitely fixed. The default keybindings are _much_ cleaner, and without the save-on-load behavior, the user's keybindings will be left in a good state
* #1398 - This might have honestly been solved by #2475
## PR Checklist
* [x] Closes #754
* [x] Closes #1378
* [x] Closes #2566
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated - it **ABSOLUTELY DOES**
## Detailed Description of the Pull Request / Additional comments
1. We start by taking all of the `FromJson` functions in Profile, ColorScheme, Globals, etc, and converting them to `LayerJson` methods. These are effectively the same, with the change that instead of building a new object, they are simply layering the values on top of `this` object.
2. Next, we add tests for layering properties like that.
3. Now, we add a `defaults.json` to the package. This is the file the users can refer to as our default settings.
4. We then take that `defaults.json` and stamp it into an auto generated `.h` file, so we can use it's data without having to worry about reading it from disk.
5. We then change the `LoadAll` function in `CascadiaSettings`. Now, the function does two loads - one from the defaults, and then a second load from the `profiles.json` file, layering the settings from each source upon the previous values.
6. If the `profiles.json` file doesn't exist, we'll create it from a hardcoded `userDefaults.json`, which is stamped in similar to how `defaults.json` is.
7. We also add support for _unbinding_ keybindings that might exist in the `defaults.json`, but the user doesn't want to be bound to anything.
8. We add support for _hiding_ a profile, which is useful if a user doesn't want one of the default profiles to appear in the list of profiles.
## TODO:
* [x] Still need to make Alt+Click work on the settings button
* [x] Need to write some user documentation on how the new settings model works
* [x] Fix the pair of tests I broke (re: Duplicate profiles)
<hr>
* Create profiles by layering them
* Update test to layer multiple times on the same profile
* Add support for layering an array of profiles, but break a couple tests
* Add a defaults.json to the package
* Layer colorschemes
* Moves tests into individual classes
* adds support for layering a colorscheme on top of another
* Layer an array of color schemes
* oh no, this was missed with #2481
must have committed without staging this change, uh oh. Not like those tests actually work so nbd
* Layer keybindings
* Read settings from defaults.json + profiles.json, layer appropriately
This is like 80% of #754. Needs tests.
* Add tests for keybindings
* add support to unbind a key with `null` or `"unbound"` or `"garbage"`
* Layer or clear optional properties
* Add a helper to get an optional variable for a bunch of different types
In the end, I think we need to ask _was this worth it_
* Do this with the stretch mode too
* Add back in the GUID check for profiles
* Add some tests for global settings layering
* M A D W I T H P O W E R
Add a MsBuild target to auto-generate a header with the defaults.json as a
string in the file. That way, we can _always_ load the defaults. Literally impossible to not.
* When the user's profile.json doesn't exist, create it from a template
* Re-order profiles to match the order set in the user's profiles.json
* Add tests for re-ordering profiles to match user ordering
* Add support for hiding profiles using `"hidden": true`
* Use the hardcoded defaults.json for the exception->"use defaults" case
* Somehow I messed up the git submodules?
* woo documentation
* Fix a Terminal.App.Unit.Tests failure
* signed/unsigned is hard
* Use Alt+Settings button to open the default settings
* Missed a signed/unsigned
* Some very preliminary PR feedback
* More PR feedback
Use the wil helper for the exe path
Move jsonutils into their own file
kill some dead code
* Add templates to these bois
* remove some code for generating defaults, reorder defaults.json a tad
* Make guid a std::optional
* Large block of PR feedback
* Remove some dead code
* add some comments
* tag some todos
* stl is love, stl is life
* add `-noprofile`
* Fix the crash that dustin found
* -Encoding ASCII
* Set a profile's default scheme to Campbell
* Fix the tests I regressed
* Update UsingJsonSetting.md to reflect that changes from these PRs
* Change how GenerateGuidForProfile works
* Make AppKeyBindings do its own serialization
* Remove leftover dead code from the previous commit
* Fix up an enormous number of PR nits
* Fix a typo; Update the defaults to match #2378
* Tiny nits
* Some typos, PR nits
* Fix this broken defaults case
2019-09-16 21:57:10 +02:00
|
|
|
fire_and_forget TerminalPage::_LaunchSettings(const bool openDefaults)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
// This will switch the execution of the function to a background (not
|
|
|
|
// UI) thread. This is IMPORTANT, because the Windows.Storage API's
|
|
|
|
// (used for retrieving the path to the file) will crash on the UI
|
|
|
|
// thread, because the main thread is a STA.
|
|
|
|
co_await winrt::resume_background();
|
|
|
|
|
Add Cascading User + Default Settings (#2515)
This PR represents the start of the work on Cascading User + default settings, #754.
Cascading settings will be done in two parts:
* [ ] Layered Default+User settings (this PR)
* [ ] Dynamic Profile Generation (#2603).
Until _both_ are done, _neither are going in. The dynamic profiles PR will target this PR when it's ready, but will go in as a separate commit into master.
This PR covers adding one primary feature: the settings are now in two separate files:
* a static `defaults.json` that ships with the package (the "default settings")
* a `profiles.json` with the user's customizations (the "user settings)
User settings are _layered_ upon the settings in the defaults settings.
## References
Other things that might be related here:
* #1378 - This seems like it's definitely fixed. The default keybindings are _much_ cleaner, and without the save-on-load behavior, the user's keybindings will be left in a good state
* #1398 - This might have honestly been solved by #2475
## PR Checklist
* [x] Closes #754
* [x] Closes #1378
* [x] Closes #2566
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated - it **ABSOLUTELY DOES**
## Detailed Description of the Pull Request / Additional comments
1. We start by taking all of the `FromJson` functions in Profile, ColorScheme, Globals, etc, and converting them to `LayerJson` methods. These are effectively the same, with the change that instead of building a new object, they are simply layering the values on top of `this` object.
2. Next, we add tests for layering properties like that.
3. Now, we add a `defaults.json` to the package. This is the file the users can refer to as our default settings.
4. We then take that `defaults.json` and stamp it into an auto generated `.h` file, so we can use it's data without having to worry about reading it from disk.
5. We then change the `LoadAll` function in `CascadiaSettings`. Now, the function does two loads - one from the defaults, and then a second load from the `profiles.json` file, layering the settings from each source upon the previous values.
6. If the `profiles.json` file doesn't exist, we'll create it from a hardcoded `userDefaults.json`, which is stamped in similar to how `defaults.json` is.
7. We also add support for _unbinding_ keybindings that might exist in the `defaults.json`, but the user doesn't want to be bound to anything.
8. We add support for _hiding_ a profile, which is useful if a user doesn't want one of the default profiles to appear in the list of profiles.
## TODO:
* [x] Still need to make Alt+Click work on the settings button
* [x] Need to write some user documentation on how the new settings model works
* [x] Fix the pair of tests I broke (re: Duplicate profiles)
<hr>
* Create profiles by layering them
* Update test to layer multiple times on the same profile
* Add support for layering an array of profiles, but break a couple tests
* Add a defaults.json to the package
* Layer colorschemes
* Moves tests into individual classes
* adds support for layering a colorscheme on top of another
* Layer an array of color schemes
* oh no, this was missed with #2481
must have committed without staging this change, uh oh. Not like those tests actually work so nbd
* Layer keybindings
* Read settings from defaults.json + profiles.json, layer appropriately
This is like 80% of #754. Needs tests.
* Add tests for keybindings
* add support to unbind a key with `null` or `"unbound"` or `"garbage"`
* Layer or clear optional properties
* Add a helper to get an optional variable for a bunch of different types
In the end, I think we need to ask _was this worth it_
* Do this with the stretch mode too
* Add back in the GUID check for profiles
* Add some tests for global settings layering
* M A D W I T H P O W E R
Add a MsBuild target to auto-generate a header with the defaults.json as a
string in the file. That way, we can _always_ load the defaults. Literally impossible to not.
* When the user's profile.json doesn't exist, create it from a template
* Re-order profiles to match the order set in the user's profiles.json
* Add tests for re-ordering profiles to match user ordering
* Add support for hiding profiles using `"hidden": true`
* Use the hardcoded defaults.json for the exception->"use defaults" case
* Somehow I messed up the git submodules?
* woo documentation
* Fix a Terminal.App.Unit.Tests failure
* signed/unsigned is hard
* Use Alt+Settings button to open the default settings
* Missed a signed/unsigned
* Some very preliminary PR feedback
* More PR feedback
Use the wil helper for the exe path
Move jsonutils into their own file
kill some dead code
* Add templates to these bois
* remove some code for generating defaults, reorder defaults.json a tad
* Make guid a std::optional
* Large block of PR feedback
* Remove some dead code
* add some comments
* tag some todos
* stl is love, stl is life
* add `-noprofile`
* Fix the crash that dustin found
* -Encoding ASCII
* Set a profile's default scheme to Campbell
* Fix the tests I regressed
* Update UsingJsonSetting.md to reflect that changes from these PRs
* Change how GenerateGuidForProfile works
* Make AppKeyBindings do its own serialization
* Remove leftover dead code from the previous commit
* Fix up an enormous number of PR nits
* Fix a typo; Update the defaults to match #2378
* Tiny nits
* Some typos, PR nits
* Fix this broken defaults case
2019-09-16 21:57:10 +02:00
|
|
|
const auto settingsPath = openDefaults ? CascadiaSettings::GetDefaultSettingsPath() :
|
|
|
|
CascadiaSettings::GetSettingsPath();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
HINSTANCE res = ShellExecute(nullptr, nullptr, settingsPath.c_str(), nullptr, nullptr, SW_SHOW);
|
|
|
|
if (static_cast<int>(reinterpret_cast<uintptr_t>(res)) <= 32)
|
|
|
|
{
|
|
|
|
ShellExecute(nullptr, nullptr, L"notepad", settingsPath.c_str(), nullptr, SW_SHOW);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Responds to changes in the TabView's item list by changing the tabview's
|
2019-11-08 18:27:20 +01:00
|
|
|
// visibility. This method is also invoked when tabs are dragged / dropped as part of tab reordering
|
|
|
|
// and this method hands that case as well in concert with TabDragStarting and TabDragCompleted handlers
|
|
|
|
// that are set up in TerminalPage::Create()
|
2019-09-04 23:34:06 +02:00
|
|
|
// Arguments:
|
|
|
|
// - sender: the control that originated this event
|
|
|
|
// - eventArgs: the event's constituent arguments
|
2019-11-08 18:27:20 +01:00
|
|
|
void TerminalPage::_OnTabItemsChanged(const IInspectable& /*sender*/, const Windows::Foundation::Collections::IVectorChangedEventArgs& eventArgs)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2019-11-08 18:27:20 +01:00
|
|
|
if (_rearranging)
|
|
|
|
{
|
|
|
|
if (eventArgs.CollectionChange() == Windows::Foundation::Collections::CollectionChange::ItemRemoved)
|
|
|
|
{
|
|
|
|
_rearrangeFrom = eventArgs.Index();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eventArgs.CollectionChange() == Windows::Foundation::Collections::CollectionChange::ItemInserted)
|
|
|
|
{
|
|
|
|
_rearrangeTo = eventArgs.Index();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
_UpdateTabView();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Additional responses to clicking on a TabView's item. Currently, just remove tab with middle click
|
|
|
|
// Arguments:
|
|
|
|
// - sender: the control that originated this event (TabViewItem)
|
|
|
|
// - eventArgs: the event's constituent arguments
|
|
|
|
void TerminalPage::_OnTabClick(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs)
|
|
|
|
{
|
|
|
|
if (eventArgs.GetCurrentPoint(*this).Properties().IsMiddleButtonPressed())
|
|
|
|
{
|
2019-10-15 07:41:43 +02:00
|
|
|
_RemoveTabViewItem(sender.as<MUX::Controls::TabViewItem>());
|
2019-09-04 23:34:06 +02:00
|
|
|
eventArgs.Handled(true);
|
|
|
|
}
|
2020-05-04 22:57:12 +02:00
|
|
|
else if (eventArgs.GetCurrentPoint(*this).Properties().IsRightButtonPressed())
|
|
|
|
{
|
|
|
|
eventArgs.Handled(true);
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
void TerminalPage::_UpdatedSelectedTab(const int32_t index)
|
|
|
|
{
|
|
|
|
// Unfocus all the tabs.
|
|
|
|
for (auto tab : _tabs)
|
|
|
|
{
|
|
|
|
auto tabImpl{ _GetStrongTabImpl(tab) };
|
|
|
|
tabImpl->SetFocused(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index >= 0)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
auto tab{ _GetStrongTabImpl(index) };
|
|
|
|
|
|
|
|
_tabContent.Children().Clear();
|
|
|
|
_tabContent.Children().Append(tab->GetRootElement());
|
|
|
|
|
|
|
|
tab->SetFocused(true);
|
2020-05-04 22:57:12 +02:00
|
|
|
|
|
|
|
// Raise an event that our title changed
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
_titleChangeHandlers(*this, Title());
|
2020-05-04 22:57:12 +02:00
|
|
|
|
|
|
|
// Raise an event that our titlebar color changed
|
|
|
|
std::optional<Windows::UI::Color> color = tab->GetTabColor();
|
|
|
|
if (color.has_value())
|
|
|
|
{
|
|
|
|
_SetNonClientAreaColors(color.value());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_ClearNonClientAreaColors();
|
|
|
|
}
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
}
|
|
|
|
CATCH_LOG();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Responds to the TabView control's Selection Changed event (to move a
|
2019-11-08 18:27:20 +01:00
|
|
|
// new terminal control into focus) when not in in the middle of a tab rearrangement.
|
2019-09-04 23:34:06 +02:00
|
|
|
// Arguments:
|
|
|
|
// - sender: the control that originated this event
|
|
|
|
// - eventArgs: the event's constituent arguments
|
2019-11-05 23:29:11 +01:00
|
|
|
void TerminalPage::_OnTabSelectionChanged(const IInspectable& sender, const WUX::Controls::SelectionChangedEventArgs& /*eventArgs*/)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2019-11-08 18:27:20 +01:00
|
|
|
if (!_rearranging)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2019-11-08 18:27:20 +01:00
|
|
|
auto tabView = sender.as<MUX::Controls::TabView>();
|
|
|
|
auto selectedIndex = tabView.SelectedIndex();
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
_UpdatedSelectedTab(selectedIndex);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when our tab content size changes. This updates each tab with
|
|
|
|
// the new size, so they have a chance to update each of their panes with
|
|
|
|
// the new size.
|
|
|
|
// Arguments:
|
|
|
|
// - e: the SizeChangedEventArgs with the new size of the tab content area.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_OnContentSizeChanged(const IInspectable& /*sender*/, Windows::UI::Xaml::SizeChangedEventArgs const& e)
|
|
|
|
{
|
|
|
|
const auto newSize = e.NewSize();
|
2020-02-04 22:51:11 +01:00
|
|
|
for (auto tab : _tabs)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
auto tabImpl{ _GetStrongTabImpl(tab) };
|
|
|
|
tabImpl->ResizeContent(newSize);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Responds to the TabView control's Tab Closing event by removing
|
|
|
|
// the indicated tab from the set and focusing another one.
|
|
|
|
// The event is cancelled so App maintains control over the
|
|
|
|
// items in the tabview.
|
|
|
|
// Arguments:
|
|
|
|
// - sender: the control that originated this event
|
|
|
|
// - eventArgs: the event's constituent arguments
|
2019-11-05 23:29:11 +01:00
|
|
|
void TerminalPage::_OnTabCloseRequested(const IInspectable& /*sender*/, const MUX::Controls::TabViewTabCloseRequestedEventArgs& eventArgs)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2019-10-15 07:41:43 +02:00
|
|
|
const auto tabViewItem = eventArgs.Tab();
|
2019-09-04 23:34:06 +02:00
|
|
|
_RemoveTabViewItem(tabViewItem);
|
|
|
|
}
|
|
|
|
|
2019-09-17 07:43:27 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Called when the primary button of the content dialog is clicked.
|
|
|
|
// This calls _CloseAllTabs(), which closes all the tabs currently
|
|
|
|
// opened and then the Terminal app. This method will be called if
|
|
|
|
// the user confirms to close all the tabs.
|
|
|
|
// Arguments:
|
|
|
|
// - sender: unused
|
|
|
|
// - ContentDialogButtonClickEventArgs: unused
|
2019-10-15 07:41:43 +02:00
|
|
|
void TerminalPage::_CloseWarningPrimaryButtonOnClick(WUX::Controls::ContentDialog /* sender */,
|
|
|
|
WUX::Controls::ContentDialogButtonClickEventArgs /* eventArgs*/)
|
2019-09-17 07:43:27 +02:00
|
|
|
{
|
|
|
|
_CloseAllTabs();
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Hook up keybindings, and refresh the UI of the terminal.
|
|
|
|
// 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
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
winrt::fire_and_forget TerminalPage::_RefreshUIForSettingsReload()
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
|
|
|
// Re-wire the keybindings to their handlers, as we'll have created a
|
|
|
|
// new AppKeyBindings object.
|
|
|
|
_HookupKeyBindings(_settings->GetKeybindings());
|
|
|
|
|
|
|
|
// Refresh UI elements
|
|
|
|
auto profiles = _settings->GetProfiles();
|
|
|
|
for (auto& profile : profiles)
|
|
|
|
{
|
|
|
|
const GUID profileGuid = profile.GetGuid();
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
try
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// BuildSettings can throw an exception if the profileGuid does
|
|
|
|
// not belong to an actual profile in the list of profiles.
|
|
|
|
const auto settings = _settings->BuildSettings(profileGuid);
|
|
|
|
|
|
|
|
for (auto tab : _tabs)
|
|
|
|
{
|
|
|
|
// Attempt to reload the settings of any panes with this profile
|
|
|
|
auto tabImpl{ _GetStrongTabImpl(tab) };
|
|
|
|
tabImpl->UpdateSettings(settings, profileGuid);
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
CATCH_LOG();
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// GH#2455: If there are any panes with controls that had been
|
|
|
|
// initialized with a Profile that no longer exists in our list of
|
|
|
|
// profiles, we'll leave it unmodified. The profile doesn't exist
|
|
|
|
// anymore, so we can't possibly update its settings.
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Update the icon of the tab for the currently focused profile in that tab.
|
2020-02-04 22:51:11 +01:00
|
|
|
for (auto tab : _tabs)
|
2019-09-04 23:34:06 +02:00
|
|
|
{
|
2020-02-04 22:51:11 +01:00
|
|
|
auto tabImpl{ _GetStrongTabImpl(tab) };
|
|
|
|
_UpdateTabIcon(*tabImpl);
|
|
|
|
_UpdateTitle(*tabImpl);
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
Fixed self reference capture in Tab and TerminalPage (#3835)
<!-- 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
Every lambda capture in `Tab` and `TerminalPage` has been changed from capturing raw `this` to `std::weak_ptr<Tab>` or `winrt::weak_ref<TerminalPage>`. Lambda bodies have been changed to check the weak reference before use.
Capturing raw `this` in `Tab`'s [title change event handler](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Tab.cpp#L299) was the root cause of #3776, and is fixed in this PR among other instance of raw `this` capture.
The lambda fixes to `TerminalPage` are unrelated to the core issue addressed in the PR checklist. Because I was already editing `TerminalPage`, figured I'd do a [weak_ref pass](https://github.com/microsoft/terminal/issues/3776#issuecomment-560575575).
<!-- 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 #3776, potentially #2248, likely closes others
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3776
<!-- 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
`Tab` now inherits from `enable_shared_from_this`, which enable accessing `Tab` objects as `std::weak_ptr<Tab>` objects. All instances of lambdas capturing `this` now capture `std::weak_ptr<Tab>` instead. `TerminalPage` is a WinRT type which supports `winrt::weak_ref<TerminalPage>`. All previous instance of `TerminalPage` lambdas capturing `this` has been replaced to capture `winrt::weak_ref<TerminalPage>`. These weak pointers/references can only be created after object construction necessitating for `Tab` a new function called after construction to bind lambdas.
Any anomalous crash related to the following functionality during closing a tab or WT may be fixed by this PR:
- Tab icon updating
- Tab text updating
- Tab dragging
- Clicking new tab button
- Changing active pane
- Closing an active tab
- Clicking on a tab
- Creating the new tab flyout menu
Sorry about all the commits. Will fix my fork after this PR! 😅
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Attempted to repro the steps indicated in issue #3776 with the new changes and failed. When before the changes, the issue could consistently be reproed.
2019-12-06 00:18:22 +01:00
|
|
|
auto weakThis{ get_weak() };
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- 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 #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- 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
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
2019-09-04 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
2020-01-27 16:34:12 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Sets the initial commandline to process on startup, and attempts to
|
|
|
|
// parse it. Commands will be parsed into a list of ShortcutActions that
|
|
|
|
// will be processed on TerminalPage::Create().
|
|
|
|
// - This function will have no effective result after Create() is called.
|
|
|
|
// - This function returns 0, unless a there was a non-zero result from
|
|
|
|
// trying to parse one of the commands provided. In that case, no commands
|
|
|
|
// after the failing command will be parsed, and the non-zero code
|
|
|
|
// returned.
|
|
|
|
// Arguments:
|
|
|
|
// - args: an array of strings to process as a commandline. These args can contain spaces
|
|
|
|
// Return Value:
|
|
|
|
// - the result of the first command who's parsing returned a non-zero code,
|
|
|
|
// or 0. (see TerminalPage::_ParseArgs)
|
|
|
|
int32_t TerminalPage::SetStartupCommandline(winrt::array_view<const hstring> args)
|
|
|
|
{
|
|
|
|
return _ParseArgs(args);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Attempts to parse an array of commandline args into a list of
|
|
|
|
// commands to execute, and then parses these commands. As commands are
|
ci: run spell check in CI, fix remaining issues (#4799)
This commit introduces a github action to check our spelling and fixes
the following misspelled words so that we come up green.
It also renames TfEditSes to TfEditSession, because Ses is not a word.
currently, excerpt, fallthrough, identified, occurred, propagate,
provided, rendered, resetting, separate, succeeded, successfully,
terminal, transferred, adheres, breaks, combining, preceded,
architecture, populated, previous, setter, visible, window, within,
appxmanifest, hyphen, control, offset, powerpoint, suppress, parsing,
prioritized, aforementioned, check in, build, filling, indices, layout,
mapping, trying, scroll, terabyte, vetoes, viewport, whose
2020-03-25 19:02:53 +01:00
|
|
|
// successfully parsed, they will generate ShortcutActions for us to be
|
2020-01-27 16:34:12 +01:00
|
|
|
// able to execute. If we fail to parse any commands, we'll return the
|
|
|
|
// error code from the failure to parse that command, and stop processing
|
|
|
|
// additional commands.
|
|
|
|
// Arguments:
|
|
|
|
// - args: an array of strings to process as a commandline. These args can contain spaces
|
|
|
|
// Return Value:
|
|
|
|
// - 0 if the commandline was successfully parsed
|
|
|
|
int TerminalPage::_ParseArgs(winrt::array_view<const hstring>& args)
|
|
|
|
{
|
|
|
|
auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args);
|
|
|
|
|
|
|
|
for (auto& cmdBlob : commands)
|
|
|
|
{
|
|
|
|
// On one hand, it seems like we should be able to have one
|
|
|
|
// AppCommandlineArgs for parsing all of them, and collect the
|
|
|
|
// results one at a time.
|
|
|
|
//
|
|
|
|
// On the other hand, re-using a CLI::App seems to leave state from
|
|
|
|
// previous parsings around, so we could get mysterious behavior
|
|
|
|
// where one command affects the values of the next.
|
|
|
|
//
|
|
|
|
// From https://cliutils.github.io/CLI11/book/chapters/options.html:
|
|
|
|
// > If that option is not given, CLI11 will not touch the initial
|
|
|
|
// > value. This allows you to set up defaults by simply setting
|
|
|
|
// > your value beforehand.
|
|
|
|
//
|
|
|
|
// So we pretty much need the to either manually reset the state
|
|
|
|
// each command, or build new ones.
|
|
|
|
const auto result = _appArgs.ParseCommand(cmdBlob);
|
|
|
|
|
|
|
|
// If this succeeded, result will be 0. Otherwise, the caller should
|
|
|
|
// exit(result), to exit the program.
|
|
|
|
if (result != 0)
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all the args were successfully parsed, we'll have some commands
|
|
|
|
// built in _appArgs, which we'll use when the application starts up.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// Method Description:
|
|
|
|
// - This is the method that App will call when the titlebar
|
|
|
|
// has been clicked. It dismisses any open flyouts.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::TitlebarClicked()
|
|
|
|
{
|
|
|
|
if (_newTabButton && _newTabButton.Flyout())
|
|
|
|
{
|
|
|
|
_newTabButton.Flyout().Hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Search - add search box control and implement search experience (#3590)
<!-- 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)? -->
This is the PR for feature Search: #605
This PR includes the newly introduced SearchBoxControl in TermControl dir, which is the search bar for the search experience. And the codes that enable Search in Windows Terminal.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
The PR that migrates the Conhost search module: https://github.com/microsoft/terminal/pull/3279
Spec (still actively updating): https://github.com/microsoft/terminal/pull/3299
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #605
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be 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 -->
These functionalities are included in the search experience.
1. Search in Terminal text buffer.
2. Automatic wrap-around.
3. Search up or down switch by clicking different buttons.
4. Search case sensitively/insensitively by clicking a button. S. Move the search box to the top/bottom by clicking a button.
6. Close by clicking 'X'.
7. Open search by ctrl + F.
When the searchbox is open, the user could still interact with the terminal by clicking the terminal input area.
While I already have the search functionalities, currently there are still some known to-do works and I will keep updating my PR:
1. Optimize the search box UI, this includes:
1) Theme adaptation. The search box background and font color
should change according to the theme,
2) Add background. Currently the elements in search box are all
transparent. However, we need a background.
3) Move button should be highlighted once clicked.
2. Accessibility: search process should be able to performed without mouse. Once the search box is focused, the user should be able to navigate between all interactive elements on the searchbox using keyboard.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
To test:
1. checkout this branch.
2. Build the project.
3. Start Windows Terminal and press Ctrl+F
4. The search box should appear on the top right corner.
2019-12-17 16:52:37 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Called when the user tries to do a search using keybindings.
|
|
|
|
// This will tell the current focused terminal control to create
|
|
|
|
// a search box and enable find process.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_Find()
|
|
|
|
{
|
|
|
|
const auto termControl = _GetActiveControl();
|
|
|
|
termControl.CreateSearchBoxControl();
|
|
|
|
}
|
|
|
|
|
Enable fullscreen mode (#3408)
## Summary of the Pull Request
Enables the `toggleFullscreen` action to be able to enter fullscreen mode, bound by default to <kbd>alt+enter</kbd>.
The action is bubbled up to the WindowsTerminal (Win32) layer, where the window resizes itself to take the entire size of the monitor.
This largely reuses code from conhost. Conhost already had a fullscreen mode, so I figured I might as well re-use that.
## References
Unfortunately there are still very thin borders around the window when the NonClientIslandWindow is fullscreened. I think I know where the problem is. However, that area of code is about to get a massive overhaul with #3064, so I didn't want to necessarily make it worse right now.
A follow up should be filed to add support for "Always show / reveal / never show tabs in fullscreen mode". Currently, the only mode is "never show tabs".
Additionally, some of this code (particularily re:drawing the nonclient area) could be re-used for #2238.
## PR Checklist
* [x] Closes #531, #3411
* [x] I work here
* [n/a] Tests added/passed 😭
* [x] Requires documentation to be updated
## Validation Steps Performed
* Manually tested both the NonClientIslandWindow and the IslandWindow.
* Cherry-pick commit 8e56bfe
* Don't draw the tab strip when maximized
(cherry picked from commit bac4be7c0f3ed1cdcd4f9ae8980fc98103538613)
* Fix the vista window flash for the NCIW
(cherry picked from commit 7d3a18a893c02bd2ed75026f2aac52e20321a1cf)
* Some code cleanup for review
(cherry picked from commit 9e22b7730bba426adcbfd9e7025f192dbf8efb32)
* A tad bit more notes and cleanup
* Update schema, docs
* Most of the PR comments
* I'm not sure this actually works, so I'm committing it to revert it and check
* Update some comments that were lost.
* Fix a build break?
* oh no
2019-11-05 20:40:29 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Toggles fullscreen mode. Hides the tab row, and raises our
|
|
|
|
// ToggleFullscreen event.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_ToggleFullscreen()
|
|
|
|
{
|
|
|
|
_toggleFullscreenHandlers(*this, nullptr);
|
|
|
|
|
|
|
|
_isFullscreen = !_isFullscreen;
|
|
|
|
|
|
|
|
_UpdateTabView();
|
|
|
|
}
|
|
|
|
|
2020-01-27 16:34:12 +01:00
|
|
|
// Method Description:
|
|
|
|
// - If there were any errors parsing the commandline that was used to
|
|
|
|
// initialize the terminal, this will return a string containing that
|
|
|
|
// message. If there were no errors, this message will be blank.
|
|
|
|
// - If the user requested help on any command (using --help), this will
|
|
|
|
// contain the help message.
|
2020-05-04 22:56:15 +02:00
|
|
|
// - If the user requested the version number (using --version), this will
|
|
|
|
// contain the version string.
|
2020-01-27 16:34:12 +01:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
ci: run spell check in CI, fix remaining issues (#4799)
This commit introduces a github action to check our spelling and fixes
the following misspelled words so that we come up green.
It also renames TfEditSes to TfEditSession, because Ses is not a word.
currently, excerpt, fallthrough, identified, occurred, propagate,
provided, rendered, resetting, separate, succeeded, successfully,
terminal, transferred, adheres, breaks, combining, preceded,
architecture, populated, previous, setter, visible, window, within,
appxmanifest, hyphen, control, offset, powerpoint, suppress, parsing,
prioritized, aforementioned, check in, build, filling, indices, layout,
mapping, trying, scroll, terabyte, vetoes, viewport, whose
2020-03-25 19:02:53 +01:00
|
|
|
// - the help text or error message for the provided commandline, if one
|
2020-01-27 16:34:12 +01:00
|
|
|
// exists, otherwise the empty string.
|
2020-05-04 22:56:15 +02:00
|
|
|
winrt::hstring TerminalPage::ParseCommandlineMessage()
|
2020-01-27 16:34:12 +01:00
|
|
|
{
|
|
|
|
return winrt::to_hstring(_appArgs.GetExitMessage());
|
|
|
|
}
|
|
|
|
|
2020-02-04 22:51:11 +01:00
|
|
|
// Method Description:
|
2020-05-04 22:56:15 +02:00
|
|
|
// - Returns true if we should exit the application before even starting the
|
|
|
|
// window. We might want to do this if we're displaying an error message or
|
|
|
|
// the version string, or if we want to open the settings file.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - true iff we should exit the application before even starting the window
|
|
|
|
bool TerminalPage::ShouldExitEarly()
|
|
|
|
{
|
|
|
|
return _appArgs.ShouldExitEarly();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2020-02-04 22:51:11 +01:00
|
|
|
// - Returns a com_ptr to the implementation type of the tab at the given index
|
|
|
|
// Arguments:
|
|
|
|
// - index: an unsigned integer index to a tab in _tabs
|
|
|
|
// Return Value:
|
|
|
|
// - a com_ptr to the implementation type of the Tab
|
|
|
|
winrt::com_ptr<Tab> TerminalPage::_GetStrongTabImpl(const uint32_t index) const
|
|
|
|
{
|
|
|
|
winrt::com_ptr<Tab> tabImpl;
|
|
|
|
tabImpl.copy_from(winrt::get_self<Tab>(_tabs.GetAt(index)));
|
|
|
|
return tabImpl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Returns a com_ptr to the implementation type of the given projected Tab
|
|
|
|
// Arguments:
|
|
|
|
// - tab: the projected type of a Tab
|
|
|
|
// Return Value:
|
|
|
|
// - a com_ptr to the implementation type of the Tab
|
|
|
|
winrt::com_ptr<Tab> TerminalPage::_GetStrongTabImpl(const ::winrt::TerminalApp::Tab& tab) const
|
|
|
|
{
|
|
|
|
winrt::com_ptr<Tab> tabImpl;
|
|
|
|
tabImpl.copy_from(winrt::get_self<Tab>(tab));
|
|
|
|
return tabImpl;
|
|
|
|
}
|
|
|
|
|
2020-05-04 22:57:12 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Sets the tab split button color when a new tab color is selected
|
|
|
|
// Arguments:
|
|
|
|
// - color: The color of the newly selected tab, used to properly calculate
|
|
|
|
// the foreground color of the split button (to match the font
|
|
|
|
// color of the tab)
|
|
|
|
// - accentColor: the actual color we are going to use to paint the tab row and
|
|
|
|
// split button, so that there is some contrast between the tab
|
|
|
|
// and the non-client are behind it
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_SetNewTabButtonColor(const Windows::UI::Color& color, const Windows::UI::Color& accentColor)
|
|
|
|
{
|
|
|
|
// TODO GH#3327: Look at what to do with the tab button when we have XAML theming
|
|
|
|
bool IsBrightColor = ColorHelper::IsBrightColor(color);
|
|
|
|
bool isLightAccentColor = ColorHelper::IsBrightColor(accentColor);
|
|
|
|
winrt::Windows::UI::Color pressedColor{};
|
|
|
|
winrt::Windows::UI::Color hoverColor{};
|
|
|
|
winrt::Windows::UI::Color foregroundColor{};
|
|
|
|
const float hoverColorAdjustment = 5.f;
|
|
|
|
const float pressedColorAdjustment = 7.f;
|
|
|
|
|
|
|
|
if (IsBrightColor)
|
|
|
|
{
|
|
|
|
foregroundColor = winrt::Windows::UI::Colors::Black();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
foregroundColor = winrt::Windows::UI::Colors::White();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isLightAccentColor)
|
|
|
|
{
|
|
|
|
hoverColor = ColorHelper::Darken(accentColor, hoverColorAdjustment);
|
|
|
|
pressedColor = ColorHelper::Darken(accentColor, pressedColorAdjustment);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hoverColor = ColorHelper::Lighten(accentColor, hoverColorAdjustment);
|
|
|
|
pressedColor = ColorHelper::Lighten(accentColor, pressedColorAdjustment);
|
|
|
|
}
|
|
|
|
|
|
|
|
Media::SolidColorBrush backgroundBrush{ accentColor };
|
|
|
|
Media::SolidColorBrush backgroundHoverBrush{ hoverColor };
|
|
|
|
Media::SolidColorBrush backgroundPressedBrush{ pressedColor };
|
|
|
|
Media::SolidColorBrush foregroundBrush{ foregroundColor };
|
|
|
|
|
|
|
|
_newTabButton.Resources().Insert(winrt::box_value(L"SplitButtonBackground"), backgroundBrush);
|
|
|
|
_newTabButton.Resources().Insert(winrt::box_value(L"SplitButtonBackgroundPointerOver"), backgroundHoverBrush);
|
|
|
|
_newTabButton.Resources().Insert(winrt::box_value(L"SplitButtonBackgroundPressed"), backgroundPressedBrush);
|
|
|
|
|
|
|
|
_newTabButton.Resources().Insert(winrt::box_value(L"SplitButtonForeground"), foregroundBrush);
|
|
|
|
_newTabButton.Resources().Insert(winrt::box_value(L"SplitButtonForegroundPointerOver"), foregroundBrush);
|
|
|
|
_newTabButton.Resources().Insert(winrt::box_value(L"SplitButtonForegroundPressed"), foregroundBrush);
|
|
|
|
|
|
|
|
_newTabButton.Background(backgroundBrush);
|
|
|
|
_newTabButton.Foreground(foregroundBrush);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Clears the tab split button color to a system color
|
|
|
|
// (or white if none is found) when the tab's color is cleared
|
|
|
|
// - Clears the tab row color to a system color
|
|
|
|
// (or white if none is found) when the tab's color is cleared
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_ClearNewTabButtonColor()
|
|
|
|
{
|
|
|
|
// TODO GH#3327: Look at what to do with the tab button when we have XAML theming
|
|
|
|
winrt::hstring keys[] = {
|
|
|
|
L"SplitButtonBackground",
|
|
|
|
L"SplitButtonBackgroundPointerOver",
|
|
|
|
L"SplitButtonBackgroundPressed",
|
|
|
|
L"SplitButtonForeground",
|
|
|
|
L"SplitButtonForegroundPointerOver",
|
|
|
|
L"SplitButtonForegroundPressed"
|
|
|
|
};
|
|
|
|
|
|
|
|
// simply clear any of the colors in the split button's dict
|
|
|
|
for (auto keyString : keys)
|
|
|
|
{
|
|
|
|
auto key = winrt::box_value(keyString);
|
|
|
|
if (_newTabButton.Resources().HasKey(key))
|
|
|
|
{
|
|
|
|
_newTabButton.Resources().Remove(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto res = Application::Current().Resources();
|
|
|
|
|
|
|
|
const auto defaultBackgroundKey = winrt::box_value(L"TabViewItemHeaderBackground");
|
|
|
|
const auto defaultForegroundKey = winrt::box_value(L"SystemControlForegroundBaseHighBrush");
|
|
|
|
winrt::Windows::UI::Xaml::Media::SolidColorBrush backgroundBrush;
|
|
|
|
winrt::Windows::UI::Xaml::Media::SolidColorBrush foregroundBrush;
|
|
|
|
|
2020-05-05 22:33:07 +02:00
|
|
|
// TODO: Related to GH#3917 - I think if the system is set to "Dark"
|
|
|
|
// theme, but the app is set to light theme, then this lookup still
|
|
|
|
// returns to us the dark theme brushes. There's gotta be a way to get
|
|
|
|
// the right brushes...
|
|
|
|
// See also GH#5741
|
2020-05-04 22:57:12 +02:00
|
|
|
if (res.HasKey(defaultBackgroundKey))
|
|
|
|
{
|
|
|
|
winrt::Windows::Foundation::IInspectable obj = res.Lookup(defaultBackgroundKey);
|
|
|
|
backgroundBrush = obj.try_as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
backgroundBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush{ winrt::Windows::UI::Colors::Black() };
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res.HasKey(defaultForegroundKey))
|
|
|
|
{
|
|
|
|
winrt::Windows::Foundation::IInspectable obj = res.Lookup(defaultForegroundKey);
|
|
|
|
foregroundBrush = obj.try_as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
foregroundBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush{ winrt::Windows::UI::Colors::White() };
|
|
|
|
}
|
|
|
|
|
|
|
|
_newTabButton.Background(backgroundBrush);
|
|
|
|
_newTabButton.Foreground(foregroundBrush);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Sets the tab split button color when a new tab color is selected
|
|
|
|
// - This method could also set the color of the title bar and tab row
|
|
|
|
// in the future
|
|
|
|
// Arguments:
|
|
|
|
// - selectedTabColor: The color of the newly selected tab
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_SetNonClientAreaColors(const Windows::UI::Color& /*selectedTabColor*/)
|
|
|
|
{
|
|
|
|
// TODO GH#3327: Look at what to do with the NC area when we have XAML theming
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Clears the tab split button color when the tab's color is cleared
|
|
|
|
// - This method could also clear the color of the title bar and tab row
|
|
|
|
// in the future
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TerminalPage::_ClearNonClientAreaColors()
|
|
|
|
{
|
|
|
|
// TODO GH#3327: Look at what to do with the NC area when we have XAML theming
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// -------------------------------- WinRT Events ---------------------------------
|
|
|
|
// Winrt events need a method for adding a callback to the event and removing the callback.
|
|
|
|
// These macros will define them both for you.
|
|
|
|
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring);
|
|
|
|
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs);
|
|
|
|
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, UIElement);
|
2019-10-15 07:41:43 +02:00
|
|
|
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ShowDialog, _showDialogHandlers, winrt::Windows::Foundation::IInspectable, WUX::Controls::ContentDialog);
|
Enable fullscreen mode (#3408)
## Summary of the Pull Request
Enables the `toggleFullscreen` action to be able to enter fullscreen mode, bound by default to <kbd>alt+enter</kbd>.
The action is bubbled up to the WindowsTerminal (Win32) layer, where the window resizes itself to take the entire size of the monitor.
This largely reuses code from conhost. Conhost already had a fullscreen mode, so I figured I might as well re-use that.
## References
Unfortunately there are still very thin borders around the window when the NonClientIslandWindow is fullscreened. I think I know where the problem is. However, that area of code is about to get a massive overhaul with #3064, so I didn't want to necessarily make it worse right now.
A follow up should be filed to add support for "Always show / reveal / never show tabs in fullscreen mode". Currently, the only mode is "never show tabs".
Additionally, some of this code (particularily re:drawing the nonclient area) could be re-used for #2238.
## PR Checklist
* [x] Closes #531, #3411
* [x] I work here
* [n/a] Tests added/passed 😭
* [x] Requires documentation to be updated
## Validation Steps Performed
* Manually tested both the NonClientIslandWindow and the IslandWindow.
* Cherry-pick commit 8e56bfe
* Don't draw the tab strip when maximized
(cherry picked from commit bac4be7c0f3ed1cdcd4f9ae8980fc98103538613)
* Fix the vista window flash for the NCIW
(cherry picked from commit 7d3a18a893c02bd2ed75026f2aac52e20321a1cf)
* Some code cleanup for review
(cherry picked from commit 9e22b7730bba426adcbfd9e7025f192dbf8efb32)
* A tad bit more notes and cleanup
* Update schema, docs
* Most of the PR comments
* I'm not sure this actually works, so I'm committing it to revert it and check
* Update some comments that were lost.
* Fix a build break?
* oh no
2019-11-05 20:40:29 +01:00
|
|
|
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs);
|
2019-07-09 23:47:30 +02:00
|
|
|
}
|