Switch Connections to use ValueSets to initialize them (#10184)

#### ⚠️ 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.
This commit is contained in:
Mike Griese 2021-07-20 10:02:17 -05:00 committed by GitHub
parent b05a557f48
commit 6e70c4ae07
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 304 additions and 79 deletions

View file

@ -5,7 +5,7 @@
#include "MyPage.h"
#include <LibraryResources.h>
#include "MyPage.g.cpp"
#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
#include "MySettings.h"
using namespace std::chrono_literals;
using namespace winrt::Microsoft::Terminal;
@ -26,17 +26,24 @@ namespace winrt::SampleApp::implementation
void MyPage::Create()
{
TerminalConnection::EchoConnection conn{};
auto settings = winrt::make_self<ControlUnitTests::MockControlSettings>();
auto settings = winrt::make_self<implementation::MySettings>();
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted in-proc...",
winrt::hstring{},
L"",
nullptr,
32,
80,
winrt::guid()) };
// "Microsoft.Terminal.TerminalConnection.ConptyConnection"
winrt::hstring myClass{ winrt::name_of<TerminalConnection::ConptyConnection>() };
TerminalConnection::ConnectionInformation connectInfo{ myClass, connectionSettings };
TerminalConnection::ITerminalConnection conn{ TerminalConnection::ConnectionInformation::CreateConnection(connectInfo) };
Control::TermControl control{ *settings, conn };
InProcContent().Children().Append(control);
// Once the control loads (and not before that), write some text for debugging:
control.Initialized([conn](auto&&, auto&&) {
conn.WriteInput(L"This TermControl is hosted in-proc...");
});
}
// Method Description:

View file

@ -19,10 +19,15 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button x:Name="TabRow"
Grid.Row="0">
&quot;Tabs&quot;
</Button>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="GuidInput"
Width="400"
PlaceholderText="{}{guid here}" />
<Button Grid.Row="0">
Create
</Button>
</StackPanel>
<Grid x:Name="TabContent"
Grid.Row="1"

View file

@ -4,6 +4,8 @@ Licensed under the MIT license.
--*/
#pragma once
#include "../../inc/cppwinrt_utils.h"
#include "../types/inc/colorTable.hpp"
#include <DefaultSettings.h>
#include <conattrs.hpp>
#include "MySettings.g.h"
@ -12,9 +14,6 @@ namespace winrt::SampleApp::implementation
{
struct MySettings : MySettingsT<MySettings>
{
public:
MySettings() = default;
// --------------------------- Core Settings ---------------------------
// All of these settings are defined in ICoreSettings.
@ -88,6 +87,14 @@ namespace winrt::SampleApp::implementation
winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept { return _ColorTable.at(index); }
std::array<winrt::Microsoft::Terminal::Core::Color, 16> ColorTable() { return _ColorTable; }
void ColorTable(std::array<winrt::Microsoft::Terminal::Core::Color, 16> /*colors*/) {}
MySettings()
{
const auto campbellSpan = ::Microsoft::Console::Utils::CampbellColorTable();
std::transform(campbellSpan.begin(), campbellSpan.end(), _ColorTable.begin(), [](auto&& color) {
return static_cast<winrt::Microsoft::Terminal::Core::Color>(til::color{ color });
});
}
};
}

View file

@ -48,6 +48,10 @@
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj">
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
</ProjectReference>
</ItemGroup>

View file

