diff --git a/.github/actions/spell-check/expect/5757ec679b03a4240130c3c53766c91bbc5cd6a7.txt b/.github/actions/spell-check/expect/5757ec679b03a4240130c3c53766c91bbc5cd6a7.txt index 9f713a5ff52..696b9b1e499 100644 --- a/.github/actions/spell-check/expect/5757ec679b03a4240130c3c53766c91bbc5cd6a7.txt +++ b/.github/actions/spell-check/expect/5757ec679b03a4240130c3c53766c91bbc5cd6a7.txt @@ -1 +1 @@ -renamer \ No newline at end of file +renamer diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt index 55298a2bdec..9bb806aa3f4 100644 --- a/.github/actions/spell-check/expect/expect.txt +++ b/.github/actions/spell-check/expect/expect.txt @@ -2829,4 +2829,4 @@ zy AAAAABBBBBBCCC AAAAA BBBBBCCC -abcd \ No newline at end of file +abcd diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 698d5861285..7690b12d085 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -1,17 +1,17 @@  - @@ -488,4 +488,19 @@ Back - + + OK + + + Debug + + + Error + + + Information + + + Warning + + \ No newline at end of file diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index d476a906f0a..4b1cba8fa73 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1121,6 +1121,8 @@ namespace winrt::TerminalApp::implementation // - hostingTab: The Tab that's hosting this TermControl instance void TerminalPage::_RegisterTerminalEvents(TermControl term, TerminalTab& hostingTab) { + term.RaiseNotice({ this, &TerminalPage::_ControlNoticeRaisedHandler }); + // Add an event handler when the terminal's selection wants to be copied. // When the text buffer data is retrieved, we'll copy the data into the Clipboard term.CopyToClipboard({ this, &TerminalPage::_CopyToClipboardHandler }); @@ -1928,6 +1930,48 @@ namespace winrt::TerminalApp::implementation } } + void TerminalPage::_ControlNoticeRaisedHandler(const IInspectable /*sender*/, const Microsoft::Terminal::TerminalControl::NoticeEventArgs eventArgs) + { + winrt::hstring message = eventArgs.Message(); + + winrt::hstring title; + + switch (eventArgs.Level()) + { + case TerminalControl::NoticeLevel::Debug: + title = RS_(L"NoticeDebug"); //\xebe8 + break; + case TerminalControl::NoticeLevel::Info: + title = RS_(L"NoticeInfo"); // \xe946 + break; + case TerminalControl::NoticeLevel::Warning: + title = RS_(L"NoticeWarning"); //\xe7ba + break; + case TerminalControl::NoticeLevel::Error: + title = RS_(L"NoticeError"); //\xe783 + break; + } + + _ShowControlNoticeDialog(title, message); + } + + void TerminalPage::_ShowControlNoticeDialog(const winrt::hstring& title, const winrt::hstring& message) + { + if (auto presenter{ _dialogPresenter.get() }) + { + // FindName needs to be called first to actually load the xaml object + auto controlNoticeDialog = FindName(L"ControlNoticeDialog").try_as(); + + ControlNoticeDialog().Title(winrt::box_value(title)); + + // Insert the message + NoticeMessage().Text(message); + + // Show the dialog + presenter.ShowDialog(controlNoticeDialog); + } + } + // Method Description: // - Copy text from the focused terminal to the Windows Clipboard // Arguments: diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 65d318cadc6..5275227f613 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -197,6 +197,9 @@ namespace winrt::TerminalApp::implementation void _PasteText(); + void _ControlNoticeRaisedHandler(const IInspectable sender, const Microsoft::Terminal::TerminalControl::NoticeEventArgs eventArgs); + void _ShowControlNoticeDialog(const winrt::hstring& title, const winrt::hstring& message); + fire_and_forget _LaunchSettings(const Microsoft::Terminal::Settings::Model::SettingsTarget target); void _OnTabClick(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs); diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml index 4e3e2b5b16f..ae5c242a9d4 100644 --- a/src/cascadia/TerminalApp/TerminalPage.xaml +++ b/src/cascadia/TerminalApp/TerminalPage.xaml @@ -69,6 +69,16 @@ the MIT License. See LICENSE in the project root for license information. --> DefaultButton="Primary"> + + + + + + - @@ -178,4 +178,12 @@ Ctrl+Click to follow link - + + Unable to find the selected font "{0}". + +"{1}" has been selected instead. + +Please either install the missing font or choose another one. + 0 and 1 are names of fonts provided by the user and system respectively. + + \ No newline at end of file diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index ffc6aeb0f69..1711b2fef0e 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1987,6 +1987,33 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // actually fail. We need a way to gracefully fallback. _renderer->TriggerFontChange(newDpi, _desiredFont, _actualFont); + // If the actual font isn't what was requested... + if (_actualFont.GetFaceName() != _desiredFont.GetFaceName()) + { + // Then warn the user that we picked something because we couldn't find their font. + + // Format message with user's choice of font and the font that was chosen instead. + const winrt::hstring message{ fmt::format(std::wstring_view{ RS_(L"NoticeFontNotFound") }, _desiredFont.GetFaceName(), _actualFont.GetFaceName()) }; + + // Capture what we need to resume later. + [strongThis = get_strong(), message]() -> winrt::fire_and_forget { + // Take these out of the lambda and store them locally + // because the coroutine will lose them into space + // by the time it resumes. + const auto msg = message; + const auto strong = strongThis; + + // Pop the rest of this function to the tail of the UI thread + // Just in case someone was holding a lock when they called us and + // the handlers decide to do something that take another lock + // (like ShellExecute pumping our messaging thread...GH#7994) + co_await strong->Dispatcher(); + + auto noticeArgs = winrt::make(NoticeLevel::Warning, std::move(msg)); + strong->_raiseNoticeHandlers(*strong, std::move(noticeArgs)); + }(); + } + const auto actualNewSize = _actualFont.GetSize(); _fontSizeChangedHandlers(actualNewSize.X, actualNewSize.Y, initialUpdate); } @@ -3074,5 +3101,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, PasteFromClipboard, _clipboardPasteHandlers, TerminalControl::TermControl, TerminalControl::PasteFromClipboardEventArgs); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, RaiseNotice, _raiseNoticeHandlers, TerminalControl::TermControl, TerminalControl::NoticeEventArgs); // clang-format on } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index cc7601f728d..c5dcd819f6c 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -7,6 +7,7 @@ #include "CopyToClipboardEventArgs.g.h" #include "PasteFromClipboardEventArgs.g.h" #include "OpenHyperlinkEventArgs.g.h" +#include "NoticeEventArgs.g.h" #include #include "../../renderer/base/Renderer.hpp" #include "../../renderer/dx/DxRenderer.hpp" @@ -81,6 +82,22 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation hstring _uri; }; + struct NoticeEventArgs : + public NoticeEventArgsT + { + public: + NoticeEventArgs(const NoticeLevel level, const hstring& message) : + _level(level), + _message(message) {} + + NoticeLevel Level() { return _level; }; + hstring Message() { return _message; }; + + private: + const NoticeLevel _level; + const hstring _message; + }; + struct TermControl : TermControlT { TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection); @@ -150,6 +167,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(PasteFromClipboard, _clipboardPasteHandlers, TerminalControl::TermControl, TerminalControl::PasteFromClipboardEventArgs); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RaiseNotice, _raiseNoticeHandlers, TerminalControl::TermControl, TerminalControl::NoticeEventArgs); TYPED_EVENT(WarningBell, IInspectable, IInspectable); TYPED_EVENT(ConnectionStateChanged, TerminalControl::TermControl, IInspectable); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index d8bc580e0e9..f1cfcef3bf1 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -45,6 +45,20 @@ namespace Microsoft.Terminal.TerminalControl String Uri { get; }; } + enum NoticeLevel + { + Debug = 10, + Info = 20, + Warning = 30, + Error = 40, + }; + + runtimeclass NoticeEventArgs + { + NoticeLevel Level { get; }; + String Message { get; }; + } + [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IDirectKeyListener, IMouseWheelListener { TermControl(Microsoft.Terminal.TerminalControl.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); @@ -60,6 +74,7 @@ namespace Microsoft.Terminal.TerminalControl event Windows.Foundation.TypedEventHandler CopyToClipboard; event Windows.Foundation.TypedEventHandler PasteFromClipboard; event Windows.Foundation.TypedEventHandler OpenHyperlink; + event Windows.Foundation.TypedEventHandler RaiseNotice; event Windows.Foundation.TypedEventHandler WarningBell; event Windows.Foundation.TypedEventHandler Initialized;