Compare commits

...

45 Commits

Author SHA1 Message Date
Mike Griese
2dfebce150 this is everything to rename the page to Compatibility 2023-07-06 14:16:35 -05:00
Mike Griese
8c3e03670e more renames 2023-07-06 14:09:11 -05:00
Mike Griese
9c8c174753 some file renames 2023-07-06 14:08:10 -05:00
Mike Griese
3b079735ba start renaming some stuff so git doesn't totally explode 2023-07-06 14:03:12 -05:00
Mike Griese
741b7732a1 This needs to go way earlier in the stack of PRs
(cherry picked from commit d3e572d8fd)
2023-07-06 10:20:44 -05:00
Mike Griese
2cf9f412d2 Merge branch 'main' into dev/migrie/fhl-2023/pwsh-autocomplete-demo 2023-07-05 13:33:45 -05:00
Mike Griese
fb40b5d6b5 lazy loading for fun and profit 2023-05-31 13:54:28 -05:00
Mike Griese
3fc364cf8a Merge branch 'main' into dev/migrie/fhl-2023/pwsh-autocomplete-demo 2023-05-31 13:38:57 -05:00
Mike Griese
057098ea6f Merge remote-tracking branch 'origin/main' into dev/migrie/fhl-2023/pwsh-autocomplete-demo 2023-04-05 10:08:16 -05:00
Mike Griese
11916fd623 Merge remote-tracking branch 'origin/main' into dev/migrie/fhl-2023/pwsh-autocomplete-demo 2023-03-24 16:11:10 -05:00
Mike Griese
dd5458cf8c spell
(cherry picked from commit 62fb61d048)
2023-03-21 11:08:30 -05:00
Mike Griese
19c1ed90ed This fixes a previewing issue, all the way back in the first PR
(cherry picked from commit 0c19591d48)
2023-03-21 11:08:08 -05:00
Mike Griese
6c778a69cd yea no I always run the tests 2023-03-20 17:26:05 -05:00
Mike Griese
b0964692ed austin mode 2023-03-20 13:26:52 -05:00
Mike Griese
36b676a16c Add a setting to opt in, because feature flags are imprecise 2023-03-20 12:53:39 -05:00
Mike Griese
28555a6faa Merge remote-tracking branch 'origin/main' into dev/migrie/fhl-2023/pwsh-autocomplete-demo 2023-03-20 11:51:43 -05:00
Mike Griese
22c94bf10d spell 2023-03-10 14:57:56 -06:00
Mike Griese
cd2db82515 Merge branch 'main' into dev/migrie/fhl-2023/pwsh-autocomplete-demo 2023-03-10 14:57:31 -06:00
Mike Griese
20f5651224 final cleanup for review 2023-03-01 11:07:24 -06:00
Mike Griese
173a830339 Finish detaching it from the popup
(cherry picked from commit a172f53597)
2023-03-01 08:23:39 -06:00
Mike Griese
e544871893 very confident we can get all the logic into the sxnui
(cherry picked from commit 57a53279ae)
2023-03-01 08:23:32 -06:00
Mike Griese
e2cc27889a POC: We can take it out of the Popup and have it still work
(cherry picked from commit 5defde545f)
2023-03-01 08:23:16 -06:00
Mike Griese
36b5759604 [PARENT] lmao I deleted the line that sends the inpu :facepalm" 2023-02-24 10:43:30 -06:00
Mike Griese
84a41b4504 cleanup _for review_? 2023-02-23 16:34:16 -06:00
Mike Griese
7988d89c08 code cleanup 2023-02-23 14:08:07 -06:00
Mike Griese
a3c4776355 clamp horizontally 2023-02-23 14:01:36 -06:00
Mike Griese
4516b4b1b3 Properly account for the position of panes when opening the menu 2023-02-22 14:51:47 -06:00
Mike Griese
f5909d9baa Open in different directions based on available space 2023-02-22 13:56:01 -06:00
Mike Griese
8feb9098b9 bottom-up mode is basically done 2023-02-21 15:52:39 -06:00
Mike Griese
d94183b897 icons are _slick_ 2023-02-21 14:25:58 -06:00
Mike Griese
2c66c32f97 bottoms up bottoms up 2023-02-21 11:20:03 -06:00
Mike Griese
ff5eead9ea Very important that the backspaces are trimmed from the preview 2023-02-21 10:25:55 -06:00
Mike Griese
026f342bc5 Merge remote-tracking branch 'origin/dev/migrie/f/3121-wE-dOnT-hAvE-dEv-DaYs' into dev/migrie/fhl-2023/pwsh-autocomplete-demo 2023-02-21 10:00:20 -06:00
Mike Griese
48e7348f5c small updates to the protocol 2023-02-16 13:04:13 -06:00
Mike Griese
e785bfc8bb Merge branch 'main' into dev/migrie/f/12861-preview-input 2023-02-16 13:02:40 -06:00
Mike Griese
985fcdbdb6 better UX for typing 2023-02-12 15:37:36 -06:00
Mike Griese
b0fa972ec1 make the menu mode compact, and remove the search box 2023-02-12 11:07:00 -06:00
Mike Griese
f361b6c879 lots of removal of dead code from the sxnui 2023-02-10 06:55:16 -06:00
Mike Griese
7404dc3d35 zhu li, do the thing 2023-02-10 06:02:03 -06:00
Mike Griese
c97ac66d5d resart with fresh plumbing 2023-02-09 06:31:44 -06:00
Dustin L. Howett
ccfc83443b Migrate spelling-0.0.21 changes from main 2022-04-29 06:55:15 -05:00
Mike Griese
0bda66fc2f a comment I missed 2022-04-29 06:55:15 -05:00
Mike Griese
d3b5533a1e fix remaining bugs 2022-04-29 06:22:48 -05:00
Mike Griese
1449088e80 bugfixes for the demo 2022-04-28 16:17:21 -05:00
Mike Griese
c96799c6e9 Preview the input via the TSF input control. This is awesome, and should go into main 2022-04-28 16:14:51 -05:00
57 changed files with 2207 additions and 67 deletions

View File

@@ -95,6 +95,7 @@ slnt
Sos
ssh
stakeholders
sxn
timeline
timelines
timestamped

View File

@@ -315,6 +315,7 @@ CPLINFO
cplusplus
CPPCORECHECK
cppcorecheckrules
cpprest
cpprestsdk
cppwinrt
CProc
@@ -1452,6 +1453,7 @@ PPEB
ppf
ppguid
ppidl
pplx
PPROC
ppropvar
ppsi
@@ -2132,6 +2134,7 @@ WDDMCONSOLECONTEXT
wdm
webpage
websites
websockets
wekyb
wex
wextest

View File

@@ -50,6 +50,7 @@ namespace winrt::TerminalApp::implementation
{
case ShortcutAction::SetColorScheme:
case ShortcutAction::AdjustOpacity:
case ShortcutAction::SendInput:
{
_RunRestorePreviews();
break;
@@ -140,6 +141,23 @@ namespace winrt::TerminalApp::implementation
});
}
void TerminalPage::_PreviewSendInput(const Settings::Model::SendInputArgs& args)
{
const auto backup = _restorePreviewFuncs.empty();
_ApplyToActiveControls([&](const auto& control) {
const auto& str{ args.Input() };
control.PreviewInput(str);
if (backup)
{
_restorePreviewFuncs.emplace_back([=]() {
// On dismiss:
control.PreviewInput(L"");
});
}
});
}
void TerminalPage::_PreviewAction(const Settings::Model::ActionAndArgs& args)
{
switch (args.Action())
@@ -150,6 +168,9 @@ namespace winrt::TerminalApp::implementation
case ShortcutAction::AdjustOpacity:
_PreviewAdjustOpacity(args.Args().try_as<AdjustOpacityArgs>());
break;
case ShortcutAction::SendInput:
_PreviewSendInput(args.Args().try_as<SendInputArgs>());
break;
}
// GH#9818 Other ideas for actions that could be preview-able:

View File