@ -19,6 +19,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
_wrappedConnection{ std::move(wrappedConnection) }
{
}
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {}
~DebugInputTapConnection() = default;
void Start()
{

View file

@ -13,6 +13,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
{
public:
explicit DebugTapConnection(Microsoft::Terminal::TerminalConnection::ITerminalConnection wrappedConnection);
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/){};
~DebugTapConnection();
void Start();
void WriteInput(hstring const& data);

View file

@ -797,13 +797,14 @@ namespace winrt::TerminalApp::implementation
// TODO GH#4661: Replace this with directly using the AzCon when our VT is better
std::filesystem::path azBridgePath{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
azBridgePath.replace_filename(L"TerminalAzBridge.exe");
connection = TerminalConnection::ConptyConnection(azBridgePath.wstring(),
L".",
L"Azure",
nullptr,
settings.InitialRows(),
settings.InitialCols(),
winrt::guid());
connection = TerminalConnection::ConptyConnection();
connection.Initialize(TerminalConnection::ConptyConnection::CreateSettings(azBridgePath.wstring(),
L".",
L"Azure",
nullptr,
::base::saturated_cast<uint32_t>(settings.InitialRows()),
::base::saturated_cast<uint32_t>(settings.InitialCols()),
winrt::guid()));
}
else
@ -833,14 +834,14 @@ namespace winrt::TerminalApp::implementation
std::filesystem::path cwd{ cwdString };
cwd /= settings.StartingDirectory().c_str();
auto conhostConn = TerminalConnection::ConptyConnection(
settings.Commandline(),
winrt::hstring{ cwd.c_str() },
settings.StartingTitle(),
envMap.GetView(),
settings.InitialRows(),
settings.InitialCols(),
winrt::guid());
auto conhostConn = TerminalConnection::ConptyConnection();
conhostConn.Initialize(TerminalConnection::ConptyConnection::CreateSettings(settings.Commandline(),
winrt::hstring{ cwd.wstring() },
settings.StartingTitle(),
envMap.GetView(),
::base::saturated_cast<uint32_t>(settings.InitialRows()),
::base::saturated_cast<uint32_t>(settings.InitialCols()),
winrt::guid()));
sessionGuid = conhostConn.Guid();
connection = conhostConn;

View file

@ -96,7 +96,11 @@ int wmain(int /*argc*/, wchar_t** /*argv*/)
const auto size = GetConsoleScreenSize(conOut);
AzureConnection azureConn{ gsl::narrow_cast<uint32_t>(size.Y), gsl::narrow_cast<uint32_t>(size.X) };
AzureConnection azureConn{};
winrt::Windows::Foundation::Collections::ValueSet vs{};
vs.Insert(L"initialRows", winrt::Windows::Foundation::PropertyValue::CreateUInt32(gsl::narrow_cast<uint32_t>(size.Y)));
vs.Insert(L"initialCols", winrt::Windows::Foundation::PropertyValue::CreateUInt32(gsl::narrow_cast<uint32_t>(size.X)));
azureConn.Initialize(vs);
const auto state = RunConnectionToCompletion(azureConn, conOut, conIn);

View file

@ -33,6 +33,7 @@ Abstract:
#include <wil/cppwinrt.h>
#include <winrt/Windows.system.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <wil/resource.h>

View file

@ -71,11 +71,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
return (AzureClientID != L"0");
}
AzureConnection::AzureConnection(const uint32_t initialRows, const uint32_t initialCols) :
_initialRows{ initialRows },
_initialCols{ initialCols },
_expiry{}
void AzureConnection::Initialize(const Windows::Foundation::Collections::ValueSet& settings)
{
if (settings)
{
_initialRows = winrt::unbox_value_or<uint32_t>(settings.TryLookup(L"initialRows").try_as<Windows::Foundation::IPropertyValue>(), _initialRows);
_initialCols = winrt::unbox_value_or<uint32_t>(settings.TryLookup(L"initialCols").try_as<Windows::Foundation::IPropertyValue>(), _initialCols);
}
}
// Method description:

View file

@ -21,7 +21,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
{
static winrt::guid ConnectionType() noexcept;
static bool IsAzureConnectionAvailable() noexcept;
AzureConnection(const uint32_t rows, const uint32_t cols);
AzureConnection() = default;
void Initialize(const Windows::Foundation::Collections::ValueSet& settings);
void Start();
void WriteInput(hstring const& data);

View file

@ -10,7 +10,7 @@ namespace Microsoft.Terminal.TerminalConnection
static Guid ConnectionType { get; };
static Boolean IsAzureConnectionAvailable();
AzureConnection(UInt32 rows, UInt32 columns);
AzureConnection();
};
}

View file

