6e70c4ae07
#### ⚠️ targets #10051 ## Summary of the Pull Request This PR does one big, primary thing. It removes all the constructors from any TerminalConnections, and changes them to use an `Initialize` method that accepts a `ValueSet` of properties. Why? For the upcoming window/content process work, we'll need the content process to be able to initialize the connection _in the content process_. However, the window process will be the one that knows what type of connection to make. Enter `ConnectionInformation`. This class will let us specify the class name of the type we want to create, and a set of settings to use when initializing that connection. **IMPORTANT**: As a part of this, the constructor for a connection must have 0 arguments. `RoActivateInstance` lets you just conjure a WinRT type just by class name, but that class must have a 0 arg ctor. Hence the need for `Initialize`, to actually pass the settings. We're using a `ValueSet` here because it's basically a json blob, with more steps. In the future, when extension authors want to have custom connections, we can always deserialize the json into a `ValueSet`, pass it to their connection's `Initialize`, and let then get what they need out of it. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760298 * [x] I work here * [n/a] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments `ConnectionInformation` was included as a part of this PR, to demonstrate how this will eventually be used. `ConnectionInformation` is not _currently_ used. ## Validation Steps Performed It still builds and runs.
128 lines
5.1 KiB
C++
128 lines
5.1 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "pch.h"
|
|
#include "DebugTapConnection.h"
|
|
|
|
using namespace ::winrt::Microsoft::Terminal::TerminalConnection;
|
|
using namespace ::winrt::Windows::Foundation;
|
|
namespace winrt::Microsoft::TerminalApp::implementation
|
|
{
|
|
// DebugInputTapConnection is an implementation detail of DebugTapConnection.
|
|
// It wraps the _actual_ connection so it can hook WriteInput and forward it
|
|
// into the actual debug panel.
|
|
class DebugInputTapConnection : public winrt::implements<DebugInputTapConnection, ITerminalConnection>
|
|
{
|
|
public:
|
|
DebugInputTapConnection(winrt::com_ptr<DebugTapConnection> pairedTap, ITerminalConnection wrappedConnection) :
|
|
_pairedTap{ pairedTap },
|
|
_wrappedConnection{ std::move(wrappedConnection) }
|
|
{
|
|
}
|
|
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {}
|
|
~DebugInputTapConnection() = default;
|
|
void Start()
|
|
{
|
|
_wrappedConnection.Start();
|
|
}
|
|
void WriteInput(hstring const& data)
|
|
{
|
|
_pairedTap->_PrintInput(data);
|
|
_wrappedConnection.WriteInput(data);
|
|
}
|
|
void Resize(uint32_t rows, uint32_t columns) { _wrappedConnection.Resize(rows, columns); }
|
|
void Close() { _wrappedConnection.Close(); }
|
|
winrt::event_token TerminalOutput(TerminalOutputHandler const& args) { return _wrappedConnection.TerminalOutput(args); };
|
|
void TerminalOutput(winrt::event_token const& token) noexcept { _wrappedConnection.TerminalOutput(token); };
|
|
winrt::event_token StateChanged(TypedEventHandler<ITerminalConnection, IInspectable> const& handler) { return _wrappedConnection.StateChanged(handler); };
|
|
void StateChanged(winrt::event_token const& token) noexcept { _wrappedConnection.StateChanged(token); };
|
|
ConnectionState State() const noexcept { return _wrappedConnection.State(); }
|
|
|
|
private:
|
|
winrt::com_ptr<DebugTapConnection> _pairedTap;
|
|
ITerminalConnection _wrappedConnection;
|
|
};
|
|
|
|
DebugTapConnection::DebugTapConnection(ITerminalConnection wrappedConnection)
|
|
{
|
|
_outputRevoker = wrappedConnection.TerminalOutput(winrt::auto_revoke, { this, &DebugTapConnection::_OutputHandler });
|
|
_stateChangedRevoker = wrappedConnection.StateChanged(winrt::auto_revoke, [this](auto&& /*s*/, auto&& /*e*/) {
|
|
_StateChangedHandlers(*this, nullptr);
|
|
});
|
|
_wrappedConnection = wrappedConnection;
|
|
}
|
|
|
|
DebugTapConnection::~DebugTapConnection()
|
|
{
|
|
}
|
|
|
|
void DebugTapConnection::Start()
|
|
{
|
|
// presume the wrapped connection is started.
|
|
}
|
|
|
|
void DebugTapConnection::WriteInput(hstring const& data)
|
|
{
|
|
// If the user types into the tap side, forward it to the input side
|
|
if (auto strongInput{ _inputSide.get() })
|
|
{
|
|
auto inputAsTap{ winrt::get_self<DebugInputTapConnection>(strongInput) };
|
|
inputAsTap->WriteInput(data);
|
|
}
|
|
}
|
|
|
|
void DebugTapConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/)
|
|
{
|
|
// no resize events are propagated
|
|
}
|
|
|
|
void DebugTapConnection::Close()
|
|
{
|
|
_outputRevoker.revoke();
|
|
_stateChangedRevoker.revoke();
|
|
_wrappedConnection = nullptr;
|
|
}
|
|
|
|
ConnectionState DebugTapConnection::State() const noexcept
|
|
{
|
|
if (auto strongConnection{ _wrappedConnection.get() })
|
|
{
|
|
return strongConnection.State();
|
|
}
|
|
return ConnectionState::Failed;
|
|
}
|
|
|
|
void DebugTapConnection::_OutputHandler(const hstring str)
|
|
{
|
|
_TerminalOutputHandlers(til::visualize_control_codes(str));
|
|
}
|
|
|
|
// Called by the DebugInputTapConnection to print user input
|
|
void DebugTapConnection::_PrintInput(const hstring& str)
|
|
{
|
|
auto clean{ til::visualize_control_codes(str) };
|
|
auto formatted{ wil::str_printf<std::wstring>(L"\x1b[91m%ls\x1b[m", clean.data()) };
|
|
_TerminalOutputHandlers(formatted);
|
|
}
|
|
|
|
// Wire us up so that we can forward input through
|
|
void DebugTapConnection::SetInputTap(const Microsoft::Terminal::TerminalConnection::ITerminalConnection& inputTap)
|
|
{
|
|
_inputSide = inputTap;
|
|
}
|
|
}
|
|
|
|
// Function Description
|
|
// - Takes one connection and returns two connections:
|
|
// 1. One that can be used in place of the original connection (wrapped)
|
|
// 2. One that will print raw VT sequences sent into and received _from_ the original connection.
|
|
std::tuple<ITerminalConnection, ITerminalConnection> OpenDebugTapConnection(ITerminalConnection baseConnection)
|
|
{
|
|
using namespace winrt::Microsoft::TerminalApp::implementation;
|
|
auto debugSide{ winrt::make_self<DebugTapConnection>(baseConnection) };
|
|
auto inputSide{ winrt::make_self<DebugInputTapConnection>(debugSide, baseConnection) };
|
|
debugSide->SetInputTap(*inputSide);
|
|
std::tuple<ITerminalConnection, ITerminalConnection> p{ *inputSide, *debugSide };
|
|
return p;
|
|
}
|