@@ -225,15 +225,24 @@ namespace winrt::TerminalApp::implementation
void CommandPalette::_selectedCommandChanged(const IInspectable& /*sender*/,
const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
{
const auto currentlyVisible{ Visibility() == Visibility::Visible };
const auto selectedCommand = _filteredActionsView().SelectedItem();
const auto filteredCommand{ selectedCommand.try_as<winrt::TerminalApp::FilteredCommand>() };
if (_currentMode == CommandPaletteMode::TabSwitchMode)
{
_switchToTab(filteredCommand);
}
else if (_currentMode == CommandPaletteMode::ActionMode && filteredCommand != nullptr)
else if (_currentMode == CommandPaletteMode::ActionMode &&
currentlyVisible)
{
if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
// If we don't have a selected command, then end any previews we
// might currently be showing.
if (filteredCommand == nullptr)
{
_PreviewActionHandlers(*this, nullptr);
}
else if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
{
_PreviewActionHandlers(*this, actionPaletteItem.Command());
}
@@ -1083,7 +1092,9 @@ namespace winrt::TerminalApp::implementation
{
std::copy(begin(commandsToFilter), end(commandsToFilter), std::back_inserter(actions));
}
else if (_currentMode == CommandPaletteMode::TabSearchMode || _currentMode == CommandPaletteMode::ActionMode || _currentMode == CommandPaletteMode::CommandlineMode)
else if (_currentMode == CommandPaletteMode::TabSearchMode ||
_currentMode == CommandPaletteMode::ActionMode ||
_currentMode == CommandPaletteMode::CommandlineMode)
{
for (const auto& action : commandsToFilter)
{

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,144 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "FilteredCommand.h"
#include "SuggestionsControl.g.h"
#include "AppCommandlineArgs.h"
#include <til/hash.h>
// fwdecl unittest classes
namespace TerminalAppLocalTests
{
class TabTests;
};
namespace winrt::TerminalApp::implementation
{
struct SuggestionsControl : SuggestionsControlT<SuggestionsControl>
{
SuggestionsControl();
Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::FilteredCommand> FilteredActions();
void SetCommands(const Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::Command>& actions);
void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap);
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
void SelectNextItem(const bool moveDown);
void ScrollPageUp();
void ScrollPageDown();
void ScrollToTop();
void ScrollToBottom();
Windows::UI::Xaml::FrameworkElement SelectedItem();
TerminalApp::SuggestionsMode Mode() const;
void Mode(TerminalApp::SuggestionsMode mode);
void Anchor(Windows::Foundation::Point anchor, Windows::Foundation::Size space, float characterHeight);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ControlName, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ParentCommandName, _PropertyChangedHandlers);
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ParsedCommandLineText, _PropertyChangedHandlers);
TYPED_EVENT(SwitchToTabRequested, winrt::TerminalApp::SuggestionsControl, winrt::TerminalApp::TabBase);
TYPED_EVENT(CommandLineExecutionRequested, winrt::TerminalApp::SuggestionsControl, winrt::hstring);
TYPED_EVENT(DispatchCommandRequested, winrt::TerminalApp::SuggestionsControl, Microsoft::Terminal::Settings::Model::Command);
TYPED_EVENT(PreviewAction, Windows::Foundation::IInspectable, Microsoft::Terminal::Settings::Model::Command);
private:
struct winrt_object_hash
{
size_t operator()(const auto& value) const noexcept
{
return til::hash(winrt::get_abi(value));
}
};
friend struct SuggestionsControlT<SuggestionsControl>; // for Xaml to bind events
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _allCommands{ nullptr };
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _currentNestedCommands{ nullptr };
Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::FilteredCommand> _filteredActions{ nullptr };
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _nestedActionStack{ nullptr };
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _commandsToFilter();
TerminalApp::SuggestionsMode _mode{ TerminalApp::SuggestionsMode::Palette };
TerminalApp::SuggestionsDirection _direction{ TerminalApp::SuggestionsDirection::TopDown };
bool _lastFilterTextWasEmpty{ true };
Windows::Foundation::Point _anchor;
Windows::Foundation::Size _space;
void _filterTextChanged(const Windows::Foundation::IInspectable& sender,
const Windows::UI::Xaml::RoutedEventArgs& args);
void _previewKeyDownHandler(const Windows::Foundation::IInspectable& sender,
const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
void _keyUpHandler(const Windows::Foundation::IInspectable& sender,
const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
void _selectedCommandChanged(const Windows::Foundation::IInspectable& sender,
const Windows::UI::Xaml::RoutedEventArgs& args);
void _updateUIForStackChange();
void _rootPointerPressed(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);
void _lostFocusHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
void _backdropPointerPressed(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);
void _listItemClicked(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::ItemClickEventArgs& e);
void _listItemSelectionChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& e);
void _moveBackButtonClicked(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs&);
void _updateFilteredActions();
void _updateCurrentNestedCommands(const winrt::Microsoft::Terminal::Settings::Model::Command& parentCommand);
std::vector<winrt::TerminalApp::FilteredCommand> _collectFilteredActions();
void _close();
void _switchToMode();
void _setDirection(TerminalApp::SuggestionsDirection direction);
std::wstring _getTrimmedInput();
Microsoft::Terminal::Settings::Model::IActionMapView _actionMap{ nullptr };
winrt::Windows::UI::Xaml::Controls::ListView::SizeChanged_revoker _sizeChangedRevoker;
void _dispatchCommand(const winrt::TerminalApp::FilteredCommand& command);
static std::optional<winrt::TerminalApp::FilteredCommand> _buildCommandLineCommand(const winrt::hstring& commandLine);
void _dismissPalette();
void _scrollToIndex(uint32_t index);
uint32_t _getNumVisibleItems();
void _choosingItemContainer(const Windows::UI::Xaml::Controls::ListViewBase& sender, const Windows::UI::Xaml::Controls::ChoosingItemContainerEventArgs& args);
void _containerContentChanging(const Windows::UI::Xaml::Controls::ListViewBase& sender, const Windows::UI::Xaml::Controls::ContainerContentChangingEventArgs& args);
winrt::TerminalApp::PaletteItemTemplateSelector _itemTemplateSelector{ nullptr };
std::unordered_map<Windows::UI::Xaml::DataTemplate, std::unordered_set<Windows::UI::Xaml::Controls::Primitives::SelectorItem, winrt_object_hash>, winrt_object_hash> _listViewItemsCache;
Windows::UI::Xaml::DataTemplate _listItemTemplate;
friend class TerminalAppLocalTests::TabTests;
};
}
namespace winrt::TerminalApp::factory_implementation
{
BASIC_FACTORY(SuggestionsControl);
}

View File

@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "TabBase.idl";
import "IDirectKeyListener.idl";
import "HighlightedTextControl.idl";
import "FilteredCommand.idl";
namespace TerminalApp
{
enum SuggestionsMode
{
Palette = 0,
Menu,
// Inline,
};
enum SuggestionsDirection {
TopDown,
BottomUp
};
[default_interface] runtimeclass SuggestionsControl : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged, IDirectKeyListener
{
SuggestionsControl();
String NoMatchesText { get; };
String SearchBoxPlaceholderText { get; };
String ControlName { get; };
String ParentCommandName { get; };
String ParsedCommandLineText { get; };
Windows.UI.Xaml.FrameworkElement SelectedItem { get; };
Windows.Foundation.Collections.IObservableVector<FilteredCommand> FilteredActions { get; };
SuggestionsMode Mode { get; set; };
void SetCommands(Windows.Foundation.Collections.IVector<Microsoft.Terminal.Settings.Model.Command> actions);
void SetActionMap(Microsoft.Terminal.Settings.Model.IActionMapView actionMap);
void SelectNextItem(Boolean moveDown);
void Anchor(Windows.Foundation.Point anchor, Windows.Foundation.Size space, Single characterHeight);
event Windows.Foundation.TypedEventHandler<SuggestionsControl, Microsoft.Terminal.Settings.Model.Command> DispatchCommandRequested;
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Command> PreviewAction;
}
}

View File

@@ -0,0 +1,328 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<UserControl x:Class="TerminalApp.SuggestionsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
AllowFocusOnInteraction="True"
AutomationProperties.Name="{x:Bind ControlName, Mode=OneWay}"
IsTabStop="True"
LostFocus="_lostFocusHandler"
PointerPressed="_rootPointerPressed"
PreviewKeyDown="_previewKeyDownHandler"
PreviewKeyUp="_keyUpHandler"
TabNavigation="Cycle"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<!-- This creates an instance of our CommandKeyChordVisibilityConverter we can reference below -->
<local:EmptyStringVisibilityConverter x:Key="CommandKeyChordVisibilityConverter" />
<local:EmptyStringVisibilityConverter x:Key="ParsedCommandLineTextVisibilityConverter" />
<local:EmptyStringVisibilityConverter x:Key="ParentCommandVisibilityConverter" />
<model:IconPathConverter x:Key="IconSourceConverter" />
<DataTemplate x:Key="ListItemTemplate"
x:DataType="local:FilteredCommand">
<ListViewItem Height="32"
MinHeight="0"
Padding="16,0,12,0"
HorizontalContentAlignment="Stretch"
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}"
AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}"
FontSize="12" />
</DataTemplate>
<DataTemplate x:Key="GeneralItemTemplate"
x:DataType="local:FilteredCommand">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<!-- icon -->
<ColumnDefinition Width="Auto" />
<!-- command label -->
<ColumnDefinition Width="*" />
<!-- key chord -->
<ColumnDefinition Width="16" />
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"
Width="16"
Height="16"
Content="{x:Bind Item.ResolvedIcon, Mode=OneWay}" />
<local:HighlightedTextControl Grid.Column="1"
HorizontalAlignment="Left"
Text="{x:Bind HighlightedName, Mode=OneWay}" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="NestedItemTemplate"
x:DataType="local:FilteredCommand">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<!-- icon -->
<ColumnDefinition Width="Auto" />
<!-- command label -->
<ColumnDefinition Width="*" />
<!-- key chord -->
<ColumnDefinition Width="16" />
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"
Width="16"
Height="16"
Content="{x:Bind Item.ResolvedIcon, Mode=OneWay}" />
<local:HighlightedTextControl Grid.Column="1"
HorizontalAlignment="Left"
Text="{x:Bind HighlightedName, Mode=OneWay}" />
<!--
The block for the key chord is only visible
when there's actual text set as the label. See
CommandKeyChordVisibilityConverter for details.
We're setting the accessibility view on the
border and text block to Raw because otherwise,
Narrator will read out the key chord. Problem is,
it already did that because it was the list item's
"AcceleratorKey". It's redundant.
-->
<Border Grid.Column="2"
Padding="2,0,2,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Style="{ThemeResource KeyChordBorderStyle}"
Visibility="{x:Bind Item.KeyChordText, Mode=OneWay, Converter={StaticResource CommandKeyChordVisibilityConverter}}">
<TextBlock AutomationProperties.AccessibilityView="Raw"
FontSize="12"
Style="{ThemeResource KeyChordTextBlockStyle}"
Text="{x:Bind Item.KeyChordText, Mode=OneWay}" />
</Border>
<FontIcon Grid.Column="2"
HorizontalAlignment="Right"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="12"
Glyph="&#xE76C;" />
</Grid>
</DataTemplate>
<local:PaletteItemTemplateSelector x:Key="PaletteItemTemplateSelector"
GeneralItemTemplate="{StaticResource GeneralItemTemplate}"
NestedItemTemplate="{StaticResource NestedItemTemplate}" />
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="2" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
</Style>
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="2" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
</Style>
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border" />
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock" />
<!-- ParsedCommandLineText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border" />
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="6*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Grid x:Name="_backdrop"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
Grid.ColumnSpan="3"
MaxWidth="300"
MaxHeight="300"
Margin="0"
Padding="0,8,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{ThemeResource FlyoutPresenterBackground}"
BorderBrush="{ThemeResource FlyoutBorderThemeBrush}"
BorderThickness="{ThemeResource FlyoutBorderThemeThickness}"
CornerRadius="{ThemeResource OverlayCornerRadius}"
PointerPressed="_backdropPointerPressed"
Shadow="{StaticResource SharedShadow}"
Translation="0,0,32">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<!-- Top-down _searchBox -->
<RowDefinition Height="Auto" />
<!-- Top-down ParentCommandName -->
<RowDefinition Height="Auto" />
<!-- Top-down UNUSED???????? -->
<RowDefinition Height="*" />
<!-- _filteredActionsView -->
<RowDefinition Height="Auto" />
<!-- bottom-up _searchBox -->
</Grid.RowDefinitions>
<TextBox x:Name="_searchBox"
Grid.Row="0"
Margin="8,0,8,8"
Padding="18,8,8,8"
IsSpellCheckEnabled="False"
PlaceholderText="{x:Bind SearchBoxPlaceholderText, Mode=OneWay}"
Text=""
TextChanged="_filterTextChanged"
Visibility="Collapsed" />
<StackPanel Grid.Row="1"
Margin="8,0,8,8"
Orientation="Horizontal"
Visibility="{x:Bind ParentCommandName, Mode=OneWay, Converter={StaticResource ParentCommandVisibilityConverter}}">
<Button x:Name="_parentCommandBackButton"
x:Uid="ParentCommandBackButton"
VerticalAlignment="Center"
Click="_moveBackButtonClicked"
ClickMode="Press">
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="11"
Glyph="&#xE76b;" />
</Button>
<TextBlock x:Name="_parentCommandText"
Padding="16,4"
VerticalAlignment="Center"
FontStyle="Italic"
Text="{x:Bind ParentCommandName, Mode=OneWay}" />
</StackPanel>
<Border Grid.Row="1"
Margin="8,0,8,8"
Padding="16,12"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Style="{ThemeResource ParsedCommandLineBorderStyle}"
Visibility="{x:Bind ParsedCommandLineText, Mode=OneWay, Converter={StaticResource ParsedCommandLineTextVisibilityConverter}}">
<ScrollViewer MaxHeight="200"
VerticalScrollBarVisibility="Auto">
<TextBlock FontStyle="Italic"
Text="{x:Bind ParsedCommandLineText, Mode=OneWay}"
TextWrapping="Wrap" />
</ScrollViewer>
</Border>
<Border x:Name="_noMatchesText"
Grid.Row="3"
Height="36"
Margin="8,0,8,8"
Visibility="Collapsed">
<TextBlock Padding="12,0"
VerticalAlignment="Center"
FontStyle="Italic"
Text="{x:Bind NoMatchesText, Mode=OneWay}" />
</Border>
<ListView x:Name="_filteredActionsView"
Grid.Row="3"
Padding="4,-2,4,6"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AllowDrop="False"
CanReorderItems="False"
ChoosingItemContainer="_choosingItemContainer"
ContainerContentChanging="_containerContentChanging"
IsItemClickEnabled="True"
ItemClick="_listItemClicked"
ItemsSource="{x:Bind FilteredActions}"
SelectionChanged="_listItemSelectionChanged"
SelectionMode="Single" />
</Grid>
</Grid>
</UserControl>

View File

@@ -68,6 +68,9 @@
<Page Include="CommandPalette.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="SuggestionsControl.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
@@ -159,6 +162,9 @@
<DependentUpon>TerminalWindow.idl</DependentUpon>
</ClInclude>
<ClInclude Include="Toast.h" />
<ClInclude Include="SuggestionsControl.h">
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
</ClInclude>
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
@@ -262,6 +268,9 @@
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="Toast.cpp" />
<ClCompile Include="SuggestionsControl.cpp">
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
</ClCompile>
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
@@ -325,6 +334,10 @@
<DependentUpon>CommandPalette.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="SuggestionsControl.idl">
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="FilteredCommand.idl" />
<Midl Include="EmptyStringVisibilityConverter.idl" />
</ItemGroup>

View File

@@ -1457,6 +1457,11 @@ namespace winrt::TerminalApp::implementation
{
CommandPaletteElement().Visibility(Visibility::Collapsed);
}
if (_suggestionsControlIs(Visibility::Visible) &&
cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
{
SuggestionsElement().Visibility(Visibility::Collapsed);
}
// Let's assume the user has bound the dead key "^" to a sendInput command that sends "b".
// If the user presses the two keys "^a" it'll produce "bâ", despite us marking the key event as handled.
@@ -1645,6 +1650,8 @@ namespace winrt::TerminalApp::implementation
term.ShowWindowChanged({ get_weak(), &TerminalPage::_ShowWindowChangedHandler });
term.MenuChanged({ get_weak(), &TerminalPage::_ControlMenuChangedHandler });
term.ContextMenu().Opening({ this, &TerminalPage::_ContextMenuOpened });
term.SelectionContextMenu().Opening({ this, &TerminalPage::_SelectionMenuOpened });
}
@@ -1816,6 +1823,37 @@ namespace winrt::TerminalApp::implementation
return p;
}
SuggestionsControl TerminalPage::LoadSuggestionsUI()
{
if (const auto p = SuggestionsElement())
{
return p;
}
return _loadSuggestionsElementSlowPath();
}
bool TerminalPage::_suggestionsControlIs(WUX::Visibility visibility)
{
const auto p = SuggestionsControl();
return p && p.Visibility() == visibility;
}
SuggestionsControl TerminalPage::_loadSuggestionsElementSlowPath()
{
const auto p = FindName(L"SuggestionsElement").as<SuggestionsControl>();
p.RegisterPropertyChangedCallback(UIElement::VisibilityProperty(), [this](auto&&, auto&&) {
if (SuggestionsElement().Visibility() == Visibility::Collapsed)
{
_FocusActiveControl(nullptr, nullptr);
}
});
p.DispatchCommandRequested({ this, &TerminalPage::_OnDispatchCommandRequested });
p.PreviewAction({ this, &TerminalPage::_PreviewActionHandler });
return p;
}
// Method Description:
// - Warn the user that they are about to close all open windows, then
// signal that we want to close everything.
@@ -2777,8 +2815,9 @@ namespace winrt::TerminalApp::implementation
// Arguments:
// - sender (not used)
// - args: the arguments specifying how to set the display status to ShowWindow for our window handle
void TerminalPage::_ShowWindowChangedHandler(const IInspectable& /*sender*/, const Microsoft::Terminal::Control::ShowWindowArgs args)
winrt::fire_and_forget TerminalPage::_ShowWindowChangedHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::ShowWindowArgs args)
{
co_await resume_foreground(Dispatcher());
_ShowWindowChangedHandlers(*this, args);
}
@@ -4579,6 +4618,85 @@ namespace winrt::TerminalApp::implementation
_updateThemeColors();
}
winrt::fire_and_forget TerminalPage::_ControlMenuChangedHandler(const IInspectable /*sender*/,
const MenuChangedEventArgs args)
{
if constexpr (!Feature_ShellCompletions::IsEnabled())
{
co_return;
}
// User must explicitly opt-in on Preview builds
if (!_settings.GlobalSettings().EnableShellCompletionMenu())
{
co_return;
}
auto weakThis{ get_weak() };
co_await winrt::resume_background();
if (const auto& page{ weakThis.get() })
{
// `this` is safe to use
// Parse the json
try
{
auto commandsCollection = Command::ParsePowerShellMenuComplete(args.MenuJson(),
args.ReplacementLength());
// Open the Suggestions UI with the commands from the control
_OpenSuggestions(commandsCollection, SuggestionsMode::Menu);
}
CATCH_LOG();
}
}
winrt::fire_and_forget TerminalPage::_OpenSuggestions(IVector<Command> commandsCollection,
winrt::TerminalApp::SuggestionsMode mode)
{
if (commandsCollection == nullptr)
{
co_return;
}
if (commandsCollection.Size() == 0)
{
if (const auto p = SuggestionsElement())
{
p.Visibility(Visibility::Collapsed);
}
co_return;
}
auto weakThis{ get_weak() };
co_await wil::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal);
const auto& page{ weakThis.get() };
if (!page)
{
co_return;
}
// page is now keeping `this` alive to use safely
const auto& control{ _GetActiveControl() };
if (!control)
{
co_return;
}
const auto& sxnUi{ LoadSuggestionsUI() };
sxnUi.Mode(mode);
sxnUi.SetCommands(commandsCollection);
sxnUi.Visibility(commandsCollection.Size() > 0 ? Visibility::Visible : Visibility::Collapsed);
const auto characterSize{ control.CharacterDimensions() };
// This is in control-relative space. We'll need to convert it to page-relative space.
const til::point cursorPos{ control.CursorPositionInDips() };
const auto controlTransform = control.TransformToVisual(this->Root());
const til::point controlOrigin{ til::math::rounding, controlTransform.TransformPoint(Windows::Foundation::Point{ 0, 0 }) };
const til::point realCursorPos = controlOrigin + cursorPos;
const til::size windowDimensions{ til::math::rounding, ActualWidth(), ActualHeight() };
sxnUi.Anchor(realCursorPos.to_winrt_point(), windowDimensions.to_winrt_size(), characterSize.Height);
}
void TerminalPage::_ContextMenuOpened(const IInspectable& sender,
const IInspectable& /*args*/)
{

View File

@@ -117,6 +117,8 @@ namespace winrt::TerminalApp::implementation
winrt::hstring ApplicationVersion();
CommandPalette LoadCommandPalette();
SuggestionsControl LoadSuggestionsUI();
winrt::fire_and_forget RequestQuit();
winrt::fire_and_forget CloseWindow(bool bypassDialog);
@@ -278,6 +280,8 @@ namespace winrt::TerminalApp::implementation
__declspec(noinline) CommandPalette _loadCommandPaletteSlowPath();
bool _commandPaletteIs(winrt::Windows::UI::Xaml::Visibility visibility);
__declspec(noinline) SuggestionsControl _loadSuggestionsElementSlowPath();
bool _suggestionsControlIs(winrt::Windows::UI::Xaml::Visibility visibility);
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowDialogHelper(const std::wstring_view& name);
@@ -479,6 +483,8 @@ namespace winrt::TerminalApp::implementation
void _RunRestorePreviews();
void _PreviewColorScheme(const Microsoft::Terminal::Settings::Model::SetColorSchemeArgs& args);
void _PreviewAdjustOpacity(const Microsoft::Terminal::Settings::Model::AdjustOpacityArgs& args);
void _PreviewSendInput(const Microsoft::Terminal::Settings::Model::SendInputArgs& args);
winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs _lastPreviewedAction{ nullptr };
std::vector<std::function<void()>> _restorePreviewFuncs{};
@@ -511,7 +517,11 @@ namespace winrt::TerminalApp::implementation
void _updateAllTabCloseButtons(const winrt::TerminalApp::TabBase& focusedTab);
void _updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
void _ShowWindowChangedHandler(const IInspectable& sender, const winrt::Microsoft::Terminal::Control::ShowWindowArgs args);
winrt::fire_and_forget _ControlMenuChangedHandler(const winrt::Windows::Foundation::IInspectable sender, const winrt::Microsoft::Terminal::Control::MenuChangedEventArgs args);
winrt::fire_and_forget _OpenSuggestions(Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::Command> commandsCollection, winrt::TerminalApp::SuggestionsMode mode);
winrt::fire_and_forget _ShowWindowChangedHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::ShowWindowArgs args);
winrt::fire_and_forget _windowPropertyChanged(const IInspectable& sender, const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
void _onTabDragStarting(const winrt::Microsoft::UI::Xaml::Controls::TabView& sender, const winrt::Microsoft::UI::Xaml::Controls::TabViewTabDragStartingEventArgs& e);

View File

@@ -175,6 +175,14 @@
PreviewKeyDown="_KeyDownHandler"
Visibility="Collapsed" />
<local:SuggestionsControl x:Name="SuggestionsElement"
Grid.Row="2"
HorizontalAlignment="Left"
VerticalAlignment="Top"
x:Load="False"
PreviewKeyDown="_KeyDownHandler"
Visibility="Collapsed" />
<!--
A TeachingTip with IsLightDismissEnabled="True" will immediately
dismiss itself if the window is unfocused (In Xaml Islands). This is

View File

@@ -119,6 +119,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto pfnPlayMidiNote = std::bind(&ControlCore::_terminalPlayMidiNote, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
_terminal->SetPlayMidiNoteCallback(pfnPlayMidiNote);
auto pfnMenuChanged = std::bind(&ControlCore::_terminalMenuChanged, this, std::placeholders::_1, std::placeholders::_2);
_terminal->MenuChangedCallback(pfnMenuChanged);
// MSFT 33353327: Initialize the renderer in the ctor instead of Initialize().
// We need the renderer to be ready to accept new engines before the SwapChainPanel is ready to go.
// If we wait, a screen reader may try to get the AutomationPeer (aka the UIA Engine), and we won't be able to attach
@@ -1447,10 +1450,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
viewHeight,
bufferSize) };
if (_inUnitTests) [[unlikely]]
{
_ScrollPositionChangedHandlers(*this, update);
}
if (_inUnitTests)
[[unlikely]]
{
_ScrollPositionChangedHandlers(*this, update);
}
else
{
const auto shared = _shared.lock_shared();
@@ -2228,6 +2232,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void ControlCore::_terminalMenuChanged(std::wstring_view menuJson,
unsigned int replaceLength)
{
auto args = winrt::make_self<MenuChangedEventArgs>(winrt::hstring{ menuJson },
replaceLength);
_MenuChangedHandlers(*this, *args);
}
void ControlCore::_selectSpan(til::point_span s)
{
const auto bufferSize{ _terminal->GetTextBuffer().GetSize() };

View File

@@ -258,6 +258,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TYPED_EVENT(ShowWindowChanged, IInspectable, Control::ShowWindowArgs);
TYPED_EVENT(UpdateSelectionMarkers, IInspectable, Control::UpdateSelectionMarkersEventArgs);
TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
TYPED_EVENT(MenuChanged, IInspectable, Control::MenuChangedEventArgs);
TYPED_EVENT(CloseTerminalRequested, IInspectable, IInspectable);
TYPED_EVENT(RestartTerminalRequested, IInspectable, IInspectable);
@@ -347,6 +349,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _terminalPlayMidiNote(const int noteNumber,
const int velocity,
const std::chrono::microseconds duration);
void _terminalMenuChanged(std::wstring_view menuJson, unsigned int replaceLength);
#pragma endregion
MidiAudio _midiAudio;

View File

@@ -175,5 +175,8 @@ namespace Microsoft.Terminal.Control
event Windows.Foundation.TypedEventHandler<Object, Object> RestartTerminalRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> Attached;
event Windows.Foundation.TypedEventHandler<Object, MenuChangedEventArgs> MenuChanged;
};
}

