Merge branch 'dev/migrie/f/non-terminal-content-elevation-warning' into dev/migrie/f/632-on-warning-dialog

This commit is contained in:
Mike Griese 2021-10-28 07:04:41 -05:00
commit 88da035e8a
10 changed files with 129 additions and 36 deletions

View file

@ -6,7 +6,9 @@
#include "pch.h"
#include "AdminWarningPlaceholder.h"
#include "AdminWarningPlaceholder.g.cpp"
#include <LibraryResources.h>
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Automation::Peers;
namespace winrt::TerminalApp::implementation
{
@ -37,4 +39,37 @@ namespace winrt::TerminalApp::implementation
{
return _control;
}
// Method Description:
// - Move the focus to the cancel button by default. This has the LOAD
// BEARING side effect of also triggering Narrator to read out the
// contents of the dialog. It's unclear why doing this works, but it does.
// - Using a LayoutUpdated event to trigger the focus change when we're
// added to the UI tree did not seem to work.
// - Whoever is adding us to the UI tree is responsible for calling this!
// Arguments:
// - <none>
// Return Value:
// - <none>
void AdminWarningPlaceholder::FocusOnLaunch()
{
CancelButton().Focus(FocusState::Programmatic);
}
winrt::hstring AdminWarningPlaceholder::ControlName()
{
return RS_(L"AdminWarningPlaceholderName");
}
void AdminWarningPlaceholder::_keyUpHandler(IInspectable const& /*sender*/,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
// If the user presses escape, close the dialog (without confirming)
const auto key = e.OriginalKey();
if (key == winrt::Windows::System::VirtualKey::Escape)
{
_CancelButtonClickedHandlers(*this, e);
e.Handled(true);
}
}
}

View file

@ -1,5 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- AdminWarningPlaceholder
Abstract:
- The AdminaWarningPlaceholder is a control used to fill space in a pane and
present a warning to the user. It holds on to a real control that it should be
replaced with. It looks just like a ContentDialog, except it exists per-pane,
whereas a ContentDialog can only be added to take up the whole window.
- The caller should make sure to bind our PrimaryButtonClicked and
CancelButtonClicked events, to be informed as to which was pressed.
Author(s):
- Mike Griese - September 2021
--*/
#pragma once
@ -11,8 +28,9 @@ namespace winrt::TerminalApp::implementation
struct AdminWarningPlaceholder : AdminWarningPlaceholderT<AdminWarningPlaceholder>
{
AdminWarningPlaceholder(const winrt::Microsoft::Terminal::Control::TermControl& control, const winrt::hstring& cmdline);
void FocusOnLaunch();
winrt::Windows::UI::Xaml::Controls::UserControl Control();
winrt::hstring ControlName();
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Commandline, _PropertyChangedHandlers);
TYPED_EVENT(PrimaryButtonClicked, TerminalApp::AdminWarningPlaceholder, winrt::Windows::UI::Xaml::RoutedEventArgs);
@ -27,5 +45,7 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void _cancelButtonClick(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void _keyUpHandler(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
};
}

View file

@ -7,5 +7,6 @@ namespace TerminalApp
Windows.UI.Xaml.Data.INotifyPropertyChanged
{
String Commandline { get; };
String ControlName { get; };
}
}

View file

@ -9,6 +9,10 @@
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
AutomationProperties.AccessibilityView="Content"
AutomationProperties.IsDialog="True"
AutomationProperties.Name="{x:Bind ControlName, Mode=OneWay}"
PreviewKeyUp="_keyUpHandler"
mc:Ignorable="d">
<!--
@ -27,44 +31,60 @@
VerticalAlignment="Center">
<Border Margin="8,8,8,8"
Padding="16,8,16,8"
AllowFocusOnInteraction="True"
AutomationProperties.AccessibilityView="Raw"
AutomationProperties.IsDialog="True"
Background="{ThemeResource SystemControlBackgroundAltHighBrush}"
BorderBrush="{ThemeResource SystemAccentColor}"
BorderThickness="2,2,2,2"
CornerRadius="{ThemeResource OverlayCornerRadius}">
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="ApproveCommandlineWarningTitle"
<TextBlock x:Name="ApproveCommandlineWarningTitle"
x:Uid="ApproveCommandlineWarningTitle"
Padding="0,0,0,16"
HorizontalAlignment="Left"
FontSize="20"
FontWeight="Normal"
TextWrapping="WrapWholeWords" />
<TextBlock x:Uid="ApproveCommandlineWarningPrefixTextBlock"
<TextBlock x:Name="PrefixTextBlock"
x:Uid="ApproveCommandlineWarningPrefixTextBlock"
HorizontalAlignment="Left"
TextWrapping="WrapWholeWords" />
<TextBlock Margin="0,8,0,8"
HorizontalAlignment="Center"
FontFamily="Cascadia Code"
<TextBlock x:Name="CommandlineText"
Margin="0,16,0,16"
HorizontalAlignment="Left"
FontFamily="Cascadia Mono"
Text="{x:Bind Commandline, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<TextBlock x:Uid="ApproveCommandlineWarningSuffixTextBlock"
<TextBlock x:Name="SuffixTextBlock"
x:Uid="ApproveCommandlineWarningSuffixTextBlock"
HorizontalAlignment="Left"
TextWrapping="WrapWholeWords" />
<StackPanel HorizontalAlignment="Right"
Orientation="Horizontal">
<Grid Margin="0,8,0,8"
HorizontalAlignment="Stretch"
XYFocusKeyboardNavigation="Enabled">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="PrimaryButton"
x:Uid="ApproveCommandlineWarning_PrimaryButton"
Margin="8"
HorizontalAlignment="Right"
Grid.Column="0"
Margin="0,0,8,0"
HorizontalAlignment="Stretch"
Click="_primaryButtonClick"
IsTabStop="True"
Style="{StaticResource AccentButtonStyle}" />
<Button x:Name="CancelButton"
x:Uid="ApproveCommandlineWarning_CancelButton"
HorizontalAlignment="Right"
Click="_cancelButtonClick" />
</StackPanel>
Grid.Column="1"
HorizontalAlignment="Stretch"
Click="_cancelButtonClick"
IsTabStop="True" />
</Grid>
</StackPanel>
</Border>
</Grid>

