From 76497251509d90dd658f3a5b48d5af036c7c5528 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 23 Feb 2023 16:51:16 -0600 Subject: [PATCH] [ainulindale] The Terminal shouldn't crash on a WM_SETTINGCHANGE --- src/cascadia/WindowsTerminal/AppHost.cpp | 10 +++++++++- src/cascadia/WindowsTerminal/AppHost.h | 4 ++++ src/cascadia/WindowsTerminal/WindowEmperor.cpp | 7 ++++++- src/cascadia/WindowsTerminal/WindowThread.cpp | 2 +- src/cascadia/WindowsTerminal/WindowThread.h | 1 + 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 2cc8c0b5190..c815dd86b9b 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -335,7 +335,7 @@ void AppHost::Initialize() _window->DragRegionClicked([this]() { _windowLogic.TitlebarClicked(); }); _window->WindowVisibilityChanged([this](bool showOrHide) { _windowLogic.WindowVisibilityChanged(showOrHide); }); - _window->UpdateSettingsRequested([this]() { _appLogic.ReloadSettings(); }); + _window->UpdateSettingsRequested({ this, &AppHost::_requestUpdateSettings }); _revokers.RequestedThemeChanged = _windowLogic.RequestedThemeChanged(winrt::auto_revoke, { this, &AppHost::_UpdateTheme }); _revokers.FullscreenChanged = _windowLogic.FullscreenChanged(winrt::auto_revoke, { this, &AppHost::_FullscreenChanged }); @@ -1228,3 +1228,11 @@ void AppHost::_handleSendContent(const winrt::Windows::Foundation::IInspectable& { _windowLogic.SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs{ args.SourceWindow(), args.TargetWindow(), args.TabIndex() }); } + +// Bubble the update settings request up to the emperor. We're being called on +// the Window thread, but the Emperor needs to update the settings on the _main_ +// thread. +void AppHost::_requestUpdateSettings() +{ + _UpdateSettingsRequestedHandlers(); +} diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 02359d72db0..0b9566531e6 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -26,6 +26,8 @@ class AppHost static void s_DisplayMessageBox(const winrt::TerminalApp::ParseCommandlineResult& message); + WINRT_CALLBACK(UpdateSettingsRequested, winrt::delegate); + private: std::unique_ptr _window; @@ -123,6 +125,8 @@ class AppHost void _handleAttach(const winrt::Windows::Foundation::IInspectable& sender, winrt::Microsoft::Terminal::Remoting::AttachRequest args); + void _requestUpdateSettings(); + // Page -> us -> monarch void _handleReceiveContent(const winrt::Windows::Foundation::IInspectable& sender, winrt::TerminalApp::RequestReceiveContentArgs args); diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp index fc23db42c2d..72c55c127ad 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp +++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp @@ -122,10 +122,15 @@ void WindowEmperor::CreateNewWindowThread(Remoting::WindowRequestedArgs args, co // Add a callback to the window's logic to let us know when the window's // quake mode state changes. We'll use this to check if we need to add // or remove the notification icon. - sender->Logic().IsQuakeWindowChanged([this](auto&&, auto&&) -> winrt::fire_and_forget { + sender->Logic().IsQuakeWindowChanged([this](auto&&, auto &&) -> winrt::fire_and_forget { co_await wil::resume_foreground(this->_dispatcher); this->_checkWindowsForNotificationIcon(); }); + sender->UpdateSettingsRequested([this]() -> winrt::fire_and_forget { + // We MUST be on the main thread to update the settings. We will crash when trying to enumerate fragement extensions otherwise. + co_await wil::resume_foreground(this->_dispatcher); + _app.Logic().ReloadSettings(); + }); // These come in on the sender's thread. Move back to our thread. co_await wil::resume_foreground(_dispatcher); diff --git a/src/cascadia/WindowsTerminal/WindowThread.cpp b/src/cascadia/WindowsTerminal/WindowThread.cpp index 7da27b91013..917435a69f3 100644 --- a/src/cascadia/WindowsTerminal/WindowThread.cpp +++ b/src/cascadia/WindowsTerminal/WindowThread.cpp @@ -24,7 +24,7 @@ void WindowThread::Start() _args, _manager, _peasant); - + _host->UpdateSettingsRequested([this]() { _UpdateSettingsRequestedHandlers(); }); // Enter the main window loop. const auto exitCode = WindowProc(); _host = nullptr; diff --git a/src/cascadia/WindowsTerminal/WindowThread.h b/src/cascadia/WindowsTerminal/WindowThread.h index 6719734fc6f..720c70b89d6 100644 --- a/src/cascadia/WindowsTerminal/WindowThread.h +++ b/src/cascadia/WindowsTerminal/WindowThread.h @@ -19,6 +19,7 @@ class WindowThread WINRT_CALLBACK(Started, winrt::delegate<>); WINRT_CALLBACK(Exited, winrt::delegate); + WINRT_CALLBACK(UpdateSettingsRequested, winrt::delegate); private: winrt::Microsoft::Terminal::Remoting::Peasant _peasant{ nullptr };