From 462d8003a7aee2f61e4a86020508c77506a6e3d1 Mon Sep 17 00:00:00 2001 From: MPela <1140981+mpela81@users.noreply.github.com> Date: Tue, 12 Oct 2021 20:00:06 +0200 Subject: [PATCH] Dismiss any open content dialog when window is moved (#11485) ## Summary of the Pull Request When the window moves, hide any visible content dialog (only one can be shown at a time) and ensure its associated async operation is terminated. #10922 dismisses any open popups when the window is moved or any scroll viewer scrolls. However, if you just close a Popup from the UI tree, the async operation associated to a ContentDialog (started with `dialog.ShowAsync`) does not terminate. The dialog lock that prevents opening multiple dialogs at the same time is not released, and no further dialog can be shown. Explicitly dismissing the only visible ContentDialog using its `Hide` method terminates the operation. ## Validation Steps Performed Manual tests, open up dialogs and move the window (like in #11425) References #10922 Closes #11425 --- src/cascadia/TerminalApp/AppLogic.cpp | 12 ++++++++++++ src/cascadia/TerminalApp/AppLogic.h | 2 ++ src/cascadia/TerminalApp/AppLogic.idl | 1 + src/cascadia/WindowsTerminal/AppHost.cpp | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 72f25b83e..b7e1c0ff3 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -375,6 +375,8 @@ namespace winrt::TerminalApp::implementation co_return ContentDialogResult::None; } + _dialog = dialog; + // IMPORTANT: This is necessary as documented in the ContentDialog MSDN docs. // Since we're hosting the dialog in a Xaml island, we need to connect it to the // xaml tree somehow. @@ -412,6 +414,16 @@ namespace winrt::TerminalApp::implementation // be released so another can be shown } + // Method Description: + // - Dismiss the (only) visible ContentDialog + void AppLogic::DismissDialog() + { + if (auto localDialog = std::exchange(_dialog, nullptr)) + { + localDialog.Hide(); + } + } + // Method Description: // - Displays a dialog for errors found while loading or validating the // settings. Uses the resources under the provided title and content keys diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 17bd61aaa..e121043d1 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -106,6 +106,7 @@ namespace winrt::TerminalApp::implementation bool GetShowTitleInTitlebar(); winrt::Windows::Foundation::IAsyncOperation ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog); + void DismissDialog(); Windows::Foundation::Collections::IMapView GlobalHotkeys(); @@ -132,6 +133,7 @@ namespace winrt::TerminalApp::implementation uint64_t _numOpenWindows{ 0 }; std::shared_mutex _dialogLock; + winrt::Windows::UI::Xaml::Controls::ContentDialog _dialog; ::TerminalApp::AppCommandlineArgs _appArgs; ::TerminalApp::AppCommandlineArgs _settingsAppArgs; diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index cfe93321a..674322d35 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -91,6 +91,7 @@ namespace TerminalApp // See IDialogPresenter and TerminalPage's DialogPresenter for more // information. Windows.Foundation.IAsyncOperation ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog); + void DismissDialog(); event Windows.Foundation.TypedEventHandler SetTitleBarContent; event Windows.Foundation.TypedEventHandler TitleChanged; diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index c2b8dcda2..aa84b9e9e 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -1316,6 +1316,11 @@ void AppHost::_WindowMoved() { if (_logic) { + // Ensure any open ContentDialog is dismissed. + // Closing the popup in the UI tree as done below is not sufficient because + // it does not terminate the dialog's async operation. + _logic.DismissDialog(); + const auto root{ _logic.GetRoot() }; // This is basically DismissAllPopups which is also in