View File

@@ -15,3 +15,4 @@
#include "FoundResultsArgs.g.cpp"
#include "ShowWindowArgs.g.cpp"
#include "UpdateSelectionMarkersEventArgs.g.cpp"
#include "MenuChangedEventArgs.g.cpp"

View File

@@ -15,6 +15,7 @@
#include "FoundResultsArgs.g.h"
#include "ShowWindowArgs.g.h"
#include "UpdateSelectionMarkersEventArgs.g.h"
#include "MenuChangedEventArgs.g.h"
namespace winrt::Microsoft::Terminal::Control::implementation
{
@@ -179,6 +180,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation
WINRT_PROPERTY(bool, ClearMarkers, false);
};
struct MenuChangedEventArgs : public MenuChangedEventArgsT<MenuChangedEventArgs>
{
public:
MenuChangedEventArgs(const winrt::hstring menuJson, const unsigned int replaceLength) :
_MenuJson(menuJson),
_ReplacementLength(replaceLength)
{
}
WINRT_PROPERTY(winrt::hstring, MenuJson, L"");
WINRT_PROPERTY(uint32_t, ReplacementLength, 0);
};
}
namespace winrt::Microsoft::Terminal::Control::factory_implementation

View File

@@ -89,4 +89,10 @@ namespace Microsoft.Terminal.Control
{
Boolean ClearMarkers { get; };
}
runtimeclass MenuChangedEventArgs
{
String MenuJson { get; };
UInt32 ReplacementLength { get; };
}
}