View file

@ -144,7 +144,7 @@ NewTerminalArgs Pane::GetTerminalArgsForPane() const
args.Profile(controlSettings.ProfileName());
// If we know the user's working directory use it instead of the profile.
if (const auto dir = _control.WorkingDirectory(); !dir.empty())
if (const auto dir = termControl.WorkingDirectory(); !dir.empty())
{
args.StartingDirectory(dir);
}

View file

@ -504,21 +504,24 @@
<data name="MultiLinePasteDialog.Title" xml:space="preserve">
<value>Warning</value>
</data>
<data name="ApproveCommandlineWarning_CancelButton.Content" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ApproveCommandlineWarningPrefixTextBlock.Text" xml:space="preserve">
<value>You are about to execute the following commandline:</value>
<value>You are about to execute the following command-line:</value>
</data>
<data name="ApproveCommandlineWarningSuffixTextBlock.Text" xml:space="preserve">
<value>Do you wish to continue?</value>
</data>
<data name="ApproveCommandlineWarning_PrimaryButton.Content" xml:space="preserve">
<value>Allow Commandline</value>
<value>Allow command-line</value>
</data>
<data name="ApproveCommandlineWarning_CancelButton.Content" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="ApproveCommandlineWarningTitle.Text" xml:space="preserve">
<value>Warning</value>
</data>
<data name="AdminWarningPlaceholderName" xml:space="preserve">
<value>Elevated command-line warning</value>
</data>
<data name="CommandPalette_SearchBox.PlaceholderText" xml:space="preserve">
<value>Type a command name...</value>
</data>

View file

@ -315,6 +315,17 @@ namespace winrt::TerminalApp::implementation
// Split (auto) with the debug tap.
newTabImpl->SplitPane(SplitDirection::Automatic, 0.5f, profile, newControl);
}
if (doAdminWarning)
{
// We know this is safe - we literally just added the
// AdminWarningPlaceholder as the controlToAdd like 20 lines up.
//
// Focus the warning here. The LayoutUpdated within the dialog
// itself isn't good enough. That, for some reason, fires _before_
// the dialog is in the UI tree, which is useless for us.
controlToAdd.try_as<implementation::AdminWarningPlaceholder>()->FocusOnLaunch();
}
}
// Method Description:

View file

@ -1919,7 +1919,8 @@ namespace winrt::TerminalApp::implementation
WUX::Controls::UserControl controlToAdd{ newControl };
const auto& cmdline{ controlSettings.DefaultSettings().Commandline() };
if (_shouldPromptForCommandline(cmdline))
const auto doAdminWarning{ _shouldPromptForCommandline(cmdline) };
if (doAdminWarning)
{
auto warningControl{ winrt::make_self<implementation::AdminWarningPlaceholder>(newControl, cmdline) };
warningControl->PrimaryButtonClicked({ get_weak(), &TerminalPage::_adminWarningPrimaryClicked });
@ -1944,6 +1945,17 @@ namespace winrt::TerminalApp::implementation
activeControl.Focus(FocusState::Programmatic);
}
}
if (doAdminWarning)
{
// We know this is safe - we literally just added the
// AdminWarningPlaceholder as the controlToAdd like 20 lines up.
//
// Focus the warning here. The LayoutUpdated within the dialog
// itself isn't good enough. That, for some reason, fires _before_
// the dialog is in the UI tree, which is useless for us.
controlToAdd.try_as<implementation::AdminWarningPlaceholder>()->FocusOnLaunch();
}
}
CATCH_LOG();
}

View file

@ -62,6 +62,7 @@
<!-- Must be Stdcall on all platforms to resolve _ObjectStublessClient3 -->
<PreprocessorDefinitions>REGISTER_PROXY_DLL;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<BufferSecurityCheck>false</BufferSecurityCheck>
<SDLCheck>false</SDLCheck>
<ForcedIncludeFiles>nodefaultlib_shim.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>

View file

@ -1,18 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include <guiddef.h>
#if !defined(_M_IX86) && !defined(_M_X64)
// ARM64 doesn't define a (__builtin_)memcmp function without CRT,
// but we need one to compile IID_GENERIC_CHECK_IID.
// Luckily we only ever use memcmp for IIDs.
#pragma function(memcmp)
inline int memcmp(const IID* a, const IID* b, size_t count)
{
(void)(count);
return 1 - InlineIsEqualGUID(a, b);
}
#endif
#define memcmp(a, b, c) (!InlineIsEqualGUID(a, b))