mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-19 18:11:39 -05:00
## Summary of the Pull Request Brace yourselves, it's finally here. This PR does the dirty work of splitting the monolithic `TermControl` into three components. These components are: * `ControlCore`: This encapsulates the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. This is intended to everything that someone might need to stand up a terminal instance in a control, but without any regard for how the UX works. * `ControlInteractivity`: This is a wrapper for the `ControlCore`, which holds the logic for things like double-click, right click copy/paste, selection, etc. This is intended to be a UI framework-independent abstraction. The methods this layer exposes can be called the same from both the WinUI TermControl and the WPF control. * `TermControl`: This is the UWP control. It's got a Core and Interactivity inside it, which it uses for the actual logic of the terminal itself. TermControl's main responsibility is now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` in an out-of-proc core process in the future, to enable tab tearout. However, we're not doing that work quite yet. There's still lots of work to be done to enable that, thought this is likely the biggest portion. Ideally, this would just be methods moved wholesale from one file to another. Unfortunately, there are a bunch of cases where that didn't work as well as expected. Especially when trying to better enforce the boundary between the classes. We've got a couple tests here that I've added. These are partially examples, and partially things I ran into while implementing this. A bunch of things from #7001 can go in now that we have this. This PR is gonna be a huge pain to review - 38 files with 3,730 additions and 1,661 deletions is nothing to scoff at. It will also conflict 100% with anything that's targeting `TermControl`. I'm hoping we can review this over the course of the next week and just be done with it, and leave plenty of runway for 1.9 bugs in post. ## References * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` need to know". In the future, these will all need to be handled specially, because they might involve an RPC call to retrieve the info from the core (or cache it) in the window process. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @miniksa wrote this originally in30b8335, I'm just finally committing it here. We'll need that in the future for the out-of-proc stuff.~~ * I reverted this inc113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. Some might be able to move down into core/interactivity, but once we figure out how to use a different kind of Dispatcher (because a UI thread won't necessarily exist for those components). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
154 lines
6.2 KiB
C++
154 lines
6.2 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#pragma once
|
|
#include "Pane.h"
|
|
#include "ColorPickupFlyout.h"
|
|
#include "TabBase.h"
|
|
#include "TerminalTab.g.h"
|
|
|
|
static constexpr double HeaderRenameBoxWidthDefault{ 165 };
|
|
static constexpr double HeaderRenameBoxWidthTitleLength{ std::numeric_limits<double>::infinity() };
|
|
|
|
// fwdecl unittest classes
|
|
namespace TerminalAppLocalTests
|
|
{
|
|
class TabTests;
|
|
};
|
|
|
|
namespace winrt::TerminalApp::implementation
|
|
{
|
|
struct TerminalTab : TerminalTabT<TerminalTab, TabBase>
|
|
{
|
|
public:
|
|
TerminalTab(const GUID& profile, const winrt::Microsoft::Terminal::Control::TermControl& control);
|
|
|
|
// Called after construction to perform the necessary setup, which relies on weak_ptr
|
|
void Initialize(const winrt::Microsoft::Terminal::Control::TermControl& control);
|
|
|
|
winrt::Microsoft::Terminal::Control::TermControl GetActiveTerminalControl() const;
|
|
std::optional<GUID> GetFocusedProfile() const noexcept;
|
|
|
|
void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override;
|
|
|
|
winrt::fire_and_forget Scroll(const int delta);
|
|
|
|
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
|
const float splitSize,
|
|
const GUID& profile,
|
|
winrt::Microsoft::Terminal::Control::TermControl& control);
|
|
|
|
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
|
|
winrt::fire_and_forget HideIcon(const bool hide);
|
|
|
|
winrt::fire_and_forget ShowBellIndicator(const bool show);
|
|
winrt::fire_and_forget ActivateBellIndicatorTimer();
|
|
|
|
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
|
winrt::Microsoft::Terminal::Settings::Model::SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
|
|
bool PreCalculateCanSplit(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
|
const float splitSize,
|
|
winrt::Windows::Foundation::Size availableSpace) const;
|
|
|
|
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
|
void ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
|
void NavigateFocus(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction);
|
|
|
|
void UpdateSettings(const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, const GUID& profile);
|
|
winrt::fire_and_forget UpdateTitle();
|
|
|
|
void Shutdown() override;
|
|
void ClosePane();
|
|
|
|
void SetTabText(winrt::hstring title);
|
|
winrt::hstring GetTabText() const;
|
|
void ResetTabText();
|
|
void ActivateTabRenamer();
|
|
|
|
std::optional<winrt::Windows::UI::Color> GetTabColor();
|
|
|
|
void SetRuntimeTabColor(const winrt::Windows::UI::Color& color);
|
|
void ResetRuntimeTabColor();
|
|
void ActivateColorPicker();
|
|
|
|
void ToggleZoom();
|
|
bool IsZoomed();
|
|
void EnterZoom();
|
|
void ExitZoom();
|
|
|
|
int GetLeafPaneCount() const noexcept;
|
|
|
|
void TogglePaneReadOnly();
|
|
std::shared_ptr<Pane> GetActivePane() const;
|
|
|
|
winrt::TerminalApp::TerminalTabStatus TabStatus()
|
|
{
|
|
return _tabStatus;
|
|
}
|
|
|
|
DECLARE_EVENT(ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
|
|
DECLARE_EVENT(ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
|
|
DECLARE_EVENT(ColorCleared, _colorCleared, winrt::delegate<>);
|
|
DECLARE_EVENT(TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>);
|
|
DECLARE_EVENT(DuplicateRequested, _DuplicateRequestedHandlers, winrt::delegate<>);
|
|
FORWARDED_TYPED_EVENT(TabRenamerDeactivated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, (&_headerControl), RenameEnded);
|
|
TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable);
|
|
|
|
private:
|
|
std::shared_ptr<Pane> _rootPane{ nullptr };
|
|
std::shared_ptr<Pane> _activePane{ nullptr };
|
|
std::shared_ptr<Pane> _zoomedPane{ nullptr };
|
|
winrt::hstring _lastIconPath{};
|
|
winrt::TerminalApp::ColorPickupFlyout _tabColorPickup{};
|
|
std::optional<winrt::Windows::UI::Color> _themeTabColor{};
|
|
std::optional<winrt::Windows::UI::Color> _runtimeTabColor{};
|
|
winrt::TerminalApp::TabHeaderControl _headerControl{};
|
|
winrt::TerminalApp::TerminalTabStatus _tabStatus{};
|
|
|
|
std::vector<uint16_t> _mruPanes;
|
|
uint16_t _nextPaneId{ 0 };
|
|
|
|
bool _receivedKeyDown{ false };
|
|
bool _iconHidden{ false };
|
|
|
|
winrt::hstring _runtimeTabText{};
|
|
bool _inRename{ false };
|
|
winrt::Windows::UI::Xaml::Controls::TextBox::LayoutUpdated_revoker _tabRenameBoxLayoutUpdatedRevoker;
|
|
|
|
winrt::TerminalApp::ShortcutActionDispatch _dispatch;
|
|
|
|
std::optional<Windows::UI::Xaml::DispatcherTimer> _bellIndicatorTimer;
|
|
void _BellIndicatorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
|
|
|
|
void _MakeTabViewItem();
|
|
|
|
winrt::fire_and_forget _UpdateHeaderControlMaxWidth();
|
|
|
|
void _CreateContextMenu() override;
|
|
virtual winrt::hstring _CreateToolTipTitle() override;
|
|
|
|
void _RefreshVisualState();
|
|
|
|
void _BindEventHandlers(const winrt::Microsoft::Terminal::Control::TermControl& control) noexcept;
|
|
|
|
void _AttachEventHandlersToControl(const winrt::Microsoft::Terminal::Control::TermControl& control);
|
|
void _AttachEventHandlersToPane(std::shared_ptr<Pane> pane);
|
|
|
|
void _UpdateActivePane(std::shared_ptr<Pane> pane);
|
|
|
|
winrt::hstring _GetActiveTitle() const;
|
|
|
|
void _RecalculateAndApplyTabColor();
|
|
void _ApplyTabColor(const winrt::Windows::UI::Color& color);
|
|
void _ClearTabBackgroundColor();
|
|
|
|
void _RecalculateAndApplyReadOnly();
|
|
|
|
void _UpdateProgressState();
|
|
|
|
void _DuplicateTab();
|
|
|
|
friend class ::TerminalAppLocalTests::TabTests;
|
|
};
|
|
}
|