View File

@@ -437,4 +437,26 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TSFInputControl::_formatUpdatingHandler(CoreTextEditContext sender, const CoreTextFormatUpdatingEventArgs& /*args*/)
{
}
void TSFInputControl::ManuallyDisplayText(const winrt::hstring& text)
{
_focused = !text.empty();
Canvas().Visibility(text.empty() ? Visibility::Collapsed : Visibility::Visible);
_inputBuffer.clear();
_activeTextStart = 0;
_inComposition = false;
// HACK trim off leading DEL chars.
std::wstring_view view{ text.c_str() };
const auto strBegin = view.find_first_not_of(L"\x7f");
if (strBegin != std::wstring::npos)
{
view = view.substr(strBegin * 2);
}
TextBlock().Text(winrt::hstring{ view });
TextBlock().UpdateLayout();
TryRedrawCanvas();
}
}

View File

@@ -40,6 +40,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ClearBuffer();
void TryRedrawCanvas();
void ManuallyDisplayText(const winrt::hstring& text);
void Close();
// -------------------------------- WinRT Events ---------------------------------

View File

@@ -31,6 +31,9 @@ namespace Microsoft.Terminal.Control
void ClearBuffer();
void TryRedrawCanvas();
void ManuallyDisplayText(String text);
void Close();
}
}

