Add a information popup about default terminals (#11397)

This commit adds a simple information popup about default terminals,
guiding first-time Windows 11 users into changing the default terminal.

## Validation Steps Performed
* Info bar pops up on Windows 11 ✔️
* Info bar can be dismissed persistently ✔️
This commit is contained in:
Leonard Hecker 2021-10-07 19:44:03 +02:00 committed by GitHub
parent e1c830dde0
commit 2b1468eaa2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 99 additions and 7 deletions

View file

@ -718,6 +718,9 @@
<data name="CloseOnExitInfoBar.Message" xml:space="preserve"> <data name="CloseOnExitInfoBar.Message" xml:space="preserve">
<value>Termination behavior can be configured in advanced profile settings.</value> <value>Termination behavior can be configured in advanced profile settings.</value>
</data> </data>
<data name="SetAsDefaultInfoBar.Message" xml:space="preserve">
<value>Windows Terminal can be set as the default terminal application in your settings.</value>
</data>
<data name="InfoBarDismissButton.Content" xml:space="preserve"> <data name="InfoBarDismissButton.Content" xml:space="preserve">
<value>Don't show again</value> <value>Don't show again</value>
</data> </data>

View file

@ -287,6 +287,8 @@ namespace winrt::TerminalApp::implementation
_defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor(); _defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor();
} }
CATCH_LOG(); CATCH_LOG();
ShowSetAsDefaultInfoBar();
} }
// Method Description; // Method Description;
@ -2893,6 +2895,29 @@ namespace winrt::TerminalApp::implementation
} }
} }
// Method Description:
// - Displays a info popup guiding the user into setting their default terminal.
void TerminalPage::ShowSetAsDefaultInfoBar() const
{
if (!CascadiaSettings::IsDefaultTerminalAvailable() || _IsMessageDismissed(InfoBarMessage::SetAsDefault))
{
return;
}
// If the user has already configured any terminal for hand-off we
// shouldn't inform them again about the possibility to do so.
if (CascadiaSettings::IsDefaultTerminalSet())
{
_DismissMessage(InfoBarMessage::SetAsDefault);
return;
}
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
{
infoBar.IsOpen(true);
}
}
// Function Description: // Function Description:
// - Helper function to get the OS-localized name for the "Touch Keyboard // - Helper function to get the OS-localized name for the "Touch Keyboard
// and Handwriting Panel Service". If we can't open up the service for any // and Handwriting Panel Service". If we can't open up the service for any
@ -3313,6 +3338,22 @@ namespace winrt::TerminalApp::implementation
} }
} }
// Method Description:
// - Persists the user's choice not to show the information bar warning about "Windows Terminal can be set as your default terminal application"
// Then hides this information buffer.
// Arguments:
// - <none>
// Return Value:
// - <none>
void TerminalPage::_SetAsDefaultDismissHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/) const
{
_DismissMessage(InfoBarMessage::SetAsDefault);
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
{
infoBar.IsOpen(false);
}
}
// Method Description: // Method Description:
// - Checks whether information bar message was dismissed earlier (in the application state) // - Checks whether information bar message was dismissed earlier (in the application state)
// Arguments: // Arguments:
@ -3342,13 +3383,20 @@ namespace winrt::TerminalApp::implementation
// - <none> // - <none>
void TerminalPage::_DismissMessage(const InfoBarMessage& message) void TerminalPage::_DismissMessage(const InfoBarMessage& message)
{ {
auto dismissedMessages = ApplicationState::SharedInstance().DismissedMessages(); const auto applicationState = ApplicationState::SharedInstance();
if (!dismissedMessages) std::vector<InfoBarMessage> messages;
if (const auto values = applicationState.DismissedMessages())
{ {
dismissedMessages = winrt::single_threaded_vector<InfoBarMessage>(); messages.resize(values.Size());
values.GetMany(0, messages);
} }
dismissedMessages.Append(message); if (std::none_of(messages.begin(), messages.end(), [&](const auto& m) { return m == message; }))
ApplicationState::SharedInstance().DismissedMessages(dismissedMessages); {
messages.emplace_back(message);
}
applicationState.DismissedMessages(std::move(messages));
} }
} }

View file

@ -95,6 +95,7 @@ namespace winrt::TerminalApp::implementation
winrt::TerminalApp::TaskbarState TaskbarState() const; winrt::TerminalApp::TaskbarState TaskbarState() const;
void ShowKeyboardServiceWarning() const; void ShowKeyboardServiceWarning() const;
void ShowSetAsDefaultInfoBar() const;
winrt::hstring KeyboardServiceDisabledText(); winrt::hstring KeyboardServiceDisabledText();
winrt::fire_and_forget IdentifyWindow(); winrt::fire_and_forget IdentifyWindow();
@ -403,6 +404,7 @@ namespace winrt::TerminalApp::implementation
winrt::fire_and_forget _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const; winrt::fire_and_forget _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const; void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const; void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
void _SetAsDefaultDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message); static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message); static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);

View file

@ -141,6 +141,19 @@
Click="_CloseOnExitInfoDismissHandler" /> Click="_CloseOnExitInfoDismissHandler" />
</mux:InfoBar.ActionButton> </mux:InfoBar.ActionButton>
</mux:InfoBar> </mux:InfoBar>
<mux:InfoBar x:Name="SetAsDefaultInfoBar"
x:Uid="SetAsDefaultInfoBar"
x:Load="False"
IsClosable="True"
IsIconVisible="True"
IsOpen="False"
Severity="Informational">
<mux:InfoBar.ActionButton>
<Button x:Uid="InfoBarDismissButton"
Click="_SetAsDefaultDismissHandler" />
</mux:InfoBar.ActionButton>
</mux:InfoBar>
</StackPanel> </StackPanel>
<!-- <!--

