mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-09 15:51:05 +00:00
Compare commits
21 Commits
dev/lhecke
...
v1.6.10412
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c24194a3f3 | ||
|
|
3ab1d724d2 | ||
|
|
e13d1a7b61 | ||
|
|
48543bb3e7 | ||
|
|
91b867102c | ||
|
|
4014100b2d | ||
|
|
3778924aa4 | ||
|
|
c01573b5d3 | ||
|
|
62a12eeb79 | ||
|
|
e457a1a868 | ||
|
|
1c0bbe72d3 | ||
|
|
cf694747a0 | ||
|
|
9444617bc6 | ||
|
|
b80f6de58c | ||
|
|
34bb1cbd01 | ||
|
|
b656fdd34f | ||
|
|
41e9c59879 | ||
|
|
680c7deb2f | ||
|
|
e9548969e4 | ||
|
|
7fe98a0344 | ||
|
|
5b1137ccff |
@@ -93,6 +93,8 @@
|
||||
"scrollDownPage",
|
||||
"scrollUp",
|
||||
"scrollUpPage",
|
||||
"scrollToBottom",
|
||||
"scrollToTop",
|
||||
"sendInput",
|
||||
"setColorScheme",
|
||||
"setTabColor",
|
||||
|
||||
BIN
res/Cascadia.ttf
BIN
res/Cascadia.ttf
Binary file not shown.
Binary file not shown.
@@ -17,5 +17,5 @@ Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadi
|
||||
|
||||
### Fonts Included
|
||||
|
||||
* Cascadia Code, Cascadia Mono (2009.21)
|
||||
* from microsoft/cascadia-code@32f84124db1970fa5d032f0fe9019e6922961beb
|
||||
* Cascadia Code, Cascadia Mono (2102.03)
|
||||
* from microsoft/cascadia-code@b358d1ba3d1629c113671312b18eab52797cc055
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace SettingsModelLocalTests
|
||||
TEST_METHOD(CanLayerColorScheme);
|
||||
TEST_METHOD(LayerColorSchemeProperties);
|
||||
TEST_METHOD(LayerColorSchemesOnArray);
|
||||
TEST_METHOD(UpdateSchemeReferences);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
@@ -290,4 +291,81 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 7, 7, 7), scheme2->_Background);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSchemeTests::UpdateSchemeReferences()
|
||||
{
|
||||
const std::string settingsString{ R"json({
|
||||
"defaultProfile": "Inherited reference",
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"colorScheme": "Scheme 1"
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"name": "Explicit scheme reference",
|
||||
"colorScheme": "Scheme 1"
|
||||
},
|
||||
{
|
||||
"name": "Explicit reference; hidden",
|
||||
"colorScheme": "Scheme 1",
|
||||
"hidden": true
|
||||
},
|
||||
{
|
||||
"name": "Inherited reference"
|
||||
},
|
||||
{
|
||||
"name": "Different reference",
|
||||
"colorScheme": "Scheme 2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemes": [
|
||||
{ "name": "Scheme 1" },
|
||||
{ "name": "Scheme 2" },
|
||||
{ "name": "Scheme 1 (renamed)" }
|
||||
]
|
||||
})json" };
|
||||
|
||||
auto settings{ winrt::make_self<CascadiaSettings>(false) };
|
||||
settings->_ParseJsonString(settingsString, false);
|
||||
settings->_ApplyDefaultsFromUserSettings();
|
||||
settings->LayerJson(settings->_userSettings);
|
||||
settings->_ValidateSettings();
|
||||
|
||||
// update all references to "Scheme 1"
|
||||
const auto newName{ L"Scheme 1 (renamed)" };
|
||||
settings->UpdateColorSchemeReferences(L"Scheme 1", newName);
|
||||
|
||||
// verify profile defaults
|
||||
Log::Comment(L"Profile Defaults");
|
||||
VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().ColorSchemeName());
|
||||
VERIFY_IS_TRUE(settings->ProfileDefaults().HasColorSchemeName());
|
||||
|
||||
// verify all other profiles
|
||||
const auto& profiles{ settings->AllProfiles() };
|
||||
{
|
||||
const auto& prof{ profiles.GetAt(0) };
|
||||
Log::Comment(prof.Name().c_str());
|
||||
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
|
||||
VERIFY_IS_TRUE(prof.HasColorSchemeName());
|
||||
}
|
||||
{
|
||||
const auto& prof{ profiles.GetAt(1) };
|
||||
Log::Comment(prof.Name().c_str());
|
||||
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
|
||||
VERIFY_IS_TRUE(prof.HasColorSchemeName());
|
||||
}
|
||||
{
|
||||
const auto& prof{ profiles.GetAt(2) };
|
||||
Log::Comment(prof.Name().c_str());
|
||||
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
|
||||
VERIFY_IS_FALSE(prof.HasColorSchemeName());
|
||||
}
|
||||
{
|
||||
const auto& prof{ profiles.GetAt(3) };
|
||||
Log::Comment(prof.Name().c_str());
|
||||
VERIFY_ARE_EQUAL(L"Scheme 2", prof.ColorSchemeName());
|
||||
VERIFY_IS_TRUE(prof.HasColorSchemeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@ namespace SettingsModelLocalTests
|
||||
const std::string settingsString{ R"({
|
||||
"$schema": "https://aka.ms/terminal-profiles-schema",
|
||||
"defaultProfile": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
|
||||
"disabledProfileSources": [ "Windows.Terminal.Wsl" ],
|
||||
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
|
||||
@@ -266,7 +266,16 @@ std::wstring OpenTerminalHere::_GetPathFromExplorer() const
|
||||
return path;
|
||||
}
|
||||
|
||||
auto shell = create_instance<IShellWindows>(CLSID_ShellWindows);
|
||||
com_ptr<IShellWindows> shell;
|
||||
try
|
||||
{
|
||||
shell = create_instance<IShellWindows>(CLSID_ShellWindows, CLSCTX_ALL);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
//look like try_create_instance is not available no more
|
||||
}
|
||||
|
||||
if (shell == nullptr)
|
||||
{
|
||||
return path;
|
||||
@@ -285,6 +294,7 @@ std::wstring OpenTerminalHere::_GetPathFromExplorer() const
|
||||
com_ptr<IWebBrowserApp> tmp;
|
||||
if (FAILED(disp->QueryInterface(tmp.put())))
|
||||
{
|
||||
disp = nullptr; // get rid of DEBUG non-nullptr warning
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -293,8 +303,11 @@ std::wstring OpenTerminalHere::_GetPathFromExplorer() const
|
||||
if (hwnd == tmpHWND)
|
||||
{
|
||||
browser = tmp;
|
||||
disp = nullptr; // get rid of DEBUG non-nullptr warning
|
||||
break; //found
|
||||
}
|
||||
|
||||
disp = nullptr; // get rid of DEBUG non-nullptr warning
|
||||
}
|
||||
|
||||
if (browser != nullptr)
|
||||
|
||||
@@ -841,7 +841,8 @@ namespace winrt::TerminalApp::implementation
|
||||
// editors, who will write a temp file, then rename it to be the
|
||||
// actual file you wrote. So listen for that too.
|
||||
if (!(event == wil::FolderChangeEvent::Modified ||
|
||||
event == wil::FolderChangeEvent::RenameNewName))
|
||||
event == wil::FolderChangeEvent::RenameNewName ||
|
||||
event == wil::FolderChangeEvent::Removed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -243,6 +243,9 @@ namespace winrt::TerminalApp::implementation
|
||||
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
|
||||
{
|
||||
auto key = e.OriginalKey();
|
||||
auto const ctrlDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
|
||||
auto const altDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
|
||||
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
|
||||
|
||||
// Some keypresses such as Tab, Return, Esc, and Arrow Keys are ignored by controls because
|
||||
// they're not considered input key presses. While they don't raise KeyDown events,
|
||||
@@ -253,10 +256,6 @@ namespace winrt::TerminalApp::implementation
|
||||
// a really widely used keyboard navigation key.
|
||||
if (_currentMode == CommandPaletteMode::TabSwitchMode && _keymap)
|
||||
{
|
||||
auto const ctrlDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
|
||||
auto const altDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
|
||||
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
|
||||
|
||||
winrt::Microsoft::Terminal::TerminalControl::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
|
||||
const auto action = _keymap.TryLookup(kc);
|
||||
if (action)
|
||||
@@ -272,41 +271,21 @@ namespace winrt::TerminalApp::implementation
|
||||
e.Handled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (key == VirtualKey::Home)
|
||||
{
|
||||
auto const state = CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control);
|
||||
if (WI_IsFlagSet(state, CoreVirtualKeyStates::Down))
|
||||
{
|
||||
ScrollToTop();
|
||||
e.Handled(true);
|
||||
}
|
||||
}
|
||||
else if (key == VirtualKey::End)
|
||||
{
|
||||
auto const state = CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control);
|
||||
if (WI_IsFlagSet(state, CoreVirtualKeyStates::Down))
|
||||
{
|
||||
ScrollToBottom();
|
||||
e.Handled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Process keystrokes in the input box. This is used for moving focus up
|
||||
// and down the list of commands in Action mode, and for executing
|
||||
// commands in both Action mode and Commandline mode.
|
||||
// Arguments:
|
||||
// - e: the KeyRoutedEventArgs containing info about the keystroke.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void CommandPalette::_keyDownHandler(IInspectable const& /*sender*/,
|
||||
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
|
||||
{
|
||||
auto key = e.OriginalKey();
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == VirtualKey::Up)
|
||||
if (key == VirtualKey::Home && ctrlDown)
|
||||
{
|
||||
ScrollToTop();
|
||||
e.Handled(true);
|
||||
}
|
||||
else if (key == VirtualKey::End && ctrlDown)
|
||||
{
|
||||
ScrollToBottom();
|
||||
e.Handled(true);
|
||||
}
|
||||
else if (key == VirtualKey::Up)
|
||||
{
|
||||
// Action Mode: Move focus to the next item in the list.
|
||||
SelectNextItem(false);
|
||||
@@ -352,16 +331,22 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
e.Handled(true);
|
||||
}
|
||||
else if (key == VirtualKey::Back)
|
||||
else if (key == VirtualKey::Back && _searchBox().Text().empty() && _lastFilterTextWasEmpty && _currentMode == CommandPaletteMode::ActionMode)
|
||||
{
|
||||
// If the last filter text was empty, and we're backspacing from
|
||||
// that state, then the user "backspaced" the virtual '>' we're
|
||||
// using as the action mode indicator. Switch into commandline mode.
|
||||
if (_searchBox().Text().empty() && _lastFilterTextWasEmpty && _currentMode == CommandPaletteMode::ActionMode)
|
||||
{
|
||||
_switchToMode(CommandPaletteMode::CommandlineMode);
|
||||
}
|
||||
|
||||
_switchToMode(CommandPaletteMode::CommandlineMode);
|
||||
e.Handled(true);
|
||||
}
|
||||
else if (key == VirtualKey::C && ctrlDown)
|
||||
{
|
||||
_searchBox().CopySelectionToClipboard();
|
||||
e.Handled(true);
|
||||
}
|
||||
else if (key == VirtualKey::V && ctrlDown)
|
||||
{
|
||||
_searchBox().PasteFromClipboard();
|
||||
e.Handled(true);
|
||||
}
|
||||
}
|
||||
@@ -451,6 +436,12 @@ namespace winrt::TerminalApp::implementation
|
||||
void CommandPalette::_lostFocusHandler(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
Windows::UI::Xaml::RoutedEventArgs const& /*args*/)
|
||||
{
|
||||
const auto flyout = _searchBox().ContextFlyout();
|
||||
if (flyout && flyout.IsOpen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto focusedElementOrAncestor = Input::FocusManager::GetFocusedElement(this->XamlRoot()).try_as<DependencyObject>();
|
||||
while (focusedElementOrAncestor)
|
||||
{
|
||||
|
||||
@@ -75,8 +75,7 @@ namespace winrt::TerminalApp::implementation
|
||||
Windows::UI::Xaml::RoutedEventArgs const& args);
|
||||
void _previewKeyDownHandler(Windows::Foundation::IInspectable const& sender,
|
||||
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||
void _keyDownHandler(Windows::Foundation::IInspectable const& sender,
|
||||
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||
|
||||
void _keyUpHandler(Windows::Foundation::IInspectable const& sender,
|
||||
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
AllowFocusOnInteraction="True"
|
||||
PointerPressed="_rootPointerPressed"
|
||||
PreviewKeyDown="_previewKeyDownHandler"
|
||||
KeyDown="_keyDownHandler"
|
||||
PreviewKeyUp="_keyUpHandler"
|
||||
LostFocus="_lostFocusHandler"
|
||||
mc:Ignorable="d"
|
||||
@@ -278,7 +277,6 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
AllowDrop="False"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="_listItemClicked"
|
||||
PreviewKeyDown="_keyDownHandler"
|
||||
ItemsSource="{x:Bind FilteredActions}">
|
||||
|
||||
<ItemsControl.ItemTemplate >
|
||||
|
||||
@@ -1550,9 +1550,9 @@ void Pane::Restore(std::shared_ptr<Pane> zoomedPane)
|
||||
// otherwise the ID value will not make sense (leaves have IDs, parents do not)
|
||||
// Return Value:
|
||||
// - The ID of this pane
|
||||
uint16_t Pane::Id() noexcept
|
||||
std::optional<uint16_t> Pane::Id() noexcept
|
||||
{
|
||||
return _id.value();
|
||||
return _id;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
void Maximize(std::shared_ptr<Pane> zoomedPane);
|
||||
void Restore(std::shared_ptr<Pane> zoomedPane);
|
||||
|
||||
uint16_t Id() noexcept;
|
||||
std::optional<uint16_t> Id() noexcept;
|
||||
void Id(uint16_t id) noexcept;
|
||||
void FocusPane(const uint16_t id);
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// Build the menu
|
||||
Controls::MenuFlyout newTabFlyout;
|
||||
newTabFlyout.Items().Append(_CreateCloseSubMenu());
|
||||
newTabFlyout.Items().Append(closeTabMenuItem);
|
||||
TabViewItem().ContextFlyout(newTabFlyout);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,14 @@ namespace winrt::TerminalApp::implementation
|
||||
void TabHeaderControl::RenameBoxLostFocusHandler(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
Windows::UI::Xaml::RoutedEventArgs const& /*e*/)
|
||||
{
|
||||
// If the context menu associated with the renamer text box is open we know it gained the focus.
|
||||
// In this case we ignore this event (we will regain the focus once the menu will be closed).
|
||||
const auto flyout = HeaderRenamerTextBox().ContextFlyout();
|
||||
if (flyout && flyout.IsOpen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Log the data here, rather than in _CloseRenameBox. If we do it there,
|
||||
// it'll get fired twice, once when the key is pressed to commit/cancel,
|
||||
// and then again when the focus is lost
|
||||
|
||||
@@ -135,6 +135,8 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
_tabRow.PointerMoved({ this, &TerminalPage::_RestorePointerCursorHandler });
|
||||
|
||||
_tabView.CanReorderTabs(!isElevated);
|
||||
_tabView.CanDragTabs(!isElevated);
|
||||
|
||||
@@ -1065,8 +1067,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
auto newTabTitle = tab.Title();
|
||||
|
||||
if (_settings.GlobalSettings().ShowTitleInTitlebar() &&
|
||||
tab.FocusState() != FocusState::Unfocused)
|
||||
if (_settings.GlobalSettings().ShowTitleInTitlebar() && tab == _GetFocusedTab())
|
||||
{
|
||||
_titleChangeHandlers(*this, newTabTitle);
|
||||
}
|
||||
@@ -2252,7 +2253,10 @@ namespace winrt::TerminalApp::implementation
|
||||
tab.TabViewItem().StartBringIntoView();
|
||||
|
||||
// Raise an event that our title changed
|
||||
_titleChangeHandlers(*this, tab.Title());
|
||||
if (_settings.GlobalSettings().ShowTitleInTitlebar())
|
||||
{
|
||||
_titleChangeHandlers(*this, tab.Title());
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
@@ -2410,7 +2414,7 @@ namespace winrt::TerminalApp::implementation
|
||||
IVectorView<Profile> profiles,
|
||||
IMapView<winrt::hstring, ColorScheme> schemes)
|
||||
{
|
||||
IVector<SettingsLoadWarnings> warnings;
|
||||
IVector<SettingsLoadWarnings> warnings{ winrt::single_threaded_vector<SettingsLoadWarnings>() };
|
||||
|
||||
std::vector<ColorScheme> sortedSchemes;
|
||||
sortedSchemes.reserve(schemes.Size());
|
||||
|
||||
@@ -390,9 +390,19 @@ namespace winrt::TerminalApp::implementation
|
||||
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
|
||||
const auto activePaneId = _activePane->Id();
|
||||
auto [first, second] = _activePane->Split(splitType, splitSize, profile, control);
|
||||
first->Id(activePaneId);
|
||||
second->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
if (activePaneId)
|
||||
{
|
||||
first->Id(activePaneId.value());
|
||||
second->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
}
|
||||
else
|
||||
{
|
||||
first->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
second->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
}
|
||||
_activePane = first;
|
||||
_AttachEventHandlersToControl(control);
|
||||
|
||||
@@ -610,16 +620,18 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// We need to move the pane to the top of our mru list
|
||||
// If its already somewhere in the list, remove it first
|
||||
const auto paneId = pane->Id();
|
||||
for (auto i = _mruPanes.begin(); i != _mruPanes.end(); ++i)
|
||||
if (const auto paneId = pane->Id())
|
||||
{
|
||||
if (*i == paneId)
|
||||
for (auto i = _mruPanes.begin(); i != _mruPanes.end(); ++i)
|
||||
{
|
||||
_mruPanes.erase(i);
|
||||
break;
|
||||
if (*i == paneId.value())
|
||||
{
|
||||
_mruPanes.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_mruPanes.insert(_mruPanes.begin(), paneId.value());
|
||||
}
|
||||
_mruPanes.insert(_mruPanes.begin(), paneId);
|
||||
// Raise our own ActivePaneChanged event.
|
||||
_ActivePaneChangedHandlers();
|
||||
}
|
||||
@@ -800,7 +812,6 @@ namespace winrt::TerminalApp::implementation
|
||||
newTabFlyout.Items().Append(chooseColorMenuItem);
|
||||
newTabFlyout.Items().Append(renameTabMenuItem);
|
||||
newTabFlyout.Items().Append(menuSeparator);
|
||||
newTabFlyout.Items().Append(_CreateCloseSubMenu());
|
||||
newTabFlyout.Items().Append(closeTabMenuItem);
|
||||
TabViewItem().ContextFlyout(newTabFlyout);
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
|
||||
_autoScrollTimer.Tick({ this, &TermControl::_UpdateAutoScroll });
|
||||
|
||||
_ApplyUISettings();
|
||||
_ApplyUISettings(_settings);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -274,6 +274,73 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
this->Focus(FocusState::Programmatic);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Given new settings for this profile, applies the settings to the current terminal.
|
||||
// - This method is separate from UpdateSettings because there is an apparent optimizer
|
||||
// issue that causes one of our hstring -> wstring_view conversions to result in garbage,
|
||||
// but only from a coroutine context. See GH#8723.
|
||||
// - INVARIANT: This method must be called from the UI thread.
|
||||
// Arguments:
|
||||
// - newSettings: New settings values for the profile in this terminal.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TermControl::_UpdateSettingsOnUIThread(const IControlSettings& newSettings)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = _terminal->LockForWriting();
|
||||
|
||||
// First, store the new settings in the instance.
|
||||
_settings = newSettings;
|
||||
|
||||
// Update our control settings
|
||||
_ApplyUISettings(_settings);
|
||||
|
||||
// Update the terminal core with its new Core settings
|
||||
_terminal->UpdateSettings(_settings);
|
||||
|
||||
if (!_initializedTerminal)
|
||||
{
|
||||
// If we haven't initialized, there's no point in continuing.
|
||||
// Initialization will handle the renderer settings.
|
||||
return;
|
||||
}
|
||||
|
||||
// Update DxEngine settings under the lock
|
||||
_renderEngine->SetSelectionBackground(_settings.SelectionBackground());
|
||||
|
||||
_renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect());
|
||||
_renderEngine->SetPixelShaderPath(_settings.PixelShaderPath());
|
||||
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
|
||||
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||
|
||||
switch (_settings.AntialiasingMode())
|
||||
{
|
||||
case TextAntialiasingMode::Cleartype:
|
||||
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
|
||||
break;
|
||||
case TextAntialiasingMode::Aliased:
|
||||
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
break;
|
||||
case TextAntialiasingMode::Grayscale:
|
||||
default:
|
||||
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Refresh our font with the renderer
|
||||
const auto actualFontOldSize = _actualFont.GetSize();
|
||||
_UpdateFont();
|
||||
const auto actualFontNewSize = _actualFont.GetSize();
|
||||
if (actualFontNewSize != actualFontOldSize)
|
||||
{
|
||||
_RefreshSizeUnderLock();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Given new settings for this profile, applies the settings to the current terminal.
|
||||
// Arguments:
|
||||
@@ -282,7 +349,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// - <none>
|
||||
winrt::fire_and_forget TermControl::UpdateSettings(IControlSettings newSettings)
|
||||
{
|
||||
_settings = newSettings;
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
// Dispatch a call to the UI thread to apply the new settings to the
|
||||
@@ -292,49 +358,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// If 'weakThis' is locked, then we can safely work with 'this'
|
||||
if (auto control{ weakThis.get() })
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
// Update our control settings
|
||||
_ApplyUISettings();
|
||||
|
||||
// Update the terminal core with its new Core settings
|
||||
_terminal->UpdateSettings(_settings);
|
||||
|
||||
auto lock = _terminal->LockForWriting();
|
||||
|
||||
// Update DxEngine settings under the lock
|
||||
_renderEngine->SetSelectionBackground(_settings.SelectionBackground());
|
||||
|
||||
_renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect());
|
||||
_renderEngine->SetPixelShaderPath(_settings.PixelShaderPath());
|
||||
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
|
||||
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||
|
||||
switch (_settings.AntialiasingMode())
|
||||
{
|
||||
case TextAntialiasingMode::Cleartype:
|
||||
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
|
||||
break;
|
||||
case TextAntialiasingMode::Aliased:
|
||||
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
break;
|
||||
case TextAntialiasingMode::Grayscale:
|
||||
default:
|
||||
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Refresh our font with the renderer
|
||||
const auto actualFontOldSize = _actualFont.GetSize();
|
||||
_UpdateFont();
|
||||
const auto actualFontNewSize = _actualFont.GetSize();
|
||||
if (actualFontNewSize != actualFontOldSize)
|
||||
{
|
||||
_RefreshSizeUnderLock();
|
||||
}
|
||||
_UpdateSettingsOnUIThread(newSettings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,21 +408,21 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TermControl::_ApplyUISettings()
|
||||
void TermControl::_ApplyUISettings(const IControlSettings& newSettings)
|
||||
{
|
||||
_InitializeBackgroundBrush();
|
||||
|
||||
COLORREF bg = _settings.DefaultBackground();
|
||||
COLORREF bg = newSettings.DefaultBackground();
|
||||
_BackgroundColorChanged(bg);
|
||||
|
||||
// Apply padding as swapChainPanel's margin
|
||||
auto newMargin = _ParseThicknessFromPadding(_settings.Padding());
|
||||
auto newMargin = _ParseThicknessFromPadding(newSettings.Padding());
|
||||
SwapChainPanel().Margin(newMargin);
|
||||
|
||||
// Initialize our font information.
|
||||
const auto fontFace = _settings.FontFace();
|
||||
const short fontHeight = gsl::narrow_cast<short>(_settings.FontSize());
|
||||
const auto fontWeight = _settings.FontWeight();
|
||||
const auto fontFace = newSettings.FontFace();
|
||||
const short fontHeight = gsl::narrow_cast<short>(newSettings.FontSize());
|
||||
const auto fontWeight = newSettings.FontWeight();
|
||||
// The font width doesn't terribly matter, we'll only be using the
|
||||
// height to look it up
|
||||
// The other params here also largely don't matter.
|
||||
@@ -410,12 +434,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
// set TSF Foreground
|
||||
Media::SolidColorBrush foregroundBrush{};
|
||||
foregroundBrush.Color(static_cast<til::color>(_settings.DefaultForeground()));
|
||||
foregroundBrush.Color(static_cast<til::color>(newSettings.DefaultForeground()));
|
||||
TSFInputControl().Foreground(foregroundBrush);
|
||||
TSFInputControl().Margin(newMargin);
|
||||
|
||||
// Apply settings for scrollbar
|
||||
if (_settings.ScrollState() == ScrollbarState::Hidden)
|
||||
if (newSettings.ScrollState() == ScrollbarState::Hidden)
|
||||
{
|
||||
// In the scenario where the user has turned off the OS setting to automatically hide scrollbars, the
|
||||
// Terminal scrollbar would still be visible; so, we need to set the control's visibility accordingly to
|
||||
@@ -1353,22 +1377,16 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
const auto cursorPosition = point.Position();
|
||||
const auto terminalPosition = _GetTerminalPosition(cursorPosition);
|
||||
|
||||
if (!_focused && (_terminal->GetHyperlinkAtPosition(terminalPosition).empty()))
|
||||
{
|
||||
args.Handled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen)
|
||||
{
|
||||
if (_CanSendVTMouseInput())
|
||||
if (_focused && _CanSendVTMouseInput())
|
||||
{
|
||||
_TrySendMouseEvent(point);
|
||||
args.Handled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (point.Properties().IsLeftButtonPressed())
|
||||
if (_focused && point.Properties().IsLeftButtonPressed())
|
||||
{
|
||||
auto lock = _terminal->LockForWriting();
|
||||
|
||||
@@ -1457,7 +1475,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch && _touchAnchor)
|
||||
else if (_focused && ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch && _touchAnchor)
|
||||
{
|
||||
const auto contactRect = point.Properties().ContactRect();
|
||||
winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y };
|
||||
@@ -2598,6 +2616,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// closed. We can just do it whenever.
|
||||
_AsyncCloseConnection();
|
||||
|
||||
{
|
||||
// GH#8734:
|
||||
// We lock the terminal here to make sure it isn't still being
|
||||
// used in the connection thread before we destroy the renderer.
|
||||
// However, we must unlock it again prior to triggering the
|
||||
// teardown, to avoid the render thread being deadlocked. The
|
||||
// renderer may be waiting to acquire the terminal lock, while
|
||||
// we're waiting for the renderer to finish.
|
||||
auto lock = _terminal->LockForWriting();
|
||||
}
|
||||
|
||||
if (auto localRenderEngine{ std::exchange(_renderEngine, nullptr) })
|
||||
{
|
||||
if (auto localRenderer{ std::exchange(_renderer, nullptr) })
|
||||
|
||||
@@ -263,7 +263,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
|
||||
|
||||
void _ApplyUISettings();
|
||||
void _ApplyUISettings(const IControlSettings&);
|
||||
void _UpdateSettingsOnUIThread(const IControlSettings& newSettings);
|
||||
void _UpdateSystemParameterSettings() noexcept;
|
||||
void _InitializeBackgroundBrush();
|
||||
winrt::fire_and_forget _BackgroundColorChanged(const COLORREF color);
|
||||
|
||||
@@ -474,7 +474,19 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept
|
||||
{
|
||||
if (parts.size() >= 2)
|
||||
{
|
||||
return _terminalApi.SetWorkingDirectory(til::at(parts, 1));
|
||||
const auto path = til::at(parts, 1);
|
||||
// The path should be surrounded with '"' according to the documentation of ConEmu.
|
||||
// An example: 9;"D:/"
|
||||
if (path.at(0) == L'"' && path.at(path.size() - 1) == L'"' && path.size() >= 3)
|
||||
{
|
||||
return _terminalApi.SetWorkingDirectory(path.substr(1, path.size() - 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we fail to find the surrounding quotation marks, we'll give the path a try anyway.
|
||||
// ConEmu also does this.
|
||||
return _terminalApi.SetWorkingDirectory(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
<!--Tab Switcher Mode-->
|
||||
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
|
||||
<muxc:RadioButtons x:Uid="Globals_TabSwitcherMode"
|
||||
SelectedItem="{x:Bind CurrentTabSwitcherMode}"
|
||||
SelectedItem="{x:Bind CurrentTabSwitcherMode, Mode=TwoWay}"
|
||||
ItemsSource="{x:Bind TabSwitcherModeList}"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
|
||||
</ContentPresenter>
|
||||
|
||||
@@ -77,7 +77,7 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
<!--Launch Mode-->
|
||||
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
|
||||
<muxc:RadioButtons x:Uid="Globals_LaunchMode"
|
||||
SelectedItem="{x:Bind CurrentLaunchMode}"
|
||||
SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}"
|
||||
ItemsSource="{x:Bind LaunchModeList}"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
|
||||
</ContentPresenter>
|
||||
|
||||
@@ -874,10 +874,18 @@ winrt::Microsoft::Terminal::Settings::Model::ColorScheme CascadiaSettings::GetCo
|
||||
// - <none>
|
||||
void CascadiaSettings::UpdateColorSchemeReferences(const hstring oldName, const hstring newName)
|
||||
{
|
||||
// update profiles.defaults, if necessary
|
||||
if (_userDefaultProfileSettings &&
|
||||
_userDefaultProfileSettings->HasColorSchemeName() &&
|
||||
_userDefaultProfileSettings->ColorSchemeName() == oldName)
|
||||
{
|
||||
_userDefaultProfileSettings->ColorSchemeName(newName);
|
||||
}
|
||||
|
||||
// update all profiles referencing this color scheme
|
||||
for (const auto& profile : _allProfiles)
|
||||
{
|
||||
if (profile.ColorSchemeName() == oldName)
|
||||
if (profile.HasColorSchemeName() && profile.ColorSchemeName() == oldName)
|
||||
{
|
||||
profile.ColorSchemeName(newName);
|
||||
}
|
||||
|
||||
@@ -1078,9 +1078,13 @@ void CascadiaSettings::WriteSettingsToDisk() const
|
||||
Json::Value CascadiaSettings::ToJson() const
|
||||
{
|
||||
// top-level json object
|
||||
// directly inject "globals" and "$schema" into here
|
||||
// directly inject "globals", "$schema", and "disabledProfileSources" into here
|
||||
Json::Value json{ _globals->ToJson() };
|
||||
JsonUtils::SetValueForKey(json, SchemaKey, JsonKey(SchemaValue));
|
||||
if (_userSettings.isMember(JsonKey(DisabledProfileSourcesKey)))
|
||||
{
|
||||
json[JsonKey(DisabledProfileSourcesKey)] = _userSettings[JsonKey(DisabledProfileSourcesKey)];
|
||||
}
|
||||
|
||||
// "profiles" will always be serialized as an object
|
||||
Json::Value profiles{ Json::ValueType::objectValue };
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace TerminalCoreUnitTests
|
||||
TEST_METHOD(AddHyperlinkCustomIdDifferentUri);
|
||||
|
||||
TEST_METHOD(SetTaskbarProgress);
|
||||
TEST_METHOD(SetWorkingDirectory);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -388,3 +389,59 @@ void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress()
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
||||
}
|
||||
|
||||
void TerminalCoreUnitTests::TerminalApiTest::SetWorkingDirectory()
|
||||
{
|
||||
Terminal term;
|
||||
DummyRenderTarget emptyRT;
|
||||
term.Create({ 100, 100 }, 0, emptyRT);
|
||||
|
||||
auto& stateMachine = *(term._stateMachine);
|
||||
|
||||
// Test setting working directory using OSC 9;9
|
||||
// Initial CWD should be empty
|
||||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
||||
|
||||
// Invalid sequences should not change CWD
|
||||
stateMachine.ProcessString(L"\x1b]9;9\x9c");
|
||||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9\"\x9c");
|
||||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9\"C:\\\"\x9c");
|
||||
VERIFY_IS_TRUE(term.GetWorkingDirectory().empty());
|
||||
|
||||
// Valid sequences should change CWD
|
||||
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\\"\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\");
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9;\"C:\\Program Files\"\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files");
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9;\"D:\\中文\"\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文");
|
||||
|
||||
// Test OSC 9;9 sequences without quotation marks
|
||||
stateMachine.ProcessString(L"\x1b]9;9;C:\\\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\");
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9;C:\\Program Files\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"C:\\Program Files");
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9;D:\\中文\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"D:\\中文");
|
||||
|
||||
// These OSC 9;9 sequences will result in invalid CWD. We shouldn't crash on these.
|
||||
stateMachine.ProcessString(L"\x1b]9;9;\"\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"");
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\"");
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"");
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;9;\"\"\"\"\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetWorkingDirectory(), L"\"\"");
|
||||
}
|
||||
|
||||
@@ -41,6 +41,16 @@ HRESULT RenderEngineBase::PrepareRenderInfo(const RenderFrameInfo& /*info*/) noe
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - By default, no one should need continuous redraw. It ruins performance
|
||||
// in terms of CPU, memory, and battery life to just paint forever.
|
||||
// That's why we sleep when there's nothing to draw.
|
||||
// But if you REALLY WANT to do special effects... you need to keep painting.
|
||||
[[nodiscard]] bool RenderEngineBase::RequiresContinuousRedraw() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Blocks until the engine is able to render without blocking.
|
||||
void RenderEngineBase::WaitUntilCanRender() noexcept
|
||||
|
||||
@@ -133,6 +133,14 @@ try
|
||||
|
||||
auto endPaint = wil::scope_exit([&]() {
|
||||
LOG_IF_FAILED(pEngine->EndPaint());
|
||||
|
||||
// If the engine tells us it really wants to redraw immediately,
|
||||
// tell the thread so it doesn't go to sleep and ticks again
|
||||
// at the next opportunity.
|
||||
if (pEngine->RequiresContinuousRedraw())
|
||||
{
|
||||
_NotifyPaintFrame();
|
||||
}
|
||||
});
|
||||
|
||||
// A. Prep Colors
|
||||
|
||||
@@ -411,6 +411,8 @@ HRESULT DxEngine::_SetupTerminalEffects()
|
||||
pixelShaderSettingsBufferDesc.ByteWidth = sizeof(_pixelShaderSettings);
|
||||
pixelShaderSettingsBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
|
||||
_shaderStartTime = std::chrono::steady_clock::now();
|
||||
|
||||
_ComputePixelShaderSettings();
|
||||
|
||||
D3D11_SUBRESOURCE_DATA pixelShaderSettingsInitData{};
|
||||
@@ -454,9 +456,8 @@ void DxEngine::_ComputePixelShaderSettings() noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
// Set the time
|
||||
// TODO:GH#7013 Grab timestamp
|
||||
_pixelShaderSettings.Time = 0.0f;
|
||||
// Set the time (seconds since the shader was loaded)
|
||||
_pixelShaderSettings.Time = std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now() - _shaderStartTime).count();
|
||||
|
||||
// Set the UI Scale
|
||||
_pixelShaderSettings.Scale = _scale;
|
||||
@@ -1438,6 +1439,28 @@ CATCH_RETURN()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - When the shaders are on, say that we need to keep redrawing every
|
||||
// possible frame in case they have some smooth action on every frame tick.
|
||||
// It is presumed that if you're using shaders, you're not about performance...
|
||||
// You're instead about OOH SHINY. And that's OK. But returning true here is 100%
|
||||
// a perf detriment.
|
||||
[[nodiscard]] bool DxEngine::RequiresContinuousRedraw() noexcept
|
||||
{
|
||||
// We're only going to request continuous redraw if someone is using
|
||||
// a pixel shader from a path because we cannot tell if those are using the
|
||||
// time parameter or not.
|
||||
// And if they are using time, they probably need it to tick continuously.
|
||||
//
|
||||
// By contrast, the in-built retro effect does NOT need it,
|
||||
// so let's not tick for it and save some amount of performance.
|
||||
//
|
||||
// Finally... if we're not using effects at all... let the render thread
|
||||
// go to sleep. It deserves it. That thread works hard. Also it sleeping
|
||||
// saves battery power and all sorts of related perf things.
|
||||
return _terminalEffectsEnabled && !_pixelShaderPath.empty();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Blocks until the engine is able to render without blocking.
|
||||
// - See https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains.
|
||||
|
||||
@@ -84,6 +84,8 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] HRESULT StartPaint() noexcept override;
|
||||
[[nodiscard]] HRESULT EndPaint() noexcept override;
|
||||
|
||||
[[nodiscard]] bool RequiresContinuousRedraw() noexcept override;
|
||||
|
||||
void WaitUntilCanRender() noexcept override;
|
||||
[[nodiscard]] HRESULT Present() noexcept override;
|
||||
|
||||
@@ -246,6 +248,8 @@ namespace Microsoft::Console::Render
|
||||
std::wstring _pixelShaderPath;
|
||||
bool _pixelShaderLoaded{ false };
|
||||
|
||||
std::chrono::steady_clock::time_point _shaderStartTime;
|
||||
|
||||
// DX resources needed for terminal effects
|
||||
::Microsoft::WRL::ComPtr<ID3D11RenderTargetView> _renderTargetView;
|
||||
::Microsoft::WRL::ComPtr<ID3D11VertexShader> _vertexShader;
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace Microsoft::Console::Render
|
||||
[[nodiscard]] virtual HRESULT StartPaint() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT EndPaint() noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual bool RequiresContinuousRedraw() noexcept = 0;
|
||||
virtual void WaitUntilCanRender() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT Present() noexcept = 0;
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace Microsoft::Console::Render
|
||||
|
||||
[[nodiscard]] HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept override;
|
||||
|
||||
[[nodiscard]] virtual bool RequiresContinuousRedraw() noexcept override;
|
||||
|
||||
void WaitUntilCanRender() noexcept override;
|
||||
|
||||
protected:
|
||||
|
||||
Reference in New Issue
Block a user