View File

@@ -104,6 +104,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_revokers.ConnectionStateChanged = _core.ConnectionStateChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleConnectionStateChanged });
_revokers.ShowWindowChanged = _core.ShowWindowChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleShowWindowChanged });
_revokers.CloseTerminalRequested = _core.CloseTerminalRequested(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleCloseTerminalRequested });
_revokers.MenuChanged = _core.MenuChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleMenuChanged });
_revokers.RestartTerminalRequested = _core.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleRestartTerminalRequested });
_revokers.PasteFromClipboard = _interactivity.PasteFromClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubblePasteFromClipboard });
@@ -524,6 +525,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <none>
void TermControl::SendInput(const winrt::hstring& wstr)
{
PreviewInput(L"");
_core.SendInput(wstr);
}
void TermControl::ClearBuffer(Control::ClearBufferType clearType)
@@ -3377,6 +3379,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _core.OwningHwnd();
}
void TermControl::PreviewInput(const winrt::hstring& text)
{
TSFInputControl().ManuallyDisplayText(text);
}
void TermControl::AddMark(const Control::ScrollMark& mark)
{
_core.AddMark(mark);
@@ -3405,6 +3412,29 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_core.ColorSelection(fg, bg, matchMode);
}
// Returns the text cursor's position relative to our origin, in DIPs.
Microsoft::Terminal::Core::Point TermControl::CursorPositionInDips()
{
const til::point cursorPos{ _core.CursorPosition() };
const til::size fontSize{ til::math::flooring, CharacterDimensions() };
// Convert text buffer cursor position to client coordinate position
// within the window. This point is in _pixels_
const til::point clientCursorPos{ cursorPos * fontSize };
// Get scale factor for view
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
const til::point clientCursorInDips{ til::math::flooring, clientCursorPos.x / scaleFactor, clientCursorPos.y / scaleFactor };
auto padding{ GetPadding() };
til::point relativeToOrigin{ til::math::flooring,
clientCursorInDips.x + padding.Left,
clientCursorInDips.y + padding.Top };
return relativeToOrigin.to_core_point();
}
void TermControl::_contextMenuHandler(IInspectable /*sender*/,
Control::ContextMenuRequestedEventArgs args)
{

View File

@@ -51,6 +51,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Windows::Foundation::Size MinimumSize();
float SnapDimensionToGrid(const bool widthOrHeight, const float dimension);
void PreviewInput(const winrt::hstring& text);
Microsoft::Terminal::Core::Point CursorPositionInDips();
void WindowVisibilityChanged(const bool showOrHide);
void ColorSelection(Control::SelectionColor fg, Control::SelectionColor bg, Core::MatchMode matchMode);
@@ -168,6 +172,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
BUBBLED_FORWARDED_TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable);
BUBBLED_FORWARDED_TYPED_EVENT(ShowWindowChanged, IInspectable, Control::ShowWindowArgs);
BUBBLED_FORWARDED_TYPED_EVENT(CloseTerminalRequested, IInspectable, IInspectable);
BUBBLED_FORWARDED_TYPED_EVENT(MenuChanged, IInspectable, Control::MenuChangedEventArgs);
BUBBLED_FORWARDED_TYPED_EVENT(RestartTerminalRequested, IInspectable, IInspectable);
BUBBLED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);
@@ -386,7 +391,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Control::ControlCore::ConnectionStateChanged_revoker ConnectionStateChanged;
Control::ControlCore::ShowWindowChanged_revoker ShowWindowChanged;
Control::ControlCore::CloseTerminalRequested_revoker CloseTerminalRequested;
Control::ControlCore::MenuChanged_revoker MenuChanged;
Control::ControlCore::RestartTerminalRequested_revoker RestartTerminalRequested;
// These are set up in _InitializeTerminal
Control::ControlCore::RendererWarning_revoker RendererWarning;
Control::ControlCore::SwapChainChanged_revoker SwapChainChanged;