View file

@ -8,7 +8,8 @@ namespace Microsoft.Terminal.Settings.Model
enum InfoBarMessage enum InfoBarMessage
{ {
CloseOnExitInfo = 0, CloseOnExitInfo = 0,
KeyboardServiceWarning KeyboardServiceWarning,
SetAsDefault,
}; };
runtimeclass WindowLayout runtimeclass WindowLayout

View file

@ -10,6 +10,7 @@
#include <LibraryResources.h> #include <LibraryResources.h>
#include <VersionHelpers.h> #include <VersionHelpers.h>
#include <WtExeUtils.h>
using namespace winrt::Microsoft::Terminal; using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::Microsoft::Terminal::Settings;
@ -837,6 +838,11 @@ winrt::hstring CascadiaSettings::ApplicationVersion()
// - True if OS supports default terminal. False otherwise. // - True if OS supports default terminal. False otherwise.
bool CascadiaSettings::IsDefaultTerminalAvailable() noexcept bool CascadiaSettings::IsDefaultTerminalAvailable() noexcept
{ {
if (!IsPackaged())
{
return false;
}
OSVERSIONINFOEXW osver{}; OSVERSIONINFOEXW osver{};
osver.dwOSVersionInfoSize = sizeof(osver); osver.dwOSVersionInfoSize = sizeof(osver);
osver.dwBuildNumber = 22000; osver.dwBuildNumber = 22000;
@ -847,6 +853,11 @@ bool CascadiaSettings::IsDefaultTerminalAvailable() noexcept
return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE; return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE;
} }
bool CascadiaSettings::IsDefaultTerminalSet() noexcept
{
return DefaultTerminal::HasCurrent();
}
// Method Description: // Method Description:
// - Returns an iterable collection of all available terminals. // - Returns an iterable collection of all available terminals.
// Arguments: // Arguments:

View file

@ -134,6 +134,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
// defterm // defterm
static bool IsDefaultTerminalAvailable() noexcept; static bool IsDefaultTerminalAvailable() noexcept;
static bool IsDefaultTerminalSet() noexcept;
winrt::Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> DefaultTerminals() noexcept; winrt::Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> DefaultTerminals() noexcept;
Model::DefaultTerminal CurrentDefaultTerminal() noexcept; Model::DefaultTerminal CurrentDefaultTerminal() noexcept;
void CurrentDefaultTerminal(const Model::DefaultTerminal& terminal); void CurrentDefaultTerminal(const Model::DefaultTerminal& terminal);

View file

@ -49,6 +49,7 @@ namespace Microsoft.Terminal.Settings.Model
Profile GetProfileForArgs(NewTerminalArgs newTerminalArgs); Profile GetProfileForArgs(NewTerminalArgs newTerminalArgs);
static Boolean IsDefaultTerminalAvailable { get; }; static Boolean IsDefaultTerminalAvailable { get; };
static Boolean IsDefaultTerminalSet { get; };
IObservableVector<DefaultTerminal> DefaultTerminals { get; }; IObservableVector<DefaultTerminal> DefaultTerminals { get; };
DefaultTerminal CurrentDefaultTerminal; DefaultTerminal CurrentDefaultTerminal;
} }

View file

@ -73,6 +73,16 @@ std::pair<std::vector<Model::DefaultTerminal>, Model::DefaultTerminal> DefaultTe
return { std::move(defaultTerminals), std::move(defaultTerminal) }; return { std::move(defaultTerminals), std::move(defaultTerminal) };
} }
bool DefaultTerminal::HasCurrent()
{
std::vector<DelegationConfig::DelegationPackage> allPackages;
DelegationConfig::DelegationPackage currentPackage;
LOG_IF_FAILED(DelegationConfig::s_GetAvailablePackages(allPackages, currentPackage));
// Good old conhost has a hardcoded GUID of {00000000-0000-0000-0000-000000000000}.
return currentPackage.terminal.clsid != CLSID{};
}
void DefaultTerminal::Current(const Model::DefaultTerminal& term) void DefaultTerminal::Current(const Model::DefaultTerminal& term)
{ {
THROW_IF_FAILED(DelegationConfig::s_SetDefaultByPackage(winrt::get_self<DefaultTerminal>(term)->_pkg, true)); THROW_IF_FAILED(DelegationConfig::s_SetDefaultByPackage(winrt::get_self<DefaultTerminal>(term)->_pkg, true));

View file

@ -34,6 +34,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
hstring Icon() const; hstring Icon() const;
static std::pair<std::vector<Model::DefaultTerminal>, Model::DefaultTerminal> Available(); static std::pair<std::vector<Model::DefaultTerminal>, Model::DefaultTerminal> Available();
static bool HasCurrent();
static void Current(const Model::DefaultTerminal& term); static void Current(const Model::DefaultTerminal& term);
private: private:

View file

@ -537,8 +537,9 @@ JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::IntenseStyle)
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage) JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage)
{ {
JSON_MAPPINGS(2) = { JSON_MAPPINGS(3) = {
pair_type{ "closeOnExitInfo", ValueType::CloseOnExitInfo }, pair_type{ "closeOnExitInfo", ValueType::CloseOnExitInfo },
pair_type{ "keyboardServiceWarning", ValueType::KeyboardServiceWarning }, pair_type{ "keyboardServiceWarning", ValueType::KeyboardServiceWarning },
pair_type{ "setAsDefault", ValueType::SetAsDefault },
}; };
}; };