terminal/src/cascadia/TerminalApp/Tab.cpp

394 lines
12 KiB
C++
Raw Normal View History

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "Tab.h"
#include "Utils.h"
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Microsoft::Terminal::Settings;
using namespace winrt::Microsoft::Terminal::TerminalControl;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
}
Tab::Tab(const GUID& profile, const TermControl& control)
{
_rootPane = std::make_shared<Pane>(profile, control, true);
_rootPane->Closed([=](auto&& /*s*/, auto&& /*e*/) {
_ClosedHandlers(nullptr, nullptr);
});
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
_activePane = _rootPane;
_MakeTabViewItem();
}
void Tab::_MakeTabViewItem()
{
_tabViewItem = ::winrt::MUX::Controls::TabViewItem{};
}
UIElement Tab::GetRootElement()
{
return _rootPane->GetRootElement();
}
// Method Description:
// - Returns nullptr if no children of this tab were the last control to be
// focused, or the TermControl that _was_ the last control to be focused (if
// there was one).
// - This control might not currently be focused, if the tab itself is not
// currently focused.
// Arguments:
// - <none>
// Return Value:
// - nullptr if no children were marked `_lastFocused`, else the TermControl
// that was last focused.
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
TermControl Tab::GetActiveTerminalControl() const
{
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
return _activePane->GetTerminalControl();
}
winrt::MUX::Controls::TabViewItem Tab::GetTabViewItem()
{
return _tabViewItem;
}
// Method Description:
// - Returns true if this is the currently focused tab. For any set of tabs,
// there should only be one tab that is marked as focused, though each tab has
// no control over the other tabs in the set.
// Arguments:
// - <none>
// Return Value:
// - true iff this tab is focused.
bool Tab::IsFocused() const noexcept
{
return _focused;
}
// Method Description:
// - Updates our focus state. If we're gaining focus, make sure to transfer
// focus to the last focused terminal control in our tree of controls.
// Arguments:
// - focused: our new focus state. If true, we should be focused. If false, we
// should be unfocused.
// Return Value:
// - <none>
void Tab::SetFocused(const bool focused)
{
_focused = focused;
if (_focused)
{
_Focus();
}
}
// Method Description:
// - Returns nullopt if no children of this tab were the last control to be
// focused, or the GUID of the profile of the last control to be focused (if
// there was one).
// Arguments:
// - <none>
// Return Value:
// - nullopt if no children of this tab were the last control to be
// focused, else the GUID of the profile of the last control to be focused
std::optional<GUID> Tab::GetFocusedProfile() const noexcept
{
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
return _activePane->GetFocusedProfile();
}
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
// Method Description:
// - Called after construction of a Tab object to bind event handlers to its
// associated Pane and TermControl object
// Arguments:
// - control: reference to the TermControl object to bind event to
// Return Value:
// - <none>
void Tab::BindEventHandlers(const TermControl& control) noexcept
{
_AttachEventHandlersToPane(_rootPane);
_AttachEventHandlersToControl(control);
}
// Method Description:
// - Attempts to update the settings of this tab's tree of panes.
// Arguments:
// - settings: The new TerminalSettings to apply to any matching controls
// - profile: The GUID of the profile these settings should apply to.
// Return Value:
// - <none>
void Tab::UpdateSettings(const TerminalSettings& settings, const GUID& profile)
{
_rootPane->UpdateSettings(settings, profile);
}
// Method Description:
// - Focus the last focused control in our tree of panes.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Tab::_Focus()
{
_focused = true;
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
auto lastFocusedControl = GetActiveTerminalControl();
if (lastFocusedControl)
{
Accessibility: TermControl Automation Peer (#2083) Builds on the work of #1691 and #1915 Let's start with the easy change: - `TermControl`'s `controlRoot` was removed. `TermControl` is a `UserControl` now. Ok. Now we've got a story to tell here.... ### TermControlAP - the Automation Peer Here's an in-depth guide on custom automation peers: https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers We have a custom XAML element (TermControl). So XAML can't really hold our hands and determine an accessible behavior for us. So this automation peer is responsible for enabling that interaction. We made it a FrameworkElementAutomationPeer to get as much accessibility as possible from it just being a XAML element (i.e.: where are we on the screen? what are my dimensions?). This is recommended. Any functions with "Core" at the end, are overwritten here to tweak this automation peer into what we really need. But what kind of interactions can a user expect from this XAML element? Introducing ControlPatterns! There's a ton of interfaces that just define "what can I do". Thankfully, we already know that we're supposed to be `ScreenInfoUiaProvider` and that was an `ITextProvider`, so let's just make the TermControlAP an `ITextProvider` too. So now we have a way to define what accessible actions can be performed on us, but what should those actions do? Well let's just use the automation providers from ConHost that are now in a shared space! (Note: this is a great place to stop and get some coffee. We're about to hop into the .cpp file in the next section) ### Wrapping our shared Automation Providers Unfortunately, we can't just use the automation providers from ConHost. Or, at least not just hook them up as easily as we wish. ConHost's UIA Providers were written using UIAutomationCore and ITextRangeProiuder. XAML's interfaces ITextProvider and ITextRangeProvider are lined up to be exactly the same. So we need to wrap our ConHost UIA Providers (UIAutomationCore) with the XAML ones. We had two providers, so that means we have two wrappers. #### TermControlAP (XAML) <----> ScreenInfoUiaProvider (UIAutomationCore) Each of the functions in the pragma region `ITextProvider` for TermControlAP.cpp is just wrapping what we do in `ScreenInfoUiaProvider`, and returning an acceptable version of it. Most of `ScreenInfoUiaProvider`'s functions return `UiaTextRange`s. So we need to wrap that too. That's this next section... #### XamlUiaTextRange (XAML) <----> UiaTextRange (UIAutomationCore) Same idea. We're wrapping everything that we could do with `UiaTextRange` and putting it inside of `XamlUiaTextRange`. ### Additional changes to `UiaTextRange` and `ScreenInfoUiaProvider` If you don't know what I just said, please read this background: - #1691: how accessibility works and the general responsibility of these two classes - #1915: how we pulled these Accessibility Providers into a shared area TL;DR: `ScreenInfoUiaProvider` lets you interact with the displayed text. `UiaTextRange` is specific ranges of text in the display and navigate the text. Thankfully, we didn't do many changes here. I feel like some of it is hacked together but now that we have a somewhat working system, making changes shouldn't be too hard...I hope. #### UiaTextRange We don't have access to the window handle. We really only need it to draw the bounding rects using WinUser's `ScreenToClient()` and `ClientToScreen()`. I need to figure out how to get around this. In the meantime, I made the window handle optional. And if we don't have one....well, we need to figure that out. But other than that, we have a `UiaTextRange`. #### ScreenInfoUiaProvider At some point, we need to hook up this automation provider to the WindowUiaProvider. This should help with navigation of the UIA Tree and make everything just look waaaay better. For now, let's just do the same approach and make the pUiaParent optional. This one's the one I'm not that proud of, but it works. We need the parent to get a bounding rect of the terminal. While we figure out how to attach the WindowUiaProvider, we should at the very least be able to get a bunch of info from our xaml automation peer. So, I've added a _getBoundingRect optional function. This is what's called when we don't have a WindowUiaProvider as our parent. ## Validation Steps Performed I've been using inspect.exe to see the UIA tree. I was able to interact with the terminal mostly fine. A few known issues below. Unfortunately, I tried running Narrator on this and it didn't seem to like it (by that I mean WT crashed). Then again, I don't really know how to use narrator other than "click on object" --> "listen voice". I feel like there's a way to get the other interactions with narrator, but I'll be looking into more of that soon. I bet if I fix the two issues below, Narrator will be happy. ## Miscellaneous Known Issues - `GetSelection()` and `GetVisibleRanges()` crashes. I need to debug through these. I want to include them in this PR. Fixes #1353.
2019-07-31 01:43:10 +02:00
lastFocusedControl.Focus(FocusState::Programmatic);
}
}
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 Tab::UpdateIcon(const winrt::hstring iconPath)
{
// Don't reload our icon if it hasn't changed.
if (iconPath == _lastIconPath)
{
return;
}
_lastIconPath = iconPath;
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
std::weak_ptr<Tab> weakThis{ shared_from_this() };
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(_tabViewItem.Dispatcher());
if (auto tab{ weakThis.lock() })
{
_tabViewItem.IconSource(GetColoredIcon<winrt::MUX::Controls::IconSource>(_lastIconPath));
}
}
// Method Description:
// - Gets the title string of the last focused terminal control in our tree.
// Returns the empty string if there is no such control.
// Arguments:
// - <none>
// Return Value:
// - the title string of the last focused terminal control in our tree.
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::hstring Tab::GetActiveTitle() const
{
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 lastFocusedControl = GetActiveTerminalControl();
return lastFocusedControl ? lastFocusedControl.Title() : L"";
}
// Method Description:
// - Set the text on the TabViewItem for this tab.
// Arguments:
// - text: The new text string to use as the Header for our TabViewItem
// Return Value:
// - <none>
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 Tab::SetTabText(const winrt::hstring text)
{
// Copy the hstring, so we don't capture a dead reference
winrt::hstring textCopy{ text };
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
std::weak_ptr<Tab> weakThis{ shared_from_this() };
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(_tabViewItem.Dispatcher());
if (auto tab{ weakThis.lock() })
{
_tabViewItem.Header(winrt::box_value(text));
}
}
// Method Description:
// - Move the viewport of the terminal 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.
// Return Value:
// - <none>
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 Tab::Scroll(const int delta)
{
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
auto control = GetActiveTerminalControl();
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(control.Dispatcher());
const auto currentOffset = control.GetScrollOffset();
control.KeyboardScrollViewport(currentOffset + delta);
}
// Method Description:
// - Determines whether the focused pane has sufficient space to be split.
// Arguments:
// - splitType: The type of split we want to create.
// Return Value:
// - True if the focused pane can be split. False otherwise.
bool Tab::CanSplitPane(winrt::TerminalApp::SplitState splitType)
{
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
return _activePane->CanSplit(splitType);
}
// Method Description:
// - Split the focused pane in our tree of panes, and place the
// given TermControl into the newly created pane.
// Arguments:
// - splitType: The type of split we want to create.
// - profile: The profile GUID to associate with the newly created pane.
// - control: A TermControl to use in the new pane.
// Return Value:
// - <none>
void Tab::SplitPane(winrt::TerminalApp::SplitState splitType, const GUID& profile, TermControl& control)
{
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
auto [first, second] = _activePane->Split(splitType, profile, control);
_activePane = first;
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
_AttachEventHandlersToControl(control);
// Add a event handlers to the new panes' GotFocus event. When the pane
// gains focus, we'll mark it as the new active pane.
_AttachEventHandlersToPane(first);
_AttachEventHandlersToPane(second);
}
Snap to character grid when resizing window (#3181) When user resizes window, snap the size to align with the character grid (like e.g. putty, mintty and most unix terminals). Properly resolves arbitrary pane configuration (even with different font sizes and padding) trying to align each pane as close as possible. It also fixes terminal minimum size enforcement which was not quite well handled, especially with multiple panes. This PR does not however try to keep the terminals aligned at other user actions (e.g. font change or pane split). That is to be tracked by some other activity. Snapping is resolved in the pane tree, recursively, so it (hopefully) works for any possible layout. Along the way I had to clean up some things as so to make the resulting code not so cumbersome: 1. Pane.cpp: Replaced _firstPercent and _secondPercent with single _desiredSplitPosition to reduce invariants - these had to be kept in sync so their sum always gives 1 (and were not really a percent). The desired part refers to fact that since panes are aligned, there is usually some deviation from that ratio. 2. Pane.cpp: Fixed _GetMinSize() - it was improperly accounting for split direction 3. TerminalControl: Made dedicated member for padding instead of reading it from a control itself. This is because the winrt property functions turned out to be slow and this algorithm needs to access it many times. I also cached scrollbar width for the same reason. 4. AppHost: Moved window to client size resolution to virtual method, where IslandWindow and NonClientIslandWindow have their own implementations (as opposite to pointer casting). One problem with current implementation is I had to make a long call chain from the window that requests snapping to the (root) pane that implements it: IslandWindow -> AppHost's callback -> App -> TerminalPage -> Tab -> Pane. I don't know if this can be done better. ## Validation Steps Performed Spam split pane buttons, randomly change font sizes with ctrl+mouse wheel and drag the window back and forth. Closes #2834 Closes #2277
2020-01-08 22:19:23 +01:00
// Method Description:
// - See Pane::CalcSnappedDimension
float Tab::CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
{
return _rootPane->CalcSnappedDimension(widthOrHeight, dimension);
}
// Method Description:
// - Update the size of our panes to fill the new given size. This happens when
// the window is resized.
// Arguments:
// - newSize: the amount of space that the panes have to fill now.
// Return Value:
// - <none>
void Tab::ResizeContent(const winrt::Windows::Foundation::Size& newSize)
{
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
// NOTE: This _must_ be called on the root pane, so that it can propogate
// throughout the entire tree.
_rootPane->ResizeContent(newSize);
}
// 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.
// Arguments:
// - direction: The direction to move the separator in.
// Return Value:
// - <none>
void Tab::ResizePane(const winrt::TerminalApp::Direction& direction)
{
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
// NOTE: This _must_ be called on the root pane, so that it can propogate
// throughout the entire tree.
_rootPane->ResizePane(direction);
}
// 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.
// Arguments:
// - direction: The direction to move the focus in.
// Return Value:
// - <none>
void Tab::NavigateFocus(const winrt::TerminalApp::Direction& direction)
{
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
// NOTE: This _must_ be called on the root pane, so that it can propogate
// throughout the entire tree.
_rootPane->NavigateFocus(direction);
}
// Method Description:
// - Prepares this tab for being removed from the UI hierarchy by shutting down all active connections.
void Tab::Shutdown()
{
_rootPane->Shutdown();
}
// Method Description:
// - Closes the currently focused pane in this tab. If it's the last pane in
// this tab, our Closed event will be fired (at a later time) for anyone
// registered as a handler of our close event.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Tab::ClosePane()
{
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
_activePane->Close();
}
// Method Description:
// - Register any event handlers that we may need with the given TermControl.
// This should be called on each and every TermControl that we add to the tree
// of Panes in this tab. We'll add events too:
// * notify us when the control's title changed, so we can update our own
// title (if necessary)
// Arguments:
// - control: the TermControl to add events to.
// Return Value:
// - <none>
void Tab::_AttachEventHandlersToControl(const TermControl& control)
{
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
std::weak_ptr<Tab> weakThis{ shared_from_this() };
control.TitleChanged([weakThis](auto newTitle) {
// Check if Tab's lifetime has expired
if (auto tab{ weakThis.lock() })
{
// The title of the control changed, but not necessarily the title of the tab.
// Set the tab's text to the active panes' text.
tab->SetTabText(tab->GetActiveTitle());
}
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
});
Snap to character grid when resizing window (#3181) When user resizes window, snap the size to align with the character grid (like e.g. putty, mintty and most unix terminals). Properly resolves arbitrary pane configuration (even with different font sizes and padding) trying to align each pane as close as possible. It also fixes terminal minimum size enforcement which was not quite well handled, especially with multiple panes. This PR does not however try to keep the terminals aligned at other user actions (e.g. font change or pane split). That is to be tracked by some other activity. Snapping is resolved in the pane tree, recursively, so it (hopefully) works for any possible layout. Along the way I had to clean up some things as so to make the resulting code not so cumbersome: 1. Pane.cpp: Replaced _firstPercent and _secondPercent with single _desiredSplitPosition to reduce invariants - these had to be kept in sync so their sum always gives 1 (and were not really a percent). The desired part refers to fact that since panes are aligned, there is usually some deviation from that ratio. 2. Pane.cpp: Fixed _GetMinSize() - it was improperly accounting for split direction 3. TerminalControl: Made dedicated member for padding instead of reading it from a control itself. This is because the winrt property functions turned out to be slow and this algorithm needs to access it many times. I also cached scrollbar width for the same reason. 4. AppHost: Moved window to client size resolution to virtual method, where IslandWindow and NonClientIslandWindow have their own implementations (as opposite to pointer casting). One problem with current implementation is I had to make a long call chain from the window that requests snapping to the (root) pane that implements it: IslandWindow -> AppHost's callback -> App -> TerminalPage -> Tab -> Pane. I don't know if this can be done better. ## Validation Steps Performed Spam split pane buttons, randomly change font sizes with ctrl+mouse wheel and drag the window back and forth. Closes #2834 Closes #2277
2020-01-08 22:19:23 +01:00
// This is called when the terminal changes its font size or sets it for the first
// time (because when we just create terminal via its ctor it has invalid font size).
// On the latter event, we tell the root pane to resize itself so that its descendants
// (including ourself) can properly snap to character grids. In future, we may also
// want to do that on regular font changes.
control.FontSizeChanged([this](const int /* fontWidth */,
const int /* fontHeight */,
const bool isInitialChange) {
if (isInitialChange)
{
_rootPane->Relayout();
}
});
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
}
// Method Description:
// - Add an event handler to this pane's GotFocus event. When that pane gains
// focus, we'll mark it as the new active pane. We'll also query the title of
// that pane when it's focused to set our own text, and finally, we'll trigger
// our own ActivePaneChanged event.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Tab::_AttachEventHandlersToPane(std::shared_ptr<Pane> pane)
{
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
std::weak_ptr<Tab> weakThis{ shared_from_this() };
pane->GotFocus([weakThis](std::shared_ptr<Pane> sender) {
// Do nothing if the Tab's lifetime is expired or pane isn't new.
auto tab{ weakThis.lock() };
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
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 (tab && sender != tab->_activePane)
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
{
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
// Clear the active state of the entire tree, and mark only the sender as active.
tab->_rootPane->ClearActive();
tab->_activePane = sender;
tab->_activePane->SetActive();
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
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
// Update our own title text to match the newly-active pane.
tab->SetTabText(tab->GetActiveTitle());
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
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
// Raise our own ActivePaneChanged event.
tab->_ActivePaneChangedHandlers();
}
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
});
}
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
DEFINE_EVENT(Tab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);