View File

@@ -53,6 +53,7 @@ namespace Microsoft.Terminal.Control
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> ReadOnlyChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> FocusFollowMouseRequested;
event Windows.Foundation.TypedEventHandler<Object, MenuChangedEventArgs> MenuChanged;
Microsoft.UI.Xaml.Controls.CommandBarFlyout ContextMenu { get; };
Microsoft.UI.Xaml.Controls.CommandBarFlyout SelectionContextMenu { get; };
@@ -111,12 +112,16 @@ namespace Microsoft.Terminal.Control
// opacity set by the settings should call this instead.
Double BackgroundOpacity { get; };
void PreviewInput(String text);
Boolean DisplayCursorWhileBlurred;
Windows.UI.Xaml.Media.Brush BackgroundBrush { get; };
void ColorSelection(SelectionColor fg, SelectionColor bg, Microsoft.Terminal.Core.MatchMode matchMode);
Microsoft.Terminal.Core.Point CursorPositionInDips { get; };
void ShowContextMenu();
void Detach();

View File

@@ -1259,6 +1259,11 @@ const size_t Microsoft::Terminal::Core::Terminal::GetTaskbarProgress() const noe
return _taskbarProgress;
}
void Microsoft::Terminal::Core::Terminal::MenuChangedCallback(std::function<void(std::wstring_view, unsigned int)> pfn) noexcept
{
_pfnMenuChanged.swap(pfn);
}
Scheme Terminal::GetColorScheme() const
{
Scheme s;

View File

@@ -136,6 +136,9 @@ public:
bool IsVtInputEnabled() const noexcept override;
void NotifyAccessibilityChange(const til::rect& changedRect) noexcept override;
void NotifyBufferRotation(const int delta) override;
void InvokeMenu(std::wstring_view menuJson, unsigned int replaceLength) override;
#pragma endregion
void ClearMark();
@@ -209,6 +212,7 @@ public:
void TaskbarProgressChangedCallback(std::function<void()> pfn) noexcept;
void SetShowWindowCallback(std::function<void(bool)> pfn) noexcept;
void SetPlayMidiNoteCallback(std::function<void(const int, const int, const std::chrono::microseconds)> pfn) noexcept;
void MenuChangedCallback(std::function<void(std::wstring_view, unsigned int)> pfn) noexcept;
void SetCursorOn(const bool isOn);
bool IsCursorBlinkingAllowed() const noexcept;
@@ -306,6 +310,7 @@ private:
std::function<void()> _pfnTaskbarProgressChanged;
std::function<void(bool)> _pfnShowWindowChanged;
std::function<void(const int, const int, const std::chrono::microseconds)> _pfnPlayMidiNote;
std::function<void(std::wstring_view, unsigned int)> _pfnMenuChanged;
RenderSettings _renderSettings;
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;

View File

@@ -432,6 +432,14 @@ void Terminal::NotifyAccessibilityChange(const til::rect& /*changedRect*/) noexc
// This is only needed in conhost. Terminal handles accessibility in another way.
}
void Terminal::InvokeMenu(std::wstring_view menuJson, unsigned int replaceLength)
{
if (_pfnMenuChanged)
{
_pfnMenuChanged(menuJson, replaceLength);
}
}
void Terminal::NotifyBufferRotation(const int delta)
{
// Update our selection, so it doesn't move as the buffer is cycled

View File

@@ -2,20 +2,20 @@
// Licensed under the MIT license.
#include "pch.h"
#include "Rendering.h"
#include "Rendering.g.cpp"
#include "Compatibility.h"
#include "Compatibility.g.cpp"
using namespace winrt::Windows::UI::Xaml::Navigation;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Rendering::Rendering()
Compatibility::Compatibility()
{
InitializeComponent();
}
void Rendering::OnNavigatedTo(const NavigationEventArgs& e)
void Compatibility::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::RenderingViewModel>();
_ViewModel = e.Parameter().as<Editor::CompatibilityViewModel>();
}
}

View File

@@ -3,23 +3,23 @@
#pragma once
#include "Rendering.g.h"
#include "Compatibility.g.h"
#include "Utils.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct Rendering : public HasScrollViewer<Rendering>, RenderingT<Rendering>
struct Compatibility : public HasScrollViewer<Compatibility>, CompatibilityT<Compatibility>
{
Rendering();
Compatibility();
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_OBSERVABLE_PROPERTY(Editor::RenderingViewModel, ViewModel, _PropertyChangedHandlers, nullptr);
WINRT_OBSERVABLE_PROPERTY(Editor::CompatibilityViewModel, ViewModel, _PropertyChangedHandlers, nullptr);
};
}
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(Rendering);
BASIC_FACTORY(Compatibility);
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "CompatibilityViewModel.idl";
namespace Microsoft.Terminal.Settings.Editor
{
[default_interface] runtimeclass Compatibility : Windows.UI.Xaml.Controls.Page
{
Compatibility();
CompatibilityViewModel ViewModel { get; };
}
}

View File

@@ -2,7 +2,7 @@
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Page x:Class="Microsoft.Terminal.Settings.Editor.Rendering"
<Page x:Class="Microsoft.Terminal.Settings.Editor.Compatibility"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

View File

@@ -2,15 +2,15 @@
// Licensed under the MIT license.
#include "pch.h"
#include "RenderingViewModel.h"
#include "RenderingViewModel.g.cpp"
#include "CompatibilityViewModel.h"
#include "CompatibilityViewModel.g.cpp"
using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::Terminal::Settings::Model;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
RenderingViewModel::RenderingViewModel(Model::CascadiaSettings settings) noexcept :
CompatibilityViewModel::CompatibilityViewModel(Model::CascadiaSettings settings) noexcept :
_settings{ std::move(settings) }
{
}

View File

@@ -3,14 +3,14 @@
#pragma once
#include "RenderingViewModel.g.h"
#include "CompatibilityViewModel.g.h"
#include "ViewModelHelpers.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct RenderingViewModel : RenderingViewModelT<RenderingViewModel>, ViewModelHelper<RenderingViewModel>
struct CompatibilityViewModel : CompatibilityViewModelT<CompatibilityViewModel>, ViewModelHelper<CompatibilityViewModel>
{
explicit RenderingViewModel(Model::CascadiaSettings settings) noexcept;
explicit CompatibilityViewModel(Model::CascadiaSettings settings) noexcept;
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_settings.ProfileDefaults(), UseAtlasEngine);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_settings.GlobalSettings(), ForceFullRepaintRendering);
@@ -23,5 +23,5 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(RenderingViewModel);
BASIC_FACTORY(CompatibilityViewModel);
}

View File

@@ -7,9 +7,9 @@ import "EnumEntry.idl";
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass RenderingViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
runtimeclass CompatibilityViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
RenderingViewModel(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
CompatibilityViewModel(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, UseAtlasEngine);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ForceFullRepaintRendering);

View File

@@ -6,8 +6,8 @@
#include "MainPage.g.cpp"
#include "Launch.h"
#include "Interaction.h"
#include "Rendering.h"
#include "RenderingViewModel.h"
#include "Compatibility.h"
#include "CompatibilityViewModel.h"
#include "Actions.h"
#include "ProfileViewModel.h"
#include "GlobalAppearance.h"
@@ -38,7 +38,7 @@ using namespace winrt::Windows::Foundation::Collections;
static const std::wstring_view launchTag{ L"Launch_Nav" };
static const std::wstring_view interactionTag{ L"Interaction_Nav" };
static const std::wstring_view renderingTag{ L"Rendering_Nav" };
static const std::wstring_view compatibilityTag{ L"Compatibility_Nav" };
static const std::wstring_view actionsTag{ L"Actions_Nav" };
static const std::wstring_view globalProfileTag{ L"GlobalProfile_Nav" };
static const std::wstring_view addProfileTag{ L"AddProfile" };
@@ -359,10 +359,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_Interaction/Content"), BreadcrumbSubPage::None);
_breadcrumbs.Append(crumb);
}
else if (clickedItemTag == renderingTag)
else if (clickedItemTag == compatibilityTag)
{
contentFrame().Navigate(xaml_typename<Editor::Rendering>(), winrt::make<RenderingViewModel>(_settingsClone));
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_Rendering/Content"), BreadcrumbSubPage::None);
contentFrame().Navigate(xaml_typename<Editor::Compatibility>(), winrt::make<CompatibilityViewModel>(_settingsClone));
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_Compatibility/Content"), BreadcrumbSubPage::None);
_breadcrumbs.Append(crumb);
}
else if (clickedItemTag == actionsTag)