@ -0,0 +1,66 @@
#include "pch.h"
#include "ConnectionInformation.h"
#include "ConnectionInformation.g.cpp"
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
{
ConnectionInformation::ConnectionInformation(hstring const& className,
const Windows::Foundation::Collections::ValueSet& settings) :
_ClassName{ className },
_Settings{ settings }
{
}
// Function Description:
// - Create an instance of the connection specified in the
// ConnectionInformation, and Initialize it.
// - This static method allows the content process to create a connection
// from information that lives in the window process.
// Arguments:
// - info: A ConnectionInformation object that possibly lives out-of-proc,
// containing the name of the WinRT class we should activate for this
// connection, and a bag of setting to use to initialize that object.
// Return Value:
// - <none>
TerminalConnection::ITerminalConnection ConnectionInformation::CreateConnection(TerminalConnection::ConnectionInformation info)
try
{
Windows::Foundation::IInspectable inspectable{};
const auto name = static_cast<HSTRING>(winrt::get_abi(info.ClassName()));
const auto pointer = winrt::put_abi(inspectable);
#pragma warning(push)
#pragma warning(disable : 26490)
// C++/WinRT just loves it's void**, nothing we can do here _except_ reinterpret_cast
::IInspectable** raw = reinterpret_cast<::IInspectable**>(pointer);
#pragma warning(pop)
// RoActivateInstance() will try to create an instance of the object,
// who's fully qualified name is the string in Name().
//
// The class has to be activatable. For the Terminal, this is easy
// enough - we're not hosting anything that's not already in our
// manifest, or living as a .dll & .winmd SxS.
//
// When we get to extensions (GH#4000), we may want to revisit.
if (LOG_IF_FAILED(RoActivateInstance(name, raw)))
{
return nullptr;
}
// Now that thing we made, make sure it's actually a ITerminalConnection
if (const auto connection{ inspectable.try_as<TerminalConnection::ITerminalConnection>() })
{
// Initialize it, and return it.
connection.Initialize(info.Settings());
return connection;
}
return nullptr;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return nullptr;
}
}

View file

@ -0,0 +1,43 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Class Name:
- ConnectionInformation.h
Abstract:
- This is a helper object for storing both the name of a type of connection, and
a bag of settings to use to initialize that connection.
- This helper is used primarily in cross-proc scenarios, to allow the window
process to tell the content process the name of the connection type it wants
created, and how to set that connection up. This is done so the connection can
live entirely in the content process, without having to go through the window
process at all.
--*/
#pragma once
#include "../inc/cppwinrt_utils.h"
#include "ConnectionInformation.g.h"
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
{
struct ConnectionInformation : ConnectionInformationT<ConnectionInformation>
{
ConnectionInformation(hstring const& className,
const Windows::Foundation::Collections::ValueSet& settings);
static TerminalConnection::ITerminalConnection CreateConnection(TerminalConnection::ConnectionInformation info);
winrt::hstring ClassName() const { return _ClassName; }
void ClassName(const winrt::hstring& value) { _ClassName = value; }
WINRT_PROPERTY(Windows::Foundation::Collections::ValueSet, Settings);
private:
winrt::hstring _ClassName{};
};
}
namespace winrt::Microsoft::Terminal::TerminalConnection::factory_implementation
{
BASIC_FACTORY(ConnectionInformation);
}

View file

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "ITerminalConnection.idl";
namespace Microsoft.Terminal.TerminalConnection
{
[default_interface] runtimeclass ConnectionInformation
{
ConnectionInformation(String className, Windows.Foundation.Collections.ValueSet settings);
String ClassName { get; };
Windows.Foundation.Collections.ValueSet Settings { get; };
static ITerminalConnection CreateConnection(ConnectionInformation info);
}
}

View file

