mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-11 04:38:24 -06:00
Lazily load the settings UI DLL (#15628)
Due to an implementation detail in the Xaml compiler--which wants to ensure that all metadata providers on an App are available immediately--we were eagerly loading the settings UI DLL and all of its dependencies, even in sessions where the user was not going to open Settings. By turning off eager provider generation and handling it ourselves, we get to control exactly when the settings UI is loaded. This required some gentle poking-through of the barrier between App and Page, but it is almost certainly worth it. Turning on the Xaml code generation flag to not generate providers automatically adds an `AddProvider` member to the internal interface for the autogenerated XamlMetadataProvider. We needed to switch to using the internal interface rather than the projected type in our custom App base class to get at it. Providers that App/Page use must be initialized by the time we start the WindowsXamlManager, so we load Control and Controls (ha) eagerly and early. It looks like it may save 400ms of CPU time (?) on startup.
This commit is contained in:
parent
72b44888b5
commit
0f41851e67
@ -9,22 +9,35 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
IXamlType GetXamlType(const ::winrt::Windows::UI::Xaml::Interop::TypeName& type)
|
||||
{
|
||||
return _appProvider.GetXamlType(type);
|
||||
return AppProvider()->GetXamlType(type);
|
||||
}
|
||||
|
||||
IXamlType GetXamlType(const ::winrt::hstring& fullName)
|
||||
{
|
||||
return _appProvider.GetXamlType(fullName);
|
||||
return AppProvider()->GetXamlType(fullName);
|
||||
}
|
||||
|
||||
::winrt::com_array<::winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions()
|
||||
{
|
||||
return _appProvider.GetXmlnsDefinitions();
|
||||
return AppProvider()->GetXmlnsDefinitions();
|
||||
}
|
||||
|
||||
void AddOtherProvider(const ::winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider& provider)
|
||||
{
|
||||
AppProvider()->AddOtherProvider(provider);
|
||||
}
|
||||
|
||||
private:
|
||||
bool _contentLoaded{ false };
|
||||
winrt::TerminalApp::XamlMetaDataProvider _appProvider;
|
||||
winrt::com_ptr<XamlMetaDataProvider> _appProvider;
|
||||
winrt::com_ptr<XamlMetaDataProvider> AppProvider()
|
||||
{
|
||||
if (!_appProvider)
|
||||
{
|
||||
_appProvider = winrt::make_self<XamlMetaDataProvider>();
|
||||
}
|
||||
return _appProvider;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename D, typename... I>
|
||||
|
||||
@ -29,6 +29,10 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void App::Initialize()
|
||||
{
|
||||
// LOAD BEARING
|
||||
AddOtherProvider(winrt::Microsoft::Terminal::Control::XamlMetaDataProvider{});
|
||||
AddOtherProvider(winrt::Microsoft::UI::Xaml::XamlTypeInfo::XamlControlsXamlMetaDataProvider{});
|
||||
|
||||
const auto dispatcherQueue = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
|
||||
if (!dispatcherQueue)
|
||||
{
|
||||
@ -102,4 +106,12 @@ namespace winrt::TerminalApp::implementation
|
||||
// We used to support a pure UWP version of the Terminal. This method
|
||||
// was only ever used to do UWP-specific setup of our App.
|
||||
}
|
||||
|
||||
void App::PrepareForSettingsUI()
|
||||
{
|
||||
if (!std::exchange(_preparedForSettingsUI, true))
|
||||
{
|
||||
AddOtherProvider(winrt::Microsoft::Terminal::Settings::Editor::XamlMetaDataProvider{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ namespace winrt::TerminalApp::implementation
|
||||
TerminalApp::AppLogic Logic();
|
||||
|
||||
void Close();
|
||||
void PrepareForSettingsUI();
|
||||
|
||||
bool IsDisposed() const
|
||||
{
|
||||
@ -27,8 +28,8 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
private:
|
||||
winrt::Windows::UI::Xaml::Hosting::WindowsXamlManager _windowsXamlManager = nullptr;
|
||||
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider> _providers = winrt::single_threaded_vector<Windows::UI::Xaml::Markup::IXamlMetadataProvider>();
|
||||
bool _bIsClosed = false;
|
||||
bool _preparedForSettingsUI{ false };
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,11 @@
|
||||
-->
|
||||
<DisableEmbeddedXbf>false</DisableEmbeddedXbf>
|
||||
<XamlComponentResourceLocation>nested</XamlComponentResourceLocation>
|
||||
<!--
|
||||
Disable automatic provider generation so that we can control when they initialize.
|
||||
We do this so we can delay the Settings UI DLL loading until absolutely necessary.
|
||||
-->
|
||||
<XamlCodeGenerationControlFlags>DoNotGenerateOtherProviders</XamlCodeGenerationControlFlags>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <til/latch.h>
|
||||
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "App.h"
|
||||
#include "ColorHelper.h"
|
||||
#include "DebugTapConnection.h"
|
||||
#include "SettingsTab.h"
|
||||
@ -3722,6 +3723,15 @@ namespace winrt::TerminalApp::implementation
|
||||
// If we're holding the settings tab's switch command, don't create a new one, switch to the existing one.
|
||||
if (!_settingsTab)
|
||||
{
|
||||
if (auto app{ winrt::Windows::UI::Xaml::Application::Current().try_as<winrt::TerminalApp::App>() })
|
||||
{
|
||||
if (auto appPrivate{ winrt::get_self<implementation::App>(app) })
|
||||
{
|
||||
// Lazily load the Settings UI components so that we don't do it on startup.
|
||||
appPrivate->PrepareForSettingsUI();
|
||||
}
|
||||
}
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Editor::MainPage sui{ _settings };
|
||||
if (_hostingHwnd)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user