b3fa88eaed
This PR has evolved to encapsulate two related fixes that I can't really untie anymore. #2455 - Duplicating a tab that doesn't exist anymore This was the bug I was originally fixing in #4429. When the user tries to `duplicateTab` with a profile that doesn't exist anymore (like might happen after a settings reload), don't crash. As I was going about adding tests for this, got blocked by the fact that the Terminal couldn't open _any_ panes while the `TerminalPage` was size 0x0. This had two theoretical solutions: * Fake the `TerminalPage` into thinking it had a real size in the test - probably possible, though I'm unsure how it would work in practice. * Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on initialization. Fortuately, the second option was something else that was already on my backlog of bugs. #4618 - `wt` command-line can't consistently parse more than one arg Presently, the Terminal just arbitrarily dispatches a bunch of handlers to try and handle all the commands provided on the commandline. That's lead to a bunch of reports that not all the commands will always get executed, nor will they all get executed in the same order. This PR also changes the `TerminalPage` to be able to dispatch all the commands sequentially, all at once in the startup. No longer will there be a hot second where the commands seem to execute themselves in from of the user - they'll all happen behind the scenes on startup. This involved a couple other changes areound the `TerminalPage` * I had to make sure that panes could be opened at a 0x0 size. Now they use a star sizing based off the percentage of the parent they're supposed to consume, so that when the parent _does_ get laid out, they'll take the appropriate size of that parent. * I had to do some math ahead of time to try and calculate what a `SplitState::Automatic` would be evaluated as, despite the fact that we don't actually know how big the pane will be. * I had to ensure that `focus-tab` commands appropriately mark a single tab as focused while we're in startup, without roundtripping to the Dispatcher thread and back ## References #4429 - the original PR for #2455 #5047 - a follow-up task from discussion in #4429 #4953 - a PR for making panes use star sizing, which was immensly helpful for this PR. ## Detailed Description of the Pull Request / Additional comments `CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist. This wraps those calls up with a try/catch. It also adds a couple tests - a few `SettingsTests` for try/catching this state. It also adds a XAML-y test in `TabTests` that creates a `TerminalPage` and then performs som UI-like actions on it. This test required a minor change to how we generate the new tab dropdown - in the tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it doesn't have a `Logic()` to query. So wrap that in a try/catch as well. While working on these tests, I found that we'd crash pretty agressively for mysterious reasons if the TestHostApp became focused while the test was running. This was due to a call in `TSFInputControl::NotifyFocusEnter` that would callback to `TSFInputControl::_layoutRequested`, which would crash on setting the `MaxSize` of the canvas to a negative value. This PR includes a hotfix for that bug as well. ## Validation Steps Performed * Manual testing with a _lot_ of commands in a commandline * run the tests * Team tested in selfhost Closes #2455 Closes #4618
81 lines
3.2 KiB
C++
81 lines
3.2 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#pragma once
|
|
#include "Pane.h"
|
|
#include "Tab.g.h"
|
|
|
|
// fwdecl unittest classes
|
|
namespace TerminalAppLocalTests
|
|
{
|
|
class TabTests;
|
|
};
|
|
|
|
namespace winrt::TerminalApp::implementation
|
|
{
|
|
struct Tab : public TabT<Tab>
|
|
{
|
|
public:
|
|
Tab() = delete;
|
|
Tab(const GUID& profile, const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
|
|
|
// Called after construction to setup events with weak_ptr
|
|
void BindEventHandlers(const winrt::Microsoft::Terminal::TerminalControl::TermControl& control) noexcept;
|
|
|
|
winrt::Microsoft::UI::Xaml::Controls::TabViewItem GetTabViewItem();
|
|
winrt::Windows::UI::Xaml::UIElement GetRootElement();
|
|
winrt::Microsoft::Terminal::TerminalControl::TermControl GetActiveTerminalControl() const;
|
|
std::optional<GUID> GetFocusedProfile() const noexcept;
|
|
|
|
bool IsFocused() const noexcept;
|
|
void SetFocused(const bool focused);
|
|
|
|
winrt::fire_and_forget Scroll(const int delta);
|
|
|
|
bool CanSplitPane(winrt::TerminalApp::SplitState splitType);
|
|
void SplitPane(winrt::TerminalApp::SplitState splitType, const GUID& profile, winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
|
|
|
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
|
|
|
|
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
|
SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
|
|
|
|
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
|
void ResizePane(const winrt::TerminalApp::Direction& direction);
|
|
void NavigateFocus(const winrt::TerminalApp::Direction& direction);
|
|
|
|
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::TerminalSettings& settings, const GUID& profile);
|
|
winrt::hstring GetActiveTitle() const;
|
|
winrt::fire_and_forget SetTabText(const winrt::hstring text);
|
|
|
|
void Shutdown();
|
|
void ClosePane();
|
|
|
|
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
|
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
|
DECLARE_EVENT(ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
|
|
|
|
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Title, _PropertyChangedHandlers);
|
|
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, IconPath, _PropertyChangedHandlers);
|
|
|
|
private:
|
|
std::shared_ptr<Pane> _rootPane{ nullptr };
|
|
std::shared_ptr<Pane> _activePane{ nullptr };
|
|
winrt::hstring _lastIconPath{};
|
|
|
|
bool _focused{ false };
|
|
winrt::Microsoft::UI::Xaml::Controls::TabViewItem _tabViewItem{ nullptr };
|
|
|
|
void _MakeTabViewItem();
|
|
void _Focus();
|
|
|
|
void _AttachEventHandlersToControl(const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
|
void _AttachEventHandlersToPane(std::shared_ptr<Pane> pane);
|
|
|
|
int _GetLeafPaneCount() const noexcept;
|
|
void _UpdateActivePane(std::shared_ptr<Pane> pane);
|
|
|
|
friend class ::TerminalAppLocalTests::TabTests;
|
|
};
|
|
}
|