@ -116,17 +116,23 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
// add additional WT env vars like WT_SETTINGS, WT_DEFAULTS and WT_PROFILE_ID
for (auto item : _environment)
{
auto key = item.Key();
auto value = item.Value();
// avoid clobbering WSLENV
if (std::wstring_view{ key } == L"WSLENV")
try
{
auto current = environment[L"WSLENV"];
value = current + L":" + value;
}
auto key = item.Key();
// This will throw if the value isn't a string. If that
// happens, then just skip this entry.
auto value = winrt::unbox_value<hstring>(item.Value());
environment.insert_or_assign(key.c_str(), value.c_str());
// avoid clobbering WSLENV
if (std::wstring_view{ key } == L"WSLENV")
{
auto current = environment[L"WSLENV"];
value = current + L":" + value;
}
environment.insert_or_assign(key.c_str(), value.c_str());
}
CATCH_LOG();
}
}
@ -219,24 +225,54 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
_piClient.hProcess = hClientProcess;
}
ConptyConnection::ConptyConnection(const hstring& commandline,
const hstring& startingDirectory,
const hstring& startingTitle,
const Windows::Foundation::Collections::IMapView<hstring, hstring>& environment,
const uint32_t initialRows,
const uint32_t initialCols,
const guid& initialGuid) :
_initialRows{ initialRows },
_initialCols{ initialCols },
_commandline{ commandline },
_startingDirectory{ startingDirectory },
_startingTitle{ startingTitle },
_environment{ environment },
_guid{ initialGuid },
_u8State{},
_u16Str{},
_buffer{}
// Function Description:
// - Helper function for constructing a ValueSet that we can use to get our settings from.
Windows::Foundation::Collections::ValueSet ConptyConnection::CreateSettings(const winrt::hstring& cmdline,
const winrt::hstring& startingDirectory,
const winrt::hstring& startingTitle,
Windows::Foundation::Collections::IMapView<hstring, hstring> const& environment,
uint32_t rows,
uint32_t columns,
winrt::guid const& guid)
{
Windows::Foundation::Collections::ValueSet vs{};
vs.Insert(L"commandline", Windows::Foundation::PropertyValue::CreateString(cmdline));
vs.Insert(L"startingDirectory", Windows::Foundation::PropertyValue::CreateString(startingDirectory));
vs.Insert(L"startingTitle", Windows::Foundation::PropertyValue::CreateString(startingTitle));
vs.Insert(L"initialRows", Windows::Foundation::PropertyValue::CreateUInt32(rows));
vs.Insert(L"initialCols", Windows::Foundation::PropertyValue::CreateUInt32(columns));
vs.Insert(L"guid", Windows::Foundation::PropertyValue::CreateGuid(guid));
if (environment)
{
Windows::Foundation::Collections::ValueSet env{};
for (const auto& [k, v] : environment)
{
env.Insert(k, Windows::Foundation::PropertyValue::CreateString(v));
}
vs.Insert(L"environment", env);
}
return vs;
}
void ConptyConnection::Initialize(const Windows::Foundation::Collections::ValueSet& settings)
{
if (settings)
{
// For the record, the following won't crash:
// auto bad = unbox_value_or<hstring>(settings.TryLookup(L"foo").try_as<IPropertyValue>(), nullptr);
// It'll just return null
_commandline = winrt::unbox_value_or<winrt::hstring>(settings.TryLookup(L"commandline").try_as<Windows::Foundation::IPropertyValue>(), _commandline);
_startingDirectory = winrt::unbox_value_or<winrt::hstring>(settings.TryLookup(L"startingDirectory").try_as<Windows::Foundation::IPropertyValue>(), _startingDirectory);
_startingTitle = winrt::unbox_value_or<winrt::hstring>(settings.TryLookup(L"startingTitle").try_as<Windows::Foundation::IPropertyValue>(), _startingTitle);
_initialRows = winrt::unbox_value_or<uint32_t>(settings.TryLookup(L"initialRows").try_as<Windows::Foundation::IPropertyValue>(), _initialRows);
_initialCols = winrt::unbox_value_or<uint32_t>(settings.TryLookup(L"initialCols").try_as<Windows::Foundation::IPropertyValue>(), _initialCols);
_guid = winrt::unbox_value_or<winrt::guid>(settings.TryLookup(L"guid").try_as<Windows::Foundation::IPropertyValue>(), _guid);
_environment = settings.TryLookup(L"environment").try_as<Windows::Foundation::Collections::ValueSet>();
}
if (_guid == guid{})
{
_guid = Utils::CreateGuid();

View file

@ -26,14 +26,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
const HANDLE hServerProcess,
const HANDLE hClientProcess);
ConptyConnection(
const hstring& cmdline,
const hstring& startingDirectory,
const hstring& startingTitle,
const Windows::Foundation::Collections::IMapView<hstring, hstring>& environment,
const uint32_t rows,
const uint32_t cols,
const guid& guid);
ConptyConnection() noexcept = default;
void Initialize(const Windows::Foundation::Collections::ValueSet& settings);
static winrt::fire_and_forget final_release(std::unique_ptr<ConptyConnection> connection);
void Start();
@ -49,6 +44,14 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
static winrt::event_token NewConnection(NewConnectionHandler const& handler);
static void NewConnection(winrt::event_token const& token);
static Windows::Foundation::Collections::ValueSet CreateSettings(const winrt::hstring& cmdline,
const winrt::hstring& startingDirectory,
const winrt::hstring& startingTitle,
Windows::Foundation::Collections::IMapView<hstring, hstring> const& environment,
uint32_t rows,
uint32_t columns,
winrt::guid const& guid);
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);
private:
@ -60,10 +63,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
uint32_t _initialRows{};
uint32_t _initialCols{};
hstring _commandline;
hstring _startingDirectory;
hstring _startingTitle;
Windows::Foundation::Collections::IMapView<hstring, hstring> _environment;
hstring _commandline{};
hstring _startingDirectory{};
hstring _startingTitle{};
Windows::Foundation::Collections::ValueSet _environment{ nullptr };
guid _guid{}; // A unique session identifier for connected client
hstring _clientName{}; // The name of the process hosted by this ConPTY connection (as of launch).
@ -77,9 +80,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
wil::unique_static_pseudoconsole_handle _hPC;
wil::unique_threadpool_wait _clientExitWait;
til::u8state _u8State;
std::wstring _u16Str;
std::array<char, 4096> _buffer;
til::u8state _u8State{};
std::wstring _u16Str{};
std::array<char, 4096> _buffer{};
DWORD _OutputThread();
};