View File

@@ -127,13 +127,6 @@
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Nav_Rendering"
Tag="Rendering_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE7F8;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Nav_Actions"
Tag="Actions_Nav">
<muxc:NavigationViewItem.Icon>
@@ -141,6 +134,14 @@
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Nav_Compatibility"
Tag="Compatibility_Nav">
<muxc:NavigationViewItem.Icon>
<!-- DeveloperTools -->
<FontIcon Glyph="&#xEC7A;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItemHeader x:Uid="Nav_Profiles" />
<muxc:NavigationViewItem x:Name="BaseLayerMenuItem"

View File

@@ -90,8 +90,8 @@
<DependentUpon>ColorSchemesPageViewModel.idl</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="RenderingViewModel.h">
<DependentUpon>RenderingViewModel.idl</DependentUpon>
<ClInclude Include="CompatibilityViewModel.h">
<DependentUpon>CompatibilityViewModel.idl</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="InteractionViewModel.h">
@@ -122,8 +122,8 @@
<DependentUpon>Appearances.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="Rendering.h">
<DependentUpon>Rendering.xaml</DependentUpon>
<ClInclude Include="Compatibility.h">
<DependentUpon>Compatibility.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="SettingContainer.h">
<DependentUpon>SettingContainer.idl</DependentUpon>
@@ -175,7 +175,7 @@
<Page Include="Appearances.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Rendering.xaml">
<Page Include="Compatibility.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="SettingContainerStyle.xaml">
@@ -233,8 +233,8 @@
<DependentUpon>ColorSchemesPageViewModel.idl</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="RenderingViewModel.cpp">
<DependentUpon>RenderingViewModel.idl</DependentUpon>
<ClCompile Include="CompatibilityViewModel.cpp">
<DependentUpon>CompatibilityViewModel.idl</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="InteractionViewModel.cpp">
@@ -265,8 +265,8 @@
<DependentUpon>Appearances.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="Rendering.cpp">
<DependentUpon>Rendering.xaml</DependentUpon>
<ClCompile Include="Compatibility.cpp">
<DependentUpon>Compatibility.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="SettingContainer.cpp">
<DependentUpon>SettingContainer.idl</DependentUpon>
@@ -312,8 +312,8 @@
<DependentUpon>Interaction.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="Rendering.idl">
<DependentUpon>Rendering.xaml</DependentUpon>
<Midl Include="Compatibility.idl">
<DependentUpon>Compatibility.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="MainPage.idl">
@@ -322,7 +322,7 @@
<Midl Include="ProfileViewModel.idl" />
<Midl Include="ColorSchemeViewModel.idl" />
<Midl Include="ColorSchemesPageViewModel.idl" />
<Midl Include="RenderingViewModel.idl" />
<Midl Include="CompatibilityViewModel.idl" />
<Midl Include="InteractionViewModel.idl" />
<Midl Include="GlobalAppearanceViewModel.idl" />
<Midl Include="LaunchViewModel.idl" />

View File

@@ -1,13 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "RenderingViewModel.idl";
namespace Microsoft.Terminal.Settings.Editor
{
[default_interface] runtimeclass Rendering : Windows.UI.Xaml.Controls.Page
{
Rendering();
RenderingViewModel ViewModel { get; };
}
}

View File

@@ -586,6 +586,10 @@
<value>Rendering</value>
<comment>Header for the "rendering" menu item. This navigates to a page that lets you see and modify settings related to the app's rendering of text in the terminal.</comment>
</data>
<data name="Nav_Compatibility.Content" xml:space="preserve">
<value>Compatibility</value>
<comment>Header for the "compatibility" menu item. This navigates to a page that lets you see and modify settings related to backwards-compatibility</comment>
</data>
<data name="Nav_Actions.Content" xml:space="preserve">
<value>Actions</value>
<comment>Header for the "actions" menu item. This navigates to a page that lets you see and modify commands, key bindings, and actions that can be done in the app.</comment>

View File

@@ -815,6 +815,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
BASIC_FACTORY(RenameTabArgs);
BASIC_FACTORY(SwapPaneArgs);
BASIC_FACTORY(SplitPaneArgs);
BASIC_FACTORY(SendInputArgs);
BASIC_FACTORY(SetFocusModeArgs);
BASIC_FACTORY(SetFullScreenArgs);
BASIC_FACTORY(SetMaximizedArgs);

View File

@@ -202,6 +202,8 @@ namespace Microsoft.Terminal.Settings.Model
[default_interface] runtimeclass SendInputArgs : IActionArgs
{
SendInputArgs(String input);
String Input { get; };
};

View File

@@ -632,4 +632,98 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return newCommands;
}
winrt::Windows::Foundation::Collections::IVector<Model::Command> Command::ParsePowerShellMenuComplete(winrt::hstring json, int32_t replaceLength)
{
if (json.empty())
{
return nullptr;
}
auto data = winrt::to_string(json);
std::string errs;
static std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
Json::Value root;
if (!reader->parse(data.data(), data.data() + data.size(), &root, &errs))
{
throw winrt::hresult_error(WEB_E_INVALID_JSON_STRING, winrt::to_hstring(errs));
}
auto result = winrt::single_threaded_vector<Model::Command>();
auto backspaces = std::wstring(::base::saturated_cast<size_t>(replaceLength), L'\x7f');
const auto parseElement = [&](const auto& element) {
winrt::hstring completionText;
winrt::hstring listText;
JsonUtils::GetValueForKey(element, "CompletionText", completionText);
JsonUtils::GetValueForKey(element, "ListItemText", listText);
Model::SendInputArgs args{ winrt::hstring{ fmt::format(L"{}{}", backspaces, completionText.c_str()) } };
Model::ActionAndArgs actionAndArgs{ ShortcutAction::SendInput, args };
auto c = winrt::make_self<Command>();
c->_name = listText;
c->_ActionAndArgs = actionAndArgs;
// Try to assign a sensible icon based on the result type. These are
// roughly chosen to align with the icons in
// https://github.com/PowerShell/PowerShellEditorServices/pull/1738
// as best as possible.
if (const auto resultType{ JsonUtils::GetValueForKey<int>(element, "ResultType") })
{
// PowerShell completion result -> Segoe Fluent icon value & name
switch (resultType)
{
case 1: // History -> 0xe81c History
c->_iconPath = L"\ue81c";
break;
case 2: // Command -> 0xecaa AppIconDefault
c->_iconPath = L"\uecaa";
break;
case 3: // ProviderItem -> 0xe8e4 AlignLeft
c->_iconPath = L"\ue8e4";
break;
case 4: // ProviderContainer -> 0xe838 FolderOpen
c->_iconPath = L"\ue838";
break;
case 5: // Property -> 0xe7c1 Flag
c->_iconPath = L"\ue7c1";
break;
case 6: // Method -> 0xecaa AppIconDefault
c->_iconPath = L"\uecaa";
break;
case 7: // ParameterName -> 0xe7c1 Flag
c->_iconPath = L"\ue7c1";
break;
case 8: // ParameterValue -> 0xf000 KnowledgeArticle
c->_iconPath = L"\uf000";
break;
case 10: // Namespace -> 0xe943 Code
c->_iconPath = L"\ue943";
break;
case 13: // DynamicKeyword -> 0xe945 LightningBolt
c->_iconPath = L"\ue945";
break;
}
}
result.Append(*c);
};
if (root.isArray())
{
// If we got a whole array of suggestions, parse each one.
for (const auto& element : root)
{
parseElement(element);
}
}
else if (root.isObject())
{
// If we instead only got a single element back, just parse the root element.
parseElement(root);
}
return result;
}
}

