This contains all the parts of #16598 that aren't specific to session restore, but are required for the code in #16598: * Adds new GUID<>String functions that remove the `{}` brackets. * Adds `SessionId` to the `ITerminalConnection` interface. * Flush the `ApplicationState` before we terminate the process. * Not monitoring `state.json` for changes is important as it prevents disturbing the session state while session persistence is ongoing. That's because when `ApplicationState` flushes to disk, the FS monitor will be triggered and reload the `ApplicationState` again.
This commit is contained in:
parent
b70fd5e9c6
commit
5dda50767b
|
@ -183,6 +183,7 @@ chh
|
|||
chshdng
|
||||
CHT
|
||||
Cic
|
||||
CLASSSTRING
|
||||
CLE
|
||||
cleartype
|
||||
CLICKACTIVE
|
||||
|
|
|
@ -124,8 +124,7 @@ namespace winrt::TerminalApp::implementation
|
|||
return appLogic->GetSettings();
|
||||
}
|
||||
|
||||
AppLogic::AppLogic() :
|
||||
_reloadState{ std::chrono::milliseconds(100), []() { ApplicationState::SharedInstance().Reload(); } }
|
||||
AppLogic::AppLogic()
|
||||
{
|
||||
// For your own sanity, it's better to do setup outside the ctor.
|
||||
// If you do any setup in the ctor that ends up throwing an exception,
|
||||
|
@ -327,10 +326,6 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
_reloadSettings->Run();
|
||||
}
|
||||
else if (ApplicationState::SharedInstance().IsStatePath(modifiedBasename))
|
||||
{
|
||||
_reloadState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,6 @@ namespace winrt::TerminalApp::implementation
|
|||
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _reloadSettings;
|
||||
til::throttled_func_trailing<> _reloadState;
|
||||
|
||||
std::vector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> _warnings{};
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
|||
void TerminalOutput(const winrt::event_token& token) noexcept { _wrappedConnection.TerminalOutput(token); };
|
||||
winrt::event_token StateChanged(const TypedEventHandler<ITerminalConnection, IInspectable>& handler) { return _wrappedConnection.StateChanged(handler); };
|
||||
void StateChanged(const winrt::event_token& token) noexcept { _wrappedConnection.StateChanged(token); };
|
||||
winrt::guid SessionId() const noexcept { return {}; }
|
||||
ConnectionState State() const noexcept { return _wrappedConnection.State(); }
|
||||
|
||||
private:
|
||||
|
@ -98,6 +99,15 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
|||
_wrappedConnection = nullptr;
|
||||
}
|
||||
|
||||
guid DebugTapConnection::SessionId() const noexcept
|
||||
{
|
||||
if (const auto c = _wrappedConnection.get())
|
||||
{
|
||||
return c.SessionId();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ConnectionState DebugTapConnection::State() const noexcept
|
||||
{
|
||||
if (auto strongConnection{ _wrappedConnection.get() })
|
||||
|
|
|
@ -19,6 +19,8 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
|||
void WriteInput(const hstring& data);
|
||||
void Resize(uint32_t rows, uint32_t columns);
|
||||
void Close();
|
||||
|
||||
winrt::guid SessionId() const noexcept;
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept;
|
||||
|
||||
void SetInputTap(const Microsoft::Terminal::TerminalConnection::ITerminalConnection& inputTap);
|
||||
|
|
|
@ -1210,7 +1210,7 @@ namespace winrt::TerminalApp::implementation
|
|||
TerminalConnection::ITerminalConnection connection{ nullptr };
|
||||
|
||||
auto connectionType = profile.ConnectionType();
|
||||
winrt::guid sessionGuid{};
|
||||
Windows::Foundation::Collections::ValueSet valueSet;
|
||||
|
||||
if (connectionType == TerminalConnection::AzureConnection::ConnectionType() &&
|
||||
TerminalConnection::AzureConnection::IsAzureConnectionAvailable())
|
||||
|
@ -1226,23 +1226,16 @@ namespace winrt::TerminalApp::implementation
|
|||
connection = TerminalConnection::ConptyConnection{};
|
||||
}
|
||||
|
||||
auto valueSet = TerminalConnection::ConptyConnection::CreateSettings(azBridgePath.native(),
|
||||
L".",
|
||||
L"Azure",
|
||||
false,
|
||||
L"",
|
||||
nullptr,
|
||||
settings.InitialRows(),
|
||||
settings.InitialCols(),
|
||||
winrt::guid(),
|
||||
profile.Guid());
|
||||
|
||||
if constexpr (Feature_VtPassthroughMode::IsEnabled())
|
||||
{
|
||||
valueSet.Insert(L"passthroughMode", Windows::Foundation::PropertyValue::CreateBoolean(settings.VtPassthrough()));
|
||||
}
|
||||
|
||||
connection.Initialize(valueSet);
|
||||
valueSet = TerminalConnection::ConptyConnection::CreateSettings(azBridgePath.native(),
|
||||
L".",
|
||||
L"Azure",
|
||||
false,
|
||||
L"",
|
||||
nullptr,
|
||||
settings.InitialRows(),
|
||||
settings.InitialCols(),
|
||||
winrt::guid(),
|
||||
profile.Guid());
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -1267,38 +1260,38 @@ namespace winrt::TerminalApp::implementation
|
|||
// process until later, on another thread, after we've already
|
||||
// restored the CWD to its original value.
|
||||
auto newWorkingDirectory{ _evaluatePathForCwd(settings.StartingDirectory()) };
|
||||
auto conhostConn = TerminalConnection::ConptyConnection();
|
||||
auto valueSet = TerminalConnection::ConptyConnection::CreateSettings(settings.Commandline(),
|
||||
newWorkingDirectory,
|
||||
settings.StartingTitle(),
|
||||
settings.ReloadEnvironmentVariables(),
|
||||
_WindowProperties.VirtualEnvVars(),
|
||||
environment,
|
||||
settings.InitialRows(),
|
||||
settings.InitialCols(),
|
||||
winrt::guid(),
|
||||
profile.Guid());
|
||||
|
||||
valueSet.Insert(L"passthroughMode", Windows::Foundation::PropertyValue::CreateBoolean(settings.VtPassthrough()));
|
||||
connection = TerminalConnection::ConptyConnection{};
|
||||
valueSet = TerminalConnection::ConptyConnection::CreateSettings(settings.Commandline(),
|
||||
newWorkingDirectory,
|
||||
settings.StartingTitle(),
|
||||
settings.ReloadEnvironmentVariables(),
|
||||
_WindowProperties.VirtualEnvVars(),
|
||||
environment,
|
||||
settings.InitialRows(),
|
||||
settings.InitialCols(),
|
||||
winrt::guid(),
|
||||
profile.Guid());
|
||||
|
||||
if (inheritCursor)
|
||||
{
|
||||
valueSet.Insert(L"inheritCursor", Windows::Foundation::PropertyValue::CreateBoolean(true));
|
||||
}
|
||||
|
||||
conhostConn.Initialize(valueSet);
|
||||
|
||||
sessionGuid = conhostConn.Guid();
|
||||
connection = conhostConn;
|
||||
}
|
||||
|
||||
if constexpr (Feature_VtPassthroughMode::IsEnabled())
|
||||
{
|
||||
valueSet.Insert(L"passthroughMode", Windows::Foundation::PropertyValue::CreateBoolean(settings.VtPassthrough()));
|
||||
}
|
||||
|
||||
connection.Initialize(valueSet);
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"ConnectionCreated",
|
||||
TraceLoggingDescription("Event emitted upon the creation of a connection"),
|
||||
TraceLoggingGuid(connectionType, "ConnectionTypeGuid", "The type of the connection"),
|
||||
TraceLoggingGuid(profile.Guid(), "ProfileGuid", "The profile's GUID"),
|
||||
TraceLoggingGuid(sessionGuid, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingGuid(connection.SessionId(), "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
|
|
|
@ -77,8 +77,14 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
{
|
||||
if (settings)
|
||||
{
|
||||
_initialRows = gsl::narrow<til::CoordType>(winrt::unbox_value_or<uint32_t>(settings.TryLookup(L"initialRows").try_as<Windows::Foundation::IPropertyValue>(), _initialRows));
|
||||
_initialCols = gsl::narrow<til::CoordType>(winrt::unbox_value_or<uint32_t>(settings.TryLookup(L"initialCols").try_as<Windows::Foundation::IPropertyValue>(), _initialCols));
|
||||
_initialRows = unbox_prop_or<uint32_t>(settings, L"initialRows", _initialRows);
|
||||
_initialCols = unbox_prop_or<uint32_t>(settings, L"initialCols", _initialCols);
|
||||
_sessionId = unbox_prop_or<guid>(settings, L"sessionId", _sessionId);
|
||||
}
|
||||
|
||||
if (_sessionId == guid{})
|
||||
{
|
||||
_sessionId = Utils::CreateGuid();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#include "ConnectionStateHolder.h"
|
||||
#include "BaseTerminalConnection.h"
|
||||
#include "AzureClient.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
struct AzureConnection : AzureConnectionT<AzureConnection>, ConnectionStateHolder<AzureConnection>
|
||||
struct AzureConnection : AzureConnectionT<AzureConnection>, BaseTerminalConnection<AzureConnection>
|
||||
{
|
||||
static winrt::guid ConnectionType() noexcept;
|
||||
static bool IsAzureConnectionAvailable() noexcept;
|
||||
|
|
|
@ -4,13 +4,28 @@
|
|||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
template<typename T>
|
||||
struct ConnectionStateHolder
|
||||
struct BaseTerminalConnection
|
||||
{
|
||||
public:
|
||||
ConnectionState State() const noexcept { return _connectionState; }
|
||||
winrt::guid SessionId() const noexcept
|
||||
{
|
||||
return _sessionId;
|
||||
}
|
||||
|
||||
ConnectionState State() const noexcept
|
||||
{
|
||||
return _connectionState;
|
||||
}
|
||||
|
||||
TYPED_EVENT(StateChanged, ITerminalConnection, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
protected:
|
||||
template<typename U>
|
||||
U unbox_prop_or(const Windows::Foundation::Collections::ValueSet& blob, std::wstring_view key, U defaultValue)
|
||||
{
|
||||
return winrt::unbox_value_or<U>(blob.TryLookup(key).try_as<Windows::Foundation::IPropertyValue>(), defaultValue);
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26447) // Analyzer is still upset about noexcepts throwing even with function level try.
|
||||
// Method Description:
|
||||
|
@ -86,6 +101,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
return _isStateOneOf(ConnectionState::Connected);
|
||||
}
|
||||
|
||||
winrt::guid _sessionId{};
|
||||
|
||||
private:
|
||||
std::atomic<ConnectionState> _connectionState{ ConnectionState::NotConnected };
|
||||
mutable std::mutex _stateMutex;
|
|
@ -85,18 +85,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
auto environment = _initialEnv;
|
||||
|
||||
{
|
||||
// Convert connection Guid to string and ignore the enclosing '{}'.
|
||||
auto wsGuid{ Utils::GuidToString(_guid) };
|
||||
wsGuid.pop_back();
|
||||
|
||||
const auto guidSubStr = std::wstring_view{ wsGuid }.substr(1);
|
||||
|
||||
// Ensure every connection has the unique identifier in the environment.
|
||||
environment.as_map().insert_or_assign(L"WT_SESSION", guidSubStr.data());
|
||||
// Convert connection Guid to string and ignore the enclosing '{}'.
|
||||
environment.as_map().insert_or_assign(L"WT_SESSION", Utils::GuidToPlainString(_sessionId));
|
||||
|
||||
// The profile Guid does include the enclosing '{}'
|
||||
const auto profileGuid{ Utils::GuidToString(_profileGuid) };
|
||||
environment.as_map().insert_or_assign(L"WT_PROFILE_ID", profileGuid.data());
|
||||
environment.as_map().insert_or_assign(L"WT_PROFILE_ID", Utils::GuidToString(_profileGuid));
|
||||
|
||||
// WSLENV is a colon-delimited list of environment variables (+flags) that should appear inside WSL
|
||||
// https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows/
|
||||
|
@ -171,7 +165,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
g_hTerminalConnectionProvider,
|
||||
"ConPtyConnected",
|
||||
TraceLoggingDescription("Event emitted when ConPTY connection is started"),
|
||||
TraceLoggingGuid(_guid, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingGuid(_sessionId, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingWideString(_clientName.c_str(), "Client", "The attached client process"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
@ -189,7 +183,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
TERMINAL_STARTUP_INFO startupInfo) :
|
||||
_rows{ 25 },
|
||||
_cols{ 80 },
|
||||
_guid{ Utils::CreateGuid() },
|
||||
_inPipe{ hIn },
|
||||
_outPipe{ hOut }
|
||||
{
|
||||
|
@ -249,12 +242,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
return vs;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T unbox_prop_or(const Windows::Foundation::Collections::ValueSet& blob, std::wstring_view key, T defaultValue)
|
||||
{
|
||||
return winrt::unbox_value_or<T>(blob.TryLookup(key).try_as<Windows::Foundation::IPropertyValue>(), defaultValue);
|
||||
}
|
||||
|
||||
void ConptyConnection::Initialize(const Windows::Foundation::Collections::ValueSet& settings)
|
||||
{
|
||||
if (settings)
|
||||
|
@ -268,7 +255,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
_startingTitle = unbox_prop_or<winrt::hstring>(settings, L"startingTitle", _startingTitle);
|
||||
_rows = unbox_prop_or<uint32_t>(settings, L"initialRows", _rows);
|
||||
_cols = unbox_prop_or<uint32_t>(settings, L"initialCols", _cols);
|
||||
_guid = unbox_prop_or<winrt::guid>(settings, L"guid", _guid);
|
||||
_sessionId = unbox_prop_or<winrt::guid>(settings, L"sessionId", _sessionId);
|
||||
_environment = settings.TryLookup(L"environment").try_as<Windows::Foundation::Collections::ValueSet>();
|
||||
if constexpr (Feature_VtPassthroughMode::IsEnabled())
|
||||
{
|
||||
|
@ -299,17 +286,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
_initialEnv = til::env::from_current_environment();
|
||||
}
|
||||
}
|
||||
|
||||
if (_guid == guid{})
|
||||
{
|
||||
_guid = Utils::CreateGuid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
winrt::guid ConptyConnection::Guid() const noexcept
|
||||
{
|
||||
return _guid;
|
||||
if (_sessionId == guid{})
|
||||
{
|
||||
_sessionId = Utils::CreateGuid();
|
||||
}
|
||||
}
|
||||
|
||||
winrt::hstring ConptyConnection::Commandline() const
|
||||
|
@ -382,7 +364,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
g_hTerminalConnectionProvider,
|
||||
"ConPtyConnectedToDefterm",
|
||||
TraceLoggingDescription("Event emitted when ConPTY connection is started, for a defterm session"),
|
||||
TraceLoggingGuid(_guid, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingGuid(_sessionId, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingWideString(_clientName.c_str(), "Client", "The attached client process"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
@ -686,7 +668,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
TraceLoggingWrite(g_hTerminalConnectionProvider,
|
||||
"ReceivedFirstByte",
|
||||
TraceLoggingDescription("An event emitted when the connection receives the first byte"),
|
||||
TraceLoggingGuid(_guid, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingGuid(_sessionId, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingFloat64(delta.count(), "Duration"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "ConptyConnection.g.h"
|
||||
#include "ConnectionStateHolder.h"
|
||||
#include "BaseTerminalConnection.h"
|
||||
|
||||
#include "ITerminalHandoff.h"
|
||||
#include <til/env.h>
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
struct ConptyConnection : ConptyConnectionT<ConptyConnection>, ConnectionStateHolder<ConptyConnection>
|
||||
struct ConptyConnection : ConptyConnectionT<ConptyConnection>, BaseTerminalConnection<ConptyConnection>
|
||||
{
|
||||
ConptyConnection(const HANDLE hSig,
|
||||
const HANDLE hIn,
|
||||
|
@ -36,7 +36,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
|
||||
void ReparentWindow(const uint64_t newParent);
|
||||
|
||||
winrt::guid Guid() const noexcept;
|
||||
winrt::hstring Commandline() const;
|
||||
winrt::hstring StartingTitle() const;
|
||||
WORD ShowWindow() const noexcept;
|
||||
|
@ -77,7 +76,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
hstring _startingTitle{};
|
||||
bool _initialVisibility{ true };
|
||||
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).
|
||||
|
||||
bool _receivedFirstByte{ false };
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace Microsoft.Terminal.TerminalConnection
|
|||
[default_interface] runtimeclass ConptyConnection : ITerminalConnection
|
||||
{
|
||||
ConptyConnection();
|
||||
Guid Guid { get; };
|
||||
String Commandline { get; };
|
||||
String StartingTitle { get; };
|
||||
UInt16 ShowWindow { get; };
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) const noexcept {};
|
||||
|
||||
winrt::guid SessionId() const noexcept { return {}; }
|
||||
ConnectionState State() const noexcept { return ConnectionState::Connected; }
|
||||
|
||||
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);
|
||||
|
|
|
@ -25,8 +25,9 @@ namespace Microsoft.Terminal.TerminalConnection
|
|||
void Close();
|
||||
|
||||
event TerminalOutputHandler TerminalOutput;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<ITerminalConnection, Object> StateChanged;
|
||||
|
||||
Guid SessionId { get; };
|
||||
ConnectionState State { get; };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AzureClientID.h" />
|
||||
<ClInclude Include="BaseTerminalConnection.h" />
|
||||
<ClInclude Include="ConnectionInformation.h">
|
||||
<DependentUpon>ConnectionInformation.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<ClInclude Include="AzureConnection.h" />
|
||||
<ClInclude Include="AzureClientID.h" />
|
||||
<ClInclude Include="CTerminalHandoff.h" />
|
||||
<ClInclude Include="BaseTerminalConnection.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ITerminalConnection.idl" />
|
||||
|
@ -34,11 +35,9 @@
|
|||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="ConnectionInformation.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\Resources.resw" />
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
|
||||
void DisplayPowerlineGlyphs(bool d) noexcept;
|
||||
|
||||
winrt::guid SessionId() const noexcept { return {}; }
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept { return winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::Connected; }
|
||||
|
||||
WINRT_CALLBACK(TerminalOutput, winrt::Microsoft::Terminal::TerminalConnection::TerminalOutputHandler);
|
||||
|
|
|
@ -117,7 +117,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
|
||||
private:
|
||||
Model::Profile _profile;
|
||||
winrt::guid _originalProfileGuid;
|
||||
winrt::guid _originalProfileGuid{};
|
||||
winrt::hstring _lastBgImagePath;
|
||||
winrt::hstring _lastStartingDirectoryPath;
|
||||
Editor::AppearanceViewModel _defaultAppearanceViewModel;
|
||||
|
|
|
@ -102,34 +102,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
// The destructor ensures that the last write is flushed to disk before returning.
|
||||
ApplicationState::~ApplicationState()
|
||||
{
|
||||
TraceLoggingWrite(g_hSettingsModelProvider,
|
||||
"ApplicationState_Dtor_Start",
|
||||
TraceLoggingDescription("Event at the start of the ApplicationState destructor"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
Flush();
|
||||
}
|
||||
|
||||
void ApplicationState::Flush()
|
||||
{
|
||||
// This will ensure that we not just cancel the last outstanding timer,
|
||||
// but instead force it to run as soon as possible and wait for it to complete.
|
||||
_throttler.flush();
|
||||
|
||||
TraceLoggingWrite(g_hSettingsModelProvider,
|
||||
"ApplicationState_Dtor_End",
|
||||
TraceLoggingDescription("Event at the end of the ApplicationState destructor"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
// Re-read the state.json from disk.
|
||||
void ApplicationState::Reload() const noexcept
|
||||
{
|
||||
_read();
|
||||
}
|
||||
|
||||
bool ApplicationState::IsStatePath(const winrt::hstring& filename)
|
||||
{
|
||||
static const auto sharedPath{ _sharedPath.filename() };
|
||||
static const auto elevatedPath{ _elevatedPath.filename() };
|
||||
return filename == sharedPath || filename == elevatedPath;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -299,7 +279,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
Json::Value ApplicationState::_toJsonWithBlob(Json::Value& root, FileSource parseSource) const noexcept
|
||||
{
|
||||
{
|
||||
auto state = _state.lock_shared();
|
||||
const auto state = _state.lock_shared();
|
||||
|
||||
// GH#11222: We only write properties that are of the same type (Local
|
||||
// or Shared) which we requested. If we didn't want to serialize this
|
||||
|
@ -326,7 +306,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
void ApplicationState::name(const type& value) noexcept \
|
||||
{ \
|
||||
{ \
|
||||
auto state = _state.lock(); \
|
||||
const auto state = _state.lock(); \
|
||||
state->name.emplace(value); \
|
||||
} \
|
||||
\
|
||||
|
|
|
@ -63,15 +63,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
~ApplicationState();
|
||||
|
||||
// Methods
|
||||
void Reload() const noexcept;
|
||||
void Flush();
|
||||
void Reset() noexcept;
|
||||
|
||||
void FromJson(const Json::Value& root, FileSource parseSource) const noexcept;
|
||||
Json::Value ToJson(FileSource parseSource) const noexcept;
|
||||
|
||||
// General getters/setters
|
||||
bool IsStatePath(const winrt::hstring& filename);
|
||||
|
||||
// State getters/setters
|
||||
#define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \
|
||||
type name() const noexcept; \
|
||||
|
|
|
@ -28,11 +28,9 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
[default_interface] runtimeclass ApplicationState {
|
||||
static ApplicationState SharedInstance();
|
||||
|
||||
void Reload();
|
||||
void Flush();
|
||||
void Reset();
|
||||
|
||||
Boolean IsStatePath(String filename);
|
||||
|
||||
String SettingsHash;
|
||||
Windows.Foundation.Collections.IVector<WindowLayout> PersistedWindowLayouts;
|
||||
Windows.Foundation.Collections.IVector<String> RecentCommands;
|
||||
|
|
|
@ -410,7 +410,7 @@ bool SettingsLoader::FixupUserSettings()
|
|||
{
|
||||
struct CommandlinePatch
|
||||
{
|
||||
winrt::guid guid;
|
||||
winrt::guid guid{};
|
||||
std::wstring_view before;
|
||||
std::wstring_view after;
|
||||
};
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
static constexpr bool debugFeaturesDefault{ true };
|
||||
#endif
|
||||
|
||||
winrt::guid _defaultProfile;
|
||||
winrt::guid _defaultProfile{};
|
||||
bool _legacyReloadEnvironmentVariables{ true };
|
||||
winrt::com_ptr<implementation::ActionMap> _actionMap{ winrt::make_self<implementation::ActionMap>() };
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace ControlUnitTests
|
|||
void Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept {}
|
||||
void Close() noexcept {}
|
||||
|
||||
winrt::guid SessionId() const noexcept { return {}; }
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept { return winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::Connected; }
|
||||
|
||||
WINRT_CALLBACK(TerminalOutput, winrt::Microsoft::Terminal::TerminalConnection::TerminalOutputHandler);
|
||||
|
|
|
@ -127,6 +127,9 @@ void WindowEmperor::WaitForWindows()
|
|||
TranslateMessage(&message);
|
||||
DispatchMessage(&message);
|
||||
}
|
||||
|
||||
_finalizeSessionPersistence();
|
||||
TerminateProcess(GetCurrentProcess(), 0);
|
||||
}
|
||||
|
||||
void WindowEmperor::_createNewWindowThread(const Remoting::WindowRequestedArgs& args)
|
||||
|
@ -575,6 +578,14 @@ winrt::fire_and_forget WindowEmperor::_close()
|
|||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
void WindowEmperor::_finalizeSessionPersistence() const
|
||||
{
|
||||
const auto state = ApplicationState::SharedInstance();
|
||||
|
||||
// Ensure to write the state.json before we TerminateProcess()
|
||||
state.Flush();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
#pragma region GlobalHotkeys
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
winrt::fire_and_forget _setupGlobalHotkeys();
|
||||
|
||||
winrt::fire_and_forget _close();
|
||||
void _finalizeSessionPersistence() const;
|
||||
|
||||
void _createNotificationIcon();
|
||||
void _destroyNotificationIcon();
|
||||
|
|
|
@ -39,8 +39,10 @@ namespace Microsoft::Console::Utils
|
|||
static_cast<long>(SHRT_MAX)));
|
||||
}
|
||||
|
||||
std::wstring GuidToString(const GUID guid);
|
||||
std::wstring GuidToString(const GUID& guid);
|
||||
std::wstring GuidToPlainString(const GUID& guid);
|
||||
GUID GuidFromString(_Null_terminated_ const wchar_t* str);
|
||||
GUID GuidFromPlainString(_Null_terminated_ const wchar_t* str);
|
||||
GUID CreateGuid();
|
||||
|
||||
std::string ColorToHexString(const til::color color);
|
||||
|
|
|
@ -66,15 +66,23 @@ void UtilsTests::TestClampToShortMax()
|
|||
|
||||
void UtilsTests::TestGuidToString()
|
||||
{
|
||||
constexpr GUID constantGuid{
|
||||
static constexpr GUID constantGuid{
|
||||
0x01020304, 0x0506, 0x0708, { 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 }
|
||||
};
|
||||
constexpr std::wstring_view constantGuidString{ L"{01020304-0506-0708-090a-0b0c0d0e0f10}" };
|
||||
|
||||
auto generatedGuid{ GuidToString(constantGuid) };
|
||||
{
|
||||
const auto str = GuidToString(constantGuid);
|
||||
const auto guid = GuidFromString(str.c_str());
|
||||
VERIFY_ARE_EQUAL(L"{01020304-0506-0708-090a-0b0c0d0e0f10}", str);
|
||||
VERIFY_ARE_EQUAL(constantGuid, guid);
|
||||
}
|
||||
|
||||
VERIFY_ARE_EQUAL(constantGuidString.size(), generatedGuid.size());
|
||||
VERIFY_ARE_EQUAL(constantGuidString, generatedGuid);
|
||||
{
|
||||
const auto str = GuidToPlainString(constantGuid);
|
||||
const auto guid = GuidFromPlainString(str.c_str());
|
||||
VERIFY_ARE_EQUAL(L"01020304-0506-0708-090a-0b0c0d0e0f10", str);
|
||||
VERIFY_ARE_EQUAL(constantGuid, guid);
|
||||
}
|
||||
}
|
||||
|
||||
void UtilsTests::TestSplitString()
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "precomp.h"
|
||||
#include "inc/utils.hpp"
|
||||
|
||||
#include <propsys.h>
|
||||
|
||||
#include "inc/colorTable.hpp"
|
||||
|
||||
#include <wil/token_helpers.h>
|
||||
|
@ -21,27 +24,28 @@ static constexpr bool _isNumber(const wchar_t wch) noexcept
|
|||
return wch >= L'0' && wch <= L'9'; // 0x30 - 0x39
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Creates a String representation of a guid, in the format
|
||||
// "{12345678-ABCD-EF12-3456-7890ABCDEF12}"
|
||||
// Arguments:
|
||||
// - guid: the GUID to create the string for
|
||||
// Return Value:
|
||||
// - a string representation of the GUID. On failure, throws E_INVALIDARG.
|
||||
std::wstring Utils::GuidToString(const GUID guid)
|
||||
[[gsl::suppress(bounds)]] static std::wstring guidToStringCommon(const GUID& guid, size_t offset, size_t length)
|
||||
{
|
||||
return wil::str_printf<std::wstring>(L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
||||
// This is just like StringFromGUID2 but with lowercase hexadecimal.
|
||||
wchar_t buffer[39];
|
||||
swprintf_s(&buffer[0], 39, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
||||
return { &buffer[offset], length };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Parses a GUID from a string representation of the GUID. Throws an exception
|
||||
// if it fails to parse the GUID. See documentation of IIDFromString for
|
||||
// details.
|
||||
// Arguments:
|
||||
// - wstr: a string representation of the GUID to parse
|
||||
// Return Value:
|
||||
// - A GUID if the string could successfully be parsed. On failure, throws the
|
||||
// failing HRESULT.
|
||||
// Creates a string from the given GUID in the format "{12345678-abcd-ef12-3456-7890abcdef12}".
|
||||
std::wstring Utils::GuidToString(const GUID& guid)
|
||||
{
|
||||
return guidToStringCommon(guid, 0, 38);
|
||||
}
|
||||
|
||||
// Creates a string from the given GUID in the format "12345678-abcd-ef12-3456-7890abcdef12".
|
||||
std::wstring Utils::GuidToPlainString(const GUID& guid)
|
||||
{
|
||||
return guidToStringCommon(guid, 1, 36);
|
||||
}
|
||||
|
||||
// Creates a GUID from a string in the format "{12345678-abcd-ef12-3456-7890abcdef12}".
|
||||
// Throws if the conversion failed.
|
||||
GUID Utils::GuidFromString(_Null_terminated_ const wchar_t* str)
|
||||
{
|
||||
GUID result;
|
||||
|
@ -49,6 +53,25 @@ GUID Utils::GuidFromString(_Null_terminated_ const wchar_t* str)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Creates a GUID from a string in the format "12345678-abcd-ef12-3456-7890abcdef12".
|
||||
// Throws if the conversion failed.
|
||||
//
|
||||
// Side-note: An interesting quirk of this method is that the given string doesn't need to be null-terminated.
|
||||
// This method could be combined with GuidFromString() so that it also doesn't require null-termination.
|
||||
[[gsl::suppress(bounds)]] GUID Utils::GuidFromPlainString(_Null_terminated_ const wchar_t* str)
|
||||
{
|
||||
// Add "{}" brackets around our string, as required by IIDFromString().
|
||||
wchar_t buffer[39];
|
||||
buffer[0] = L'{';
|
||||
// This wcscpy_s() copies 36 characters and 1 terminating null.
|
||||
// The latter forces us to call this method before filling buffer[37] with '}'.
|
||||
THROW_HR_IF(CO_E_CLASSSTRING, wcscpy_s(&buffer[1], 37, str));
|
||||
buffer[37] = L'}';
|
||||
buffer[38] = L'\0';
|
||||
|
||||
return GuidFromString(&buffer[0]);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates a GUID, but not via an out parameter.
|
||||
// Return Value:
|
||||
|
|
Loading…
Reference in New Issue