View file

@ -7,11 +7,19 @@ namespace Microsoft.Terminal.TerminalConnection
{
[default_interface] runtimeclass ConptyConnection : ITerminalConnection
{
ConptyConnection(String cmdline, String startingDirectory, String startingTitle, IMapView<String, String> environment, UInt32 rows, UInt32 columns, Guid guid);
ConptyConnection();
Guid Guid { get; };
static event NewConnectionHandler NewConnection;
static void StartInboundListener();
static void StopInboundListener();
static Windows.Foundation.Collections.ValueSet CreateSettings(String cmdline,
String startingDirectory,
String startingTitle,
IMapView<String, String> environment,
UInt32 rows,
UInt32 columns,
Guid guid);
};
}

View file

@ -18,6 +18,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void Resize(uint32_t rows, uint32_t columns) noexcept;
void Close() noexcept;
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) const noexcept {};
ConnectionState State() const noexcept { return ConnectionState::Connected; }
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);

View file

@ -17,6 +17,8 @@ namespace Microsoft.Terminal.TerminalConnection
interface ITerminalConnection
{
void Initialize(Windows.Foundation.Collections.ValueSet settings);
void Start();
void WriteInput(String data);
void Resize(UInt32 rows, UInt32 columns);

View file

@ -13,6 +13,9 @@
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemGroup>
<ClInclude Include="AzureClientID.h" />
<ClInclude Include="ConnectionInformation.h">
<DependentUpon>ConnectionInformation.idl</DependentUpon>
</ClInclude>
<ClInclude Include="AzureConnection.h">
<DependentUpon>AzureConnection.idl</DependentUpon>
</ClInclude>
@ -28,6 +31,9 @@
<ItemGroup>
<ClCompile Include="CTerminalHandoff.cpp" />
<ClCompile Include="init.cpp" />
<ClCompile Include="ConnectionInformation.cpp">
<DependentUpon>ConnectionInformation.idl</DependentUpon>
</ClCompile>
<ClCompile Include="AzureConnection.cpp">
<DependentUpon>AzureConnection.idl</DependentUpon>
</ClCompile>
@ -43,6 +49,7 @@
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
</ItemGroup>
<ItemGroup>
<Midl Include="ConnectionInformation.idl" />
<Midl Include="ITerminalConnection.idl" />
<Midl Include="ConptyConnection.idl" />
<Midl Include="EchoConnection.idl" />

View file

@ -24,6 +24,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_TerminalOutputHandlers(PreviewText);
}
void PreviewConnection::Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) noexcept
{
}
void PreviewConnection::WriteInput(hstring const& /*data*/)
{
}

View file

@ -22,6 +22,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
public:
PreviewConnection() noexcept;
void Initialize(const Windows::Foundation::Collections::ValueSet& settings) noexcept;
void Start() noexcept;
void WriteInput(hstring const& data);
void Resize(uint32_t rows, uint32_t columns) noexcept;

View file

@ -16,6 +16,7 @@ namespace ControlUnitTests
public:
MockConnection() noexcept = default;
void Initialize(const winrt::Windows::Foundation::Collections::ValueSet& /*settings*/){};
void Start() noexcept {};
void WriteInput(winrt::hstring const& data)
{