Add shield to tab row when elevated (#11224)

## Summary of the Pull Request

Adds a visible indicator that a Terminal window is elevated. This icon can be disabled with `"showAdminShield" false` in the global settings.

## References

* spec'd in #8455 
* Also in https://github.com/microsoft/terminal/projects/5
* big picture: #5000

## PR Checklist
* [x] Closes #1939
* [x] I work here
* [n/a] Tests added/passed
* [ ] Requires documentation to be updated - yea probably

## Validation Steps Performed

![image](https://user-images.githubusercontent.com/18356694/133293009-4215e319-fbf9-4ca8-8af5-afe2fa8bb62d.png)

![image](https://user-images.githubusercontent.com/18356694/133292970-90cb17fd-16c7-429a-a25f-8457850eb278.png)
This commit is contained in:
Mike Griese 2021-09-23 12:44:20 -05:00 committed by GitHub
parent f04fd089fe
commit 171e0a0242
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 64 additions and 14 deletions

View file

@ -1274,6 +1274,11 @@
"description": "When set to true, the Terminal's notification icon will always be shown in the notification area.", "description": "When set to true, the Terminal's notification icon will always be shown in the notification area.",
"type": "boolean" "type": "boolean"
}, },
"showAdminShield": {
"default": "true",
"description": "When set to true, the Terminal's tab row will display a shield icon when the Terminal is running with administrator privileges",
"type": "boolean"
},
"useAcrylicInTabRow": { "useAcrylicInTabRow": {
"default": "false", "default": "false",
"description": "When set to true, the tab row will have an acrylic background with 50% opacity.", "description": "When set to true, the tab row will have an acrylic background with 50% opacity.",

View file

@ -715,4 +715,7 @@
<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>
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>This Terminal window is running as Admin</value>
</data>
</root> </root>

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include "winrt/Microsoft.UI.Xaml.Controls.h" #include "winrt/Microsoft.UI.Xaml.Controls.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
#include "TabRowControl.g.h" #include "TabRowControl.g.h"
@ -16,6 +17,9 @@ namespace winrt::TerminalApp::implementation
void OnNewTabButtonClick(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Controls::SplitButtonClickEventArgs const& args); void OnNewTabButtonClick(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Controls::SplitButtonClickEventArgs const& args);
void OnNewTabButtonDrop(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::DragEventArgs const& e); void OnNewTabButtonDrop(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::DragEventArgs const& e);
void OnNewTabButtonDragOver(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::DragEventArgs const& e); void OnNewTabButtonDragOver(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::DragEventArgs const& e);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_OBSERVABLE_PROPERTY(bool, ShowElevationShield, _PropertyChangedHandlers, false);
}; };
} }

View file

@ -3,9 +3,11 @@
namespace TerminalApp namespace TerminalApp
{ {
[default_interface] runtimeclass TabRowControl : Windows.UI.Xaml.Controls.ContentPresenter [default_interface] runtimeclass TabRowControl : Windows.UI.Xaml.Controls.ContentPresenter,
Windows.UI.Xaml.Data.INotifyPropertyChanged
{ {
TabRowControl(); TabRowControl();
Microsoft.UI.Xaml.Controls.TabView TabView { get; }; Microsoft.UI.Xaml.Controls.TabView TabView { get; };
Boolean ShowElevationShield;
} }
} }

View file

@ -20,6 +20,17 @@
IsAddTabButtonVisible="false" IsAddTabButtonVisible="false"
TabWidthMode="Equal"> TabWidthMode="Equal">
<mux:TabView.TabStripHeader>
<!-- EA18 is the "Shield" glyph -->
<FontIcon x:Uid="ElevationShield"
Margin="9,4,0,0"
FontFamily="Segoe MDL2 Assets"
FontSize="16"
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}"
Glyph="&#xEA18;"
Visibility="{x:Bind ShowElevationShield, Mode=OneWay}" />
</mux:TabView.TabStripHeader>
<mux:TabView.TabStripFooter> <mux:TabView.TabStripFooter>
<mux:SplitButton x:Name="NewTabButton" <mux:SplitButton x:Name="NewTabButton"
x:Uid="NewTabSplitButton" x:Uid="NewTabSplitButton"

View file

