Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shield to tab row when elevated #11224

Merged
14 commits merged into from
Sep 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,11 @@
"description": "When set to true, the Terminal's notification icon will always be shown in the notification area.",
"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": {
"default": "false",
"description": "When set to true, the tab row will have an acrylic background with 50% opacity.",
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -715,4 +715,7 @@
<data name="InfoBarDismissButton.Content" xml:space="preserve">
<value>Don't show again</value>
</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>
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/TabRowControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once

#include "winrt/Microsoft.UI.Xaml.Controls.h"
#include "../../cascadia/inc/cppwinrt_utils.h"

#include "TabRowControl.g.h"

Expand All @@ -16,6 +17,9 @@ namespace winrt::TerminalApp::implementation
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 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);
};
}

Expand Down
4 changes: 3 additions & 1 deletion src/cascadia/TerminalApp/TabRowControl.idl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

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();
Microsoft.UI.Xaml.Controls.TabView TabView { get; };
Boolean ShowElevationShield;
}
}
11 changes: 11 additions & 0 deletions src/cascadia/TerminalApp/TabRowControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@
IsAddTabButtonVisible="false"
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:SplitButton x:Name="NewTabButton"
x:Uid="NewTabSplitButton"
Expand Down
41 changes: 28 additions & 13 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,29 @@ namespace winrt::TerminalApp::implementation
_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;
lhecker marked this conversation as resolved.
Show resolved Hide resolved

// 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this try-catch work with the magic static? If the try fails, is isElevated permanently stuck as false?

(Also, is this even a valid concern? Does Application::Current fail often?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does Application::Current fail often

literally only in the tests, because Application::Current isn't a TerminalApp::App in the tests. With the magic static, we catch the exception as it's getting initialized, return false, and then put false in the static member to store forever

Copy link
Contributor

@Rosefield Rosefield Sep 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now AppLogic just sets a member on itself already when it is created, but also the implementation of IsUserAdmin doesn't actually rely on any part of AppLogic's state. Would it make sense to then make a free function/static function IsElevated somewhere else that could just be used directly without multiple layers of caching and indirection? As an optimization that IsElevated function could store a static member, should you choose to.

If that free function exists somewhere sufficiently up the stack, it could also be used for ApplicationState :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW there's one of my many branches hanging around that does this. I think it's going to get looped in to #11222 when I bump that next (hopefully today, likely monday tho)

{
result = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated();
}
CATCH_LOG();
return result;
}();

return isElevated;
}

void TerminalPage::Create()
{
// Hookup the key bindings
Expand All @@ -128,19 +151,7 @@ namespace winrt::TerminalApp::implementation
_tabView = _tabRow.TabView();
_rearranging = 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
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();
const auto isElevated = IsElevated();

if (_settings.GlobalSettings().UseAcrylicInTabRow())
{
Expand Down Expand Up @@ -267,6 +278,8 @@ namespace winrt::TerminalApp::implementation
// Setup mouse vanish attributes
SystemParametersInfoW(SPI_GETMOUSEVANISH, 0, &_shouldMouseVanish, false);

_tabRow.ShowElevationShield(IsElevated() && _settings.GlobalSettings().ShowAdminShield());

// 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)
try
Expand Down Expand Up @@ -2242,6 +2255,8 @@ namespace winrt::TerminalApp::implementation
// enabled application-wide, so we don't need to check it each time we
// want to create an animation.
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.
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ namespace winrt::TerminalApp::implementation
winrt::hstring WindowIdForDisplay() const noexcept;
winrt::hstring WindowNameForDisplay() const noexcept;
bool IsQuakeWindow() const noexcept;
bool IsElevated() const noexcept;

WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);

Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" };
static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" };
static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" };
static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSources" };
static constexpr std::string_view ShowAdminShieldKey{ "showAdminShield" };

static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };

Expand Down Expand Up @@ -121,6 +122,8 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea;
globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon;
globals->_DisabledProfileSources = _DisabledProfileSources;
globals->_ShowAdminShield = _ShowAdminShield;

globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;

globals->_defaultProfile = _defaultProfile;
Expand Down Expand Up @@ -227,6 +230,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
JsonUtils::GetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);

JsonUtils::GetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield);

static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey };
for (const auto& jsonKey : bindingsKeys)
{
Expand Down Expand Up @@ -324,6 +329,7 @@ Json::Value GlobalAppSettings::ToJson() const
JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
JsonUtils::SetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
JsonUtils::SetValueForKey(json, ShowAdminShieldKey, _ShowAdminShield);
// clang-format on

json[JsonKey(ActionsKey)] = _actionMap->ToJson();
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false);
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, nullptr);
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ShowAdminShield, true);

private:
#ifdef NDEBUG
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Boolean, MinimizeToNotificationArea);
INHERITABLE_SETTING(Boolean, AlwaysShowNotificationIcon);
INHERITABLE_SETTING(IVector<String>, DisabledProfileSources);
INHERITABLE_SETTING(Boolean, ShowAdminShield);

Windows.Foundation.Collections.IMapView<String, ColorScheme> ColorSchemes();
void AddColorScheme(ColorScheme scheme);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"showTerminalTitleInTitlebar": true,
"tabWidthMode": "equal",
"tabSwitcherMode": "inOrder",
"showAdminShield": true,

// Miscellaneous
"confirmCloseAllTabs": true,
Expand Down