View File

@@ -66,6 +66,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
hstring IconPath() const noexcept;
void IconPath(const hstring& val);
static Windows::Foundation::Collections::IVector<Model::Command> ParsePowerShellMenuComplete(winrt::hstring json, int32_t replaceLength);
WINRT_PROPERTY(ExpandCommandType, IterateOn, ExpandCommandType::None);
WINRT_PROPERTY(Model::ActionAndArgs, ActionAndArgs);

View File

@@ -45,5 +45,7 @@ namespace Microsoft.Terminal.Settings.Model
Boolean HasNestedCommands { get; };
Windows.Foundation.Collections.IMapView<String, Command> NestedCommands { get; };
static IVector<Command> ParsePowerShellMenuComplete(String json, Int32 replaceLength);
}
}

View File

@@ -98,6 +98,7 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Boolean, ShowAdminShield);
INHERITABLE_SETTING(IVector<NewTabMenuEntry>, NewTabMenu);
INHERITABLE_SETTING(Boolean, EnableColorSelection);
INHERITABLE_SETTING(Boolean, EnableShellCompletionMenu);
INHERITABLE_SETTING(Boolean, IsolatedMode);
INHERITABLE_SETTING(Boolean, AllowHeadless);
INHERITABLE_SETTING(String, SearchWebDefaultQueryUrl);

View File

@@ -63,6 +63,7 @@ Author(s):
X(bool, ShowAdminShield, "showAdminShield", true) \
X(bool, TrimPaste, "trimPaste", true) \
X(bool, EnableColorSelection, "experimental.enableColorSelection", false) \
X(bool, EnableShellCompletionMenu, "experimental.enableShellCompletionMenu", false) \
X(winrt::Windows::Foundation::Collections::IVector<Model::NewTabMenuEntry>, NewTabMenu, "newTabMenu", winrt::single_threaded_vector<Model::NewTabMenuEntry>({ Model::RemainingProfilesEntry{} })) \
X(bool, AllowHeadless, "compatibility.allowHeadless", false) \
X(bool, IsolatedMode, "compatibility.isolatedMode", false) \

View File

@@ -163,6 +163,17 @@
</alwaysEnabledBrandingTokens>
</feature>
<feature>
<name>Feature_ShellCompletions</name>
<description>An experimental escape sequence for client applications to request the Terminal display a list of suggestions.</description>
<id>3121</id>
<stage>AlwaysDisabled</stage>
<alwaysEnabledBrandingTokens>
<brandingToken>Dev</brandingToken>
<brandingToken>Preview</brandingToken>
</alwaysEnabledBrandingTokens>
</feature>
<feature>
<name>Feature_VtChecksumReport</name>
<description>Enables the DECRQCRA checksum report, which can be used to read the screen contents</description>

View File

@@ -454,3 +454,7 @@ void ConhostInternalGetSet::MarkCommandFinish(std::optional<unsigned int> /*erro
{
// Not implemented for conhost.
}
void ConhostInternalGetSet::InvokeMenu(std::wstring_view /*menuJson*/, unsigned int /*replaceLength*/)
{
// Not implemented for conhost.
}

View File

@@ -74,6 +74,8 @@ public:
void MarkOutputStart() override;
void MarkCommandFinish(std::optional<unsigned int> error) override;
void InvokeMenu(std::wstring_view menuJson, unsigned int replaceLength) override;
private:
Microsoft::Console::IIoProvider& _io;
};

View File

@@ -137,6 +137,8 @@ public:
virtual bool DoFinalTermAction(const std::wstring_view string) = 0;
virtual bool DoXtermJsAction(const std::wstring_view string) = 0;
virtual StringHandler DownloadDRCS(const VTInt fontNumber,
const VTParameter startChar,
const DispatchTypes::DrcsEraseControl eraseControl,

View File

@@ -85,5 +85,7 @@ namespace Microsoft::Console::VirtualTerminal
virtual void MarkCommandStart() = 0;
virtual void MarkOutputStart() = 0;
virtual void MarkCommandFinish(std::optional<unsigned int> error) = 0;
virtual void InvokeMenu(std::wstring_view menuJson, unsigned int replaceLength) = 0;
};
}

View File

@@ -3728,6 +3728,73 @@ bool AdaptDispatch::DoFinalTermAction(const std::wstring_view string)
// modify the state of that mark as we go.
return false;
}
// Method Description:
// - Performs a XtermJs action
// - Ascribes to the ITermDispatch interface
// - Currently, the actions we support are:
// * Completions: An experimental protocol for passing shell completion
// information from the shell to the terminal. This sequence is still under
// active development, and subject to change.
// - Not actually used in conhost
// Arguments:
// - string: contains the parameters that define which action we do
// Return Value:
// - false in conhost, true for the SetMark action, otherwise false.
bool AdaptDispatch::DoXtermJsAction(const std::wstring_view string)
{
// This is not implemented in conhost.
if (_api.IsConsolePty())
{
// Flush the frame manually, to make sure marks end up on the right line, like the alt buffer sequence.
_renderer.TriggerFlush(false);
return false;
}
if constexpr (!Feature_ShellCompletions::IsEnabled())
{
return false;
}
const auto parts = Utils::SplitString(string, L';');
if (parts.size() < 1)
{
return false;
}
const auto action = til::at(parts, 0);
if (action == L"Completions")
{
// The structure of the message is as follows:
// `e]633;
// 0: Completions;
// 1: $($completions.ReplacementIndex);
// 2: $($completions.ReplacementLength);
// 3: $($cursorIndex);
// 4: $completions.CompletionMatches | ConvertTo-Json
unsigned int replacementIndex = 0;
unsigned int replacementLength = 0;
unsigned int cursorIndex = 0;
bool succeeded = (parts.size() >= 2) &&
(Utils::StringToUint(til::at(parts, 1), replacementIndex));
succeeded &= (parts.size() >= 3) &&
(Utils::StringToUint(til::at(parts, 2), replacementLength));
succeeded &= (parts.size() >= 4) &&
(Utils::StringToUint(til::at(parts, 3), cursorIndex));
// VsCode is using cursorIndex and replacementIndex, but we aren't currently.
if (succeeded)
{
_api.InvokeMenu(parts.size() < 5 ? L"" : til::at(parts, 4),
replacementLength);
}
return true;
}
return false;
}
// Method Description:
// - DECDLD - Downloads one or more characters of a dynamically redefinable

View File

@@ -139,6 +139,8 @@ namespace Microsoft::Console::VirtualTerminal
bool DoFinalTermAction(const std::wstring_view string) override;
bool DoXtermJsAction(const std::wstring_view string) override;
StringHandler DownloadDRCS(const VTInt fontNumber,
const VTParameter startChar,
const DispatchTypes::DrcsEraseControl eraseControl,

View File

@@ -130,6 +130,8 @@ public:
bool DoFinalTermAction(const std::wstring_view /*string*/) override { return false; }
bool DoXtermJsAction(const std::wstring_view /*string*/) override { return false; }
StringHandler DownloadDRCS(const VTInt /*fontNumber*/,
const VTParameter /*startChar*/,
const DispatchTypes::DrcsEraseControl /*eraseControl*/,

View File

@@ -231,6 +231,10 @@ public:
{
Log::Comment(L"MarkCommandFinish MOCK called...");
}
void InvokeMenu(std::wstring_view /*menuJson*/, unsigned int /*replaceLength*/) override
{
Log::Comment(L"InvokeMenu MOCK called...");
}
void PrepData()
{

View File

@@ -862,6 +862,11 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
success = _dispatch->DoFinalTermAction(string);
break;
}
case OscActionCodes::XtermJsAction:
{
success = _dispatch->DoXtermJsAction(string);
break;
}
default:
// If no functions to call, overall dispatch was a failure.
success = false;

View File

@@ -214,6 +214,7 @@ namespace Microsoft::Console::VirtualTerminal
ResetBackgroundColor = 111, // Not implemented
ResetCursorColor = 112,
FinalTermAction = 133,
XtermJsAction = 633,
ITerm2Action = 1337,
};