@ -118,6 +118,29 @@ namespace winrt::TerminalApp::implementation
_systemRowsToScroll = _ReadSystemRowsToScroll(); _systemRowsToScroll = _ReadSystemRowsToScroll();
} }
bool TerminalPage::IsElevated() const noexcept
{
// use C++11 magic statics to make sure we only do this once.
// This won't change over the lifetime of the application
static const bool isElevated = []() {
// *** THIS IS A SINGLETON ***
auto result = false;
// GH#2455 - Make sure to try/catch calls to Application::Current,
// because that _won't_ be an instance of TerminalApp::App in the
// LocalTests
try
{
result = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated();
}
CATCH_LOG();
return result;
}();
return isElevated;
}
void TerminalPage::Create() void TerminalPage::Create()
{ {
// Hookup the key bindings // Hookup the key bindings
@ -128,19 +151,7 @@ namespace winrt::TerminalApp::implementation
_tabView = _tabRow.TabView(); _tabView = _tabRow.TabView();
_rearranging = false; _rearranging = false;
// GH#2455 - Make sure to try/catch calls to Application::Current, const auto isElevated = IsElevated();
// because that _won't_ be an instance of TerminalApp::App in the
// LocalTests
auto isElevated = false;
try
{
// GH#3581 - There's a platform limitation that causes us to crash when we rearrange tabs.
// Xaml tries to send a drag visual (to wit: a screenshot) to the drag hosting process,
// but that process is running at a different IL than us.
// For now, we're disabling elevated drag.
isElevated = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated();
}
CATCH_LOG();
if (_settings.GlobalSettings().UseAcrylicInTabRow()) if (_settings.GlobalSettings().UseAcrylicInTabRow())
{ {
@ -267,6 +278,8 @@ namespace winrt::TerminalApp::implementation
// Setup mouse vanish attributes // Setup mouse vanish attributes
SystemParametersInfoW(SPI_GETMOUSEVANISH, 0, &_shouldMouseVanish, false); SystemParametersInfoW(SPI_GETMOUSEVANISH, 0, &_shouldMouseVanish, false);
_tabRow.ShowElevationShield(IsElevated() && _settings.GlobalSettings().ShowAdminShield());
// Store cursor, so we can restore it, e.g., after mouse vanishing // Store cursor, so we can restore it, e.g., after mouse vanishing
// (we'll need to adapt this logic once we make cursor context aware) // (we'll need to adapt this logic once we make cursor context aware)
try try
@ -2242,6 +2255,8 @@ namespace winrt::TerminalApp::implementation
// enabled application-wide, so we don't need to check it each time we // enabled application-wide, so we don't need to check it each time we
// want to create an animation. // want to create an animation.
WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings.GlobalSettings().DisableAnimations()); WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings.GlobalSettings().DisableAnimations());
_tabRow.ShowElevationShield(IsElevated() && _settings.GlobalSettings().ShowAdminShield());
} }
// This is a helper to aid in sorting commands by their `Name`s, alphabetically. // This is a helper to aid in sorting commands by their `Name`s, alphabetically.

View file

@ -115,6 +115,7 @@ namespace winrt::TerminalApp::implementation
winrt::hstring WindowIdForDisplay() const noexcept; winrt::hstring WindowIdForDisplay() const noexcept;
winrt::hstring WindowNameForDisplay() const noexcept; winrt::hstring WindowNameForDisplay() const noexcept;
bool IsQuakeWindow() const noexcept; bool IsQuakeWindow() const noexcept;
bool IsElevated() const noexcept;
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);

View file

@ -51,6 +51,7 @@ static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" };
static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" }; static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" };
static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" }; static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" };
static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSources" }; static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSources" };
static constexpr std::string_view ShowAdminShieldKey{ "showAdminShield" };
static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" }; static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };
@ -121,6 +122,8 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea; globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea;
globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon; globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon;
globals->_DisabledProfileSources = _DisabledProfileSources; globals->_DisabledProfileSources = _DisabledProfileSources;
globals->_ShowAdminShield = _ShowAdminShield;
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile; globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
globals->_defaultProfile = _defaultProfile; globals->_defaultProfile = _defaultProfile;
@ -227,6 +230,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon); JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
JsonUtils::GetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources); JsonUtils::GetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
JsonUtils::GetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield);
static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey }; static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey };
for (const auto& jsonKey : bindingsKeys) for (const auto& jsonKey : bindingsKeys)
{ {
@ -324,6 +329,7 @@ Json::Value GlobalAppSettings::ToJson() const
JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea); JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon); JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
JsonUtils::SetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources); JsonUtils::SetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
JsonUtils::SetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield);
// clang-format on // clang-format on
json[JsonKey(ActionsKey)] = _actionMap->ToJson(); json[JsonKey(ActionsKey)] = _actionMap->ToJson();

View file

@ -99,6 +99,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false); INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false);
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, nullptr); INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, nullptr);
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L""); INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowAdminShield, true);
private: private:
#ifdef NDEBUG #ifdef NDEBUG

View file

@ -84,6 +84,7 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Boolean, MinimizeToNotificationArea); INHERITABLE_SETTING(Boolean, MinimizeToNotificationArea);
INHERITABLE_SETTING(Boolean, AlwaysShowNotificationIcon); INHERITABLE_SETTING(Boolean, AlwaysShowNotificationIcon);
INHERITABLE_SETTING(IVector<String>, DisabledProfileSources); INHERITABLE_SETTING(IVector<String>, DisabledProfileSources);
INHERITABLE_SETTING(Boolean, ShowAdminShield);
Windows.Foundation.Collections.IMapView<String, ColorScheme> ColorSchemes(); Windows.Foundation.Collections.IMapView<String, ColorScheme> ColorSchemes();
void AddColorScheme(ColorScheme scheme); void AddColorScheme(ColorScheme scheme);

View file

@ -20,6 +20,7 @@
"showTerminalTitleInTitlebar": true, "showTerminalTitleInTitlebar": true,
"tabWidthMode": "equal", "tabWidthMode": "equal",
"tabSwitcherMode": "inOrder", "tabSwitcherMode": "inOrder",
"showAdminShield": true,
// Miscellaneous // Miscellaneous
"confirmCloseAllTabs": true, "confirmCloseAllTabs": true,