From a67a13288c9173a399143b246e18af2300ca8ee8 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Tue, 26 Mar 2024 22:31:24 +0100 Subject: [PATCH 01/16] AtlasEngine: Make Direct2D/3D and Present1 configurable (#16939) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements `SetForceFullRepaintRendering` and adds a new `SetGraphicsAPI` function. The former toggles `Present1` on and off and the latter allows users to explicitly request Direct2D/3D. On top of these changes I did a minor cleanup of the interface, because now that DxRenderer is gone we don't need all that anymore. Closes #14254 Closes #16747 ## Validation Steps Performed * Toggling Direct2D on/off changes colored ligature support ✅ * Toggling Present1 on/off can be observed in a debugger ✅ * Toggling WARP on/off changes GPU metrics ✅ --------- Co-authored-by: Dustin L. Howett --- doc/cascadia/profiles.schema.json | 16 +- src/cascadia/TerminalControl/ControlCore.cpp | 54 ++++--- src/cascadia/TerminalControl/ControlCore.h | 28 ++-- src/cascadia/TerminalControl/EventArgs.idl | 8 +- src/cascadia/TerminalControl/HwndTerminal.cpp | 1 - .../TerminalControl/IControlSettings.idl | 3 +- src/cascadia/TerminalControl/TermControl.cpp | 2 +- .../TerminalSettingsEditor/Rendering.xaml | 20 ++- .../RenderingViewModel.cpp | 6 +- .../RenderingViewModel.h | 4 +- .../RenderingViewModel.idl | 4 +- .../Resources/de-DE/Resources.resw | 10 +- .../Resources/en-US/Resources.resw | 49 +++--- .../Resources/es-ES/Resources.resw | 10 +- .../Resources/fr-FR/Resources.resw | 10 +- .../Resources/it-IT/Resources.resw | 10 +- .../Resources/ja-JP/Resources.resw | 10 +- .../Resources/ko-KR/Resources.resw | 10 +- .../Resources/pt-BR/Resources.resw | 10 +- .../Resources/qps-ploc/Resources.resw | 10 +- .../Resources/qps-ploca/Resources.resw | 10 +- .../Resources/qps-plocm/Resources.resw | 10 +- .../Resources/ru-RU/Resources.resw | 10 +- .../Resources/zh-CN/Resources.resw | 10 +- .../Resources/zh-TW/Resources.resw | 10 +- .../TerminalSettingsModel/EnumMappings.cpp | 1 + .../TerminalSettingsModel/EnumMappings.h | 1 + .../TerminalSettingsModel/EnumMappings.idl | 1 + .../GlobalAppSettings.cpp | 18 ++- .../TerminalSettingsModel/GlobalAppSettings.h | 2 +- .../GlobalAppSettings.idl | 3 +- .../TerminalSettingsModel/MTSMSettings.h | 5 +- .../TerminalSettings.cpp | 3 +- .../TerminalSettingsModel/TerminalSettings.h | 3 +- .../TerminalSettingsSerializationHelpers.h | 9 ++ .../SerializationTests.cpp | 2 - src/cascadia/inc/ControlProperties.h | 3 +- src/cppwinrt.build.pre.props | 1 - src/renderer/atlas/AtlasEngine.api.cpp | 45 +++--- src/renderer/atlas/AtlasEngine.cpp | 2 +- src/renderer/atlas/AtlasEngine.h | 44 +++--- src/renderer/atlas/AtlasEngine.r.cpp | 146 +++++++++--------- src/renderer/atlas/Backend.h | 3 - src/renderer/atlas/common.h | 11 +- src/renderer/base/RenderEngineBase.cpp | 4 + src/renderer/inc/IRenderEngine.hpp | 28 +--- src/renderer/inc/RenderEngineBase.hpp | 1 + src/renderer/uia/UiaRenderer.hpp | 2 +- src/renderer/wddmcon/WddmConRenderer.hpp | 2 +- 49 files changed, 351 insertions(+), 314 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 7225059372a..6733fe52266 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -2332,12 +2332,20 @@ }, "type": "array" }, - "experimental.rendering.forceFullRepaint": { - "description": "When set to true, we will redraw the entire screen each frame. When set to false, we will render only the updates to the screen between frames.", + "rendering.graphicsAPI": { + "description": "Direct3D 11 provides a more performant and feature-rich experience, whereas Direct2D is more stable. The default option \"Automatic\" will pick the API that best fits your graphics hardware. If you experience significant issues, consider using Direct2D.", + "type": "string", + "enum": [ + "direct2d", + "direct3d11" + ] + }, + "rendering.disablePartialInvalidation": { + "description": "By default, the text renderer uses a FLIP_SEQUENTIAL Swap Chain and declares dirty rectangles via the Present1 API. When this setting is enabled, a FLIP_DISCARD Swap Chain will be used instead, and no dirty rectangles will be declared. Whether one or the other is better depends on your hardware and various other factors.", "type": "boolean" }, - "experimental.rendering.software": { - "description": "When set to true, we will use the software renderer (a.k.a. WARP) instead of the hardware one.", + "rendering.software": { + "description": "When enabled, the terminal will use a software rasterizer (WARP). This setting should be left disabled under almost all circumstances.", "type": "boolean" }, "experimental.input.forceVT": { diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 4027e914d8f..a1070d9b811 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -9,14 +9,13 @@ #include #include -#include #include -#include #include #include "EventArgs.h" -#include "../../buffer/out/search.h" #include "../../renderer/atlas/AtlasEngine.h" +#include "../../renderer/base/renderer.hpp" +#include "../../renderer/uia/UiaRenderer.hpp" #include "ControlCore.g.cpp" #include "SelectionColor.g.cpp" @@ -43,26 +42,26 @@ constexpr const auto SearchAfterChangeDelay = std::chrono::milliseconds(200); namespace winrt::Microsoft::Terminal::Control::implementation { - static winrt::Microsoft::Terminal::Core::OptionalColor OptionalFromColor(const til::color& c) + static winrt::Microsoft::Terminal::Core::OptionalColor OptionalFromColor(const til::color& c) noexcept { Core::OptionalColor result; result.Color = c; result.HasValue = true; return result; } - static winrt::Microsoft::Terminal::Core::OptionalColor OptionalFromColor(const std::optional& c) + + static ::Microsoft::Console::Render::Atlas::GraphicsAPI parseGraphicsAPI(GraphicsAPI api) noexcept { - Core::OptionalColor result; - if (c.has_value()) - { - result.Color = *c; - result.HasValue = true; - } - else + using GA = ::Microsoft::Console::Render::Atlas::GraphicsAPI; + switch (api) { - result.HasValue = false; + case GraphicsAPI::Direct2D: + return GA::Direct2D; + case GraphicsAPI::Direct3D11: + return GA::Direct3D11; + default: + return GA::Automatic; } - return result; } TextColor SelectionColor::AsTextColor() const noexcept @@ -388,7 +387,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderEngine->SetRetroTerminalEffect(_settings->RetroTerminalEffect()); _renderEngine->SetPixelShaderPath(_settings->PixelShaderPath()); _renderEngine->SetPixelShaderImagePath(_settings->PixelShaderImagePath()); - _renderEngine->SetForceFullRepaintRendering(_settings->ForceFullRepaintRendering()); + _renderEngine->SetGraphicsAPI(parseGraphicsAPI(_settings->GraphicsAPI())); + _renderEngine->SetDisablePartialInvalidation(_settings->DisablePartialInvalidation()); _renderEngine->SetSoftwareRendering(_settings->SoftwareRendering()); _updateAntiAliasingMode(); @@ -397,8 +397,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation // GH#11315: Always do this, even if they don't have acrylic on. _renderEngine->EnableTransparentBackground(_isBackgroundTransparent()); - THROW_IF_FAILED(_renderEngine->Enable()); - _initializedTerminal.store(true, std::memory_order_relaxed); } // scope for TerminalLock @@ -883,7 +881,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation return; } - _renderEngine->SetForceFullRepaintRendering(_settings->ForceFullRepaintRendering()); + _renderEngine->SetGraphicsAPI(parseGraphicsAPI(_settings->GraphicsAPI())); + _renderEngine->SetDisablePartialInvalidation(_settings->DisablePartialInvalidation()); _renderEngine->SetSoftwareRendering(_settings->SoftwareRendering()); // Inform the renderer of our opacity _renderEngine->EnableTransparentBackground(_isBackgroundTransparent()); @@ -946,6 +945,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + Control::IControlSettings ControlCore::Settings() + { + return *_settings; + } + + Control::IControlAppearance ControlCore::FocusedAppearance() const + { + return *_settings->FocusedAppearance(); + } + + Control::IControlAppearance ControlCore::UnfocusedAppearance() const + { + return *_settings->UnfocusedAppearance(); + } + void ControlCore::_updateAntiAliasingMode() { D2D1_TEXT_ANTIALIAS_MODE mode; @@ -1960,13 +1974,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation UpdateSelectionMarkers.raise(*this, winrt::make(!showMarkers)); } - void ControlCore::AttachUiaEngine(::Microsoft::Console::Render::IRenderEngine* const pEngine) + void ControlCore::AttachUiaEngine(::Microsoft::Console::Render::UiaEngine* const pEngine) { // _renderer will always exist since it's introduced in the ctor const auto lock = _terminal->LockForWriting(); _renderer->AddRenderEngine(pEngine); } - void ControlCore::DetachUiaEngine(::Microsoft::Console::Render::IRenderEngine* const pEngine) + void ControlCore::DetachUiaEngine(::Microsoft::Console::Render::UiaEngine* const pEngine) { const auto lock = _terminal->LockForWriting(); _renderer->RemoveRenderEngine(pEngine); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index d79df07d1bc..218d1b842eb 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -18,12 +18,22 @@ #include "ControlCore.g.h" #include "SelectionColor.g.h" #include "CommandHistoryContext.g.h" + #include "ControlSettings.h" #include "../../audio/midi/MidiAudio.hpp" -#include "../../renderer/base/Renderer.hpp" +#include "../../buffer/out/search.h" #include "../../cascadia/TerminalCore/Terminal.hpp" -#include "../buffer/out/search.h" -#include "../buffer/out/TextColor.h" +#include "../../renderer/inc/FontInfoDesired.hpp" + +namespace Microsoft::Console::Render::Atlas +{ + class AtlasEngine; +} + +namespace Microsoft::Console::Render +{ + class UiaEngine; +} namespace ControlUnitTests { @@ -82,9 +92,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation void UpdateSettings(const Control::IControlSettings& settings, const IControlAppearance& newAppearance); void ApplyAppearance(const bool& focused); - Control::IControlSettings Settings() { return *_settings; }; - Control::IControlAppearance FocusedAppearance() const { return *_settings->FocusedAppearance(); }; - Control::IControlAppearance UnfocusedAppearance() const { return *_settings->UnfocusedAppearance(); }; + Control::IControlSettings Settings(); + Control::IControlAppearance FocusedAppearance() const; + Control::IControlAppearance UnfocusedAppearance() const; bool HasUnfocusedAppearance() const; winrt::Microsoft::Terminal::Core::Scheme ColorScheme() const noexcept; @@ -219,8 +229,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation const bool isOnOriginalPosition, bool& selectionNeedsToBeCopied); - void AttachUiaEngine(::Microsoft::Console::Render::IRenderEngine* const pEngine); - void DetachUiaEngine(::Microsoft::Console::Render::IRenderEngine* const pEngine); + void AttachUiaEngine(::Microsoft::Console::Render::UiaEngine* const pEngine); + void DetachUiaEngine(::Microsoft::Console::Render::UiaEngine* const pEngine); bool IsInReadOnlyMode() const; void ToggleReadOnlyMode(); @@ -306,7 +316,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // As _renderer has a dependency on _renderEngine (through a raw pointer) // we must ensure the _renderer is deallocated first. // (C++ class members are destroyed in reverse order.) - std::unique_ptr<::Microsoft::Console::Render::IRenderEngine> _renderEngine{ nullptr }; + std::unique_ptr<::Microsoft::Console::Render::Atlas::AtlasEngine> _renderEngine{ nullptr }; std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr }; ::Search _searcher; diff --git a/src/cascadia/TerminalControl/EventArgs.idl b/src/cascadia/TerminalControl/EventArgs.idl index 3caea5a0f38..978d69d8e36 100644 --- a/src/cascadia/TerminalControl/EventArgs.idl +++ b/src/cascadia/TerminalControl/EventArgs.idl @@ -11,6 +11,12 @@ namespace Microsoft.Terminal.Control All = 0xffffffff }; + enum GraphicsAPI + { + Automatic, + Direct2D, + Direct3D11, + }; runtimeclass FontSizeChangedArgs { @@ -90,7 +96,7 @@ namespace Microsoft.Terminal.Control { Boolean ShowOrHide { get; }; } - + runtimeclass UpdateSelectionMarkersEventArgs { Boolean ClearMarkers { get; }; diff --git a/src/cascadia/TerminalControl/HwndTerminal.cpp b/src/cascadia/TerminalControl/HwndTerminal.cpp index c34e5b4523f..bd05b7ca8a2 100644 --- a/src/cascadia/TerminalControl/HwndTerminal.cpp +++ b/src/cascadia/TerminalControl/HwndTerminal.cpp @@ -217,7 +217,6 @@ HRESULT HwndTerminal::Initialize() auto engine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>(); RETURN_IF_FAILED(engine->SetHwnd(_hwnd.get())); - RETURN_IF_FAILED(engine->Enable()); _renderer->AddRenderEngine(engine.get()); _UpdateFont(USER_DEFAULT_SCREEN_DPI); diff --git a/src/cascadia/TerminalControl/IControlSettings.idl b/src/cascadia/TerminalControl/IControlSettings.idl index 63c35d8a952..2db92a86a83 100644 --- a/src/cascadia/TerminalControl/IControlSettings.idl +++ b/src/cascadia/TerminalControl/IControlSettings.idl @@ -58,7 +58,8 @@ namespace Microsoft.Terminal.Control TextAntialiasingMode AntialiasingMode { get; }; // Experimental Settings - Boolean ForceFullRepaintRendering { get; }; + Microsoft.Terminal.Control.GraphicsAPI GraphicsAPI { get; }; + Boolean DisablePartialInvalidation { get; }; Boolean SoftwareRendering { get; }; Boolean ShowMarks { get; }; Boolean UseBackgroundImageForWindow { get; }; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index de8ec920d3e..c8b378672c5 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2409,7 +2409,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation LOG_IF_FAILED(engine->UpdateDpi(dpi)); LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont)); - const auto scale = engine->GetScaling(); + const auto scale = dpi / static_cast(USER_DEFAULT_SCREEN_DPI); const auto actualFontSize = actualFont.GetSize(); // UWP XAML scrollbars aren't guaranteed to be the same size as the diff --git a/src/cascadia/TerminalSettingsEditor/Rendering.xaml b/src/cascadia/TerminalSettingsEditor/Rendering.xaml index fe057486859..4b9534167d0 100644 --- a/src/cascadia/TerminalSettingsEditor/Rendering.xaml +++ b/src/cascadia/TerminalSettingsEditor/Rendering.xaml @@ -15,20 +15,28 @@ + + + + - + + + - - - + - diff --git a/src/cascadia/TerminalSettingsEditor/RenderingViewModel.cpp b/src/cascadia/TerminalSettingsEditor/RenderingViewModel.cpp index 42190c4e6a7..74c4d5922a8 100644 --- a/src/cascadia/TerminalSettingsEditor/RenderingViewModel.cpp +++ b/src/cascadia/TerminalSettingsEditor/RenderingViewModel.cpp @@ -3,6 +3,9 @@ #include "pch.h" #include "RenderingViewModel.h" + +#include "EnumEntry.h" + #include "RenderingViewModel.g.cpp" using namespace winrt::Windows::Foundation; @@ -10,8 +13,9 @@ using namespace winrt::Microsoft::Terminal::Settings::Model; namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { - RenderingViewModel::RenderingViewModel(Model::CascadiaSettings settings) noexcept : + RenderingViewModel::RenderingViewModel(CascadiaSettings settings) noexcept : _settings{ std::move(settings) } { + INITIALIZE_BINDABLE_ENUM_SETTING(GraphicsAPI, GraphicsAPI, winrt::Microsoft::Terminal::Control::GraphicsAPI, L"Globals_GraphicsAPI_", L"Text"); } } diff --git a/src/cascadia/TerminalSettingsEditor/RenderingViewModel.h b/src/cascadia/TerminalSettingsEditor/RenderingViewModel.h index 663d4cef877..b3042d893a1 100644 --- a/src/cascadia/TerminalSettingsEditor/RenderingViewModel.h +++ b/src/cascadia/TerminalSettingsEditor/RenderingViewModel.h @@ -4,6 +4,7 @@ #pragma once #include "RenderingViewModel.g.h" +#include "Utils.h" #include "ViewModelHelpers.h" namespace winrt::Microsoft::Terminal::Settings::Editor::implementation @@ -12,7 +13,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { explicit RenderingViewModel(Model::CascadiaSettings settings) noexcept; - PERMANENT_OBSERVABLE_PROJECTED_SETTING(_settings.GlobalSettings(), ForceFullRepaintRendering); + GETSET_BINDABLE_ENUM_SETTING(GraphicsAPI, winrt::Microsoft::Terminal::Control::GraphicsAPI, _settings.GlobalSettings().GraphicsAPI); + PERMANENT_OBSERVABLE_PROJECTED_SETTING(_settings.GlobalSettings(), DisablePartialInvalidation); PERMANENT_OBSERVABLE_PROJECTED_SETTING(_settings.GlobalSettings(), SoftwareRendering); private: diff --git a/src/cascadia/TerminalSettingsEditor/RenderingViewModel.idl b/src/cascadia/TerminalSettingsEditor/RenderingViewModel.idl index aa728bfad03..1ca164fbd97 100644 --- a/src/cascadia/TerminalSettingsEditor/RenderingViewModel.idl +++ b/src/cascadia/TerminalSettingsEditor/RenderingViewModel.idl @@ -11,7 +11,9 @@ namespace Microsoft.Terminal.Settings.Editor { RenderingViewModel(Microsoft.Terminal.Settings.Model.CascadiaSettings settings); - PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ForceFullRepaintRendering); + IInspectable CurrentGraphicsAPI; + Windows.Foundation.Collections.IObservableVector GraphicsAPIList { get; }; + PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, DisablePartialInvalidation); PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, SoftwareRendering); } } diff --git a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw index 5c27fe81845..13a0809dfd4 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw @@ -311,13 +311,13 @@ Die Terminalanwendung, die gestartet wird, wenn eine Befehlszeilenanwendung ohne vorhandene Sitzung gestartet wird, beispielsweise vom Startmenü oder über das Dialogfeld "Ausführen". A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Gesamten Bildschirm beim Anzeigen von Updates aktualisieren Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Wenn diese Option deaktiviert ist, rendert das Terminal die Aktualisierungen nur zwischen den Frames auf den Bildschirm. - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Spalten @@ -446,10 +446,6 @@ An das zuletzt verwendete Fenster auf diesem Desktop anhängen An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Diese Einstellungen eignen sich möglicherweise für die Problembehandlung, Sie wirken sich jedoch auf die Leistung aus. - A disclaimer presented at the top of a page. - Titelleiste ausblenden (Neustart erforderlich) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index 5bb762f6b22..e8995079ead 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -311,13 +311,38 @@ The terminal application that launches when a command-line application is run without an existing session, like from the Start Menu or Run dialog. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - Redraw entire screen when display updates - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. + + Graphics API + This text is shown next to a list of choices. - - When disabled, the terminal will render only the updates to the screen between frames. - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + + Direct3D 11 provides a more performant and feature-rich experience, whereas Direct2D is more stable. The default option "Automatic" will pick the API that best fits your graphics hardware. If you experience significant issues, consider using Direct2D. + + + Automatic + The default choice between multiple graphics APIs. + + + Direct2D + + + Direct3D 11 + + + Disable partial Swap Chain invalidation + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + + + By default, the text renderer uses a FLIP_SEQUENTIAL Swap Chain and declares dirty rectangles via the Present1 API. When this setting is enabled, a FLIP_DISCARD Swap Chain will be used instead, and no dirty rectangles will be declared. Whether one or the other is better depends on your hardware and various other factors. + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Use software rendering (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + When enabled, the terminal will use a software rasterizer (WARP). This setting should be left disabled under almost all circumstances. + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". Columns @@ -446,10 +471,6 @@ Attach to the most recently used window on this desktop An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - These settings may be useful for troubleshooting an issue, however they will impact your performance. - A disclaimer presented at the top of a page. - Hide the title bar (requires relaunch) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. @@ -478,14 +499,6 @@ When disabled, the window will resize smoothly. A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Use software rendering - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - When enabled, the terminal will use the software renderer (a.k.a. WARP) instead of the hardware one. - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - Launch on machine startup Header for a control to toggle whether the app should launch when the user's machine starts up, or not. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw index ef08ff08fe1..76400095b16 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw @@ -311,13 +311,13 @@ Aplicación de terminal que se inicia cuando se ejecuta una aplicación de línea de comandos sin una sesión existente, como en el menú Inicio o en el cuadro de diálogo Ejecutar. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Redibujar toda la pantalla cuando se muestren actualizaciones Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Cuando está deshabilitada, el terminal representará solo las actualizaciones de la pantalla entre fotogramas. - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Columnas @@ -446,10 +446,6 @@ Adjuntar a la ventana de uso más reciente en este escritorio An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Esta configuración puede ser útil para solucionar un problema, pero afectará al rendimiento. - A disclaimer presented at the top of a page. - Ocultar la barra de título (requiere reiniciar) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw index 37caf840fca..2887b95e286 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw @@ -311,13 +311,13 @@ L’application Terminal qui se lance lorsqu’une application de ligne de commande est exécutée sans session existante, par exemple à partir du menu Démarrer ou de la boîte de dialogue Exécuter. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Redessiner l’intégralité de l’écran entre chaque trame Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Une fois désactivé, le terminal n’affiche à l’écran que les modifications effectuées entre les trames. - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Colonnes @@ -446,10 +446,6 @@ Attacher à la dernière fenêtre utilisée sur ce bureau An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Ces paramètres permettent parfois de résoudre des problèmes, mais ont un impact sur la performance. - A disclaimer presented at the top of a page. - Masquer la barre de titre (redémarrage nécessaire) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw index cd06973a50e..4ce446f17ba 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw @@ -311,13 +311,13 @@ L'applicazione terminale che viene avviata quando viene eseguita un'applicazione della riga di comando senza una sessione esistente, ad esempio dalla finestra di dialogo menu Start o Esegui. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Ridisegna l'intero schermo durante la visualizzazione degli aggiornamenti Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Se disabilitato, il terminale eseguirà il rendering solo degli aggiornamenti sullo schermo tra i fotogrammi. - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Colonne @@ -446,10 +446,6 @@ Allega alla finestra usata più di recente su questo desktop An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Queste impostazioni potrebbero essere utili per la risoluzione di un problema, ma influiranno sulle prestazioni. - A disclaimer presented at the top of a page. - Nascondi la barra del titolo (sarà necessario riavviare) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw index a8935f14470..d57a8288d57 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw @@ -311,13 +311,13 @@ [スタート] メニューや [ファイル名を指定して実行] ダイアログなど、既存のセッションなしでコマンドライン アプリケーションを実行したときに起動するターミナル アプリケーション。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + ディスプレイの更新時に画面全体を再描画する Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + 無効にすると、ターミナルはフレームとフレームの間において情報更新分のみレンダリングします。 - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". @@ -446,10 +446,6 @@ このデスクトップで最近使用したウィンドウに接続する An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - これらの設定は問題のトラブルシューティングに役立つ場合がありますが、パフォーマンスに影響を与えます。 - A disclaimer presented at the top of a page. - タイトル バーを非表示にする (再起動が必要) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw index 9c8f8e9663f..aef454bd85d 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw @@ -311,13 +311,13 @@ 시작 메뉴나 실행 대화 상자와 같이 기존 세션이 없으면 명령 줄 응용 프로그램을 실행하고 있는 터미널 응용 프로그램입니다. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + 업데이트를 표시할 때 전체 화면 다시 그리기 Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + 사용하지 않도록 설정하면 터미널이 프레임 간 화면 업데이트만 렌더링합니다. - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". @@ -446,10 +446,6 @@ 이 데스크톱에서 가장 최근에 사용한 창에 첨부 An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - 이런 설정은 문제를 해결하는 데는 유용할 수 있지만 성능에 영향을 미칩니다. - A disclaimer presented at the top of a page. - 제목 표시줄 숨기기(다시 시작해야 함) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw index 543cb2ec43d..56fff0a611d 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw @@ -311,13 +311,13 @@ O aplicativo de terminal que é iniciado quando um aplicativo de linha de comando é executado sem uma sessão existente, como no menu iniciar ou na caixa de diálogo Executar. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Redesenhar a tela inteira ao exibir atualizações Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Quando desabilitado, o terminal renderizará somente as atualizações na tela entre quadros. - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Colunas @@ -446,10 +446,6 @@ Anexar à última janela usada nesta área de trabalho An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Essas configurações podem ser úteis para solucionar um problema, no entanto, elas impactarão seu desempenho. - A disclaimer presented at the top of a page. - Oculta a barra do título (requer reinicialização) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw index f7193ce8d63..f954fb623fb 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw @@ -311,13 +311,13 @@ Ťђě ţэřмīηãĺ ǻφφℓï¢ǻтΐбň ŧђáт łáůйčĥēś ẅĥэп ā сöмmǻńđ-ľіʼnэ ăρρĺįċāτΐôⁿ ϊš яųñ шíţћöυţ ªņ ĕхϊŝŧĭñğ şěŝѕïŏπ, ŀĩĸė ƒѓом ţћĕ Ŝτáґт Μęπü бг Яųņ ďīäℓöğ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Ŗёδѓªŵ еñţιŗę šĉřέëŋ шн℮й đĩşρℓâў υρďάţëš !!! !!! !!! !!! Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Щħ℮п đįѕāъĺèđ, ťђέ тèřмΐņäľ ωìľľ řεʼnďęŗ όʼnľŷ ŧђέ ŭρďăţзŝ τö ŧђë šсгèзņ вêţшзэʼn ƒяāméş. !!! !!! !!! !!! !!! !!! !!! !!! ! - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Ċσŀùмñѕ !! @@ -446,10 +446,6 @@ Äţŧαĉђ τǿ τħе mοѕт ѓěςęńτļγ ûѕєď ŵíñðοω øи тћϊѕ ďёšкτǿφ !!! !!! !!! !!! !!! ! An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Τћέŝė ѕëτтίņģš мâу ьê üѕēƒµľ ƒόґ τřóųьŀėѕĥбοτілġ ǻл іŝśü℮, нσώéνєŕ τĥêў ŵīŀł ΐmρåςť убŭя ρěгƒόґмåñĉę. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! - A disclaimer presented at the top of a page. - Ĥìđε тħê τīţĺё ъªř (ŗėqūΐŗêś яеľаϋʼnčћ) !!! !!! !!! !! Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw index f7193ce8d63..f954fb623fb 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw @@ -311,13 +311,13 @@ Ťђě ţэřмīηãĺ ǻφφℓï¢ǻтΐбň ŧђáт łáůйčĥēś ẅĥэп ā сöмmǻńđ-ľіʼnэ ăρρĺįċāτΐôⁿ ϊš яųñ шíţћöυţ ªņ ĕхϊŝŧĭñğ şěŝѕïŏπ, ŀĩĸė ƒѓом ţћĕ Ŝτáґт Μęπü бг Яųņ ďīäℓöğ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Ŗёδѓªŵ еñţιŗę šĉřέëŋ шн℮й đĩşρℓâў υρďάţëš !!! !!! !!! !!! Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Щħ℮п đįѕāъĺèđ, ťђέ тèřмΐņäľ ωìľľ řεʼnďęŗ όʼnľŷ ŧђέ ŭρďăţзŝ τö ŧђë šсгèзņ вêţшзэʼn ƒяāméş. !!! !!! !!! !!! !!! !!! !!! !!! ! - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Ċσŀùмñѕ !! @@ -446,10 +446,6 @@ Äţŧαĉђ τǿ τħе mοѕт ѓěςęńτļγ ûѕєď ŵíñðοω øи тћϊѕ ďёšкτǿφ !!! !!! !!! !!! !!! ! An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Τћέŝė ѕëτтίņģš мâу ьê üѕēƒµľ ƒόґ τřóųьŀėѕĥбοτілġ ǻл іŝśü℮, нσώéνєŕ τĥêў ŵīŀł ΐmρåςť убŭя ρěгƒόґмåñĉę. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! - A disclaimer presented at the top of a page. - Ĥìđε тħê τīţĺё ъªř (ŗėqūΐŗêś яеľаϋʼnčћ) !!! !!! !!! !! Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw index f7193ce8d63..f954fb623fb 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw @@ -311,13 +311,13 @@ Ťђě ţэřмīηãĺ ǻφφℓï¢ǻтΐбň ŧђáт łáůйčĥēś ẅĥэп ā сöмmǻńđ-ľіʼnэ ăρρĺįċāτΐôⁿ ϊš яųñ шíţћöυţ ªņ ĕхϊŝŧĭñğ şěŝѕïŏπ, ŀĩĸė ƒѓом ţћĕ Ŝτáґт Μęπü бг Яųņ ďīäℓöğ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Ŗёδѓªŵ еñţιŗę šĉřέëŋ шн℮й đĩşρℓâў υρďάţëš !!! !!! !!! !!! Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Щħ℮п đįѕāъĺèđ, ťђέ тèřмΐņäľ ωìľľ řεʼnďęŗ όʼnľŷ ŧђέ ŭρďăţзŝ τö ŧђë šсгèзņ вêţшзэʼn ƒяāméş. !!! !!! !!! !!! !!! !!! !!! !!! ! - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Ċσŀùмñѕ !! @@ -446,10 +446,6 @@ Äţŧαĉђ τǿ τħе mοѕт ѓěςęńτļγ ûѕєď ŵíñðοω øи тћϊѕ ďёšкτǿφ !!! !!! !!! !!! !!! ! An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Τћέŝė ѕëτтίņģš мâу ьê üѕēƒµľ ƒόґ τřóųьŀėѕĥбοτілġ ǻл іŝśü℮, нσώéνєŕ τĥêў ŵīŀł ΐmρåςť убŭя ρěгƒόґмåñĉę. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! - A disclaimer presented at the top of a page. - Ĥìđε тħê τīţĺё ъªř (ŗėqūΐŗêś яеľаϋʼnčћ) !!! !!! !!! !! Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw index 3af0c8f8f6b..c935675a936 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw @@ -311,13 +311,13 @@ Приложение терминала, запускаемое при запуске приложения командной строки без существующего сеанса, например из меню "Пуск" или из диалогового окна "Выполнить". A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + Перерисовка всего экрана при обновлении дисплея Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + Если этот параметр отключен, терминал будет отображать только обновления экрана между кадрами. - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". Столбцы @@ -446,10 +446,6 @@ Присоединять к последнему использованному окну на этом рабочем столе An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - Эти параметры могут быть полезны для устранения проблемы, но они повлияют на вашу производительность. - A disclaimer presented at the top of a page. - Скрыть заголовок окна (требуется перезапуск) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw index 0d602e9adc0..44f22000ddb 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw @@ -311,13 +311,13 @@ 当命令行应用程序在没有现有会话(例如从“开始菜单”或“运行”对话框)运行时启动的终端应用程序。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + 显示内容更新时重绘整个屏幕 Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + 禁用后,终端将仅在帧之间将更新呈现到屏幕。 - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". @@ -446,10 +446,6 @@ 附加到此桌面上最近使用的窗口 An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - 这些设置可能有助于解决问题,但会对性能产生影响。 - A disclaimer presented at the top of a page. - 隐藏标题栏(需要重新启动) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw index 1b1ffb8bbf2..13ab841670c 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw @@ -311,13 +311,13 @@ 當執行命令列應用程式且不使用現有工作模式而啟動的終端機應用程式 (例如從 [開始] 功能表或 [執行] 對話方塊)。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - + 顯示更新時,重新繪製整個螢幕 Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - + 停用時,終端機只會轉譯框架間螢幕的更新。 - A description for what the "force full repaint" setting does. Presented near "Globals_ForceFullRepaint.Header". + A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". @@ -446,10 +446,6 @@ 附加到此桌面最近使用的視窗 An option to choose from for the "windowing behavior" setting. When selected, new instances open in the most recently used window on this virtual desktop. - - 這些設定可能有助於解決問題,但會影響效能。 - A disclaimer presented at the top of a page. - 隱藏標題列 (需要重新啟動) Header for a control to toggle whether the title bar should be shown or not. Changing this setting requires the user to relaunch the app. diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp index 8b3d936a4a3..15665908b78 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp @@ -39,6 +39,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation DEFINE_ENUM_MAP(Microsoft::Terminal::Control::CopyFormat, CopyFormat); DEFINE_ENUM_MAP(Model::WindowingMode, WindowingMode); DEFINE_ENUM_MAP(Microsoft::Terminal::Core::MatchMode, MatchMode); + DEFINE_ENUM_MAP(Microsoft::Terminal::Control::GraphicsAPI, GraphicsAPI); // Profile Settings DEFINE_ENUM_MAP(Model::CloseOnExitMode, CloseOnExitMode); diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.h b/src/cascadia/TerminalSettingsModel/EnumMappings.h index dfdd6c46502..722ce920953 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.h +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.h @@ -35,6 +35,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static winrt::Windows::Foundation::Collections::IMap CopyFormat(); static winrt::Windows::Foundation::Collections::IMap WindowingMode(); static winrt::Windows::Foundation::Collections::IMap MatchMode(); + static winrt::Windows::Foundation::Collections::IMap GraphicsAPI(); // Profile Settings static winrt::Windows::Foundation::Collections::IMap CloseOnExitMode(); diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.idl b/src/cascadia/TerminalSettingsModel/EnumMappings.idl index a74dc96b483..11801182999 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.idl +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.idl @@ -17,6 +17,7 @@ namespace Microsoft.Terminal.Settings.Model static Windows.Foundation.Collections.IMap CopyFormat { get; }; static Windows.Foundation.Collections.IMap WindowingMode { get; }; static Windows.Foundation.Collections.IMap MatchMode { get; }; + static Windows.Foundation.Collections.IMap GraphicsAPI { get; }; // Profile Settings static Windows.Foundation.Collections.IMap CloseOnExitMode { get; }; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index 7238d38c0cd..c307050a998 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -220,8 +220,24 @@ const std::vector // Return Value: // - the JsonObject representing this instance -Json::Value GlobalAppSettings::ToJson() const +Json::Value GlobalAppSettings::ToJson() { + // These experimental options should be removed from the settings file if they're at their default value. + // This prevents them from sticking around forever, even if the user was just experimenting with them. + // One could consider this a workaround for the settings UI right now not having a "reset to default" button for these. + if (_GraphicsAPI == Control::GraphicsAPI::Automatic) + { + _GraphicsAPI.reset(); + } + if (_DisablePartialInvalidation == false) + { + _DisablePartialInvalidation.reset(); + } + if (_SoftwareRendering == false) + { + _SoftwareRendering.reset(); + } + Json::Value json{ Json::ValueType::objectValue }; JsonUtils::SetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile); diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h index aa7d8c0147f..c977094df53 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h @@ -52,7 +52,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation void LayerJson(const Json::Value& json, const OriginTag origin); void LayerActionsFrom(const Json::Value& json, const OriginTag origin, const bool withKeybindings = true); - Json::Value ToJson() const; + Json::Value ToJson(); const std::vector& KeybindingsWarnings() const; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl index 612262d4b11..7e46bcc0517 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl @@ -76,7 +76,8 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_SETTING(FirstWindowPreference, FirstWindowPreference); INHERITABLE_SETTING(LaunchMode, LaunchMode); INHERITABLE_SETTING(Boolean, SnapToGridOnResize); - INHERITABLE_SETTING(Boolean, ForceFullRepaintRendering); + INHERITABLE_SETTING(Microsoft.Terminal.Control.GraphicsAPI, GraphicsAPI); + INHERITABLE_SETTING(Boolean, DisablePartialInvalidation); INHERITABLE_SETTING(Boolean, SoftwareRendering); INHERITABLE_SETTING(Boolean, UseBackgroundImageForWindow); INHERITABLE_SETTING(Boolean, ForceVTInput); diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index cb8eb8bcdff..b4c678fd997 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -24,8 +24,9 @@ Author(s): X(hstring, WordDelimiters, "wordDelimiters", DEFAULT_WORD_DELIMITERS) \ X(bool, CopyOnSelect, "copyOnSelect", false) \ X(bool, FocusFollowMouse, "focusFollowMouse", false) \ - X(bool, ForceFullRepaintRendering, "experimental.rendering.forceFullRepaint", false) \ - X(bool, SoftwareRendering, "experimental.rendering.software", false) \ + X(winrt::Microsoft::Terminal::Control::GraphicsAPI, GraphicsAPI, "rendering.graphicsAPI") \ + X(bool, DisablePartialInvalidation, "rendering.disablePartialInvalidation", false) \ + X(bool, SoftwareRendering, "rendering.software", false) \ X(bool, UseBackgroundImageForWindow, "experimental.useBackgroundImageForWindow", false) \ X(bool, ForceVTInput, "experimental.input.forceVT", false) \ X(bool, TrimBlockSelection, "trimBlockSelection", true) \ diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp index e5c07a71103..682d79e19c7 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp @@ -360,7 +360,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation _CopyOnSelect = globalSettings.CopyOnSelect(); _CopyFormatting = globalSettings.CopyFormatting(); _FocusFollowMouse = globalSettings.FocusFollowMouse(); - _ForceFullRepaintRendering = globalSettings.ForceFullRepaintRendering(); + _GraphicsAPI = globalSettings.GraphicsAPI(); + _DisablePartialInvalidation = globalSettings.DisablePartialInvalidation(); _SoftwareRendering = globalSettings.SoftwareRendering(); _UseBackgroundImageForWindow = globalSettings.UseBackgroundImageForWindow(); _ForceVTInput = globalSettings.ForceVTInput(); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.h b/src/cascadia/TerminalSettingsModel/TerminalSettings.h index 184e05ac8f9..99e3b2d120e 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.h @@ -155,7 +155,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale); INHERITABLE_SETTING(Model::TerminalSettings, bool, RetroTerminalEffect, false); - INHERITABLE_SETTING(Model::TerminalSettings, bool, ForceFullRepaintRendering, false); + INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::GraphicsAPI, GraphicsAPI); + INHERITABLE_SETTING(Model::TerminalSettings, bool, DisablePartialInvalidation, false); INHERITABLE_SETTING(Model::TerminalSettings, bool, SoftwareRendering, false); INHERITABLE_SETTING(Model::TerminalSettings, bool, UseBackgroundImageForWindow, false); INHERITABLE_SETTING(Model::TerminalSettings, bool, ForceVTInput, false); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index f1f2bc11048..1168e0660fb 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -761,3 +761,12 @@ struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<::winr return "SelectionColor (#rrggbb, #rgb, #rrggbbaa, iNN)"; } }; + +JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::GraphicsAPI) +{ + JSON_MAPPINGS(3) = { + pair_type{ "automatic", ValueType::Automatic }, + pair_type{ "direct2d", ValueType::Direct2D }, + pair_type{ "direct3d11", ValueType::Direct3D11 }, + }; +}; diff --git a/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp b/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp index 455c0b78c27..8cfd4a14ccf 100644 --- a/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp +++ b/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp @@ -107,8 +107,6 @@ namespace SettingsModelUnitTests "trimPaste": true, "experimental.input.forceVT": false, - "experimental.rendering.forceFullRepaint": false, - "experimental.rendering.software": false, "actions": [] })" }; diff --git a/src/cascadia/inc/ControlProperties.h b/src/cascadia/inc/ControlProperties.h index a7700b04958..faf5fc6a756 100644 --- a/src/cascadia/inc/ControlProperties.h +++ b/src/cascadia/inc/ControlProperties.h @@ -73,7 +73,8 @@ X(winrt::hstring, StartingDirectory) \ X(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible) \ X(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \ - X(bool, ForceFullRepaintRendering, false) \ + X(winrt::Microsoft::Terminal::Control::GraphicsAPI, GraphicsAPI) \ + X(bool, DisablePartialInvalidation, false) \ X(bool, SoftwareRendering, false) \ X(bool, UseBackgroundImageForWindow, false) \ X(bool, ShowMarks, false) \ diff --git a/src/cppwinrt.build.pre.props b/src/cppwinrt.build.pre.props index ad36921e7b4..7fae29094ed 100644 --- a/src/cppwinrt.build.pre.props +++ b/src/cppwinrt.build.pre.props @@ -9,7 +9,6 @@ - AnyValueHereWillDisableTheOptOut true true en-US diff --git a/src/renderer/atlas/AtlasEngine.api.cpp b/src/renderer/atlas/AtlasEngine.api.cpp index a29c5e7779a..f739022e8a4 100644 --- a/src/renderer/atlas/AtlasEngine.api.cpp +++ b/src/renderer/atlas/AtlasEngine.api.cpp @@ -316,33 +316,18 @@ CATCH_RETURN() #pragma endregion -#pragma region DxRenderer - -HRESULT AtlasEngine::Enable() noexcept -{ - return S_OK; -} +#pragma region getter [[nodiscard]] std::wstring_view AtlasEngine::GetPixelShaderPath() noexcept { return _api.s->misc->customPixelShaderPath; } -[[nodiscard]] std::wstring_view AtlasEngine::GetPixelShaderImagePath() noexcept -{ - return _api.s->misc->customPixelShaderImagePath; -} - [[nodiscard]] bool AtlasEngine::GetRetroTerminalEffect() const noexcept { return _api.s->misc->useRetroTerminalEffect; } -[[nodiscard]] float AtlasEngine::GetScaling() const noexcept -{ - return static_cast(_api.s->font->dpi) / static_cast(USER_DEFAULT_SCREEN_DPI); -} - [[nodiscard]] Microsoft::Console::Types::Viewport AtlasEngine::GetViewportInCharacters(const Types::Viewport& viewInPixels) const noexcept { assert(_api.s->font->cellSize.x != 0); @@ -357,6 +342,10 @@ HRESULT AtlasEngine::Enable() noexcept return Types::Viewport::FromDimensions(viewInCharacters.Origin(), { viewInCharacters.Width() * _api.s->font->cellSize.x, viewInCharacters.Height() * _api.s->font->cellSize.y }); } +#pragma endregion + +#pragma region setter + void AtlasEngine::SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept { const auto mode = static_cast(antialiasingMode); @@ -381,10 +370,6 @@ void AtlasEngine::EnableTransparentBackground(const bool isTransparent) noexcept } } -void AtlasEngine::SetForceFullRepaintRendering(bool enable) noexcept -{ -} - [[nodiscard]] HRESULT AtlasEngine::SetHwnd(const HWND hwnd) noexcept { if (_api.s->target->hwnd != hwnd) @@ -436,9 +421,25 @@ void AtlasEngine::SetSelectionBackground(const COLORREF color, const float alpha void AtlasEngine::SetSoftwareRendering(bool enable) noexcept { - if (_api.s->target->useSoftwareRendering != enable) + if (_api.s->target->useWARP != enable) + { + _api.s.write()->target.write()->useWARP = enable; + } +} + +void AtlasEngine::SetDisablePartialInvalidation(bool enable) noexcept +{ + if (_api.s->target->disablePresent1 != enable) + { + _api.s.write()->target.write()->disablePresent1 = enable; + } +} + +void AtlasEngine::SetGraphicsAPI(GraphicsAPI graphicsAPI) noexcept +{ + if (_api.s->target->graphicsAPI != graphicsAPI) { - _api.s.write()->target.write()->useSoftwareRendering = enable; + _api.s.write()->target.write()->graphicsAPI = graphicsAPI; } } diff --git a/src/renderer/atlas/AtlasEngine.cpp b/src/renderer/atlas/AtlasEngine.cpp index f7ed91b169a..e05e5b033eb 100644 --- a/src/renderer/atlas/AtlasEngine.cpp +++ b/src/renderer/atlas/AtlasEngine.cpp @@ -550,7 +550,7 @@ void AtlasEngine::_handleSettingsUpdate() if (targetChanged) { - // target->useSoftwareRendering affects the selection of our IDXGIAdapter which requires us to reset _p.dxgi. + // target->useWARP affects the selection of our IDXGIAdapter which requires us to reset _p.dxgi. // This will indirectly also recreate the backend, when AtlasEngine::_recreateAdapter() detects this change. _p.dxgi = {}; } diff --git a/src/renderer/atlas/AtlasEngine.h b/src/renderer/atlas/AtlasEngine.h index 1c238dad048..b75a2a5cdce 100644 --- a/src/renderer/atlas/AtlasEngine.h +++ b/src/renderer/atlas/AtlasEngine.h @@ -57,31 +57,29 @@ namespace Microsoft::Console::Render::Atlas [[nodiscard]] HRESULT GetFontSize(_Out_ til::size* pFontSize) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(std::wstring_view glyph, _Out_ bool* pResult) noexcept override; [[nodiscard]] HRESULT UpdateTitle(std::wstring_view newTitle) noexcept override; - - // DxRenderer - getter - HRESULT Enable() noexcept override; - [[nodiscard]] std::wstring_view GetPixelShaderPath() noexcept override; - [[nodiscard]] std::wstring_view GetPixelShaderImagePath() noexcept override; - [[nodiscard]] bool GetRetroTerminalEffect() const noexcept override; - [[nodiscard]] float GetScaling() const noexcept override; - [[nodiscard]] Types::Viewport GetViewportInCharacters(const Types::Viewport& viewInPixels) const noexcept override; - [[nodiscard]] Types::Viewport GetViewportInPixels(const Types::Viewport& viewInCharacters) const noexcept override; - // DxRenderer - setter - void SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept override; - void SetCallback(std::function pfn) noexcept override; - void EnableTransparentBackground(const bool isTransparent) noexcept override; - void SetForceFullRepaintRendering(bool enable) noexcept override; - [[nodiscard]] HRESULT SetHwnd(HWND hwnd) noexcept override; - void SetPixelShaderPath(std::wstring_view value) noexcept override; - void SetPixelShaderImagePath(std::wstring_view value) noexcept override; - void SetRetroTerminalEffect(bool enable) noexcept override; - void SetSelectionBackground(COLORREF color, float alpha = 0.5f) noexcept override; - void SetSoftwareRendering(bool enable) noexcept override; - void SetWarningCallback(std::function pfn) noexcept override; - [[nodiscard]] HRESULT SetWindowSize(til::size pixels) noexcept override; - [[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& pfiFontInfoDesired, FontInfo& fiFontInfo, const std::unordered_map& features, const std::unordered_map& axes) noexcept override; void UpdateHyperlinkHoveredId(uint16_t hoveredId) noexcept override; + // getter + [[nodiscard]] std::wstring_view GetPixelShaderPath() noexcept; + [[nodiscard]] bool GetRetroTerminalEffect() const noexcept; + [[nodiscard]] Types::Viewport GetViewportInCharacters(const Types::Viewport& viewInPixels) const noexcept; + [[nodiscard]] Types::Viewport GetViewportInPixels(const Types::Viewport& viewInCharacters) const noexcept; + // setter + void SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept; + void SetCallback(std::function pfn) noexcept; + void EnableTransparentBackground(const bool isTransparent) noexcept; + [[nodiscard]] HRESULT SetHwnd(HWND hwnd) noexcept; + void SetPixelShaderPath(std::wstring_view value) noexcept; + void SetPixelShaderImagePath(std::wstring_view value) noexcept; + void SetRetroTerminalEffect(bool enable) noexcept; + void SetSelectionBackground(COLORREF color, float alpha = 0.5f) noexcept; + void SetSoftwareRendering(bool enable) noexcept; + void SetDisablePartialInvalidation(bool enable) noexcept; + void SetGraphicsAPI(GraphicsAPI graphicsAPI) noexcept; + void SetWarningCallback(std::function pfn) noexcept; + [[nodiscard]] HRESULT SetWindowSize(til::size pixels) noexcept; + [[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& pfiFontInfoDesired, FontInfo& fiFontInfo, const std::unordered_map& features, const std::unordered_map& axes) noexcept; + private: // AtlasEngine.cpp ATLAS_ATTR_COLD void _handleSettingsUpdate(); diff --git a/src/renderer/atlas/AtlasEngine.r.cpp b/src/renderer/atlas/AtlasEngine.r.cpp index 0c546a8dceb..ac87c246dc9 100644 --- a/src/renderer/atlas/AtlasEngine.r.cpp +++ b/src/renderer/atlas/AtlasEngine.r.cpp @@ -134,7 +134,7 @@ void AtlasEngine::_recreateAdapter() DXGI_ADAPTER_DESC1 desc{}; { - const auto useSoftwareRendering = _p.s->target->useSoftwareRendering; + const auto useWARP = _p.s->target->useWARP; UINT index = 0; do @@ -142,13 +142,13 @@ void AtlasEngine::_recreateAdapter() THROW_IF_FAILED(_p.dxgi.factory->EnumAdapters1(index++, adapter.put())); THROW_IF_FAILED(adapter->GetDesc1(&desc)); - // If useSoftwareRendering is false we exit during the first iteration. Using the default adapter (index 0) + // If useWARP is false we exit during the first iteration. Using the default adapter (index 0) // is the right thing to do under most circumstances, unless you _really_ want to get your hands dirty. // The alternative is to track the window rectangle in respect to all IDXGIOutputs and select the right // IDXGIAdapter, while also considering the "graphics preference" override in the windows settings app, etc. // - // If useSoftwareRendering is true we search until we find the first WARP adapter (usually the last adapter). - } while (useSoftwareRendering && WI_IsFlagClear(desc.Flags, DXGI_ADAPTER_FLAG_SOFTWARE)); + // If useWARP is true we search until we find the first WARP adapter (usually the last adapter). + } while (useWARP && WI_IsFlagClear(desc.Flags, DXGI_ADAPTER_FLAG_SOFTWARE)); } if (memcmp(&_p.dxgi.adapterLuid, &desc.AdapterLuid, sizeof(LUID)) != 0) @@ -166,7 +166,8 @@ void AtlasEngine::_recreateBackend() // HWND, IWindow, or composition surface at a time. --> Destroy it while we still have the old device. _destroySwapChain(); - auto d2dMode = ATLAS_DEBUG_FORCE_D2D_MODE; + auto graphicsAPI = _p.s->target->graphicsAPI; + auto deviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED #ifndef NDEBUG @@ -182,8 +183,14 @@ void AtlasEngine::_recreateBackend() if (WI_IsFlagSet(_p.dxgi.adapterFlags, DXGI_ADAPTER_FLAG_SOFTWARE)) { + // If we're using WARP we don't want to disable those optimizations of course. WI_ClearFlag(deviceFlags, D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS); - d2dMode = true; + + // I'm not sure whether Direct2D is actually faster on WARP, but it's definitely better tested. + if (graphicsAPI == GraphicsAPI::Automatic) + { + graphicsAPI = GraphicsAPI::Direct2D; + } } wil::com_ptr device0; @@ -202,17 +209,16 @@ void AtlasEngine::_recreateBackend() #pragma warning(suppress : 26496) // The variable 'hr' does not change after construction, mark it as const (con.4). auto hr = D3D11CreateDevice( - /* pAdapter */ _p.dxgi.adapter.get(), - /* DriverType */ D3D_DRIVER_TYPE_UNKNOWN, - /* Software */ nullptr, - /* Flags */ deviceFlags, - /* pFeatureLevels */ featureLevels.data(), - /* FeatureLevels */ gsl::narrow_cast(featureLevels.size()), - /* SDKVersion */ D3D11_SDK_VERSION, - /* ppDevice */ device0.put(), - /* pFeatureLevel */ &featureLevel, + /* pAdapter */ _p.dxgi.adapter.get(), + /* DriverType */ D3D_DRIVER_TYPE_UNKNOWN, + /* Software */ nullptr, + /* Flags */ deviceFlags, + /* pFeatureLevels */ featureLevels.data(), + /* FeatureLevels */ gsl::narrow_cast(featureLevels.size()), + /* SDKVersion */ D3D11_SDK_VERSION, + /* ppDevice */ device0.put(), + /* pFeatureLevel */ &featureLevel, /* ppImmediateContext */ deviceContext0.put()); - #ifndef NDEBUG if (hr == DXGI_ERROR_SDK_COMPONENT_MISSING) { @@ -222,15 +228,15 @@ void AtlasEngine::_recreateBackend() WI_ClearFlag(deviceFlags, D3D11_CREATE_DEVICE_DEBUG); hr = D3D11CreateDevice( - /* pAdapter */ _p.dxgi.adapter.get(), - /* DriverType */ D3D_DRIVER_TYPE_UNKNOWN, - /* Software */ nullptr, - /* Flags */ deviceFlags, - /* pFeatureLevels */ featureLevels.data(), - /* FeatureLevels */ gsl::narrow_cast(featureLevels.size()), - /* SDKVersion */ D3D11_SDK_VERSION, - /* ppDevice */ device0.put(), - /* pFeatureLevel */ &featureLevel, + /* pAdapter */ _p.dxgi.adapter.get(), + /* DriverType */ D3D_DRIVER_TYPE_UNKNOWN, + /* Software */ nullptr, + /* Flags */ deviceFlags, + /* pFeatureLevels */ featureLevels.data(), + /* FeatureLevels */ gsl::narrow_cast(featureLevels.size()), + /* SDKVersion */ D3D11_SDK_VERSION, + /* ppDevice */ device0.put(), + /* pFeatureLevel */ &featureLevel, /* ppImmediateContext */ deviceContext0.put()); } #endif @@ -252,37 +258,44 @@ void AtlasEngine::_recreateBackend() } #endif - if (featureLevel < D3D_FEATURE_LEVEL_10_0) - { - d2dMode = true; - } - else if (featureLevel < D3D_FEATURE_LEVEL_11_0) + if (graphicsAPI == GraphicsAPI::Automatic) { - D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS options{}; - // I'm assuming if `CheckFeatureSupport` fails, it'll leave `options` untouched which will result in `d2dMode |= true`. - std::ignore = device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(options)); - d2dMode |= !options.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x; + if (featureLevel < D3D_FEATURE_LEVEL_10_0) + { + graphicsAPI = GraphicsAPI::Direct2D; + } + else if (featureLevel < D3D_FEATURE_LEVEL_11_0) + { + D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS options{}; + if (FAILED(device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(options))) || + !options.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x) + { + graphicsAPI = GraphicsAPI::Direct2D; + } + } } _p.device = std::move(device); _p.deviceContext = std::move(deviceContext); - if (d2dMode) + switch (graphicsAPI) { + case GraphicsAPI::Direct2D: _b = std::make_unique(); - } - else - { + _hackIsBackendD2D = true; + break; + default: _b = std::make_unique(_p); + _hackIsBackendD2D = false; + break; } // This ensures that the backends redraw their entire viewports whenever a new swap chain is created, // EVEN IF we got called when no actual settings changed (i.e. rendering failure, etc.). _p.MarkAllAsDirty(); - const auto hackWantsBuiltinGlyphs = _p.s->font->builtinGlyphs && !d2dMode; + const auto hackWantsBuiltinGlyphs = _p.s->font->builtinGlyphs && !_hackIsBackendD2D; _hackTriggerRedrawAll = _hackWantsBuiltinGlyphs != hackWantsBuiltinGlyphs; - _hackIsBackendD2D = d2dMode; _hackWantsBuiltinGlyphs = hackWantsBuiltinGlyphs; } @@ -330,7 +343,7 @@ void AtlasEngine::_createSwapChain() // more "intelligent" composition and display updates to occur like Panel Self Refresh // (PSR) which requires dirty rectangles (Present1 API) to work correctly. // We were asked by DWM folks to use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL for this reason (PSR). - .SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, + .SwapEffect = _p.s->target->disablePresent1 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, // If our background is opaque we can enable "independent" flips by setting DXGI_ALPHA_MODE_IGNORE. // As our swap chain won't have to compose with DWM anymore it reduces the display latency dramatically. .AlphaMode = _p.s->target->useAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE, @@ -458,44 +471,39 @@ void AtlasEngine::_present() return; } - if constexpr (!ATLAS_DEBUG_SHOW_DIRTY) + if (!ATLAS_DEBUG_SHOW_DIRTY && !_p.s->target->disablePresent1 && memcmp(&dirtyRect, &fullRect, sizeof(RECT)) != 0) { - if (memcmp(&dirtyRect, &fullRect, sizeof(RECT)) != 0) - { - params.DirtyRectsCount = 1; - params.pDirtyRects = &dirtyRect; + params.DirtyRectsCount = 1; + params.pDirtyRects = &dirtyRect; - if (_p.scrollOffset) - { - const auto offsetInPx = _p.scrollOffset * _p.s->font->cellSize.y; - const auto width = _p.s->targetSize.x; - // We don't use targetSize.y here, because "height" refers to the bottom coordinate of the last text row - // in the buffer. We then add the "offsetInPx" (which is negative when scrolling text upwards) and thus - // end up with a "bottom" value that is the bottom of the last row of text that we haven't invalidated. - const auto height = _p.s->viewportCellCount.y * _p.s->font->cellSize.y; - const auto top = std::max(0, offsetInPx); - const auto bottom = height + std::min(0, offsetInPx); - - scrollRect = { 0, top, width, bottom }; - scrollOffset = { 0, offsetInPx }; - - params.pScrollRect = &scrollRect; - params.pScrollOffset = &scrollOffset; - } + if (_p.scrollOffset) + { + const auto offsetInPx = _p.scrollOffset * _p.s->font->cellSize.y; + const auto width = _p.s->targetSize.x; + // We don't use targetSize.y here, because "height" refers to the bottom coordinate of the last text row + // in the buffer. We then add the "offsetInPx" (which is negative when scrolling text upwards) and thus + // end up with a "bottom" value that is the bottom of the last row of text that we haven't invalidated. + const auto height = _p.s->viewportCellCount.y * _p.s->font->cellSize.y; + const auto top = std::max(0, offsetInPx); + const auto bottom = height + std::min(0, offsetInPx); + + scrollRect = { 0, top, width, bottom }; + scrollOffset = { 0, offsetInPx }; + + params.pScrollRect = &scrollRect; + params.pScrollOffset = &scrollOffset; } } + auto hr = _p.swapChain.swapChain->Present1(1, 0, ¶ms); if constexpr (Feature_AtlasEnginePresentFallback::IsEnabled()) { - if (FAILED_LOG(_p.swapChain.swapChain->Present1(1, 0, ¶ms))) + if (FAILED(hr) && params.DirtyRectsCount != 0) { - THROW_IF_FAILED(_p.swapChain.swapChain->Present(1, 0)); + hr = _p.swapChain.swapChain->Present(1, 0); } } - else - { - THROW_IF_FAILED(_p.swapChain.swapChain->Present1(1, 0, ¶ms)); - } + THROW_IF_FAILED(hr); _p.swapChain.waitForPresentation = true; } diff --git a/src/renderer/atlas/Backend.h b/src/renderer/atlas/Backend.h index cdeab63b12c..65da06acb93 100644 --- a/src/renderer/atlas/Backend.h +++ b/src/renderer/atlas/Backend.h @@ -30,9 +30,6 @@ namespace Microsoft::Console::Render::Atlas // This helps with benchmarking the application as it'll run beyond display refresh rate. #define ATLAS_DEBUG_DISABLE_FRAME_LATENCY_WAITABLE_OBJECT 0 - // Forces the use of Direct2D for text rendering (= BackendD2D). -#define ATLAS_DEBUG_FORCE_D2D_MODE 0 - // Adds an artificial delay before every render pass. In milliseconds. #define ATLAS_DEBUG_RENDER_DELAY 0 diff --git a/src/renderer/atlas/common.h b/src/renderer/atlas/common.h index 967191bdfbe..2e937baf04f 100644 --- a/src/renderer/atlas/common.h +++ b/src/renderer/atlas/common.h @@ -311,11 +311,20 @@ namespace Microsoft::Console::Render::Atlas DWRITE_SCRIPT_ANALYSIS analysis; }; + enum class GraphicsAPI + { + Automatic, + Direct2D, + Direct3D11, + }; + struct TargetSettings { HWND hwnd = nullptr; bool useAlpha = false; - bool useSoftwareRendering = false; + bool useWARP = false; + bool disablePresent1 = false; + GraphicsAPI graphicsAPI = GraphicsAPI::Automatic; }; enum class AntialiasingMode : u8 diff --git a/src/renderer/base/RenderEngineBase.cpp b/src/renderer/base/RenderEngineBase.cpp index 80c1f86cda1..224ff155f35 100644 --- a/src/renderer/base/RenderEngineBase.cpp +++ b/src/renderer/base/RenderEngineBase.cpp @@ -77,6 +77,10 @@ void RenderEngineBase::WaitUntilCanRender() noexcept Sleep(8); } +void RenderEngineBase::UpdateHyperlinkHoveredId(const uint16_t /*hoveredId*/) noexcept +{ +} + // Routine Description: // - Notifies us that we're about to circle the buffer, giving us a chance to // force a repaint before the buffer contents are lost. diff --git a/src/renderer/inc/IRenderEngine.hpp b/src/renderer/inc/IRenderEngine.hpp index 2d151364463..5dcaf17685a 100644 --- a/src/renderer/inc/IRenderEngine.hpp +++ b/src/renderer/inc/IRenderEngine.hpp @@ -90,33 +90,7 @@ namespace Microsoft::Console::Render [[nodiscard]] virtual HRESULT GetFontSize(_Out_ til::size* pFontSize) noexcept = 0; [[nodiscard]] virtual HRESULT IsGlyphWideByFont(std::wstring_view glyph, _Out_ bool* pResult) noexcept = 0; [[nodiscard]] virtual HRESULT UpdateTitle(std::wstring_view newTitle) noexcept = 0; - - // The following functions used to be specific to the DxRenderer and they should - // be abstracted away and integrated into the above or simply get removed. - - // DxRenderer - getter - virtual HRESULT Enable() noexcept { return S_OK; } - [[nodiscard]] virtual std::wstring_view GetPixelShaderPath() noexcept { return {}; } - [[nodiscard]] virtual std::wstring_view GetPixelShaderImagePath() noexcept { return {}; } - [[nodiscard]] virtual bool GetRetroTerminalEffect() const noexcept { return false; } - [[nodiscard]] virtual float GetScaling() const noexcept { return 1; } - [[nodiscard]] virtual Types::Viewport GetViewportInCharacters(const Types::Viewport& viewInPixels) const noexcept { return Types::Viewport::Empty(); } - [[nodiscard]] virtual Types::Viewport GetViewportInPixels(const Types::Viewport& viewInCharacters) const noexcept { return Types::Viewport::Empty(); } - // DxRenderer - setter - virtual void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept {} - virtual void SetCallback(std::function pfn) noexcept {} - virtual void EnableTransparentBackground(const bool isTransparent) noexcept {} - virtual void SetForceFullRepaintRendering(bool enable) noexcept {} - [[nodiscard]] virtual HRESULT SetHwnd(const HWND hwnd) noexcept { return E_NOTIMPL; } - virtual void SetPixelShaderPath(std::wstring_view value) noexcept {} - virtual void SetPixelShaderImagePath(std::wstring_view value) noexcept {} - virtual void SetRetroTerminalEffect(bool enable) noexcept {} - virtual void SetSelectionBackground(const COLORREF color, const float alpha = 0.5f) noexcept {} - virtual void SetSoftwareRendering(bool enable) noexcept {} - virtual void SetWarningCallback(std::function pfn) noexcept {} - [[nodiscard]] virtual HRESULT SetWindowSize(const til::size pixels) noexcept { return E_NOTIMPL; } - [[nodiscard]] virtual HRESULT UpdateFont(const FontInfoDesired& pfiFontInfoDesired, FontInfo& fiFontInfo, const std::unordered_map& features, const std::unordered_map& axes) noexcept { return E_NOTIMPL; } - virtual void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept {} + virtual void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept = 0; }; } #pragma warning(pop) diff --git a/src/renderer/inc/RenderEngineBase.hpp b/src/renderer/inc/RenderEngineBase.hpp index 8c33d59b1e7..6390f5fe7f6 100644 --- a/src/renderer/inc/RenderEngineBase.hpp +++ b/src/renderer/inc/RenderEngineBase.hpp @@ -46,6 +46,7 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT InvalidateFlush(_In_ const bool circled, _Out_ bool* const pForcePaint) noexcept override; void WaitUntilCanRender() noexcept override; + void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept override; protected: [[nodiscard]] virtual HRESULT _DoUpdateTitle(const std::wstring_view newTitle) noexcept = 0; diff --git a/src/renderer/uia/UiaRenderer.hpp b/src/renderer/uia/UiaRenderer.hpp index bd1734c5d64..5d244dcc130 100644 --- a/src/renderer/uia/UiaRenderer.hpp +++ b/src/renderer/uia/UiaRenderer.hpp @@ -30,7 +30,7 @@ namespace Microsoft::Console::Render // Only one UiaEngine may present information at a time. // This ensures that an automation client isn't overwhelmed // by events when there are multiple TermControls - [[nodiscard]] HRESULT Enable() noexcept override; + [[nodiscard]] HRESULT Enable() noexcept; [[nodiscard]] HRESULT Disable() noexcept; // IRenderEngine Members diff --git a/src/renderer/wddmcon/WddmConRenderer.hpp b/src/renderer/wddmcon/WddmConRenderer.hpp index 930fbe6dea6..f37146daf5b 100644 --- a/src/renderer/wddmcon/WddmConRenderer.hpp +++ b/src/renderer/wddmcon/WddmConRenderer.hpp @@ -19,7 +19,7 @@ namespace Microsoft::Console::Render // Used to release device resources so that another instance of // conhost can render to the screen (i.e. only one DirectX // application may control the screen at a time.) - [[nodiscard]] HRESULT Enable() noexcept override; + [[nodiscard]] HRESULT Enable() noexcept; [[nodiscard]] HRESULT Disable() noexcept; til::rect GetDisplaySize() noexcept; From de7f931228312996a8b586e5348d5dda46610b84 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Wed, 27 Mar 2024 00:10:29 +0100 Subject: [PATCH 02/16] Add support for customizing font fallback (#16821) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for specifying more than one font family using a syntax that is similar to CSS' `font-family` property. The implementation is straight-forward and is effectively just a wrapper around `IDWriteFontFallbackBuilder`. Closes #2664 ## PR Checklist * Font fallback * Write "「猫」" * Use "Consolas" and remember the shape of the glyphs * Use "Consolas, MS Gothic" and check that it changed ✅ * Settings UI autocompletion * It completes ✅ * It filters ✅ * It recognizes commas and starts a new name ✅ * All invalid font names are listed in the warning message ✅ --------- Co-authored-by: Dustin L. Howett --- .github/actions/spelling/expect/expect.txt | 1 + src/cascadia/TerminalControl/ControlCore.cpp | 27 +- src/cascadia/TerminalControl/ControlCore.h | 2 +- src/cascadia/TerminalControl/EventArgs.h | 8 +- src/cascadia/TerminalControl/EventArgs.idl | 3 +- .../Resources/en-US/Resources.resw | 8 + src/cascadia/TerminalControl/TermControl.cpp | 55 +-- .../TerminalSettingsEditor/Appearances.cpp | 322 +++++++++++++----- .../TerminalSettingsEditor/Appearances.h | 62 ++-- .../TerminalSettingsEditor/Appearances.idl | 10 +- .../TerminalSettingsEditor/Appearances.xaml | 45 ++- .../Profiles_Appearance.cpp | 25 +- .../Profiles_Appearance.h | 1 - .../Resources/en-US/Resources.resw | 16 +- .../TerminalSettingsEditor/ViewModelHelpers.h | 16 +- src/cascadia/UIHelpers/Converters.cpp | 5 + src/cascadia/UIHelpers/Converters.h | 1 + src/cascadia/UIHelpers/Converters.idl | 1 + src/inc/til/string.h | 115 +++++-- src/renderer/atlas/AtlasEngine.api.cpp | 151 +++++--- src/renderer/atlas/AtlasEngine.cpp | 9 +- src/renderer/atlas/AtlasEngine.h | 7 +- src/renderer/atlas/AtlasEngine.r.cpp | 2 +- src/renderer/atlas/BackendD3D.cpp | 23 +- src/renderer/atlas/BackendD3D.h | 2 +- src/renderer/atlas/common.h | 7 +- src/til/ut_til/string.cpp | 39 +++ tools/Lock-CascadiaFont.ps1 | 76 +++++ 28 files changed, 727 insertions(+), 312 deletions(-) create mode 100644 tools/Lock-CascadiaFont.ps1 diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 32dd37878d7..28b9b790d7b 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -1155,6 +1155,7 @@ NOCONTEXTHELP NOCOPYBITS NODUP noexcepts +NOFONT NOINTEGRALHEIGHT NOINTERFACE NOLINKINFO diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index a1070d9b811..98c70398559 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -336,6 +336,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderEngine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>(); _renderer->AddRenderEngine(_renderEngine.get()); + // Hook up the warnings callback as early as possible so that we catch everything. + _renderEngine->SetWarningCallback([this](HRESULT hr, wil::zwstring_view parameter) { + _rendererWarning(hr, parameter); + }); + // Initialize our font with the renderer // We don't have to care about DPI. We'll get a change message immediately if it's not 96 // and react accordingly. @@ -371,12 +376,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _terminal->CreateFromSettings(*_settings, *_renderer); - // IMPORTANT! Set this callback up sooner than later. If we do it - // after Enable, then it'll be possible to paint the frame once - // _before_ the warning handler is set up, and then warnings from - // the first paint will be ignored! - _renderEngine->SetWarningCallback(std::bind(&ControlCore::_rendererWarning, this, std::placeholders::_1)); - // Tell the render engine to notify us when the swap chain changes. // We do this after we initially set the swapchain so as to avoid // unnecessary callbacks (and locking problems) @@ -1024,18 +1023,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation LOG_IF_FAILED(_renderEngine->UpdateFont(_desiredFont, _actualFont, featureMap, axesMap)); } - // If the actual font isn't what was requested... - if (_actualFont.GetFaceName() != _desiredFont.GetFaceName()) - { - // Then warn the user that we picked something because we couldn't find their font. - // Format message with user's choice of font and the font that was chosen instead. - const winrt::hstring message{ fmt::format(std::wstring_view{ RS_(L"NoticeFontNotFound") }, - _desiredFont.GetFaceName(), - _actualFont.GetFaceName()) }; - auto noticeArgs = winrt::make(NoticeLevel::Warning, message); - RaiseNotice.raise(*this, std::move(noticeArgs)); - } - const auto actualNewSize = _actualFont.GetSize(); FontSizeChanged.raise(*this, winrt::make(actualNewSize.width, actualNewSize.height)); } @@ -1724,9 +1711,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void ControlCore::_rendererWarning(const HRESULT hr) + void ControlCore::_rendererWarning(const HRESULT hr, wil::zwstring_view parameter) { - RendererWarning.raise(*this, winrt::make(hr)); + RendererWarning.raise(*this, winrt::make(hr, winrt::hstring{ parameter })); } winrt::fire_and_forget ControlCore::_renderEngineSwapChainChanged(const HANDLE sourceHandle) diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 218d1b842eb..7dbf228cd26 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -390,7 +390,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation winrt::Windows::System::DispatcherQueueTimer _midiAudioSkipTimer{ nullptr }; #pragma region RendererCallbacks - void _rendererWarning(const HRESULT hr); + void _rendererWarning(const HRESULT hr, wil::zwstring_view parameter); winrt::fire_and_forget _renderEngineSwapChainChanged(const HANDLE handle); void _rendererBackgroundColorChanged(); void _rendererTabColorChanged(); diff --git a/src/cascadia/TerminalControl/EventArgs.h b/src/cascadia/TerminalControl/EventArgs.h index 1c135cdf4f6..2ed2c2b828b 100644 --- a/src/cascadia/TerminalControl/EventArgs.h +++ b/src/cascadia/TerminalControl/EventArgs.h @@ -148,12 +148,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation struct RendererWarningArgs : public RendererWarningArgsT { public: - RendererWarningArgs(const uint64_t hr) : - _Result(hr) + RendererWarningArgs(const HRESULT hr, winrt::hstring parameter) : + _Result{ hr }, + _Parameter{ std::move(parameter) } { } - WINRT_PROPERTY(uint64_t, Result); + WINRT_PROPERTY(HRESULT, Result); + WINRT_PROPERTY(winrt::hstring, Parameter); }; struct TransparencyChangedEventArgs : public TransparencyChangedEventArgsT diff --git a/src/cascadia/TerminalControl/EventArgs.idl b/src/cascadia/TerminalControl/EventArgs.idl index 978d69d8e36..92784fc6414 100644 --- a/src/cascadia/TerminalControl/EventArgs.idl +++ b/src/cascadia/TerminalControl/EventArgs.idl @@ -77,7 +77,8 @@ namespace Microsoft.Terminal.Control runtimeclass RendererWarningArgs { - UInt64 Result { get; }; + HRESULT Result { get; }; + String Parameter { get; }; } runtimeclass TransparencyChangedEventArgs diff --git a/src/cascadia/TerminalControl/Resources/en-US/Resources.resw b/src/cascadia/TerminalControl/Resources/en-US/Resources.resw index a604fc912e4..02245a01577 100644 --- a/src/cascadia/TerminalControl/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/en-US/Resources.resw @@ -213,6 +213,14 @@ Please either install the missing font or choose another one. Renderer encountered an unexpected error: {0} {0} is an error code. + + Unable to find the following fonts: {0}. Please either install them or choose different fonts. + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + Renderer encountered an unexpected error: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + Read-only mode is enabled. diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index c8b378672c5..303d6d61482 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -991,36 +991,45 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - hr: an HRESULT describing the warning // Return Value: // - - winrt::fire_and_forget TermControl::_RendererWarning(IInspectable /*sender*/, - Control::RendererWarningArgs args) + winrt::fire_and_forget TermControl::_RendererWarning(IInspectable /*sender*/, Control::RendererWarningArgs args) { - const auto hr = static_cast(args.Result()); - auto weakThis{ get_weak() }; co_await wil::resume_foreground(Dispatcher()); - if (auto control{ weakThis.get() }) + const auto control = weakThis.get(); + if (!control) { - winrt::hstring message; - if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || - HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) - { - message = winrt::hstring{ fmt::format(std::wstring_view{ RS_(L"PixelShaderNotFound") }, - (_focused ? _core.FocusedAppearance() : _core.UnfocusedAppearance()).PixelShaderPath()) }; - } - else if (D2DERR_SHADER_COMPILE_FAILED == hr) - { - message = winrt::hstring{ fmt::format(std::wstring_view{ RS_(L"PixelShaderCompileFailed") }) }; - } - else - { - message = winrt::hstring{ fmt::format(std::wstring_view{ RS_(L"UnexpectedRendererError") }, - hr) }; - } + co_return; + } - auto noticeArgs = winrt::make(NoticeLevel::Warning, std::move(message)); - control->RaiseNotice.raise(*control, std::move(noticeArgs)); + const auto hr = args.Result(); + const auto parameter = args.Parameter(); + winrt::hstring message; + + switch (hr) + { + case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND): + case HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND): + message = winrt::hstring{ fmt::format(std::wstring_view{ RS_(L"PixelShaderNotFound") }, parameter) }; + break; + case D2DERR_SHADER_COMPILE_FAILED: + message = winrt::hstring{ fmt::format(std::wstring_view{ RS_(L"PixelShaderCompileFailed") }) }; + break; + case DWRITE_E_NOFONT: + message = winrt::hstring{ fmt::format(std::wstring_view{ RS_(L"RendererErrorFontNotFound") }, parameter) }; + break; + default: + { + wchar_t buf[512]; + const auto len = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &buf[0], ARRAYSIZE(buf), nullptr); + const std::wstring_view msg{ &buf[0], len }; + message = winrt::hstring{ fmt::format(std::wstring_view{ RS_(L"RendererErrorOther") }, hr, msg) }; + break; } + } + + auto noticeArgs = winrt::make(NoticeLevel::Warning, std::move(message)); + control->RaiseNotice.raise(*control, std::move(noticeArgs)); } void TermControl::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle) diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.cpp b/src/cascadia/TerminalSettingsEditor/Appearances.cpp index 85099de045d..fe9cabc824f 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.cpp +++ b/src/cascadia/TerminalSettingsEditor/Appearances.cpp @@ -6,8 +6,8 @@ #include "Appearances.g.cpp" #include "AxisKeyValuePair.g.cpp" #include "FeatureKeyValuePair.g.cpp" -#include "EnumEntry.h" +#include "EnumEntry.h" #include #include "..\WinRTUtils\inc\Utils.h" @@ -36,28 +36,6 @@ static constexpr std::array DefaultFeatures{ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { - bool Font::HasPowerlineCharacters() - { - if (!_hasPowerlineCharacters.has_value()) - { - try - { - winrt::com_ptr font; - THROW_IF_FAILED(_family->GetFont(0, font.put())); - BOOL exists{}; - // We're actually checking for the "Extended" PowerLine glyph set. - // They're more fun. - THROW_IF_FAILED(font->HasCharacter(0xE0B6, &exists)); - _hasPowerlineCharacters = (exists == TRUE); - } - catch (...) - { - _hasPowerlineCharacters = false; - } - } - return _hasPowerlineCharacters.value_or(false); - } - Windows::Foundation::Collections::IMap Font::FontAxesTagsAndNames() { if (!_fontAxesTagsAndNames) @@ -370,6 +348,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } }); + _refreshFontFaceDependents(); InitializeFontAxesVector(); InitializeFontFeaturesVector(); @@ -382,7 +361,119 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } } - double AppearanceViewModel::LineHeight() const noexcept + winrt::hstring AppearanceViewModel::FontFace() const + { + return _appearance.SourceProfile().FontInfo().FontFace(); + } + + void AppearanceViewModel::FontFace(const winrt::hstring& value) + { + const auto fontInfo = _appearance.SourceProfile().FontInfo(); + if (fontInfo.FontFace() == value) + { + return; + } + + fontInfo.FontFace(value); + _refreshFontFaceDependents(); + + _NotifyChanges(L"HasFontFace", L"FontFace"); + } + + bool AppearanceViewModel::HasFontFace() const + { + return _appearance.SourceProfile().FontInfo().HasFontFace(); + } + + void AppearanceViewModel::ClearFontFace() + { + const auto fontInfo = _appearance.SourceProfile().FontInfo(); + const auto hadValue = fontInfo.HasFontFace(); + + fontInfo.ClearFontFace(); + _refreshFontFaceDependents(); + + if (hadValue) + { + _NotifyChanges(L"HasFontFace", L"FontFace"); + } + } + + Model::FontConfig AppearanceViewModel::FontFaceOverrideSource() const + { + return _appearance.SourceProfile().FontInfo().FontFaceOverrideSource(); + } + + void AppearanceViewModel::_refreshFontFaceDependents() + { + wil::com_ptr factory; + THROW_IF_FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(factory), reinterpret_cast<::IUnknown**>(factory.addressof()))); + + wil::com_ptr fontCollection; + THROW_IF_FAILED(factory->GetSystemFontCollection(fontCollection.addressof(), FALSE)); + + const auto fontFace = FontFace(); + std::wstring primaryFontName; + std::wstring missingFonts; + std::wstring proportionalFonts; + BOOL hasPowerlineCharacters = FALSE; + + til::iterate_font_families(fontFace, [&](wil::zwstring_view name) { + std::wstring* accumulator = nullptr; + + UINT32 index = 0; + BOOL exists = FALSE; + THROW_IF_FAILED(fontCollection->FindFamilyName(name.c_str(), &index, &exists)); + + // Look ma, no goto! + do + { + if (!exists) + { + accumulator = &missingFonts; + break; + } + + if (primaryFontName.empty()) + { + primaryFontName = name; + } + + wil::com_ptr fontFamily; + THROW_IF_FAILED(fontCollection->GetFontFamily(index, fontFamily.addressof())); + + wil::com_ptr font; + THROW_IF_FAILED(fontFamily->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, font.addressof())); + + if (!font.query()->IsMonospacedFont()) + { + accumulator = &proportionalFonts; + } + + // We're actually checking for the "Extended" PowerLine glyph set. + // They're more fun. + BOOL hasE0B6 = FALSE; + std::ignore = font->HasCharacter(0xE0B6, &hasE0B6); + hasPowerlineCharacters |= hasE0B6; + } while (false); + + if (accumulator) + { + if (!accumulator->empty()) + { + accumulator->append(L", "); + } + accumulator->append(name); + } + }); + + _primaryFontName = std::move(primaryFontName); + MissingFontFaces(winrt::hstring{ missingFonts }); + ProportionalFontFaces(winrt::hstring{ proportionalFonts }); + HasPowerlineCharacters(hasPowerlineCharacters); + } + + double AppearanceViewModel::LineHeight() const { const auto fontInfo = _appearance.SourceProfile().FontInfo(); const auto cellHeight = fontInfo.CellHeight(); @@ -526,7 +617,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // find one axis that does not already exist, and add that // if there are no more possible axes to add, the button is disabled so there shouldn't be a way to get here - const auto possibleAxesTagsAndNames = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontAxesTagsAndNames(); + const auto possibleAxesTagsAndNames = ProfileViewModel::FindFontWithLocalizedName(_primaryFontName).FontAxesTagsAndNames(); for (const auto tagAndName : possibleAxesTagsAndNames) { if (!fontAxesMap.HasKey(tagAndName.Key())) @@ -567,7 +658,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation _FontAxesVector.Clear(); if (const auto fontAxesMap = _appearance.SourceProfile().FontInfo().FontAxes()) { - const auto fontAxesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontAxesTagsAndNames(); + const auto fontAxesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(_primaryFontName).FontAxesTagsAndNames(); for (const auto axis : fontAxesMap) { // only show the axes that the font supports @@ -585,14 +676,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // - Determines whether the currently selected font has any variable font axes bool AppearanceViewModel::AreFontAxesAvailable() { - return ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontAxesTagsAndNames().Size() > 0; + return ProfileViewModel::FindFontWithLocalizedName(_primaryFontName).FontAxesTagsAndNames().Size() > 0; } // Method Description: // - Determines whether the currently selected font has any variable font axes that have not already been set bool AppearanceViewModel::CanFontAxesBeAdded() { - if (const auto fontAxesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontAxesTagsAndNames(); fontAxesTagToNameMap.Size() > 0) + if (const auto fontAxesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(_primaryFontName).FontAxesTagsAndNames(); fontAxesTagToNameMap.Size() > 0) { if (const auto fontAxesMap = _appearance.SourceProfile().FontInfo().FontAxes()) { @@ -641,7 +732,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // find one feature that does not already exist, and add that // if there are no more possible features to add, the button is disabled so there shouldn't be a way to get here - const auto possibleFeaturesTagsAndNames = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontFeaturesTagsAndNames(); + const auto possibleFeaturesTagsAndNames = ProfileViewModel::FindFontWithLocalizedName(_primaryFontName).FontFeaturesTagsAndNames(); for (const auto tagAndName : possibleFeaturesTagsAndNames) { const auto featureKey = tagAndName.Key(); @@ -684,7 +775,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation _FontFeaturesVector.Clear(); if (const auto fontFeaturesMap = _appearance.SourceProfile().FontInfo().FontFeatures()) { - const auto fontFeaturesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontFeaturesTagsAndNames(); + const auto fontFeaturesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(_primaryFontName).FontFeaturesTagsAndNames(); for (const auto feature : fontFeaturesMap) { const auto featureKey = feature.Key(); @@ -703,14 +794,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // - Determines whether the currently selected font has any font features bool AppearanceViewModel::AreFontFeaturesAvailable() { - return ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontFeaturesTagsAndNames().Size() > 0; + return ProfileViewModel::FindFontWithLocalizedName(_primaryFontName).FontFeaturesTagsAndNames().Size() > 0; } // Method Description: // - Determines whether the currently selected font has any font features that have not already been set bool AppearanceViewModel::CanFontFeaturesBeAdded() { - if (const auto fontFeaturesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(FontFace()).FontFeaturesTagsAndNames(); fontFeaturesTagToNameMap.Size() > 0) + if (const auto fontFeaturesTagToNameMap = ProfileViewModel::FindFontWithLocalizedName(_primaryFontName).FontFeaturesTagsAndNames(); fontFeaturesTagToNameMap.Size() > 0) { if (const auto fontFeaturesMap = _appearance.SourceProfile().FontInfo().FontFeatures()) { @@ -775,9 +866,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation DependencyProperty Appearances::_AppearanceProperty{ nullptr }; - Appearances::Appearances() : - _ShowAllFonts{ false }, - _ShowProportionalFontWarning{ false } + Appearances::Appearances() { InitializeComponent(); @@ -848,61 +937,58 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation INITIALIZE_BINDABLE_ENUM_SETTING(IntenseTextStyle, IntenseTextStyle, winrt::Microsoft::Terminal::Settings::Model::IntenseStyle, L"Appearance_IntenseTextStyle", L"Content"); } - // Method Description: - // - Searches through our list of monospace fonts to determine if the settings model's current font face is a monospace font - bool Appearances::UsingMonospaceFont() const noexcept + IObservableVector Appearances::FilteredFontList() { - auto result{ false }; - const auto currentFont{ Appearance().FontFace() }; - for (const auto& font : ProfileViewModel::MonospaceFontList()) + if (!_filteredFonts) { - if (font.LocalizedName() == currentFont) - { - result = true; - } + _updateFilteredFontList(); } - return result; + return _filteredFonts; } // Method Description: // - Determines whether we should show the list of all the fonts, or we should just show monospace fonts bool Appearances::ShowAllFonts() const noexcept { - // - _ShowAllFonts is directly bound to the checkbox. So this is the user set value. - // - If we are not using a monospace font, show all of the fonts so that the ComboBox is still properly bound - return _ShowAllFonts || !UsingMonospaceFont(); + return _ShowAllFonts; } - void Appearances::ShowAllFonts(const bool& value) + void Appearances::ShowAllFonts(const bool value) { if (_ShowAllFonts != value) { _ShowAllFonts = value; + _filteredFonts = nullptr; PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"ShowAllFonts" }); + PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"FilteredFontList" }); } } - IInspectable Appearances::CurrentFontFace() const + void Appearances::FontFaceBox_GotFocus(const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) { - const auto& appearanceVM{ Appearance() }; - const auto appearanceFontFace{ appearanceVM.FontFace() }; - return box_value(ProfileViewModel::FindFontWithLocalizedName(appearanceFontFace)); + _updateFontNameFilter({}); + sender.as().IsSuggestionListOpen(true); } - void Appearances::FontFace_SelectionChanged(const IInspectable& /*sender*/, const SelectionChangedEventArgs& e) + void Appearances::FontFaceBox_LostFocus(const IInspectable& sender, const RoutedEventArgs&) { - // NOTE: We need to hook up a selection changed event handler here instead of directly binding to the appearance view model. - // A two way binding to the view model causes an infinite loop because both combo boxes keep fighting over which one's right. - const auto selectedItem{ e.AddedItems().GetAt(0) }; - const auto newFontFace{ unbox_value(selectedItem) }; - Appearance().FontFace(newFontFace.LocalizedName()); - if (!UsingMonospaceFont()) + const auto appearance = Appearance(); + const auto fontSpec = sender.as().Text(); + + if (fontSpec.empty()) { - ShowProportionalFontWarning(true); + appearance.ClearFontFace(); } else { - ShowProportionalFontWarning(false); + appearance.FontFace(fontSpec); + } + + // TODO: Any use of FindFontWithLocalizedName is broken and requires refactoring in time for version 1.21. + const auto newFontFace = ProfileViewModel::FindFontWithLocalizedName(fontSpec); + if (!newFontFace) + { + return; } _FontAxesNames.Clear(); @@ -948,6 +1034,89 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } } + void Appearances::FontFaceBox_SuggestionChosen(const AutoSuggestBox& sender, const AutoSuggestBoxSuggestionChosenEventArgs& args) + { + const auto font = unbox_value(args.SelectedItem()); + const auto fontName = font.Name(); + auto fontSpec = sender.Text(); + + const std::wstring_view fontSpecView{ fontSpec }; + if (const auto idx = fontSpecView.rfind(L','); idx != std::wstring_view::npos) + { + const auto prefix = fontSpecView.substr(0, idx); + const auto suffix = std::wstring_view{ fontName }; + fontSpec = winrt::hstring{ fmt::format(FMT_COMPILE(L"{}, {}"), prefix, suffix) }; + } + else + { + fontSpec = fontName; + } + + sender.Text(fontSpec); + } + + void Appearances::FontFaceBox_TextChanged(const AutoSuggestBox& sender, const AutoSuggestBoxTextChangedEventArgs& args) + { + if (args.Reason() != AutoSuggestionBoxTextChangeReason::UserInput) + { + return; + } + + const auto fontSpec = sender.Text(); + std::wstring_view filter{ fontSpec }; + + // Find the last font name in the font, spec, list. + if (const auto idx = filter.rfind(L','); idx != std::wstring_view::npos) + { + filter = filter.substr(idx + 1); + } + + filter = til::trim(filter, L' '); + _updateFontNameFilter(filter); + } + + void Appearances::_updateFontNameFilter(std::wstring_view filter) + { + if (_fontNameFilter != filter) + { + _filteredFonts = nullptr; + _fontNameFilter = filter; + PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"FilteredFontList" }); + } + } + + void Appearances::_updateFilteredFontList() + { + _filteredFonts = _ShowAllFonts ? ProfileViewModel::CompleteFontList() : ProfileViewModel::MonospaceFontList(); + + if (_fontNameFilter.empty()) + { + return; + } + + std::vector filtered; + filtered.reserve(_filteredFonts.Size()); + + for (const auto& font : _filteredFonts) + { + const auto name = font.Name(); + bool match = til::contains_linguistic_insensitive(name, _fontNameFilter); + + if (!match) + { + const auto localizedName = font.LocalizedName(); + match = localizedName != name && til::contains_linguistic_insensitive(localizedName, _fontNameFilter); + } + + if (match) + { + filtered.emplace_back(font); + } + } + + _filteredFonts = winrt::single_threaded_observable_vector(std::move(filtered)); + } + void Appearances::_ViewModelChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& /*args*/) { const auto& obj{ d.as() }; @@ -956,21 +1125,21 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation void Appearances::_UpdateWithNewViewModel() { - if (Appearance()) + if (const auto appearance = Appearance()) { - const auto& biAlignmentVal{ static_cast(Appearance().BackgroundImageAlignment()) }; + const auto& biAlignmentVal{ static_cast(appearance.BackgroundImageAlignment()) }; for (const auto& biButton : _BIAlignmentButtons) { biButton.IsChecked(biButton.Tag().as() == biAlignmentVal); } FontAxesCVS().Source(Appearance().FontAxesVector()); - Appearance().AreFontAxesAvailable() ? FontAxesContainer().HelpText(RS_(L"Profile_FontAxesAvailable/Text")) : FontAxesContainer().HelpText(RS_(L"Profile_FontAxesUnavailable/Text")); + FontAxesContainer().HelpText(appearance.AreFontAxesAvailable() ? RS_(L"Profile_FontAxesAvailable/Text") : RS_(L"Profile_FontAxesUnavailable/Text")); FontFeaturesCVS().Source(Appearance().FontFeaturesVector()); - Appearance().AreFontFeaturesAvailable() ? FontFeaturesContainer().HelpText(RS_(L"Profile_FontFeaturesAvailable/Text")) : FontFeaturesContainer().HelpText(RS_(L"Profile_FontFeaturesUnavailable/Text")); + FontFeaturesContainer().HelpText(appearance.AreFontFeaturesAvailable() ? RS_(L"Profile_FontFeaturesAvailable/Text") : RS_(L"Profile_FontFeaturesUnavailable/Text")); - _ViewModelChangedRevoker = Appearance().PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& args) { + _ViewModelChangedRevoker = appearance.PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& args) { const auto settingName{ args.PropertyName() }; if (settingName == L"CursorShape") { @@ -987,24 +1156,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } else if (settingName == L"BackgroundImageAlignment") { - _UpdateBIAlignmentControl(static_cast(Appearance().BackgroundImageAlignment())); + _UpdateBIAlignmentControl(static_cast(appearance.BackgroundImageAlignment())); } else if (settingName == L"FontWeight") { PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentFontWeight" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"IsCustomFontWeight" }); } - else if (settingName == L"FontFace" || settingName == L"CurrentFontList") - { - // notify listener that all font face related values might have changed - if (!UsingMonospaceFont()) - { - _ShowAllFonts = true; - } - PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentFontFace" }); - PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"ShowAllFonts" }); - PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"UsingMonospaceFont" }); - } else if (settingName == L"IntenseTextStyle") { PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentIntenseTextStyle" }); @@ -1040,12 +1198,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"IsVintageCursor" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentColorScheme" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentBackgroundImageStretchMode" }); - _UpdateBIAlignmentControl(static_cast(Appearance().BackgroundImageAlignment())); + _UpdateBIAlignmentControl(static_cast(appearance.BackgroundImageAlignment())); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentFontWeight" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"IsCustomFontWeight" }); - PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentFontFace" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"ShowAllFonts" }); - PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"UsingMonospaceFont" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentIntenseTextStyle" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"CurrentAdjustIndistinguishableColors" }); PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"ShowProportionalFontWarning" }); diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.h b/src/cascadia/TerminalSettingsEditor/Appearances.h index 72270cd78d7..d01819b24b5 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.h +++ b/src/cascadia/TerminalSettingsEditor/Appearances.h @@ -31,15 +31,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation struct Font : FontT { public: - Font(winrt::hstring name, winrt::hstring localizedName, IDWriteFontFamily* family) : + Font(winrt::hstring name, winrt::hstring localizedName, wil::com_ptr family) : _Name{ std::move(name) }, - _LocalizedName{ std::move(localizedName) } + _LocalizedName{ std::move(localizedName) }, + _family{ std::move(family) } { - _family.copy_from(family); } hstring ToString() { return _LocalizedName; } - bool HasPowerlineCharacters(); Windows::Foundation::Collections::IMap FontAxesTagsAndNames(); Windows::Foundation::Collections::IMap FontFeaturesTagsAndNames(); @@ -47,14 +46,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation WINRT_PROPERTY(hstring, LocalizedName); private: - winrt::com_ptr _family; - std::optional _hasPowerlineCharacters; - winrt::hstring _tagToString(DWRITE_FONT_AXIS_TAG tag); winrt::hstring _tagToString(DWRITE_FONT_FEATURE_TAG tag); Windows::Foundation::Collections::IMap _fontAxesTagsAndNames; Windows::Foundation::Collections::IMap _fontFeaturesTagsAndNames; + wil::com_ptr _family; }; struct AxisKeyValuePair : AxisKeyValuePairT, ViewModelHelper @@ -108,11 +105,18 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation public: AppearanceViewModel(const Model::AppearanceConfig& appearance); - double LineHeight() const noexcept; + winrt::hstring FontFace() const; + void FontFace(const winrt::hstring& value); + bool HasFontFace() const; + void ClearFontFace(); + Model::FontConfig FontFaceOverrideSource() const; + + double LineHeight() const; void LineHeight(const double value); bool HasLineHeight() const; void ClearLineHeight(); Model::FontConfig LineHeightOverrideSource() const; + void SetFontWeightFromDouble(double fontWeight); void SetBackgroundImageOpacityFromPercentageValue(double percentageValue); void SetBackgroundImagePath(winrt::hstring path); @@ -139,13 +143,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation bool CanFontFeaturesBeAdded(); WINRT_PROPERTY(bool, IsDefault, false); + WINRT_PROPERTY(bool, HasPowerlineCharacters, false); // These settings are not defined in AppearanceConfig, so we grab them // from the source profile itself. The reason we still want them in the // AppearanceViewModel is so we can continue to have the 'Text' grouping // we currently have in xaml, since that grouping has some settings that // are defined in AppearanceConfig and some that are not. - OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), FontFace); OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), FontSize); OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), FontWeight); OBSERVABLE_PROJECTED_SETTING(_appearance.SourceProfile().FontInfo(), FontAxes); @@ -165,37 +169,43 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation OBSERVABLE_PROJECTED_SETTING(_appearance, IntenseTextStyle); OBSERVABLE_PROJECTED_SETTING(_appearance, AdjustIndistinguishableColors); WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector, SchemesList, _propertyChangedHandlers, nullptr); + WINRT_OBSERVABLE_PROPERTY(winrt::hstring, MissingFontFaces, _propertyChangedHandlers); + WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ProportionalFontFaces, _propertyChangedHandlers); WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector, FontAxesVector, _propertyChangedHandlers, nullptr); WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector, FontFeaturesVector, _propertyChangedHandlers, nullptr); private: - Model::AppearanceConfig _appearance; - winrt::hstring _lastBgImagePath; - + void _refreshFontFaceDependents(); Editor::AxisKeyValuePair _CreateAxisKeyValuePairHelper(winrt::hstring axisKey, float axisValue, const Windows::Foundation::Collections::IMap& baseMap, const Windows::Foundation::Collections::IMap& tagToNameMap); Editor::FeatureKeyValuePair _CreateFeatureKeyValuePairHelper(winrt::hstring axisKey, uint32_t axisValue, const Windows::Foundation::Collections::IMap& baseMap, const Windows::Foundation::Collections::IMap& tagToNameMap); - bool _IsDefaultFeature(winrt::hstring featureTag); + + Model::AppearanceConfig _appearance; + winrt::hstring _lastBgImagePath; + std::wstring _primaryFontName; }; struct Appearances : AppearancesT { public: - Appearances(); + static winrt::hstring FontAxisName(const winrt::hstring& key); + static winrt::hstring FontFeatureName(const winrt::hstring& key); - // font face - Windows::Foundation::IInspectable CurrentFontFace() const; + Appearances(); // CursorShape visibility logic bool IsVintageCursor() const; - bool UsingMonospaceFont() const noexcept; + Windows::Foundation::Collections::IObservableVector FilteredFontList(); bool ShowAllFonts() const noexcept; - void ShowAllFonts(const bool& value); + void ShowAllFonts(bool value); + void FontFaceBox_GotFocus(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); + void FontFaceBox_LostFocus(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); + void FontFaceBox_SuggestionChosen(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox&, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxSuggestionChosenEventArgs&); + void FontFaceBox_TextChanged(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox&, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs&); fire_and_forget BackgroundImage_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); void BIAlignment_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); - void FontFace_SelectionChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& e); void DeleteAxisKeyValuePair_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); void AddNewAxisKeyValuePair_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); void DeleteFeatureKeyValuePair_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); @@ -219,21 +229,23 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation GETSET_BINDABLE_ENUM_SETTING(BackgroundImageStretchMode, Windows::UI::Xaml::Media::Stretch, Appearance().BackgroundImageStretchMode); GETSET_BINDABLE_ENUM_SETTING(IntenseTextStyle, Microsoft::Terminal::Settings::Model::IntenseStyle, Appearance().IntenseTextStyle); - WINRT_OBSERVABLE_PROPERTY(bool, ShowProportionalFontWarning, PropertyChanged.raise, nullptr); private: - bool _ShowAllFonts; - void _UpdateBIAlignmentControl(const int32_t val); + Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker; std::array _BIAlignmentButtons; - Windows::Foundation::Collections::IMap _FontWeightMap; Editor::EnumEntry _CustomFontWeight{ nullptr }; - + Windows::Foundation::Collections::IObservableVector _filteredFonts; Windows::Foundation::Collections::IObservableVector _FontAxesNames; Windows::Foundation::Collections::IObservableVector _FontFeaturesNames; + std::wstring _fontNameFilter; + bool _ShowAllFonts = false; - Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker; static void _ViewModelChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e); + + void _updateFontNameFilter(std::wstring_view filter); + void _updateFilteredFontList(); + void _UpdateBIAlignmentControl(const int32_t val); void _UpdateWithNewViewModel(); }; }; diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.idl b/src/cascadia/TerminalSettingsEditor/Appearances.idl index 45f07acaa44..88fb2c6f898 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.idl +++ b/src/cascadia/TerminalSettingsEditor/Appearances.idl @@ -21,7 +21,6 @@ namespace Microsoft.Terminal.Settings.Editor { String Name { get; }; String LocalizedName { get; }; - Boolean HasPowerlineCharacters { get; }; Windows.Foundation.Collections.IMap FontAxesTagsAndNames { get; }; Windows.Foundation.Collections.IMap FontFeaturesTagsAndNames { get; }; } @@ -59,6 +58,10 @@ namespace Microsoft.Terminal.Settings.Editor ColorSchemeViewModel CurrentColorScheme; Windows.Foundation.Collections.IObservableVector SchemesList; + String MissingFontFaces { get; }; + String ProportionalFontFaces { get; }; + Boolean HasPowerlineCharacters { get; }; + void AddNewAxisKeyValuePair(); void DeleteAxisKeyValuePair(String key); void InitializeFontAxesVector(); @@ -103,9 +106,8 @@ namespace Microsoft.Terminal.Settings.Editor IHostedInWindow WindowRoot; static Windows.UI.Xaml.DependencyProperty AppearanceProperty { get; }; - Boolean UsingMonospaceFont { get; }; + Windows.Foundation.Collections.IObservableVector FilteredFontList { get; }; Boolean ShowAllFonts; - Boolean ShowProportionalFontWarning; IInspectable CurrentCursorShape; Boolean IsVintageCursor { get; }; @@ -121,8 +123,6 @@ namespace Microsoft.Terminal.Settings.Editor Boolean IsCustomFontWeight { get; }; Windows.Foundation.Collections.IObservableVector FontWeightList { get; }; - IInspectable CurrentFontFace { get; }; - IInspectable CurrentIntenseTextStyle; Windows.Foundation.Collections.IObservableVector IntenseTextStyleList { get; }; } diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.xaml b/src/cascadia/TerminalSettingsEditor/Appearances.xaml index 35236fc509b..7d065dc4c92 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.xaml +++ b/src/cascadia/TerminalSettingsEditor/Appearances.xaml @@ -183,7 +183,6 @@ - - - - + + IsChecked="{x:Bind ShowAllFonts, Mode=TwoWay}" /> - - + + DisplayPowerlineGlyphs(_looksLikePowerlineFont()); + _previewConnection->DisplayPowerlineGlyphs(_Profile.DefaultAppearance().HasPowerlineCharacters()); _previewControl = Control::TermControl(settings, settings, *_previewConnection); _previewControl.IsEnabled(false); _previewControl.AllowFocusWhenDisabled(false); @@ -70,25 +64,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation _Profile.DeleteUnfocusedAppearance(); } - bool Profiles_Appearance::_looksLikePowerlineFont() const - { - if (_Profile && _Profile.DefaultAppearance()) - { - if (const auto fontName = _Profile.DefaultAppearance().FontFace(); !fontName.empty()) - { - if (const auto font = ProfileViewModel::FindFontWithLocalizedName(fontName)) - { - return font.HasPowerlineCharacters(); - } - } - } - return false; - } - void Profiles_Appearance::_onProfilePropertyChanged(const IInspectable&, const PropertyChangedEventArgs&) const { const auto settings = _Profile.TermSettings(); - _previewConnection->DisplayPowerlineGlyphs(_looksLikePowerlineFont()); + _previewConnection->DisplayPowerlineGlyphs(_Profile.DefaultAppearance().HasPowerlineCharacters()); _previewControl.UpdateControlSettings(settings, settings); } } diff --git a/src/cascadia/TerminalSettingsEditor/Profiles_Appearance.h b/src/cascadia/TerminalSettingsEditor/Profiles_Appearance.h index ad4a779e0cc..ab9ebf66fb0 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles_Appearance.h +++ b/src/cascadia/TerminalSettingsEditor/Profiles_Appearance.h @@ -27,7 +27,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation private: void _onProfilePropertyChanged(const IInspectable&, const PropertyChangedEventArgs&) const; - bool _looksLikePowerlineFont() const; winrt::com_ptr _previewConnection{ nullptr }; Microsoft::Terminal::Control::TermControl _previewControl{ nullptr }; diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index e8995079ead..d046ac12df7 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -137,11 +137,9 @@ This color scheme is part of the built-in settings or an installed extension - To make changes to this color scheme, you must make a copy of it. - Make a copy @@ -1810,12 +1808,12 @@ Learn more. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Warning: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts + + Missing fonts: + This is a label that is followed by a list of missing fonts. - - Choosing a non-monospaced font will likely result in visual artifacts. Use at your own discretion. - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts + + Non-monospace fonts: + This is a label that is followed by a list of proportional fonts. - + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/ViewModelHelpers.h b/src/cascadia/TerminalSettingsEditor/ViewModelHelpers.h index e306233ab63..61597935390 100644 --- a/src/cascadia/TerminalSettingsEditor/ViewModelHelpers.h +++ b/src/cascadia/TerminalSettingsEditor/ViewModelHelpers.h @@ -39,20 +39,21 @@ struct ViewModelHelper #define _BASE_OBSERVABLE_PROJECTED_SETTING(target, name) \ public: \ - auto name() const noexcept \ + auto name() const \ { \ return target.name(); \ }; \ template \ void name(const T& value) \ { \ - if (name() != value) \ + const auto t = target; \ + if (t.name() != value) \ { \ - target.name(value); \ + t.name(value); \ _NotifyChanges(L"Has" #name, L## #name); \ } \ } \ - bool Has##name() \ + bool Has##name() const \ { \ return target.Has##name(); \ } @@ -63,14 +64,15 @@ public: \ _BASE_OBSERVABLE_PROJECTED_SETTING(target, name) \ void Clear##name() \ { \ - const auto hadValue{ target.Has##name() }; \ - target.Clear##name(); \ + const auto t = target; \ + const auto hadValue{ t.Has##name() }; \ + t.Clear##name(); \ if (hadValue) \ { \ _NotifyChanges(L"Has" #name, L## #name); \ } \ } \ - auto name##OverrideSource() \ + auto name##OverrideSource() const \ { \ return target.name##OverrideSource(); \ } diff --git a/src/cascadia/UIHelpers/Converters.cpp b/src/cascadia/UIHelpers/Converters.cpp index 997f0e5ec7d..ce5123995d4 100644 --- a/src/cascadia/UIHelpers/Converters.cpp +++ b/src/cascadia/UIHelpers/Converters.cpp @@ -40,6 +40,11 @@ namespace winrt::Microsoft::Terminal::UI::implementation return expected != actual; } + bool Converters::StringNotEmpty(const winrt::hstring& value) + { + return !value.empty(); + } + winrt::Windows::UI::Xaml::Visibility Converters::StringNotEmptyToVisibility(const winrt::hstring& value) { return value.empty() ? winrt::Windows::UI::Xaml::Visibility::Collapsed : winrt::Windows::UI::Xaml::Visibility::Visible; diff --git a/src/cascadia/UIHelpers/Converters.h b/src/cascadia/UIHelpers/Converters.h index 6fda669605b..af8bcecb458 100644 --- a/src/cascadia/UIHelpers/Converters.h +++ b/src/cascadia/UIHelpers/Converters.h @@ -20,6 +20,7 @@ namespace winrt::Microsoft::Terminal::UI::implementation // Strings static bool StringsAreNotEqual(const winrt::hstring& expected, const winrt::hstring& actual); + static bool StringNotEmpty(const winrt::hstring& value); static winrt::Windows::UI::Xaml::Visibility StringNotEmptyToVisibility(const winrt::hstring& value); static winrt::hstring StringOrEmptyIfPlaceholder(const winrt::hstring& placeholder, const winrt::hstring& value); diff --git a/src/cascadia/UIHelpers/Converters.idl b/src/cascadia/UIHelpers/Converters.idl index 2c9ef90e39d..baf8a97af65 100644 --- a/src/cascadia/UIHelpers/Converters.idl +++ b/src/cascadia/UIHelpers/Converters.idl @@ -18,6 +18,7 @@ namespace Microsoft.Terminal.UI // Strings static Boolean StringsAreNotEqual(String expected, String actual); + static Boolean StringNotEmpty(String value); static Windows.UI.Xaml.Visibility StringNotEmptyToVisibility(String value); static String StringOrEmptyIfPlaceholder(String placeholder, String value); diff --git a/src/inc/til/string.h b/src/inc/til/string.h index e76639000cf..fcb6905e282 100644 --- a/src/inc/til/string.h +++ b/src/inc/til/string.h @@ -202,6 +202,26 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" return to_ulong<>(str, base); } + // Implement to_int in terms of to_ulong by negating its result. to_ulong does not expect + // to be passed signed numbers and will return an error accordingly. That error when + // compared against -1 evaluates to true. We account for that by returning to_int_error if to_ulong + // returns an error. + constexpr int to_int(const std::wstring_view& str, unsigned long base = 0) noexcept + { + auto result = to_ulong_error; + const auto signPosition = str.find(L"-"); + const bool hasSign = signPosition != std::wstring_view::npos; + result = hasSign ? to_ulong(str.substr(signPosition + 1), base) : to_ulong(str, base); + + // Check that result is valid and will fit in an int. + if (result == to_ulong_error || (result > INT_MAX)) + { + return to_int_error; + } + + return hasSign ? result * -1 : result; + } + // Just like std::tolower, but without annoying locales. template constexpr T tolower_ascii(T c) @@ -376,6 +396,81 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" return { beg, end }; } + // Splits a font-family list into individual font-families. It loosely follows the CSS spec for font-family. + // It splits by comma, handles quotes and simple escape characters, and it cleans whitespace. + // + // This is not the right place to put this, because it's highly specialized towards font-family names. + // But this code is needed both, in our renderer and in our settings UI. At the time I couldn't find a better place for it. + void iterate_font_families(const std::wstring_view& families, auto&& callback) + { + std::wstring family; + bool escape = false; + bool delayedSpace = false; + wchar_t stringType = 0; + + for (const auto ch : families) + { + if (!escape) + { + switch (ch) + { + case ' ': + if (stringType) + { + // Spaces are treated literally inside strings. + break; + } + delayedSpace = !family.empty(); + continue; + case '"': + case '\'': + if (stringType && stringType != ch) + { + // Single quotes inside double quotes are treated literally and vice versa. + break; + } + stringType = stringType == ch ? 0 : ch; + continue; + case ',': + if (stringType) + { + // Commas are treated literally inside strings. + break; + } + if (!family.empty()) + { + callback(std::move(family)); + family.clear(); + delayedSpace = false; + } + continue; + case '\\': + escape = true; + continue; + default: + break; + } + } + + // The `delayedSpace` logic automatically takes care for us to + // strip leading and trailing spaces and deduplicate them too. + if (delayedSpace) + { + delayedSpace = false; + family.push_back(L' '); + } + + family.push_back(ch); + escape = false; + } + + // Just like the comma handler above. + if (!stringType && !family.empty()) + { + callback(std::move(family)); + } + } + // This function is appropriate for case-insensitive equivalence testing of file paths and other "system" strings. // Similar to memcmp, this returns <0, 0 or >0. inline int compare_ordinal_insensitive(const std::wstring_view& lhs, const std::wstring_view& rhs) noexcept @@ -426,24 +521,4 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" #pragma warning(suppress : 26477) // Use 'nullptr' rather than 0 or NULL (es.47). return FindNLSStringEx(LOCALE_NAME_USER_DEFAULT, LINGUISTIC_IGNORECASE, str.data(), strLen, needle.data(), needleLen, nullptr, nullptr, nullptr, 0) != -1; } - - // Implement to_int in terms of to_ulong by negating its result. to_ulong does not expect - // to be passed signed numbers and will return an error accordingly. That error when - // compared against -1 evaluates to true. We account for that by returning to_int_error if to_ulong - // returns an error. - constexpr int to_int(const std::wstring_view& str, unsigned long base = 0) noexcept - { - auto result = to_ulong_error; - const auto signPosition = str.find(L"-"); - const bool hasSign = signPosition != std::wstring_view::npos; - result = hasSign ? to_ulong(str.substr(signPosition + 1), base) : to_ulong(str, base); - - // Check that result is valid and will fit in an int. - if (result == to_ulong_error || (result > INT_MAX)) - { - return to_int_error; - } - - return hasSign ? result * -1 : result; - } } diff --git a/src/renderer/atlas/AtlasEngine.api.cpp b/src/renderer/atlas/AtlasEngine.api.cpp index f739022e8a4..c031f67a154 100644 --- a/src/renderer/atlas/AtlasEngine.api.cpp +++ b/src/renderer/atlas/AtlasEngine.api.cpp @@ -264,7 +264,7 @@ try } #endif - _resolveFontMetrics(nullptr, fontInfoDesired, fontInfo); + _resolveFontMetrics(fontInfoDesired, fontInfo); return S_OK; } CATCH_RETURN() @@ -443,7 +443,7 @@ void AtlasEngine::SetGraphicsAPI(GraphicsAPI graphicsAPI) noexcept } } -void AtlasEngine::SetWarningCallback(std::function pfn) noexcept +void AtlasEngine::SetWarningCallback(std::function pfn) noexcept { _p.warningCallback = std::move(pfn); } @@ -472,31 +472,39 @@ void AtlasEngine::SetWarningCallback(std::function pfn) noexcept [[nodiscard]] HRESULT AtlasEngine::UpdateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map& features, const std::unordered_map& axes) noexcept { - try - { - _updateFont(fontInfoDesired.GetFaceName().c_str(), fontInfoDesired, fontInfo, features, axes); - return S_OK; - } - CATCH_LOG(); - + // We're currently faced with a font caching bug that we're unable to reproduce locally. See GH#9375. + // But it occurs often enough and has no proper workarounds, so we're forced to fix it. + // + // Our leading theory is: When an app package has a + // (like Windows Terminal with Cascadia Mono/Code) and it gets updated, the system locks the file somehow. + // DirectWrite still has some information about the font cached though, so it thinks that it still exists, + // but using the font causes it to error out because it can't access it. This fact became apparent in + // commit 9e86c98 (PR #16196), because it showed that it's definitely not due to FindFamilyName() failing. + // + // The workaround is to catch the exception and retry it with our nearby fonts manually loaded in. if constexpr (Feature_NearbyFontLoading::IsEnabled()) { try { - // _resolveFontMetrics() checks `_api.s->font->fontCollection` for a pre-existing font collection, - // before falling back to using the system font collection. This way we can inject our custom one. See GH#9375. - // Doing it this way is a bit hacky, but it does have the benefit that we can cache a font collection - // instance across font changes, like when zooming the font size rapidly using the scroll wheel. - _api.s.write()->font.write()->fontCollection = FontCache::GetCached(); - _updateFont(fontInfoDesired.GetFaceName().c_str(), fontInfoDesired, fontInfo, features, axes); + _updateFont(fontInfoDesired, fontInfo, features, axes); return S_OK; } CATCH_LOG(); + + // _resolveFontMetrics() checks `_api.s->font->fontCollection` for a pre-existing font collection, + // before falling back to using the system font collection. This way we can inject our custom one. + // Doing it this way is a bit hacky, but it does have the benefit that we can cache a font collection + // instance across font changes, like when zooming the font size rapidly using the scroll wheel. + try + { + _api.s.write()->font.write()->fontCollection = FontCache::GetCached(); + } + CATCH_LOG(); } try { - _updateFont(nullptr, fontInfoDesired, fontInfo, features, axes); + _updateFont(fontInfoDesired, fontInfo, features, axes); return S_OK; } CATCH_RETURN(); @@ -528,7 +536,7 @@ void AtlasEngine::_resolveTransparencySettings() noexcept } } -void AtlasEngine::_updateFont(const wchar_t* faceName, const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map& features, const std::unordered_map& axes) +void AtlasEngine::_updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map& features, const std::unordered_map& axes) { std::vector fontFeatures; if (!features.empty()) @@ -605,22 +613,19 @@ void AtlasEngine::_updateFont(const wchar_t* faceName, const FontInfoDesired& fo } const auto font = _api.s.write()->font.write(); - _resolveFontMetrics(faceName, fontInfoDesired, fontInfo, font); + _resolveFontMetrics(fontInfoDesired, fontInfo, font); font->fontFeatures = std::move(fontFeatures); font->fontAxisValues = std::move(fontAxisValues); } -void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics) const +void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics) const { + const auto& faceName = fontInfoDesired.GetFaceName(); const auto requestedFamily = fontInfoDesired.GetFamily(); auto requestedWeight = fontInfoDesired.GetWeight(); auto fontSize = fontInfoDesired.GetFontSize(); auto requestedSize = fontInfoDesired.GetEngineSize(); - if (!requestedFaceName) - { - requestedFaceName = L"Consolas"; - } if (!requestedSize.height) { fontSize = 12.0f; @@ -641,22 +646,88 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo THROW_IF_FAILED(_p.dwriteFactory->GetSystemFontCollection(fontCollection.addressof(), FALSE)); } - u32 index = 0; - BOOL exists = false; - THROW_IF_FAILED(fontCollection->FindFamilyName(requestedFaceName, &index, &exists)); - THROW_HR_IF(DWRITE_E_NOFONT, !exists); + std::wstring primaryFontName; + std::wstring missingFontNames; + wil::com_ptr primaryFontFamily; + wil::com_ptr fontFallbackBuilder; + + // Resolves a comma-separated font list similar to CSS' font-family property. The first font in the list + // that can be resolved successfully will be the primary font which dictates the cell size among others. + // All remaining fonts are "secondary" fonts used for font fallback. + til::iterate_font_families(faceName, [&](std::wstring&& fontName) { + u32 index = 0; + BOOL exists = false; + THROW_IF_FAILED(fontCollection->FindFamilyName(fontName.c_str(), &index, &exists)); + + if (!exists) + { + if (!missingFontNames.empty()) + { + missingFontNames.append(L", "); + } + missingFontNames.append(fontName); + return; + } - wil::com_ptr fontFamily; - THROW_IF_FAILED(fontCollection->GetFontFamily(index, fontFamily.addressof())); + if (!primaryFontFamily) + { + primaryFontName = std::move(fontName); + THROW_IF_FAILED(fontCollection->GetFontFamily(index, primaryFontFamily.addressof())); + } + else + { + if (!fontFallbackBuilder) + { + THROW_IF_FAILED(_p.dwriteFactory->CreateFontFallbackBuilder(fontFallbackBuilder.addressof())); + } + + static constexpr DWRITE_UNICODE_RANGE fullRange{ 0, 0x10FFFF }; + auto fontNamePtr = fontName.c_str(); + THROW_IF_FAILED(fontFallbackBuilder->AddMapping( + /* ranges */ &fullRange, + /* rangesCount */ 1, + /* targetFamilyNames */ &fontNamePtr, + /* targetFamilyNamesCount */ 1, + /* fontCollection */ fontCollection.get(), + /* localeName */ nullptr, + /* baseFamilyName */ nullptr, + /* scale */ 1.0f)); + } + }); + + if (!missingFontNames.empty() && _p.warningCallback) + { + _p.warningCallback(DWRITE_E_NOFONT, missingFontNames); + } + + // Fall back to Consolas if no font was found or specified. + if (!primaryFontFamily) + { + primaryFontName = L"Consolas"; + + u32 index = 0; + BOOL exists = false; + THROW_IF_FAILED(fontCollection->FindFamilyName(primaryFontName.c_str(), &index, &exists)); + THROW_HR_IF(DWRITE_E_NOFONT, !exists); + + THROW_IF_FAILED(fontCollection->GetFontFamily(index, primaryFontFamily.addressof())); + } + + auto fontFallback = _api.systemFontFallback; + if (fontFallbackBuilder) + { + THROW_IF_FAILED(fontFallbackBuilder->AddMappings(_api.systemFontFallback.get())); + THROW_IF_FAILED(fontFallbackBuilder->CreateFontFallback(fontFallback.put())); + } - wil::com_ptr font; - THROW_IF_FAILED(fontFamily->GetFirstMatchingFont(static_cast(requestedWeight), DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, font.addressof())); + wil::com_ptr primaryFont; + THROW_IF_FAILED(primaryFontFamily->GetFirstMatchingFont(static_cast(requestedWeight), DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, primaryFont.addressof())); - wil::com_ptr fontFace; - THROW_IF_FAILED(font->CreateFontFace(fontFace.addressof())); + wil::com_ptr primaryFontFace; + THROW_IF_FAILED(primaryFont->CreateFontFace(primaryFontFace.addressof())); DWRITE_FONT_METRICS metrics{}; - fontFace->GetMetrics(&metrics); + primaryFontFace->GetMetrics(&metrics); // Point sizes are commonly treated at a 72 DPI scale // (including by OpenType), whereas DirectWrite uses 96 DPI. @@ -682,12 +753,12 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo static constexpr u32 codePoint = '0'; u16 glyphIndex; - THROW_IF_FAILED(fontFace->GetGlyphIndicesW(&codePoint, 1, &glyphIndex)); + THROW_IF_FAILED(primaryFontFace->GetGlyphIndicesW(&codePoint, 1, &glyphIndex)); if (glyphIndex) { DWRITE_GLYPH_METRICS glyphMetrics{}; - THROW_IF_FAILED(fontFace->GetDesignGlyphMetrics(&glyphIndex, 1, &glyphMetrics, FALSE)); + THROW_IF_FAILED(primaryFontFace->GetDesignGlyphMetrics(&glyphIndex, 1, &glyphMetrics, FALSE)); advanceWidth = static_cast(glyphMetrics.advanceWidth) * designUnitsPerPx; } } @@ -746,12 +817,11 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo requestedSize.width = gsl::narrow_cast(lrintf(fontSize / cellHeight * cellWidth)); } - fontInfo.SetFromEngine(requestedFaceName, requestedFamily, requestedWeight, false, coordSize, requestedSize); + fontInfo.SetFromEngine(primaryFontName, requestedFamily, requestedWeight, false, coordSize, requestedSize); } if (fontMetrics) { - std::wstring fontName{ requestedFaceName }; const auto fontWeightU16 = gsl::narrow_cast(requestedWeight); const auto advanceWidthU16 = gsl::narrow_cast(lrintf(advanceWidth)); const auto baselineU16 = gsl::narrow_cast(lrintf(baseline)); @@ -773,8 +843,9 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo // as we might cause _api to be in an inconsistent state otherwise. fontMetrics->fontCollection = std::move(fontCollection); - fontMetrics->fontFamily = std::move(fontFamily); - fontMetrics->fontName = std::move(fontName); + fontMetrics->fontFallback = std::move(fontFallback); + fontMetrics->fontFallback.try_query_to(fontMetrics->fontFallback1.put()); + fontMetrics->fontName = std::move(primaryFontName); fontMetrics->fontSize = fontSizeInPx; fontMetrics->cellSize = { cellWidth, cellHeight }; fontMetrics->fontWeight = fontWeightU16; diff --git a/src/renderer/atlas/AtlasEngine.cpp b/src/renderer/atlas/AtlasEngine.cpp index e05e5b033eb..8cfbe995a14 100644 --- a/src/renderer/atlas/AtlasEngine.cpp +++ b/src/renderer/atlas/AtlasEngine.cpp @@ -41,8 +41,7 @@ AtlasEngine::AtlasEngine() THROW_IF_FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(_p.dwriteFactory), reinterpret_cast<::IUnknown**>(_p.dwriteFactory.addressof()))); _p.dwriteFactory4 = _p.dwriteFactory.try_query(); - THROW_IF_FAILED(_p.dwriteFactory->GetSystemFontFallback(_p.systemFontFallback.addressof())); - _p.systemFontFallback1 = _p.systemFontFallback.try_query(); + THROW_IF_FAILED(_p.dwriteFactory->GetSystemFontFallback(_api.systemFontFallback.addressof())); wil::com_ptr textAnalyzer; THROW_IF_FAILED(_p.dwriteFactory->CreateTextAnalyzer(textAnalyzer.addressof())); @@ -575,7 +574,7 @@ void AtlasEngine::_recreateFontDependentResources() { wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; - if (FAILED(GetUserDefaultLocaleName(&localeName[0], LOCALE_NAME_MAX_LENGTH))) + if (!GetUserDefaultLocaleName(&localeName[0], LOCALE_NAME_MAX_LENGTH)) { memcpy(&localeName[0], L"en-US", 12); } @@ -841,7 +840,7 @@ void AtlasEngine::_mapCharacters(const wchar_t* text, const u32 textLength, u32* if (textFormatAxis) { - THROW_IF_FAILED(_p.systemFontFallback1->MapCharacters( + THROW_IF_FAILED(_p.s->font->fontFallback1->MapCharacters( /* analysisSource */ &analysisSource, /* textPosition */ 0, /* textLength */ textLength, @@ -859,7 +858,7 @@ void AtlasEngine::_mapCharacters(const wchar_t* text, const u32 textLength, u32* const auto baseStyle = WI_IsFlagSet(_api.attributes, FontRelevantAttributes::Italic) ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; wil::com_ptr font; - THROW_IF_FAILED(_p.systemFontFallback->MapCharacters( + THROW_IF_FAILED(_p.s->font->fontFallback->MapCharacters( /* analysisSource */ &analysisSource, /* textPosition */ 0, /* textLength */ textLength, diff --git a/src/renderer/atlas/AtlasEngine.h b/src/renderer/atlas/AtlasEngine.h index b75a2a5cdce..5c9f954ae2f 100644 --- a/src/renderer/atlas/AtlasEngine.h +++ b/src/renderer/atlas/AtlasEngine.h @@ -76,7 +76,7 @@ namespace Microsoft::Console::Render::Atlas void SetSoftwareRendering(bool enable) noexcept; void SetDisablePartialInvalidation(bool enable) noexcept; void SetGraphicsAPI(GraphicsAPI graphicsAPI) noexcept; - void SetWarningCallback(std::function pfn) noexcept; + void SetWarningCallback(std::function pfn) noexcept; [[nodiscard]] HRESULT SetWindowSize(til::size pixels) noexcept; [[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& pfiFontInfoDesired, FontInfo& fiFontInfo, const std::unordered_map& features, const std::unordered_map& axes) noexcept; @@ -94,8 +94,8 @@ namespace Microsoft::Console::Render::Atlas // AtlasEngine.api.cpp void _resolveTransparencySettings() noexcept; - void _updateFont(const wchar_t* faceName, const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map& features, const std::unordered_map& axes); - void _resolveFontMetrics(const wchar_t* faceName, const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics = nullptr) const; + void _updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map& features, const std::unordered_map& axes); + void _resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics = nullptr) const; // AtlasEngine.r.cpp ATLAS_ATTR_COLD void _recreateAdapter(); @@ -156,6 +156,7 @@ namespace Microsoft::Console::Render::Atlas Buffer glyphAdvances; Buffer glyphOffsets; + wil::com_ptr systemFontFallback; wil::com_ptr replacementCharacterFontFace; u16 replacementCharacterGlyphIndex = 0; bool replacementCharacterLookedUp = false; diff --git a/src/renderer/atlas/AtlasEngine.r.cpp b/src/renderer/atlas/AtlasEngine.r.cpp index ac87c246dc9..f0a448d491b 100644 --- a/src/renderer/atlas/AtlasEngine.r.cpp +++ b/src/renderer/atlas/AtlasEngine.r.cpp @@ -65,7 +65,7 @@ catch (const wil::ResultException& exception) { try { - _p.warningCallback(hr); + _p.warningCallback(hr, {}); } CATCH_LOG() } diff --git a/src/renderer/atlas/BackendD3D.cpp b/src/renderer/atlas/BackendD3D.cpp index 19e98c6557e..6d7a86c5e4d 100644 --- a/src/renderer/atlas/BackendD3D.cpp +++ b/src/renderer/atlas/BackendD3D.cpp @@ -432,7 +432,7 @@ void BackendD3D::_recreateCustomShader(const RenderingPayload& p) } if (p.warningCallback) { - p.warningCallback(D2DERR_SHADER_COMPILE_FAILED); + p.warningCallback(D2DERR_SHADER_COMPILE_FAILED, p.s->misc->customPixelShaderPath); } } @@ -448,7 +448,7 @@ void BackendD3D::_recreateCustomShader(const RenderingPayload& p) _customPixelShader.reset(); if (p.warningCallback) { - p.warningCallback(D2DERR_SHADER_COMPILE_FAILED); + p.warningCallback(D2DERR_SHADER_COMPILE_FAILED, p.s->misc->customPixelShaderImagePath); } } } @@ -1439,7 +1439,7 @@ BackendD3D::AtlasGlyphEntry* BackendD3D::_drawBuiltinGlyph(const RenderingPayloa if (BuiltinGlyphs::IsSoftFontChar(glyphIndex)) { - _drawSoftFontGlyph(p, r, glyphIndex); + shadingType = _drawSoftFontGlyph(p, r, glyphIndex); } else { @@ -1465,22 +1465,17 @@ BackendD3D::AtlasGlyphEntry* BackendD3D::_drawBuiltinGlyph(const RenderingPayloa return glyphEntry; } -void BackendD3D::_drawSoftFontGlyph(const RenderingPayload& p, const D2D1_RECT_F& rect, u32 glyphIndex) +BackendD3D::ShadingType BackendD3D::_drawSoftFontGlyph(const RenderingPayload& p, const D2D1_RECT_F& rect, u32 glyphIndex) { - _d2dRenderTarget->PushAxisAlignedClip(&rect, D2D1_ANTIALIAS_MODE_ALIASED); - const auto restoreD2D = wil::scope_exit([&]() { - _d2dRenderTarget->PopAxisAlignedClip(); - }); - const auto width = static_cast(p.s->font->softFontCellSize.width); const auto height = static_cast(p.s->font->softFontCellSize.height); const auto softFontIndex = glyphIndex - 0xEF20u; const auto data = til::clamp_slice_len(p.s->font->softFontPattern, height * softFontIndex, height); + // This happens if someone wrote a U+EF2x character (by accident), but we don't even have soft fonts enabled yet. if (data.empty() || data.size() != height) { - _d2dRenderTarget->Clear(); - return; + return ShadingType::Default; } if (!_softFontBitmap) @@ -1517,8 +1512,14 @@ void BackendD3D::_drawSoftFontGlyph(const RenderingPayload& p, const D2D1_RECT_F THROW_IF_FAILED(_softFontBitmap->CopyFromMemory(nullptr, bitmapData.data(), pitch)); } + _d2dRenderTarget->PushAxisAlignedClip(&rect, D2D1_ANTIALIAS_MODE_ALIASED); + const auto restoreD2D = wil::scope_exit([&]() { + _d2dRenderTarget->PopAxisAlignedClip(); + }); + const auto interpolation = p.s->font->antialiasingMode == AntialiasingMode::Aliased ? D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR : D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC; _d2dRenderTarget->DrawBitmap(_softFontBitmap.get(), &rect, 1, interpolation, nullptr, nullptr); + return ShadingType::TextGrayscale; } void BackendD3D::_drawGlyphAtlasAllocate(const RenderingPayload& p, stbrp_rect& rect) diff --git a/src/renderer/atlas/BackendD3D.h b/src/renderer/atlas/BackendD3D.h index 5e8055aecd0..25833b831dc 100644 --- a/src/renderer/atlas/BackendD3D.h +++ b/src/renderer/atlas/BackendD3D.h @@ -215,7 +215,7 @@ namespace Microsoft::Console::Render::Atlas ATLAS_ATTR_COLD void _drawTextOverlapSplit(const RenderingPayload& p, u16 y); [[nodiscard]] ATLAS_ATTR_COLD AtlasGlyphEntry* _drawGlyph(const RenderingPayload& p, const ShapedRow& row, AtlasFontFaceEntry& fontFaceEntry, u32 glyphIndex); AtlasGlyphEntry* _drawBuiltinGlyph(const RenderingPayload& p, const ShapedRow& row, AtlasFontFaceEntry& fontFaceEntry, u32 glyphIndex); - void _drawSoftFontGlyph(const RenderingPayload& p, const D2D1_RECT_F& rect, u32 glyphIndex); + ShadingType _drawSoftFontGlyph(const RenderingPayload& p, const D2D1_RECT_F& rect, u32 glyphIndex); void _drawGlyphAtlasAllocate(const RenderingPayload& p, stbrp_rect& rect); static AtlasGlyphEntry* _drawGlyphAllocateEntry(const ShapedRow& row, AtlasFontFaceEntry& fontFaceEntry, u32 glyphIndex); static void _splitDoubleHeightGlyph(const RenderingPayload& p, const ShapedRow& row, AtlasFontFaceEntry& fontFaceEntry, AtlasGlyphEntry* glyphEntry); diff --git a/src/renderer/atlas/common.h b/src/renderer/atlas/common.h index 2e937baf04f..ad9bf2587be 100644 --- a/src/renderer/atlas/common.h +++ b/src/renderer/atlas/common.h @@ -345,7 +345,8 @@ namespace Microsoft::Console::Render::Atlas struct FontSettings { wil::com_ptr fontCollection; - wil::com_ptr fontFamily; + wil::com_ptr fontFallback; + wil::com_ptr fontFallback1; // optional, might be nullptr std::wstring fontName; std::vector fontFeatures; std::vector fontAxisValues; @@ -488,10 +489,8 @@ namespace Microsoft::Console::Render::Atlas wil::com_ptr d2dFactory; wil::com_ptr dwriteFactory; wil::com_ptr dwriteFactory4; // optional, might be nullptr - wil::com_ptr systemFontFallback; - wil::com_ptr systemFontFallback1; // optional, might be nullptr wil::com_ptr textAnalyzer; - std::function warningCallback; + std::function warningCallback; std::function swapChainChangedCallback; //// Parameters which are constant for the existence of the backend. diff --git a/src/til/ut_til/string.cpp b/src/til/ut_til/string.cpp index 26fbf92ea47..2ef656a04d7 100644 --- a/src/til/ut_til/string.cpp +++ b/src/til/ut_til/string.cpp @@ -7,6 +7,25 @@ using namespace WEX::Common; using namespace WEX::Logging; using namespace WEX::TestExecution; +template<> +class WEX::TestExecution::VerifyOutputTraits> +{ +public: + static WEX::Common::NoThrowString ToString(const std::vector& vec) + { + WEX::Common::NoThrowString str; + str.Append(L"{ "); + for (size_t i = 0; i < vec.size(); ++i) + { + str.Append(i == 0 ? L"\"" : L", \""); + str.Append(vec[i].c_str()); + str.Append(L"\""); + } + str.Append(L" }"); + return str; + } +}; + class StringTests { TEST_CLASS(StringTests); @@ -199,4 +218,24 @@ class StringTests VERIFY_IS_TRUE(til::is_legal_path(LR"(C:\Users\Documents and Settings\Users\;\Why not)")); VERIFY_IS_FALSE(til::is_legal_path(LR"(C:\Users\Documents and Settings\"Quote-un-quote users")")); } + + TEST_METHOD(IterateFontFamilies) + { + static constexpr auto expected = [](auto&&... args) { + return std::vector{ std::forward(args)... }; + }; + static constexpr auto actual = [](std::wstring_view families) { + std::vector split; + til::iterate_font_families(families, [&](std::wstring&& str) { + split.emplace_back(std::move(str)); + }); + return split; + }; + + VERIFY_ARE_EQUAL(expected(L"foo", L" b a r ", LR"(b"az)"), actual(LR"( foo ," b a r ",b\"az)")); + VERIFY_ARE_EQUAL(expected(LR"(foo, bar)"), actual(LR"("foo, bar")")); + VERIFY_ARE_EQUAL(expected(LR"("foo")", LR"('bar')"), actual(LR"('"foo"', "'bar'")")); + VERIFY_ARE_EQUAL(expected(LR"("foo")", LR"('bar')"), actual(LR"("\"foo\"", '\'bar\'')")); + VERIFY_ARE_EQUAL(expected(L"foo"), actual(LR"(,,,,foo,,,,)")); + } }; diff --git a/tools/Lock-CascadiaFont.ps1 b/tools/Lock-CascadiaFont.ps1 new file mode 100644 index 00000000000..f1a1e384b26 --- /dev/null +++ b/tools/Lock-CascadiaFont.ps1 @@ -0,0 +1,76 @@ +# This script is a failed attempt to lock the Cascadia Mono/Code font files in order to reproduce an issue with the font +# cache service, where it says a font exists, but then fails to use it (see GH#9375). The script doesn't work because +# for some reason DirectWrite is still able to fully use the fonts. It's left here for reference. + +#Requires -RunAsAdministrator + +Add-Type -TypeDefinition @" +using System; +using System.Runtime.InteropServices; + +public class Win32LockFile { + public const uint LOCKFILE_FAIL_IMMEDIATELY = 0x00000001; + public const uint LOCKFILE_EXCLUSIVE_LOCK = 0x00000002; + + [DllImport("kernel32.dll")] + public static extern bool LockFileEx(IntPtr hFile, uint dwFlags, uint dwReserved, uint nNumberOfBytesToLockLow, uint nNumberOfBytesToLockHigh, ref OVERLAPPED lpOverlapped); + + [StructLayout(LayoutKind.Sequential)] + public struct OVERLAPPED { + public uint Internal; + public uint InternalHigh; + public uint Offset; + public uint OffsetHigh; + public IntPtr hEvent; + } +} +"@ + +function Lock-File { + param( + [Parameter(Mandatory=$true)] + [string]$Path + ) + + $file = [System.IO.File]::Open($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) + $overlapped = New-Object Win32LockFile+OVERLAPPED + $result = [Win32LockFile]::LockFileEx( + $file.SafeFileHandle.DangerousGetHandle(), # hFile + [Win32LockFile]::LOCKFILE_EXCLUSIVE_LOCK, # dwFlags + 0, # dwReserved + [UInt32]::MaxValue, # nNumberOfBytesToLockLow + [UInt32]::MaxValue, # nNumberOfBytesToLockHigh + [ref]$overlapped # lpOverlapped + ) + + if (-not $result) { + throw "Failed to lock file" + } + + return $file +} + +$fonts = Get-ItemProperty "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Fonts\*" + | ForEach-Object { $_.PSobject.Properties } + | Where-Object { $_.Name.StartsWith("Cascadia") } + | ForEach-Object { $_.Value } + +$fonts += @("CascadiaCode.ttf", "CascadiaCodeItalic.ttf", "CascadiaMono.ttf", "CascadiaMonoItalic.ttf") + | ForEach-Object { "C:\Windows\Fonts\$_" } + | Where-Object { Test-Path $_ } + +try { + $handles = $fonts | ForEach-Object { + try { + Lock-File $_ + } + catch { + Write-Error $_ + } + } + Restart-Service FontCache + Write-Host "Press any key to unlock the font files..." + $null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") +} finally { + $handles | Where-Object { $_ } | ForEach-Object { $_.Close() } +} From 26e63203741909ee8ac00e4c6ec658884560df17 Mon Sep 17 00:00:00 2001 From: Windows Console Service Bot <14666831+consvc@users.noreply.github.com> Date: Wed, 27 Mar 2024 05:58:36 -0500 Subject: [PATCH 03/16] Localization Updates - main - 03/27/2024 02:34:17 (#16945) --- .../Resources/qps-ploc/Resources.resw | 8 +++ .../Resources/qps-ploca/Resources.resw | 8 +++ .../Resources/qps-plocm/Resources.resw | 8 +++ .../Resources/de-DE/Resources.resw | 26 --------- .../Resources/es-ES/Resources.resw | 26 --------- .../Resources/fr-FR/Resources.resw | 26 --------- .../Resources/it-IT/Resources.resw | 26 --------- .../Resources/ja-JP/Resources.resw | 26 --------- .../Resources/ko-KR/Resources.resw | 26 --------- .../Resources/pt-BR/Resources.resw | 26 --------- .../Resources/qps-ploc/Resources.resw | 55 ++++++++++++------- .../Resources/qps-ploca/Resources.resw | 55 ++++++++++++------- .../Resources/qps-plocm/Resources.resw | 55 ++++++++++++------- .../Resources/ru-RU/Resources.resw | 26 --------- .../Resources/zh-CN/Resources.resw | 26 --------- .../Resources/zh-TW/Resources.resw | 26 --------- .../Resources/qps-ploc/Resources.resw | 3 + .../Resources/qps-ploca/Resources.resw | 3 + .../Resources/qps-plocm/Resources.resw | 3 + 19 files changed, 138 insertions(+), 320 deletions(-) diff --git a/src/cascadia/TerminalControl/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalControl/Resources/qps-ploc/Resources.resw index 62835cf4c86..1cd2c9e814e 100644 --- a/src/cascadia/TerminalControl/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/qps-ploc/Resources.resw @@ -213,6 +213,14 @@ Řєʼnδέгęř зйĉóűňтëř℮δ âη ûⁿėхрєĉţēð ℮ѓґоŗ: {0} !!! !!! !!! !!! ! {0} is an error code. + + Цйǻьľė ŧò ƒіņð τнė ƒσℓľоŵíпğ ƒŏптš: {0}. Рĺёąšė èìťђėг ïŋŝţăĺℓ тħēm ôѓ ςђоōѕз ðįƒƒеřęʼnţ ƒóπţś. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + Гêʼnďěѓēŗ эήçομήťєřĕď åń µŋέхρэсťèð ęґяöя: {0:#010×} {1} !!! !!! !!! !!! !!! ! + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + Гėāδ-σπļỳ mőðê īŝ ėńäвļεδ. !!! !!! ! diff --git a/src/cascadia/TerminalControl/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalControl/Resources/qps-ploca/Resources.resw index 62835cf4c86..1cd2c9e814e 100644 --- a/src/cascadia/TerminalControl/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/qps-ploca/Resources.resw @@ -213,6 +213,14 @@ Řєʼnδέгęř зйĉóűňтëř℮δ âη ûⁿėхрєĉţēð ℮ѓґоŗ: {0} !!! !!! !!! !!! ! {0} is an error code. + + Цйǻьľė ŧò ƒіņð τнė ƒσℓľоŵíпğ ƒŏптš: {0}. Рĺёąšė èìťђėг ïŋŝţăĺℓ тħēm ôѓ ςђоōѕз ðįƒƒеřęʼnţ ƒóπţś. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + Гêʼnďěѓēŗ эήçομήťєřĕď åń µŋέхρэсťèð ęґяöя: {0:#010×} {1} !!! !!! !!! !!! !!! ! + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + Гėāδ-σπļỳ mőðê īŝ ėńäвļεδ. !!! !!! ! diff --git a/src/cascadia/TerminalControl/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalControl/Resources/qps-plocm/Resources.resw index 62835cf4c86..1cd2c9e814e 100644 --- a/src/cascadia/TerminalControl/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/qps-plocm/Resources.resw @@ -213,6 +213,14 @@ Řєʼnδέгęř зйĉóűňтëř℮δ âη ûⁿėхрєĉţēð ℮ѓґоŗ: {0} !!! !!! !!! !!! ! {0} is an error code. + + Цйǻьľė ŧò ƒіņð τнė ƒσℓľоŵíпğ ƒŏптš: {0}. Рĺёąšė èìťђėг ïŋŝţăĺℓ тħēm ôѓ ςђоōѕз ðįƒƒеřęʼnţ ƒóπţś. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + Гêʼnďěѓēŗ эήçομήťєřĕď åń µŋέхρэсťèð ęґяöя: {0:#010×} {1} !!! !!! !!! !!! !!! ! + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + Гėāδ-σπļỳ mőðê īŝ ėńäвļεδ. !!! !!! ! diff --git a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw index 13a0809dfd4..c7e5f00ab76 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw @@ -137,11 +137,9 @@ Dieses Farbschema ist Teil der integrierten Einstellungen oder einer installierten Erweiterung. - Um Änderungen an diesem Farbschema vorzunehmen, müssen Sie eine Kopie davon erstellen. - Kopie erstellen @@ -311,14 +309,6 @@ Die Terminalanwendung, die gestartet wird, wenn eine Befehlszeilenanwendung ohne vorhandene Sitzung gestartet wird, beispielsweise vom Startmenü oder über das Dialogfeld "Ausführen". A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - Gesamten Bildschirm beim Anzeigen von Updates aktualisieren - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - Wenn diese Option deaktiviert ist, rendert das Terminal die Aktualisierungen nur zwischen den Frames auf den Bildschirm. - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Spalten Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ Wenn diese Option deaktiviert ist, wird die Größe des Fensters reibungslos geändert. A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Software-Rendering verwenden - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Wenn diese Option aktiviert ist, verwendet das Terminal den Software-Renderer (alias WARP) anstelle des Hardware-Renderers. - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - Beim Starten des Computers starten Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ Weitere Informationen. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Warnung: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - Die Auswahl einer Nicht-Monospace-Schriftart führt wahrscheinlich zu visuellen Artefakten. Verwenden Sie sie nach eigenem Ermessen. - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw index 76400095b16..1aefd03fc53 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw @@ -137,11 +137,9 @@ Esta combinación de colores forma parte de la configuración integrada o de una extensión instalada - Para realizar cambios en esta combinación de colores, debe hacer una copia del mismo. - Hacer una copia @@ -311,14 +309,6 @@ Aplicación de terminal que se inicia cuando se ejecuta una aplicación de línea de comandos sin una sesión existente, como en el menú Inicio o en el cuadro de diálogo Ejecutar. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - Redibujar toda la pantalla cuando se muestren actualizaciones - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - Cuando está deshabilitada, el terminal representará solo las actualizaciones de la pantalla entre fotogramas. - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Columnas Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ Cuando se deshabilita, la ventana cambiará de tamaño sin problemas. A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Usar procesamiento de software - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Cuando está habilitado, el terminal usará el representador de software (también conocida como WARP) en lugar del hardware. - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - Iniciar al inicio del equipo Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ Más información. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Advertencia: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - Si elige una fuente sin monoespacios, es probable que se generen artefactos visuales. Úsela según su criterio. - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw index 2887b95e286..c5f582d3123 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw @@ -137,11 +137,9 @@ Ce modèle de couleurs fait partie des paramètres intégrés ou d’une extension installée - Pour apporter des modifications à ce modèle de couleurs, vous devez en faire une copie. - Dupliquer @@ -311,14 +309,6 @@ L’application Terminal qui se lance lorsqu’une application de ligne de commande est exécutée sans session existante, par exemple à partir du menu Démarrer ou de la boîte de dialogue Exécuter. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - Redessiner l’intégralité de l’écran entre chaque trame - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - Une fois désactivé, le terminal n’affiche à l’écran que les modifications effectuées entre les trames. - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Colonnes Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ Une fois désactivée, la fenêtre se redimensionne sans à-coups. A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Utiliser le rendu logiciel - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Une fois activé, le terminal utilise le convertisseur logiciel (WARP) à la place du convertisseur matériel. - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - Lancement au démarrage de l’ordinateur Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ En savoir plus. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Avertissement : - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - Le choix d’une police sans espacement fixe entraîne probablement l’utilisation d’artefacts visuels. Utilisez-la à votre seule discrétion. - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw index 4ce446f17ba..98b19357538 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw @@ -137,11 +137,9 @@ Questa combinazione di colori fa parte delle impostazioni predefinite o di un'estensione installata - Per apportare modifiche a questa combinazione di colori, è necessario crearne una copia. - Crea una copia @@ -311,14 +309,6 @@ L'applicazione terminale che viene avviata quando viene eseguita un'applicazione della riga di comando senza una sessione esistente, ad esempio dalla finestra di dialogo menu Start o Esegui. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - Ridisegna l'intero schermo durante la visualizzazione degli aggiornamenti - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - Se disabilitato, il terminale eseguirà il rendering solo degli aggiornamenti sullo schermo tra i fotogrammi. - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Colonne Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ Se disabilitata, la finestra verrà ridimensionata in modo corretto. A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Usa il rendering software - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Quando questa opzione è abilitata, il terminale userà il renderer software (detto anche WARP) anziché quello hardware. - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - Avvia all'avvio del computer Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ Scopri di più. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Avvertenza: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - Se scegli un tipo di carattere non monospaziato, è probabile che si verifichino artefatti visivi. Utilizzalo a vostra discrezione. - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw index d57a8288d57..aadbf4c8b5d 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw @@ -137,11 +137,9 @@ この配色は、組み込みの設定またはインストールされている拡張機能の一部です - この配色パターンを変更するには、コピーを作成する必要があります。 - コピーを作成 @@ -311,14 +309,6 @@ [スタート] メニューや [ファイル名を指定して実行] ダイアログなど、既存のセッションなしでコマンドライン アプリケーションを実行したときに起動するターミナル アプリケーション。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - ディスプレイの更新時に画面全体を再描画する - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - 無効にすると、ターミナルはフレームとフレームの間において情報更新分のみレンダリングします。 - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ 無効にすると、ウィンドウがスムーズにサイズ変更されます。 A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - ソフトウェア レンダリングを使用する - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - 有効にすると、ターミナルはハードウェアの代わりにソフトウェア レンダラー (別名 WARP) を使用します。 - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - コンピューターのスタートアップ時に起動 Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ 詳細をご覧ください。 A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - 警告: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - 非等幅フォントを選択すると、視覚的なアーティファクトが発生する可能性があります。 ご自身の判断でご利用ください。 - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw index aef454bd85d..dc1cf00158f 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw @@ -137,11 +137,9 @@ 이 색 구성표는 기본 제공 설정 또는 설치된 확장의 일부입니다. - 이 색 구성표를 변경하려면 복사본을 만들어야 합니다. - 복사본 만들기 @@ -311,14 +309,6 @@ 시작 메뉴나 실행 대화 상자와 같이 기존 세션이 없으면 명령 줄 응용 프로그램을 실행하고 있는 터미널 응용 프로그램입니다. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - 업데이트를 표시할 때 전체 화면 다시 그리기 - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - 사용하지 않도록 설정하면 터미널이 프레임 간 화면 업데이트만 렌더링합니다. - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ 사용하지 않도록 설정하면 창의 크기가 원활하게 조정됩니다. A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - 소프트웨어 렌더링 사용 - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - 사용하도록 설정하면 터미널에서 하드웨어 렌더러 대신 소프트웨어 렌더러(WARP)를 사용합니다. - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - 컴퓨터 시작 시 실행 Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ 자세히 알아보세요. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - 경고: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - 고정 폭이 아닌 글꼴을 선택하면 시각적 아티팩트가 발생할 수 있습니다. 사용자 판단에 따라 사용하세요. - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw index 56fff0a611d..eb0d81d9026 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw @@ -137,11 +137,9 @@ Este esquema de cores faz parte das configurações internas ou de uma extensão instalada - Para fazer alterações neste esquema de cores, você deve fazer uma cópia dele. - Fazer uma cópia @@ -311,14 +309,6 @@ O aplicativo de terminal que é iniciado quando um aplicativo de linha de comando é executado sem uma sessão existente, como no menu iniciar ou na caixa de diálogo Executar. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - Redesenhar a tela inteira ao exibir atualizações - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - Quando desabilitado, o terminal renderizará somente as atualizações na tela entre quadros. - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Colunas Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ Quando desabilitado, a janela será redimensionada sem problemas. A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Usar renderização de software - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Quando habilitado, o terminal usará o renderizador de software (também chamado DE WARP) em vez do hardware. - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - Iniciar na inicialização da máquina Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ Saiba mais. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Aviso: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - A escolha de uma fonte não monoespaçada provavelmente resultará em artefatos visuais. Use a seu critério. - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw index f954fb623fb..98bd519ebb1 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw @@ -137,11 +137,9 @@ Ţħīѕ ċøłǿґ ŝςħèм℮ îś рăŗţ õƒ тнè ъûĩľт-íπ śéţťΐлĝś õř дŋ íńşťªłĺèð èжťęлşίοη !!! !!! !!! !!! !!! !!! !!! ! - Ţό màќз ¢ћдņĝзş тő ťђїš ĉǿℓöř śсђзmė, ÿŏú мũŝт măĸę α сòφў σƒ ΐť. !!! !!! !!! !!! !!! !!! ! - Маĸέ α ċōρý !!! @@ -311,13 +309,38 @@ Ťђě ţэřмīηãĺ ǻφφℓï¢ǻтΐбň ŧђáт łáůйčĥēś ẅĥэп ā сöмmǻńđ-ľіʼnэ ăρρĺįċāτΐôⁿ ϊš яųñ шíţћöυţ ªņ ĕхϊŝŧĭñğ şěŝѕïŏπ, ŀĩĸė ƒѓом ţћĕ Ŝτáґт Μęπü бг Яųņ ďīäℓöğ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Ĝŗäрђΐсѕ ÃРΪ !!! + This text is shown next to a list of choices. + + + Đĩŗěćŧ3Đ 11 рґóνϊďèš ă мõřе φ℮ŕƒóŗmąņт аʼnđ ƒеǻŧùґê-яĩςђ ℮жφéѓιęʼnςè, ώђēѓėªŝ Ðìгëçť2Ď ĩś мθяë ŝţдвłē. Ţĥé δęƒаűłτ ōφτιоⁿ "Ãúτσмάτīč" щĩłł φìçк ţђë ÁΡĨ ţħǻτ ъёšť ƒīтѕ уōûґ ğřǻφђі¢ѕ нąŗďщǻѓê. ̓ ўöџ ê×ρёřįėʼnċê ѕįġńїƒϊĉâⁿт îśşΰёś, соńśϊδеŗ üśίńğ Đΐřěċτ2Đ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! + + + Άůтǿмąťí¢ !!! + The default choice between multiple graphics APIs. + + + Đîяе¢ť2Đ !! + + + Ďїřèĉт3Ď 11 !!! + - Ŗёδѓªŵ еñţιŗę šĉřέëŋ шн℮й đĩşρℓâў υρďάţëš !!! !!! !!! !!! - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. + Ďіşǻьłэ рàґτíàľ Šŵąр Ċнаιŋ ĭήνάŀïδαţίбπ !!! !!! !!! !!! + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. - Щħ℮п đįѕāъĺèđ, ťђέ тèřмΐņäľ ωìľľ řεʼnďęŗ όʼnľŷ ŧђέ ŭρďăţзŝ τö ŧђë šсгèзņ вêţшзэʼn ƒяāméş. !!! !!! !!! !!! !!! !!! !!! !!! ! - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". + Бў ďēƒăüℓţ, ťћэ ţèхţ ř℮ŋðěґĕґ υŝ℮ŝ ä FLIP_SEQUENTIAL Ŝωăр Сђáϊп åπδ ďεĉℓάŗέş δΐŗŧў ŗēćŧăñġℓέš νïд ťĥĕ Present1 ĀРĪ. Щĥêи тћїŝ ŝєŧŧΐñğ įѕ ℮лάьłзδ, α FLIP_DISCARD Şẁαр Ċħāīʼn ŵīĺļ ьё υѕėð íπśťεαď, āлδ ŋо ďīŗŧý ŕęсŧдиĝℓэş шīľĺ ъĕ δеĉľāŗэð. Ẃħέтħêґ òñё σř ŧнé ōтħεř ΐś ъёţŧęґ δéρ℮ήđѕ σή ÿούг ħäґďшάřέ ªήð νăŕιούѕ ǿτђēř ƒαстόяš. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Ųѕε ŝόƒťщаřė яĕŋðεříлğ (WARP) !!! !!! !!! + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + Ẅнέⁿ éñâвĺĕď, ŧĥë тěřmϊñăľ шîľĺ ŭşē ă şóƒтшářě яãѕтĕгīżεŕ (WARP). Тћįş ŝеţŧΐπģ śнσύŀδ вё ĺєƒŧ δїşâьĺεδ ύπďέя ªℓмôšţ áŀł ćϊŕçϋмśтąпćēѕ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". Ċσŀùмñѕ !! @@ -474,14 +497,6 @@ Ẅн℮ñ ðìşāьļĕð, τĥė ŵΐņďòώ ẃíļĺ řėŝîżē šмõόтнłγ. !!! !!! !!! !!! !! A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Ųѕε ŝόƒťщаřė яĕŋðεříлğ !!! !!! - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Ẅнέⁿ éñâвĺĕď, ŧĥë тěřmϊñăľ шîľĺ ŭşē ŧнé šбƒţẅāяē ґэпδėѓεŕ (д.к.ă. ẀÅЃΡ) ĭñŝτéāđ оƒ тħё ĥάґđẃаяē οлε. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - ₤áϋпςħ ôл мαςĥĭñę ŝťąřťûρ !!! !!! ! Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1793,12 +1808,12 @@ Ļĕдŗⁿ мõгĕ. !!! A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Ẃãялíʼnĝ: !! - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts + + Μįŝşìηğ ƒòńтš: !!! ! + This is a label that is followed by a list of missing fonts. - - €ħσõśïʼnğ ą ñой-мõποşφãĉєδ ƒŏŋţ ẅіľľ łîķέℓў ŕєŝùłţ íй νΐşūαℓ āѓťīƒдςţŝ. Џŝè àţ ÿοùŗ øẁη δíśčґ℮ťîбņ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !! - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts + + Νόņ-mσиόšραςз ƒоʼnтŝ: !!! !!! + This is a label that is followed by a list of proportional fonts. \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw index f954fb623fb..98bd519ebb1 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw @@ -137,11 +137,9 @@ Ţħīѕ ċøłǿґ ŝςħèм℮ îś рăŗţ õƒ тнè ъûĩľт-íπ śéţťΐлĝś õř дŋ íńşťªłĺèð èжťęлşίοη !!! !!! !!! !!! !!! !!! !!! ! - Ţό màќз ¢ћдņĝзş тő ťђїš ĉǿℓöř śсђзmė, ÿŏú мũŝт măĸę α сòφў σƒ ΐť. !!! !!! !!! !!! !!! !!! ! - Маĸέ α ċōρý !!! @@ -311,13 +309,38 @@ Ťђě ţэřмīηãĺ ǻφφℓï¢ǻтΐбň ŧђáт łáůйčĥēś ẅĥэп ā сöмmǻńđ-ľіʼnэ ăρρĺįċāτΐôⁿ ϊš яųñ шíţћöυţ ªņ ĕхϊŝŧĭñğ şěŝѕïŏπ, ŀĩĸė ƒѓом ţћĕ Ŝτáґт Μęπü бг Яųņ ďīäℓöğ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Ĝŗäрђΐсѕ ÃРΪ !!! + This text is shown next to a list of choices. + + + Đĩŗěćŧ3Đ 11 рґóνϊďèš ă мõřе φ℮ŕƒóŗmąņт аʼnđ ƒеǻŧùґê-яĩςђ ℮жφéѓιęʼnςè, ώђēѓėªŝ Ðìгëçť2Ď ĩś мθяë ŝţдвłē. Ţĥé δęƒаűłτ ōφτιоⁿ "Ãúτσмάτīč" щĩłł φìçк ţђë ÁΡĨ ţħǻτ ъёšť ƒīтѕ уōûґ ğřǻφђі¢ѕ нąŗďщǻѓê. ̓ ўöџ ê×ρёřįėʼnċê ѕįġńїƒϊĉâⁿт îśşΰёś, соńśϊδеŗ üśίńğ Đΐřěċτ2Đ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! + + + Άůтǿмąťí¢ !!! + The default choice between multiple graphics APIs. + + + Đîяе¢ť2Đ !! + + + Ďїřèĉт3Ď 11 !!! + - Ŗёδѓªŵ еñţιŗę šĉřέëŋ шн℮й đĩşρℓâў υρďάţëš !!! !!! !!! !!! - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. + Ďіşǻьłэ рàґτíàľ Šŵąр Ċнаιŋ ĭήνάŀïδαţίбπ !!! !!! !!! !!! + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. - Щħ℮п đįѕāъĺèđ, ťђέ тèřмΐņäľ ωìľľ řεʼnďęŗ όʼnľŷ ŧђέ ŭρďăţзŝ τö ŧђë šсгèзņ вêţшзэʼn ƒяāméş. !!! !!! !!! !!! !!! !!! !!! !!! ! - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". + Бў ďēƒăüℓţ, ťћэ ţèхţ ř℮ŋðěґĕґ υŝ℮ŝ ä FLIP_SEQUENTIAL Ŝωăр Сђáϊп åπδ ďεĉℓάŗέş δΐŗŧў ŗēćŧăñġℓέš νïд ťĥĕ Present1 ĀРĪ. Щĥêи тћїŝ ŝєŧŧΐñğ įѕ ℮лάьłзδ, α FLIP_DISCARD Şẁαр Ċħāīʼn ŵīĺļ ьё υѕėð íπśťεαď, āлδ ŋо ďīŗŧý ŕęсŧдиĝℓэş шīľĺ ъĕ δеĉľāŗэð. Ẃħέтħêґ òñё σř ŧнé ōтħεř ΐś ъёţŧęґ δéρ℮ήđѕ σή ÿούг ħäґďшάřέ ªήð νăŕιούѕ ǿτђēř ƒαстόяš. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Ųѕε ŝόƒťщаřė яĕŋðεříлğ (WARP) !!! !!! !!! + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + Ẅнέⁿ éñâвĺĕď, ŧĥë тěřmϊñăľ шîľĺ ŭşē ă şóƒтшářě яãѕтĕгīżεŕ (WARP). Тћįş ŝеţŧΐπģ śнσύŀδ вё ĺєƒŧ δїşâьĺεδ ύπďέя ªℓмôšţ áŀł ćϊŕçϋмśтąпćēѕ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". Ċσŀùмñѕ !! @@ -474,14 +497,6 @@ Ẅн℮ñ ðìşāьļĕð, τĥė ŵΐņďòώ ẃíļĺ řėŝîżē šмõόтнłγ. !!! !!! !!! !!! !! A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Ųѕε ŝόƒťщаřė яĕŋðεříлğ !!! !!! - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Ẅнέⁿ éñâвĺĕď, ŧĥë тěřmϊñăľ шîľĺ ŭşē ŧнé šбƒţẅāяē ґэпδėѓεŕ (д.к.ă. ẀÅЃΡ) ĭñŝτéāđ оƒ тħё ĥάґđẃаяē οлε. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - ₤áϋпςħ ôл мαςĥĭñę ŝťąřťûρ !!! !!! ! Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1793,12 +1808,12 @@ Ļĕдŗⁿ мõгĕ. !!! A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Ẃãялíʼnĝ: !! - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts + + Μįŝşìηğ ƒòńтš: !!! ! + This is a label that is followed by a list of missing fonts. - - €ħσõśïʼnğ ą ñой-мõποşφãĉєδ ƒŏŋţ ẅіľľ łîķέℓў ŕєŝùłţ íй νΐşūαℓ āѓťīƒдςţŝ. Џŝè àţ ÿοùŗ øẁη δíśčґ℮ťîбņ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !! - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts + + Νόņ-mσиόšραςз ƒоʼnтŝ: !!! !!! + This is a label that is followed by a list of proportional fonts. \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw index f954fb623fb..98bd519ebb1 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw @@ -137,11 +137,9 @@ Ţħīѕ ċøłǿґ ŝςħèм℮ îś рăŗţ õƒ тнè ъûĩľт-íπ śéţťΐлĝś õř дŋ íńşťªłĺèð èжťęлşίοη !!! !!! !!! !!! !!! !!! !!! ! - Ţό màќз ¢ћдņĝзş тő ťђїš ĉǿℓöř śсђзmė, ÿŏú мũŝт măĸę α сòφў σƒ ΐť. !!! !!! !!! !!! !!! !!! ! - Маĸέ α ċōρý !!! @@ -311,13 +309,38 @@ Ťђě ţэřмīηãĺ ǻφφℓï¢ǻтΐбň ŧђáт łáůйčĥēś ẅĥэп ā сöмmǻńđ-ľіʼnэ ăρρĺįċāτΐôⁿ ϊš яųñ шíţћöυţ ªņ ĕхϊŝŧĭñğ şěŝѕïŏπ, ŀĩĸė ƒѓом ţћĕ Ŝτáґт Μęπü бг Яųņ ďīäℓöğ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Ĝŗäрђΐсѕ ÃРΪ !!! + This text is shown next to a list of choices. + + + Đĩŗěćŧ3Đ 11 рґóνϊďèš ă мõřе φ℮ŕƒóŗmąņт аʼnđ ƒеǻŧùґê-яĩςђ ℮жφéѓιęʼnςè, ώђēѓėªŝ Ðìгëçť2Ď ĩś мθяë ŝţдвłē. Ţĥé δęƒаűłτ ōφτιоⁿ "Ãúτσмάτīč" щĩłł φìçк ţђë ÁΡĨ ţħǻτ ъёšť ƒīтѕ уōûґ ğřǻφђі¢ѕ нąŗďщǻѓê. ̓ ўöџ ê×ρёřįėʼnċê ѕįġńїƒϊĉâⁿт îśşΰёś, соńśϊδеŗ üśίńğ Đΐřěċτ2Đ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! + + + Άůтǿмąťí¢ !!! + The default choice between multiple graphics APIs. + + + Đîяе¢ť2Đ !! + + + Ďїřèĉт3Ď 11 !!! + - Ŗёδѓªŵ еñţιŗę šĉřέëŋ шн℮й đĩşρℓâў υρďάţëš !!! !!! !!! !!! - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. + Ďіşǻьłэ рàґτíàľ Šŵąр Ċнаιŋ ĭήνάŀïδαţίбπ !!! !!! !!! !!! + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. - Щħ℮п đįѕāъĺèđ, ťђέ тèřмΐņäľ ωìľľ řεʼnďęŗ όʼnľŷ ŧђέ ŭρďăţзŝ τö ŧђë šсгèзņ вêţшзэʼn ƒяāméş. !!! !!! !!! !!! !!! !!! !!! !!! ! - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". + Бў ďēƒăüℓţ, ťћэ ţèхţ ř℮ŋðěґĕґ υŝ℮ŝ ä FLIP_SEQUENTIAL Ŝωăр Сђáϊп åπδ ďεĉℓάŗέş δΐŗŧў ŗēćŧăñġℓέš νïд ťĥĕ Present1 ĀРĪ. Щĥêи тћїŝ ŝєŧŧΐñğ įѕ ℮лάьłзδ, α FLIP_DISCARD Şẁαр Ċħāīʼn ŵīĺļ ьё υѕėð íπśťεαď, āлδ ŋо ďīŗŧý ŕęсŧдиĝℓэş шīľĺ ъĕ δеĉľāŗэð. Ẃħέтħêґ òñё σř ŧнé ōтħεř ΐś ъёţŧęґ δéρ℮ήđѕ σή ÿούг ħäґďшάřέ ªήð νăŕιούѕ ǿτђēř ƒαстόяš. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Ųѕε ŝόƒťщаřė яĕŋðεříлğ (WARP) !!! !!! !!! + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + Ẅнέⁿ éñâвĺĕď, ŧĥë тěřmϊñăľ шîľĺ ŭşē ă şóƒтшářě яãѕтĕгīżεŕ (WARP). Тћįş ŝеţŧΐπģ śнσύŀδ вё ĺєƒŧ δїşâьĺεδ ύπďέя ªℓмôšţ áŀł ćϊŕçϋмśтąпćēѕ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". Ċσŀùмñѕ !! @@ -474,14 +497,6 @@ Ẅн℮ñ ðìşāьļĕð, τĥė ŵΐņďòώ ẃíļĺ řėŝîżē šмõόтнłγ. !!! !!! !!! !!! !! A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Ųѕε ŝόƒťщаřė яĕŋðεříлğ !!! !!! - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Ẅнέⁿ éñâвĺĕď, ŧĥë тěřmϊñăľ шîľĺ ŭşē ŧнé šбƒţẅāяē ґэпδėѓεŕ (д.к.ă. ẀÅЃΡ) ĭñŝτéāđ оƒ тħё ĥάґđẃаяē οлε. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - ₤áϋпςħ ôл мαςĥĭñę ŝťąřťûρ !!! !!! ! Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1793,12 +1808,12 @@ Ļĕдŗⁿ мõгĕ. !!! A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Ẃãялíʼnĝ: !! - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts + + Μįŝşìηğ ƒòńтš: !!! ! + This is a label that is followed by a list of missing fonts. - - €ħσõśïʼnğ ą ñой-мõποşφãĉєδ ƒŏŋţ ẅіľľ łîķέℓў ŕєŝùłţ íй νΐşūαℓ āѓťīƒдςţŝ. Џŝè àţ ÿοùŗ øẁη δíśčґ℮ťîбņ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !! - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts + + Νόņ-mσиόšραςз ƒоʼnтŝ: !!! !!! + This is a label that is followed by a list of proportional fonts. \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw index c935675a936..a5ac2237245 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw @@ -137,11 +137,9 @@ Эта цветовая схема является частью встроенных параметров или установленным расширением - Чтобы внести изменения в эту цветовую схему, необходимо создать ее копию. - Создать копию @@ -311,14 +309,6 @@ Приложение терминала, запускаемое при запуске приложения командной строки без существующего сеанса, например из меню "Пуск" или из диалогового окна "Выполнить". A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - Перерисовка всего экрана при обновлении дисплея - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - Если этот параметр отключен, терминал будет отображать только обновления экрана между кадрами. - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Столбцы Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ Если этот параметр отключен, размер окна будет плавно изменен. A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - Использование программного рендеринга - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - Если этот параметр включен, терминал будет использовать программный обработчик (известный как WARP) вместо аппаратного. - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - Запускать при запуске компьютера Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ Дополнительные сведения. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - Внимание! - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - Выбор не моноширинного шрифта, скорее всего, приведет к визуальным артефактам. Используйте по своему усмотрению. - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw index 44f22000ddb..516ea1b281e 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw @@ -137,11 +137,9 @@ 此配色方案是内置设置或已安装扩展的一部分 - 若要对此配色方案进行更改,必须复制该配色方案。 - 制作副本 @@ -311,14 +309,6 @@ 当命令行应用程序在没有现有会话(例如从“开始菜单”或“运行”对话框)运行时启动的终端应用程序。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - 显示内容更新时重绘整个屏幕 - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - 禁用后,终端将仅在帧之间将更新呈现到屏幕。 - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ 禁用后,窗口将平滑调整大小。 A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - 使用软件渲染 - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - 启用后,终端将使用软件渲染器(也就是WARP)而不是硬件渲染器。 - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - 在计算机启动时启动 Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ 了解详细信息。 A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - 警告: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - 选择非等宽字体可能导致视觉伪影。请自行决定使用。 - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw index 13ab841670c..65998ee399e 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw @@ -137,11 +137,9 @@ 此色彩配置是內建設定或已安裝擴充功能的一部分 - 若要變更此色彩配置,您必須製作色彩配置的複本。 - 建立複本 @@ -311,14 +309,6 @@ 當執行命令列應用程式且不使用現有工作模式而啟動的終端機應用程式 (例如從 [開始] 功能表或 [執行] 對話方塊)。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. - - 顯示更新時,重新繪製整個螢幕 - Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. - - - 停用時,終端機只會轉譯框架間螢幕的更新。 - A description for what the "force full repaint" setting does. Presented near "Globals_DisablePartialInvalidation.Header". - Header for a control to choose the number of columns in the terminal's text grid. @@ -474,14 +464,6 @@ 停用時,視窗將會順暢地調整大小。 A description for what the "snap to grid on resize" setting does. Presented near "Globals_SnapToGridOnResize.Header". - - 使用軟體呈現 - Header for a control to toggle whether the terminal should use software to render content instead of the hardware. - - - 當啟用時,終端機將使用軟體轉譯器 (又稱 WARP),而不是硬體1。 - A description for what the "software rendering" setting does. Presented near "Globals_SoftwareRendering.Header". - 在電腦啟動時啟動 Header for a control to toggle whether the app should launch when the user's machine starts up, or not. @@ -1789,12 +1771,4 @@ 深入了解。 A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. - - 警告: - Title for the warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - - - 選擇非等寬字型可能會產生視覺成品。使用時請自行斟酌。 - Warning info bar used when a non monospace font face is chosen to indicate that there may be visual artifacts - \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsModel/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/qps-ploc/Resources.resw index 8354be2b2cd..d2eea062990 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/qps-ploc/Resources.resw @@ -700,6 +700,9 @@ Ŗ℮ŝţāґт čõʼnлęčŧįоή !!! !! + + Θφěп ŝĉґαŧςђρąδ !!! ! + Šēłεĉτ πĕжţ ċômmàлð ŏµŧρūţ !!! !!! ! diff --git a/src/cascadia/TerminalSettingsModel/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/qps-ploca/Resources.resw index 8354be2b2cd..d2eea062990 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/qps-ploca/Resources.resw @@ -700,6 +700,9 @@ Ŗ℮ŝţāґт čõʼnлęčŧįоή !!! !! + + Θφěп ŝĉґαŧςђρąδ !!! ! + Šēłεĉτ πĕжţ ċômmàлð ŏµŧρūţ !!! !!! ! diff --git a/src/cascadia/TerminalSettingsModel/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/qps-plocm/Resources.resw index 8354be2b2cd..d2eea062990 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/qps-plocm/Resources.resw @@ -700,6 +700,9 @@ Ŗ℮ŝţāґт čõʼnлęčŧįоή !!! !! + + Θφěп ŝĉґαŧςђρąδ !!! ! + Šēłεĉτ πĕжţ ċômmàлð ŏµŧρūţ !!! !!! ! From 2e7c3fa3132fa3bff23255480c593cbd3432eee5 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Wed, 27 Mar 2024 18:05:56 -0500 Subject: [PATCH 04/16] Move to AzureFileCopy@6 for Managed Identity support (#16957) This is required for us to move off Entra ID Application identity. --- build/pipelines/templates-v2/job-deploy-to-azure-storage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml b/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml index 69b82e57bb3..e2ed380fd45 100644 --- a/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml +++ b/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml @@ -80,7 +80,7 @@ jobs: Install-Module -Verbose -AllowClobber -Force Az.Accounts, Az.Storage, Az.Network, Az.Resources, Az.Compute displayName: Install Azure Module Dependencies - - task: AzureFileCopy@5 + - task: AzureFileCopy@6 displayName: Publish to Storage Account inputs: sourcePath: _out/* From b0b7e50ec5d0330d188c06dccf45ff8b99f83983 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Wed, 27 Mar 2024 18:12:50 -0500 Subject: [PATCH 05/16] Revert "Move to AzureFileCopy@6 for Managed Identity support (#16957)" This reverts commit 2e7c3fa3132fa3bff23255480c593cbd3432eee5. --- build/pipelines/templates-v2/job-deploy-to-azure-storage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml b/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml index e2ed380fd45..69b82e57bb3 100644 --- a/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml +++ b/build/pipelines/templates-v2/job-deploy-to-azure-storage.yml @@ -80,7 +80,7 @@ jobs: Install-Module -Verbose -AllowClobber -Force Az.Accounts, Az.Storage, Az.Network, Az.Resources, Az.Compute displayName: Install Azure Module Dependencies - - task: AzureFileCopy@6 + - task: AzureFileCopy@5 displayName: Publish to Storage Account inputs: sourcePath: _out/* From 4458a6d8c62ff7e7cddec7a3eb628db07d1ed8dd Mon Sep 17 00:00:00 2001 From: charli <111490544+hellocharli@users.noreply.github.com> Date: Thu, 28 Mar 2024 05:11:25 -0700 Subject: [PATCH 06/16] Replace 'it'll' with 'it will' to adhere to Microsoft Style Guidelines (#16955) ## Summary of the Pull Request ## References and Relevant Issues Fixes "Align 'Run this profile as Administrator' Settings Description with Microsoft Style Guidelines" #16946 ## Detailed Description of the Pull Request / Additional comments Expanded the contraction "it'll" to "it will" on line 993 of `src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw` ## Validation Steps Performed N/A ## PR Checklist - [X] Closes #16946 - [ ] Tests added/passed - No tests were added - [ ] Documentation updated - No documentation was updated - [ ] Schema updated (if necessary) - No schema was updated --- .../TerminalSettingsEditor/Resources/en-US/Resources.resw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index d046ac12df7..a4f21bf6754 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -990,7 +990,7 @@ Header for a control to toggle whether the profile should always open elevated (in an admin window) - If enabled, the profile will open in an Admin terminal window automatically. If the current window is already running as admin, it'll open in this window. + If enabled, the profile will open in an Admin terminal window automatically. If the current window is already running as admin, it will open in this window. A description for what the "elevate" setting does. Presented near "Profile_Elevate". From e44fab921b64249d984dcc7e46ebefd4f4efc083 Mon Sep 17 00:00:00 2001 From: Windows Console Service Bot <14666831+consvc@users.noreply.github.com> Date: Thu, 28 Mar 2024 07:12:46 -0500 Subject: [PATCH 07/16] Localization Updates - main - 03/28/2024 03:03:16 (#16959) --- .../Resources/de-DE/Resources.resw | 8 ++++ .../Resources/es-ES/Resources.resw | 4 ++ .../Resources/fr-FR/Resources.resw | 8 ++++ .../Resources/it-IT/Resources.resw | 8 ++++ .../Resources/ja-JP/Resources.resw | 8 ++++ .../Resources/ko-KR/Resources.resw | 8 ++++ .../Resources/pt-BR/Resources.resw | 8 ++++ .../Resources/ru-RU/Resources.resw | 8 ++++ .../Resources/zh-CN/Resources.resw | 8 ++++ .../Resources/zh-TW/Resources.resw | 8 ++++ .../Resources/de-DE/Resources.resw | 41 +++++++++++++++++++ .../Resources/es-ES/Resources.resw | 15 +++++++ .../Resources/fr-FR/Resources.resw | 4 ++ .../Resources/it-IT/Resources.resw | 15 +++++++ .../Resources/ja-JP/Resources.resw | 41 +++++++++++++++++++ .../Resources/ko-KR/Resources.resw | 41 +++++++++++++++++++ .../Resources/pt-BR/Resources.resw | 41 +++++++++++++++++++ .../Resources/ru-RU/Resources.resw | 41 +++++++++++++++++++ .../Resources/zh-CN/Resources.resw | 15 +++++++ .../Resources/zh-TW/Resources.resw | 41 +++++++++++++++++++ .../Resources/de-DE/Resources.resw | 3 ++ .../Resources/ja-JP/Resources.resw | 3 ++ .../Resources/ko-KR/Resources.resw | 3 ++ .../Resources/pt-BR/Resources.resw | 3 ++ .../Resources/ru-RU/Resources.resw | 3 ++ .../Resources/zh-TW/Resources.resw | 3 ++ 26 files changed, 389 insertions(+) diff --git a/src/cascadia/TerminalControl/Resources/de-DE/Resources.resw b/src/cascadia/TerminalControl/Resources/de-DE/Resources.resw index 732522ca013..338cb51d30f 100644 --- a/src/cascadia/TerminalControl/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/de-DE/Resources.resw @@ -213,6 +213,14 @@ Installieren Sie entweder die fehlende Schriftart, oder wählen Sie eine andere Unerwarteter Fehler beim Renderer: {0} {0} is an error code. + + Die folgenden Schriftarten wurden nicht gefunden: {0}. Installieren Sie sie, oder wählen Sie andere Schriftarten aus. + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + Unerwarteter Rendererfehler: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + Der schreibgeschützte Modus ist aktiviert. diff --git a/src/cascadia/TerminalControl/Resources/es-ES/Resources.resw b/src/cascadia/TerminalControl/Resources/es-ES/Resources.resw index e9c2b842f9a..30231e7f63e 100644 --- a/src/cascadia/TerminalControl/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/es-ES/Resources.resw @@ -213,6 +213,10 @@ Instale la fuente que falta o elija otra. El representador encontró un error inesperado: {0} {0} is an error code. + + El representador encontró un error inesperado: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + El modo de solo lectura está habilitado. diff --git a/src/cascadia/TerminalControl/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalControl/Resources/fr-FR/Resources.resw index bb21b343fe6..6f3e367fdc9 100644 --- a/src/cascadia/TerminalControl/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/fr-FR/Resources.resw @@ -213,6 +213,14 @@ Installez la police manquante ou choisissez-en une autre. Le convertisseur a rencontré une erreur inattendue : {0} {0} is an error code. + + Impossible de trouver les polices suivantes : {0}. Installez-les ou choisissez d’autres polices. + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + Le convertisseur a rencontré une erreur inattendue : {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + Le mode lecture seule est activé. diff --git a/src/cascadia/TerminalControl/Resources/it-IT/Resources.resw b/src/cascadia/TerminalControl/Resources/it-IT/Resources.resw index 4e6e08d40c8..39a76ac1915 100644 --- a/src/cascadia/TerminalControl/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/it-IT/Resources.resw @@ -213,6 +213,14 @@ Installare il tipo di carattere mancante o sceglierne un altro. Il renderer ha rilevato un errore imprevisto: {0} {0} is an error code. + + Impossibile trovare i tipi di carattere seguenti: {0}. Installarli o scegliere tipi di carattere diversi. + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + Errore imprevisto del renderer: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + La modalità di sola lettura è abilitata. diff --git a/src/cascadia/TerminalControl/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalControl/Resources/ja-JP/Resources.resw index 4b0c96d2748..b352afeeec7 100644 --- a/src/cascadia/TerminalControl/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/ja-JP/Resources.resw @@ -213,6 +213,14 @@ レンダラーで予期しないエラーが発生しました: {0} {0} is an error code. + + 次のフォントが見つかりません: {0}。インストールするか、別のフォントを選択してください。 + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + レンダラーで予期しないエラーが発生しました: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + 読み取り専用モードが有効になっています。 diff --git a/src/cascadia/TerminalControl/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalControl/Resources/ko-KR/Resources.resw index 75e624dab29..2200c028d99 100644 --- a/src/cascadia/TerminalControl/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/ko-KR/Resources.resw @@ -213,6 +213,14 @@ 렌더러에서 예기치 않은 오류가 발생했습니다. {0} {0} is an error code. + + 다음 글꼴을 찾을 수 없습니다. {0}. 설치하거나 다른 글꼴을 선택하세요. + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + 렌더러에서 예기치 않은 오류가 발생했습니다. {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + 읽기 전용 모드가 사용 설정됩니다. diff --git a/src/cascadia/TerminalControl/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalControl/Resources/pt-BR/Resources.resw index ca6ae8a3e74..aadafd14b12 100644 --- a/src/cascadia/TerminalControl/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/pt-BR/Resources.resw @@ -213,6 +213,14 @@ Instale a fonte ausente ou escolha outra. O renderizador encontrou um erro inesperado: {0} {0} is an error code. + + Não é possível localizar as seguintes fontes: {0}. Instale-os ou escolha fontes diferentes. + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + O renderizador encontrou um erro inesperado: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + O modo somente leitura está habilitado. diff --git a/src/cascadia/TerminalControl/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalControl/Resources/ru-RU/Resources.resw index 082557f26c2..8b0c908a9bd 100644 --- a/src/cascadia/TerminalControl/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/ru-RU/Resources.resw @@ -213,6 +213,14 @@ Произошла непредвиденная ошибка обработчика: {0} {0} is an error code. + + Не удалось найти следующие шрифты: {0}. Установите их или выберите другие шрифты. + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + В обработчике произошла непредвиденная ошибка: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + Включен режим только для чтения. diff --git a/src/cascadia/TerminalControl/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalControl/Resources/zh-CN/Resources.resw index c4d729bd8bb..c331dab19ac 100644 --- a/src/cascadia/TerminalControl/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/zh-CN/Resources.resw @@ -213,6 +213,14 @@ 呈现器遇到意外错误: {0} {0} is an error code. + + 找不到以下字体: {0}。请安装它们或选择其他字体。 + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + 呈现器遇到错误: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + 只读模式已启用。 diff --git a/src/cascadia/TerminalControl/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalControl/Resources/zh-TW/Resources.resw index 4f4f8671f7c..31d8034d2a1 100644 --- a/src/cascadia/TerminalControl/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/zh-TW/Resources.resw @@ -213,6 +213,14 @@ 轉譯器發生意外的錯誤:{0} {0} is an error code. + + 找不到下列字型: {0}。請安裝它們,或選擇其他字型。 + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + + + 轉譯器發生意外的錯誤: {0:#010x} {1} + {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. + 已啟用唯讀模式。 diff --git a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw index c7e5f00ab76..9214556f77b 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw @@ -309,6 +309,39 @@ Die Terminalanwendung, die gestartet wird, wenn eine Befehlszeilenanwendung ohne vorhandene Sitzung gestartet wird, beispielsweise vom Startmenü oder über das Dialogfeld "Ausführen". A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Grafik-API + This text is shown next to a list of choices. + + + Direct3D 11 bietet eine leistungsfähigere und funktionsreichere Benutzeroberfläche, während Direct2D stabiler ist. Mit der Standardoption "Automatisch" wird die API ausgewählt, die am besten zu Ihrer Grafikhardware passt. Wenn erhebliche Probleme auftreten, erwägen Sie die Verwendung von Direct2D. + + + Automatisch + The default choice between multiple graphics APIs. + + + Direct2D + + + Direct3D 11 + + + Swapchain-Teilinvalidierung deaktivieren + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + + + Standardmäßig verwendet der Textrenderer eine FLIP_SEQUENTIAL Swap Chain und deklariert modifiziert Rechtecke über die Present1-API. Wenn diese Einstellung aktiviert ist, wird stattdessen eine FLIP_DISCARD Swap Chain verwendet, und es werden keine modifiziert Rechtecke deklariert. Ob der eine oder der andere besser ist, hängt von Ihrer Hardware und verschiedenen anderen Faktoren ab. + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Softwarerendering verwenden (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + Wenn diese Option aktiviert ist, verwendet das Terminal einen Softwarerasterer (WARP). Diese Einstellung sollte unter fast allen Umständen deaktiviert bleiben. + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Spalten Header for a control to choose the number of columns in the terminal's text grid. @@ -1771,4 +1804,12 @@ Weitere Informationen. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + Fehlende Schriftarten: + This is a label that is followed by a list of missing fonts. + + + Proportionale Schriftarten: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw index 1aefd03fc53..e4574ab1f35 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw @@ -309,6 +309,21 @@ Aplicación de terminal que se inicia cuando se ejecuta una aplicación de línea de comandos sin una sesión existente, como en el menú Inicio o en el cuadro de diálogo Ejecutar. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Direct3D 11 proporciona una experiencia con más rendimiento y características, mientras que Direct2D es más estable. La opción predeterminada "Automático" seleccionará la API que mejor se adapte a su hardware gráfico. Si experimenta problemas importantes, considere la posibilidad de usar Direct2D. + + + Automático + The default choice between multiple graphics APIs. + + + De forma predeterminada, el representador de texto usa una cadena de intercambio de FLIP_SEQUENTIAL y declara rectángulos modificados a través de la API de Present1. Cuando esta configuración está habilitada, se usará una cadena de intercambio de FLIP_DISCARD y no se declarará ningún rectángulo con modificaciones. Si uno u otro es mejor depende de su hardware y de otros factores. + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Cuando está habilitado, el terminal usará un rasterizador de software (WARP). Esta configuración debe dejarse deshabilitada en casi todas las circunstancias. + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Columnas Header for a control to choose the number of columns in the terminal's text grid. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw index c5f582d3123..2f56f3ebd4c 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw @@ -309,6 +309,10 @@ L’application Terminal qui se lance lorsqu’une application de ligne de commande est exécutée sans session existante, par exemple à partir du menu Démarrer ou de la boîte de dialogue Exécuter. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Automatique + The default choice between multiple graphics APIs. + Colonnes Header for a control to choose the number of columns in the terminal's text grid. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw index 98b19357538..3d0fb72f844 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw @@ -309,6 +309,21 @@ L'applicazione terminale che viene avviata quando viene eseguita un'applicazione della riga di comando senza una sessione esistente, ad esempio dalla finestra di dialogo menu Start o Esegui. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Direct3D 11 offre un'esperienza più performante e con funzionalità più elevate, mentre Direct2D è più stabile. L'opzione predefinita "Automatico" sceglierà l'API più adatta all'hardware grafico. Se si verificano problemi significativi, provare a usare Direct2D. + + + Automatico + The default choice between multiple graphics APIs. + + + Per impostazione predefinita, il renderer di testo usa una catena di scambio FLIP_SEQUENTIAL e dichiara rettangoli modificati ma non modificati tramite l'API Present1. Quando questa impostazione è abilitata, verrà utilizzata una catena di scambio FLIP_DISCARD e non verranno dichiarati rettangoli modificati ma non modificati. Il miglioramento dell'uno o dell'altro dipende dall'hardware e da vari altri fattori. + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Se questa opzione è abilitata, il terminale userà un rasterizzatore software (WARP). Questa impostazione deve essere lasciata disabilitata in quasi tutte le circostanze. + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Colonne Header for a control to choose the number of columns in the terminal's text grid. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw index aadbf4c8b5d..6cd0a869dd7 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw @@ -309,6 +309,39 @@ [スタート] メニューや [ファイル名を指定して実行] ダイアログなど、既存のセッションなしでコマンドライン アプリケーションを実行したときに起動するターミナル アプリケーション。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + グラフィックス API + This text is shown next to a list of choices. + + + Direct3D 11 はよりパフォーマンスが高く、機能が豊富なエクスペリエンスを提供しますが、Direct2D はより安定しています。既定のオプション [自動] では、グラフィックス ハードウェアに最適な API が選択されます。重大な問題が発生した場合は、Direct2D の使用を検討してください。 + + + 自動 + The default choice between multiple graphics APIs. + + + Direct2D + + + Direct3D 11 + + + 部分的なスワップ チェーンの無効化を無効にする + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + + + 既定では、テキスト レンダラーは FLIP_SEQUENTIAL Swap Chain を使用し、Present1 API を介してダーティ四角形を宣言します。この設定を有効にすると、代わりに FLIP_DISCARD スワップ チェーンが使用され、ダーティ四角形は宣言されません。どちらか一方が望ましいかどうかは、お使いのハードウェアとその他のさまざまな要因によって異なります。 + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + ソフトウェア レンダリングを使用する (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + 有効にすると、ターミナルはソフトウェア ラスターライザー (WARP) を使用します。この設定は、ほとんどの状況で無効のままにする必要があります。 + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Header for a control to choose the number of columns in the terminal's text grid. @@ -1771,4 +1804,12 @@ 詳細をご覧ください。 A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + 見つからないフォント: + This is a label that is followed by a list of missing fonts. + + + 非等幅フォント: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw index dc1cf00158f..40e83f7dfc4 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw @@ -309,6 +309,39 @@ 시작 메뉴나 실행 대화 상자와 같이 기존 세션이 없으면 명령 줄 응용 프로그램을 실행하고 있는 터미널 응용 프로그램입니다. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Graphics API + This text is shown next to a list of choices. + + + Direct3D 11은 성능과 기능이 풍부한 환경을 제공하는 반면 Direct2D는 더욱 안정적입니다. 기본 옵션 "자동"은 그래픽 하드웨어에 가장 적합한 API를 선택합니다. 심각한 문제가 발생하는 경우 Direct2D를 사용하는 것이 좋습니다. + + + 자동 + The default choice between multiple graphics APIs. + + + Direct2D + + + Direct3D 11 + + + 부분 스왑 체인 무효화 사용 안 함 + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + + + 기본적으로 텍스트 렌더러는 FLIP_SEQUENTIAL 스왑 체인을 사용하고 Present1 API를 통해 더티 사각형을 선언합니다. 이 설정을 사용하면 FLIP_DISCARD 스왑 체인이 대신 사용되며 더티 사각형이 선언되지 않습니다. 하나 또는 다른 요소가 더 좋은지 여부는 하드웨어 및 다양한 다른 요인에 따라 달라집니다. + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + 소프트웨어 렌더링(WARP) 사용 + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + 사용하도록 설정하면 터미널에서 소프트웨어 래스터라이저(WARP)를 사용합니다. 거의 모든 상황에서는 이 설정을 사용하지 않도록 설정해야 합니다. + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Header for a control to choose the number of columns in the terminal's text grid. @@ -1771,4 +1804,12 @@ 자세히 알아보세요. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + 누락된 글꼴: + This is a label that is followed by a list of missing fonts. + + + 고정 폭이 아닌 글꼴: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw index eb0d81d9026..1121be023e6 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw @@ -309,6 +309,39 @@ O aplicativo de terminal que é iniciado quando um aplicativo de linha de comando é executado sem uma sessão existente, como no menu iniciar ou na caixa de diálogo Executar. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + API de Gráficos + This text is shown next to a list of choices. + + + O Direct3D 11 fornece uma experiência mais completa e avançada de recursos, enquanto o Direct2D é mais estável. A opção padrão "Automático" escolherá a API que melhor se ajusta ao hardware gráfico. Se você tiver problemas significativos, considere o uso Direct2D. + + + Automático + The default choice between multiple graphics APIs. + + + Direct2D + + + Direct3D 11 + + + Desabilitar a invalidação parcial da cadeia de troca + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + + + Por padrão, o renderizador de texto usa FLIP_SEQUENTIAL Cadeia de Permuta e declara sujo retângulos por meio da API Present1. Quando esta configuração estiver habilitada, um FLIP_DISCARD cadeia de troca será usado e nenhum retângulo sujo será declarado. Se um ou outro é melhor depende do hardware e de vários outros fatores. + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Usar a renderização de software (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + Quando habilitado, o terminal usará um rasterizador de software (WARP). Esta configuração deve ser desabilitada em quase todas as circunstâncias. + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Colunas Header for a control to choose the number of columns in the terminal's text grid. @@ -1771,4 +1804,12 @@ Saiba mais. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + Fontes ausentes: + This is a label that is followed by a list of missing fonts. + + + Fontes não monoespaçadas: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw index a5ac2237245..913ae9ee97f 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw @@ -309,6 +309,39 @@ Приложение терминала, запускаемое при запуске приложения командной строки без существующего сеанса, например из меню "Пуск" или из диалогового окна "Выполнить". A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + API графики + This text is shown next to a list of choices. + + + Direct3D 11 отличается более высокой производительностью и расширенной функциональностью, но Direct2D стабильнее. По умолчанию используется параметр "Автоматически": выбирается API, лучше всего подходящий к графическому оборудованию. Если возникают серьезные проблемы, попробуйте использовать Direct2D. + + + Автоматически + The default choice between multiple graphics APIs. + + + Direct2D + + + Direct3D 11 + + + Отключить аннулирование частичной цепочки буферов + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + + + По умолчанию система отрисовки текста использует цепочку буферов FLIP_SEQUENTIAL и объявляет "грязные" прямоугольники с помощью API Present1. Когда этот параметр включен, будет использоваться цепочка буферов FLIP_DISCARD, а "грязные" прямоугольники не будут объявляться. Выбор зависит от оборудования и от ряда других факторов. + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Использовать программную отрисовку (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + Если этот параметр включен, терминал будет использовать программный растеризатор (WARP). Этот параметр должен быть отключен почти при любых обстоятельствах. + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Столбцы Header for a control to choose the number of columns in the terminal's text grid. @@ -1771,4 +1804,12 @@ Дополнительные сведения. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + Отсутствующие шрифты: + This is a label that is followed by a list of missing fonts. + + + Шрифты, кроме моноширинных: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw index 516ea1b281e..91c54379777 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw @@ -309,6 +309,21 @@ 当命令行应用程序在没有现有会话(例如从“开始菜单”或“运行”对话框)运行时启动的终端应用程序。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Direct3D 11 提供性能更佳且功能更丰富的体验,而 Direct2D 则更稳定。默认选项“自动”将选择最适合你的图形硬件的 API。如果遇到严重问题,请考虑使用 Direct2D。 + + + 自动 + The default choice between multiple graphics APIs. + + + 默认情况下,文本呈现器使用 FLIP_SEQUENTIAL 交换链并通过 Present1 API 声明脏矩形。启用此设置时,将改用 FLIP_DISCARD 交换链,并且不会声明脏矩形。一个或另一个是否更依赖于你的硬件和各种其他因素。 + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + 启用后,终端将使用软件光栅 (WARP)。几乎在所有情况下都应禁用此设置。 + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Header for a control to choose the number of columns in the terminal's text grid. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw index 65998ee399e..0e1d7c5e3ea 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw @@ -309,6 +309,39 @@ 當執行命令列應用程式且不使用現有工作模式而啟動的終端機應用程式 (例如從 [開始] 功能表或 [執行] 對話方塊)。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + 圖形 API + This text is shown next to a list of choices. + + + Direct3D 11 提供更具效能且功能更豐富的體驗,而 Direct2D 則較穩定。默認選項 [自動] 會挑選最適合您圖形硬體的 API。如果您遇到重大問題,請考慮使用 Direct2D。 + + + 自動 + The default choice between multiple graphics APIs. + + + Direct2D + + + Direct3D 11 + + + 停用部分 [交換鏈結] 失效 + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + + + 根據預設,文字轉譯器會使用 FLIP_SEQUENTIAL 交換鏈結,並透過 Present1 API 宣告變更的矩形。啟用此設定時,將改為使用 FLIP_DISCARD 交換鏈結,而且不會宣告任何已變更的矩形。一個或另一個比較好取決於您的硬體和各種其他因素。 + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + 使用軟體呈現 (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + 啟用時,終端機將使用軟體點陣器 (WARP)。在幾乎所有情況下,此設定都應該保留停用。 + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Header for a control to choose the number of columns in the terminal's text grid. @@ -1771,4 +1804,12 @@ 深入了解。 A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + 缺少的字型: + This is a label that is followed by a list of missing fonts. + + + 非等寬字型: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsModel/Resources/de-DE/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/de-DE/Resources.resw index d3ed4232bd0..1b088d57051 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/de-DE/Resources.resw @@ -700,6 +700,9 @@ Verbindung neu starten + + Notizblock öffnen + Nächste Befehlsausgabe auswählen diff --git a/src/cascadia/TerminalSettingsModel/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/ja-JP/Resources.resw index 07121f6d2a5..173663fc990 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/ja-JP/Resources.resw @@ -700,6 +700,9 @@ 接続の再起動 + + スクラッチパッドを開く + 次のコマンド出力を選択 diff --git a/src/cascadia/TerminalSettingsModel/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/ko-KR/Resources.resw index 9151622030e..90be00c1d20 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/ko-KR/Resources.resw @@ -700,6 +700,9 @@ 연결 다시 시작 + + 스크래치 패드 열기 + 다음 명령 출력 선택 diff --git a/src/cascadia/TerminalSettingsModel/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/pt-BR/Resources.resw index bac30f15998..aa4a632c367 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/pt-BR/Resources.resw @@ -700,6 +700,9 @@ Reiniciar conexão + + Abrir o scratchpad + Selecionar a próxima saída de comando diff --git a/src/cascadia/TerminalSettingsModel/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/ru-RU/Resources.resw index a85b0d2d248..d5e70d81948 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/ru-RU/Resources.resw @@ -700,6 +700,9 @@ Перезапустить подключение + + Открыть временную память + Выбрать следующую команду вывода diff --git a/src/cascadia/TerminalSettingsModel/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/zh-TW/Resources.resw index d777ffb9380..536d4b900b5 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/zh-TW/Resources.resw @@ -700,6 +700,9 @@ 重新啟動連線 + + 開啟聽寫面板 + 選取下一個命令輸出 From 68955d1ddbccf06c8f42e1c6c306ede1d3e7e157 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 28 Mar 2024 05:28:26 -0700 Subject: [PATCH 08/16] Add Dark+, CGA and IBM color schemes (#16953) As discussed in #6176 and #16754. The "CGA" and "IBM 5153" names I'm told are the right ones to use: https://github.com/microsoft/terminal/issues/16754#issuecomment-2024066880 Closes #6176 Closes #16754 --- .../TerminalSettingsModel/defaults.json | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index 360f37afaad..ae8ed369ff6 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -281,6 +281,75 @@ "brightPurple": "#AD7FA8", "brightCyan": "#34E2E2", "brightWhite": "#EEEEEC" + }, + { + "name": "Dark+", + "foreground": "#cccccc", + "background": "#1e1e1e", + "cursorColor": "#808080", + "selectionBackground": "#ffffff", + "black": "#000000", + "red": "#cd3131", + "green": "#0dbc79", + "yellow": "#e5e510", + "blue": "#2472c8", + "purple": "#bc3fbc", + "cyan": "#11a8cd", + "white": "#e5e5e5", + "brightBlack": "#666666", + "brightRed": "#f14c4c", + "brightGreen": "#23d18b", + "brightYellow": "#f5f543", + "brightBlue": "#3b8eea", + "brightPurple": "#d670d6", + "brightCyan": "#29b8db", + "brightWhite": "#e5e5e5" + }, + { + "background": "#000000", + "black": "#000000", + "blue": "#0000AA", + "brightBlack": "#555555", + "brightBlue": "#5555FF", + "brightCyan": "#55FFFF", + "brightGreen": "#55FF55", + "brightPurple": "#FF55FF", + "brightRed": "#FF5555", + "brightWhite": "#FFFFFF", + "brightYellow": "#FFFF55", + "cursorColor": "#00AA00", + "cyan": "#00AAAA", + "foreground": "#AAAAAA", + "green": "#00AA00", + "name": "CGA", + "purple": "#AA00AA", + "red": "#AA0000", + "selectionBackground": "#FFFFFF", + "white": "#AAAAAA", + "yellow": "#AA5500" + }, + { + "background": "#000000", + "black": "#000000", + "blue": "#0000AA", + "brightBlack": "#555555", + "brightBlue": "#5555FF", + "brightCyan": "#55FFFF", + "brightGreen": "#55FF55", + "brightPurple": "#FF55FF", + "brightRed": "#FF5555", + "brightWhite": "#FFFFFF", + "brightYellow": "#FFFF55", + "cursorColor": "#00AA00", + "cyan": "#00AAAA", + "foreground": "#AAAAAA", + "green": "#00AA00", + "name": "IBM 5153", + "purple": "#AA00AA", + "red": "#AA0000", + "selectionBackground": "#FFFFFF", + "white": "#AAAAAA", + "yellow": "#C47E00" } ], "themes": [ From 8349fd2728f93acccdf6d3bb1d85c5f1a96a077c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 28 Mar 2024 11:19:42 -0700 Subject: [PATCH 09/16] Fix `repositionCursorWithMouse` after the viewport starts scrolling (#16950) Yea, I used a viewport-relative mouse position, rather than the buffer-relative position. Pretty obvious in retrospect. Closes #16423 --- src/cascadia/TerminalControl/ControlCore.cpp | 25 ++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 98c70398559..95c80e4e9ad 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1891,7 +1891,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation { const auto& last{ marks.back() }; const auto [start, end] = last.GetExtent(); - const auto lastNonSpace = _terminal->GetTextBuffer().GetLastNonSpaceCharacter(); + const auto bufferSize = _terminal->GetTextBuffer().GetSize(); + auto lastNonSpace = _terminal->GetTextBuffer().GetLastNonSpaceCharacter(); + bufferSize.IncrementInBounds(lastNonSpace, true); // If the user clicked off to the right side of the prompt, we // want to send keystrokes to the last character in the prompt +1. @@ -1904,17 +1906,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation // By only sending keypresses to the end of the command + 1, we // should leave the cursor at the very end of the prompt, // without adding any characters from a previous command. - auto clampedClick = terminalPosition; - if (terminalPosition > lastNonSpace) + + // terminalPosition is viewport-relative. + const auto bufferPos = _terminal->GetViewport().Origin() + terminalPosition; + if (bufferPos.y > lastNonSpace.y) { - clampedClick = lastNonSpace + til::point{ 1, 0 }; - _terminal->GetTextBuffer().GetSize().Clamp(clampedClick); + // Clicked under the prompt. Bail. + return; } + // Limit the click to 1 past the last character on the last line. + const auto clampedClick = std::min(bufferPos, lastNonSpace); + if (clampedClick >= end) { // Get the distance between the cursor and the click, in cells. - const auto bufferSize = _terminal->GetTextBuffer().GetSize(); // First, make sure to iterate from the first point to the // second. The user may have clicked _earlier_ in the @@ -1944,7 +1950,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation append(_terminal->SendKeyEvent(key, 0, {}, false)); } - _sendInputToConnection(buffer); + { + // Sending input requires that we're unlocked, because + // writing the input pipe may block indefinitely. + const auto suspension = _terminal->SuspendLock(); + _sendInputToConnection(buffer); + } } } } From 2050416997b237361e0c5979bb1cad88d0544673 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Thu, 28 Mar 2024 19:22:39 +0100 Subject: [PATCH 10/16] Remove VtApiRoutines (#16954) This removes `VtApiRoutines` and the VT passthrough mode. Why? While VT passthrough mode has a clear advantage (doesn't corrupt VT sequences) it fails to address other pain points (performance, out-of-sync issues after resize, etc.). Alternative options are available which have less restrictions. Why now? It's spring! Spring cleanup! --- doc/cascadia/profiles.schema.json | 4 - src/cascadia/TerminalApp/TerminalPage.cpp | 5 - .../TerminalConnection/ConptyConnection.cpp | 12 - .../TerminalConnection/ConptyConnection.h | 1 - src/cascadia/TerminalCore/ICoreSettings.idl | 1 - .../ProfileViewModel.cpp | 4 - .../TerminalSettingsEditor/ProfileViewModel.h | 2 - .../ProfileViewModel.idl | 2 - .../Profiles_Advanced.xaml | 10 - .../Resources/en-US/Resources.resw | 4 - .../TerminalSettingsModel/MTSMSettings.h | 1 - .../TerminalSettingsModel/Profile.idl | 1 - .../TerminalSettings.cpp | 1 - .../TerminalSettingsModel/TerminalSettings.h | 1 - src/cascadia/inc/ControlProperties.h | 1 - src/features.xml | 22 - src/host/ConsoleArguments.cpp | 12 - src/host/ConsoleArguments.hpp | 19 +- src/host/VtApiRoutines.cpp | 810 ------------------ src/host/VtApiRoutines.h | 366 -------- src/host/VtIo.cpp | 32 - src/host/VtIo.hpp | 1 - src/host/host-common.vcxitems | 2 - src/host/lib/hostlib.vcxproj.filters | 8 +- src/host/sources.inc | 1 - src/host/ut_host/ConsoleArgumentsTests.cpp | 156 ++-- src/inc/conpty-static.h | 1 - src/renderer/vt/Xterm256Engine.hpp | 4 - src/renderer/vt/state.cpp | 13 - src/renderer/vt/vtrenderer.hpp | 1 - src/server/ApiSorter.cpp | 19 +- src/server/IApiRoutines.h | 13 +- src/winconpty/winconpty.cpp | 9 +- src/winconpty/winconpty.h | 3 - 34 files changed, 78 insertions(+), 1464 deletions(-) delete mode 100644 src/host/VtApiRoutines.cpp delete mode 100644 src/host/VtApiRoutines.h diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 6733fe52266..9593ab9f6a7 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -2777,10 +2777,6 @@ "description": "When set to true, prompts will automatically be marked.", "type": "boolean" }, - "experimental.connection.passthroughMode": { - "description": "When set to true, directs the PTY for this connection to use pass-through mode instead of the original Conhost PTY simulation engine. This is an experimental feature, and its continued existence is not guaranteed.", - "type": "boolean" - }, "experimental.retroTerminalEffect": { "description": "When set to true, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed.", "type": "boolean" diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 605110a0ad7..d3fc7a2dc25 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1277,11 +1277,6 @@ namespace winrt::TerminalApp::implementation } } - if constexpr (Feature_VtPassthroughMode::IsEnabled()) - { - valueSet.Insert(L"passthroughMode", Windows::Foundation::PropertyValue::CreateBoolean(settings.VtPassthrough())); - } - connection.Initialize(valueSet); TraceLoggingWrite( diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 063083ace36..dd85388263b 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -257,10 +257,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation _cols = unbox_prop_or(settings, L"initialCols", _cols); _sessionId = unbox_prop_or(settings, L"sessionId", _sessionId); _environment = settings.TryLookup(L"environment").try_as(); - if constexpr (Feature_VtPassthroughMode::IsEnabled()) - { - _passthroughMode = unbox_prop_or(settings, L"passthroughMode", _passthroughMode); - } _inheritCursor = unbox_prop_or(settings, L"inheritCursor", _inheritCursor); _profileGuid = unbox_prop_or(settings, L"profileGuid", _profileGuid); @@ -332,14 +328,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation flags |= PSEUDOCONSOLE_INHERIT_CURSOR; } - if constexpr (Feature_VtPassthroughMode::IsEnabled()) - { - if (_passthroughMode) - { - WI_SetFlag(flags, PSEUDOCONSOLE_PASSTHROUGH_MODE); - } - } - THROW_IF_FAILED(_CreatePseudoConsoleAndPipes(til::unwrap_coord_size(dimensions), flags, &_inPipe, &_outPipe, &_hPC)); if (_initialParentHwnd != 0) diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index 2170b1fbfdf..e1b47bee64e 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -90,7 +90,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation til::u8state _u8State{}; std::wstring _u16Str{}; std::array _buffer{}; - bool _passthroughMode{}; bool _inheritCursor{ false }; til::env _initialEnv{}; diff --git a/src/cascadia/TerminalCore/ICoreSettings.idl b/src/cascadia/TerminalCore/ICoreSettings.idl index 1f3c78aa09b..ab3f0e5cf83 100644 --- a/src/cascadia/TerminalCore/ICoreSettings.idl +++ b/src/cascadia/TerminalCore/ICoreSettings.idl @@ -22,7 +22,6 @@ namespace Microsoft.Terminal.Core Boolean ForceVTInput; Boolean TrimBlockSelection; Boolean DetectURLs; - Boolean VtPassthrough; Windows.Foundation.IReference TabColor; Windows.Foundation.IReference StartingTabColor; diff --git a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp index 75c201f76fd..a00a077ef5b 100644 --- a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp +++ b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp @@ -298,10 +298,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return _unfocusedAppearanceViewModel; } - bool ProfileViewModel::VtPassthroughAvailable() const noexcept - { - return Feature_VtPassthroughMode::IsEnabled() && Feature_VtPassthroughModeSettingInUI::IsEnabled(); - } bool ProfileViewModel::ShowMarksAvailable() const noexcept { return Feature_ScrollbarMarks::IsEnabled(); diff --git a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h index d3edd16dc48..3dd30223fe2 100644 --- a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h +++ b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h @@ -82,7 +82,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation void CreateUnfocusedAppearance(); void DeleteUnfocusedAppearance(); - bool VtPassthroughAvailable() const noexcept; bool ShowMarksAvailable() const noexcept; bool AutoMarkPromptsAvailable() const noexcept; bool RepositionCursorWithMouseAvailable() const noexcept; @@ -117,7 +116,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing); OBSERVABLE_PROJECTED_SETTING(_profile, BellStyle); OBSERVABLE_PROJECTED_SETTING(_profile, Elevate); - OBSERVABLE_PROJECTED_SETTING(_profile, VtPassthrough); OBSERVABLE_PROJECTED_SETTING(_profile, ReloadEnvironmentVariables); OBSERVABLE_PROJECTED_SETTING(_profile, RightClickContextMenu); OBSERVABLE_PROJECTED_SETTING(_profile, ShowMarks); diff --git a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl index 8dcd35f4bd9..135182a4fbf 100644 --- a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl +++ b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl @@ -75,7 +75,6 @@ namespace Microsoft.Terminal.Settings.Editor Boolean ShowUnfocusedAppearance { get; }; AppearanceViewModel UnfocusedAppearance { get; }; - Boolean VtPassthroughAvailable { get; }; Boolean ShowMarksAvailable { get; }; Boolean AutoMarkPromptsAvailable { get; }; Boolean RepositionCursorWithMouseAvailable { get; }; @@ -111,7 +110,6 @@ namespace Microsoft.Terminal.Settings.Editor OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing); OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.BellStyle, BellStyle); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, Elevate); - OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, VtPassthrough); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ReloadEnvironmentVariables); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, RightClickContextMenu); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ShowMarks); diff --git a/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml b/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml index f1e3832f85c..add8fb2cf77 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml +++ b/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml @@ -117,16 +117,6 @@ - - - - - When enabled, the Terminal will generate a new environment block when creating new tabs or panes with this profile. When disabled, the tab/pane will instead inherit the variables the Terminal was started with. A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Enable experimental virtual terminal passthrough - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Display a menu on right-click This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index b4c678fd997..cde90f910b1 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -93,7 +93,6 @@ Author(s): X(bool, RightClickContextMenu, "experimental.rightClickContextMenu", false) \ X(Windows::Foundation::Collections::IVector, BellSound, "bellSound", nullptr) \ X(bool, Elevate, "elevate", false) \ - X(bool, VtPassthrough, "experimental.connection.passthroughMode", false) \ X(bool, AutoMarkPrompts, "experimental.autoMarkPrompts", false) \ X(bool, ShowMarks, "experimental.showMarksOnScrollbar", false) \ X(bool, RepositionCursorWithMouse, "experimental.repositionCursorWithMouse", false) \ diff --git a/src/cascadia/TerminalSettingsModel/Profile.idl b/src/cascadia/TerminalSettingsModel/Profile.idl index 9023fd16edb..2d6d1ab609c 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.idl +++ b/src/cascadia/TerminalSettingsModel/Profile.idl @@ -59,7 +59,6 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState); INHERITABLE_PROFILE_SETTING(String, Padding); INHERITABLE_PROFILE_SETTING(String, Commandline); - INHERITABLE_PROFILE_SETTING(Boolean, VtPassthrough); INHERITABLE_PROFILE_SETTING(String, StartingDirectory); String EvaluatedStartingDirectory { get; }; diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp index 682d79e19c7..6f1d2932699 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp @@ -297,7 +297,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation _Padding = profile.Padding(); _Commandline = profile.Commandline(); - _VtPassthrough = profile.VtPassthrough(); _StartingDirectory = profile.EvaluatedStartingDirectory(); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.h b/src/cascadia/TerminalSettingsModel/TerminalSettings.h index 99e3b2d120e..d3410ba2628 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.h @@ -95,7 +95,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::TerminalSettings, bool, FocusFollowMouse, false); INHERITABLE_SETTING(Model::TerminalSettings, bool, TrimBlockSelection, true); INHERITABLE_SETTING(Model::TerminalSettings, bool, DetectURLs, true); - INHERITABLE_SETTING(Model::TerminalSettings, bool, VtPassthrough, false); INHERITABLE_SETTING(Model::TerminalSettings, Windows::Foundation::IReference, TabColor, nullptr); diff --git a/src/cascadia/inc/ControlProperties.h b/src/cascadia/inc/ControlProperties.h index faf5fc6a756..a882cd8b0cf 100644 --- a/src/cascadia/inc/ControlProperties.h +++ b/src/cascadia/inc/ControlProperties.h @@ -48,7 +48,6 @@ X(bool, ForceVTInput, false) \ X(winrt::hstring, StartingTitle) \ X(bool, DetectURLs, true) \ - X(bool, VtPassthrough, false) \ X(bool, AutoMarkPrompts) \ X(bool, RepositionCursorWithMouse, false) diff --git a/src/features.xml b/src/features.xml index 60191f62286..8fbf160a8c7 100644 --- a/src/features.xml +++ b/src/features.xml @@ -86,28 +86,6 @@ - - Feature_VtPassthroughMode - Enables passthrough option per profile in Terminal and ConPTY ability to use passthrough API dispatch engine - AlwaysDisabled - - - Dev - Canary - Preview - - - - - Feature_VtPassthroughModeSettingInUI - Enables the setting gated by Feature_VtPassthroughMode to appear in the UI - AlwaysDisabled - - Dev - - - - Feature_ScrollbarMarks Enables the experimental scrollbar marks feature. diff --git a/src/host/ConsoleArguments.cpp b/src/host/ConsoleArguments.cpp index 3621bca387f..6a22e8170a6 100644 --- a/src/host/ConsoleArguments.cpp +++ b/src/host/ConsoleArguments.cpp @@ -23,7 +23,6 @@ const std::wstring_view ConsoleArguments::RESIZE_QUIRK = L"--resizeQuirk"; const std::wstring_view ConsoleArguments::FEATURE_ARG = L"--feature"; const std::wstring_view ConsoleArguments::FEATURE_PTY_ARG = L"pty"; const std::wstring_view ConsoleArguments::COM_SERVER_ARG = L"-Embedding"; -const std::wstring_view ConsoleArguments::PASSTHROUGH_ARG = L"--passthrough"; // NOTE: Thinking about adding more commandline args that control conpty, for // the Terminal? Make sure you add them to the commandline in // ConsoleEstablishHandoff. We use that to initialize the ConsoleArguments for a @@ -467,12 +466,6 @@ void ConsoleArguments::s_ConsumeArg(_Inout_ std::vector& args, _In s_ConsumeArg(args, i); hr = S_OK; } - else if (arg == PASSTHROUGH_ARG) - { - _passthroughMode = true; - s_ConsumeArg(args, i); - hr = S_OK; - } else if (arg.substr(0, FILEPATH_LEADER_PREFIX.length()) == FILEPATH_LEADER_PREFIX) { // beginning of command line -- includes file path @@ -602,11 +595,6 @@ bool ConsoleArguments::ShouldRunAsComServer() const return _runAsComServer; } -bool ConsoleArguments::IsPassthroughMode() const noexcept -{ - return _passthroughMode; -} - HANDLE ConsoleArguments::GetServerHandle() const { return ULongToHandle(_serverHandle); diff --git a/src/host/ConsoleArguments.hpp b/src/host/ConsoleArguments.hpp index 8648c92ea66..926bc063924 100644 --- a/src/host/ConsoleArguments.hpp +++ b/src/host/ConsoleArguments.hpp @@ -36,7 +36,6 @@ class ConsoleArguments bool IsHeadless() const; bool ShouldCreateServerHandle() const; bool ShouldRunAsComServer() const; - bool IsPassthroughMode() const noexcept; HANDLE GetServerHandle() const; HANDLE GetVtInHandle() const; @@ -76,7 +75,6 @@ class ConsoleArguments static const std::wstring_view FEATURE_ARG; static const std::wstring_view FEATURE_PTY_ARG; static const std::wstring_view COM_SERVER_ARG; - static const std::wstring_view PASSTHROUGH_ARG; private: #ifdef UNIT_TESTING @@ -95,8 +93,7 @@ class ConsoleArguments const DWORD serverHandle, const DWORD signalHandle, const bool inheritCursor, - const bool runAsComServer, - const bool passthroughMode) : + const bool runAsComServer) : _commandline(commandline), _clientCommandline(clientCommandline), _vtInHandle(vtInHandle), @@ -112,8 +109,7 @@ class ConsoleArguments _signalHandle(signalHandle), _inheritCursor(inheritCursor), _resizeQuirk(false), - _runAsComServer{ runAsComServer }, - _passthroughMode{ passthroughMode } + _runAsComServer{ runAsComServer } { } #endif @@ -135,7 +131,6 @@ class ConsoleArguments short _width; short _height; - bool _passthroughMode{ false }; bool _runAsComServer; bool _createServerHandle; DWORD _serverHandle; @@ -191,7 +186,6 @@ namespace WEX L"Signal Handle: '0x%x'\r\n", L"Inherit Cursor: '%ws'\r\n", L"Run As Com Server: '%ws'\r\n", - L"Passthrough Mode: '%ws'\r\n", ci.GetClientCommandline().c_str(), s_ToBoolString(ci.HasVtHandles()), ci.GetVtInHandle(), @@ -206,8 +200,7 @@ namespace WEX s_ToBoolString(ci.HasSignalHandle()), ci.GetSignalHandle(), s_ToBoolString(ci.GetInheritCursor()), - s_ToBoolString(ci.ShouldRunAsComServer()), - s_ToBoolString(ci.IsPassthroughMode())); + s_ToBoolString(ci.ShouldRunAsComServer())); } private: @@ -237,8 +230,7 @@ namespace WEX expected.HasSignalHandle() == actual.HasSignalHandle() && expected.GetSignalHandle() == actual.GetSignalHandle() && expected.GetInheritCursor() == actual.GetInheritCursor() && - expected.ShouldRunAsComServer() == actual.ShouldRunAsComServer() && - expected.IsPassthroughMode() == actual.IsPassthroughMode(); + expected.ShouldRunAsComServer() == actual.ShouldRunAsComServer(); } static bool AreSame(const ConsoleArguments& expected, const ConsoleArguments& actual) @@ -264,8 +256,7 @@ namespace WEX object.GetServerHandle() == 0 && (object.GetSignalHandle() == 0 || object.GetSignalHandle() == INVALID_HANDLE_VALUE) && !object.GetInheritCursor() && - !object.ShouldRunAsComServer() && - !object.IsPassthroughMode(); + !object.ShouldRunAsComServer(); } }; } diff --git a/src/host/VtApiRoutines.cpp b/src/host/VtApiRoutines.cpp deleted file mode 100644 index fe7d0b7060e..00000000000 --- a/src/host/VtApiRoutines.cpp +++ /dev/null @@ -1,810 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "precomp.h" -#include "VtApiRoutines.h" -#include "../interactivity/inc/ServiceLocator.hpp" -#include "../types/inc/convert.hpp" - -using namespace Microsoft::Console::Interactivity; - -// When someone attempts to use the console APIs to do a "read back" -// of the console buffer, we have to give them **something**. -// These two structures are just some gaudy-colored replacement character -// text to give them data but represent they've done something that cannot -// be supported under VT passthrough mode. -// ---- -// They can't be supported because in passthrough we maintain no internal -// buffer to answer these questions, and there is no VT sequence that lets -// us query the final terminal's buffer state. Even if a VT sequence did exist -// (and we personally believe it shouldn't), there's a possibility that it would -// read a massive amount of data and cause severe perf issues as applications coded -// to this old API are likely leaning on it heavily and asking for this data in a -// loop via VT would be a nightmare of parsing and formatting and over-the-wire transmission. - -static constexpr CHAR_INFO s_readBackUnicode{ - { UNICODE_REPLACEMENT }, - FOREGROUND_INTENSITY | FOREGROUND_RED | BACKGROUND_GREEN -}; - -static constexpr CHAR_INFO s_readBackAscii{ - { L'?' }, - FOREGROUND_INTENSITY | FOREGROUND_RED | BACKGROUND_GREEN -}; - -VtApiRoutines::VtApiRoutines() : - m_inputCodepage(ServiceLocator::LocateGlobals().getConsoleInformation().CP), - m_outputCodepage(ServiceLocator::LocateGlobals().getConsoleInformation().OutputCP), - m_inputMode(), - m_outputMode(), - m_pUsualRoutines(), - m_pVtEngine(), - m_listeningForDSR(false) -{ -} - -#pragma warning(push) -#pragma warning(disable : 4100) // unreferenced param - -void VtApiRoutines::GetConsoleInputCodePageImpl(ULONG& codepage) noexcept -{ - codepage = m_inputCodepage; - return; -} - -void VtApiRoutines::GetConsoleOutputCodePageImpl(ULONG& codepage) noexcept -{ - codepage = m_outputCodepage; - return; -} - -void VtApiRoutines::GetConsoleInputModeImpl(InputBuffer& context, - ULONG& mode) noexcept -{ - mode = m_inputMode; - return; -} - -void VtApiRoutines::GetConsoleOutputModeImpl(SCREEN_INFORMATION& context, - ULONG& mode) noexcept -{ - mode = m_outputMode; - return; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleInputModeImpl(InputBuffer& context, - const ULONG mode) noexcept -{ - m_inputMode = mode; - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleOutputModeImpl(SCREEN_INFORMATION& context, - const ULONG Mode) noexcept -{ - m_outputMode = Mode; - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::GetNumberOfConsoleInputEventsImpl(const InputBuffer& context, - ULONG& events) noexcept -{ - return m_pUsualRoutines->GetNumberOfConsoleInputEventsImpl(context, events); -} - -void VtApiRoutines::_SynchronizeCursor(std::unique_ptr& waiter) noexcept -{ - // If we're about to tell the caller to wait, let's synchronize the cursor we have with what - // the terminal is presenting in case there's a cooked read going on. - // TODO GH#10001: we only need to do this in cooked read mode. - if (waiter) - { - m_listeningForDSR = true; - (void)m_pVtEngine->_ListenForDSR(); - (void)m_pVtEngine->RequestCursor(); - } -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleInputImpl( - IConsoleInputObject& context, - InputEventQueue& outEvents, - const size_t eventReadCount, - INPUT_READ_HANDLE_DATA& readHandleState, - const bool IsUnicode, - const bool IsPeek, - std::unique_ptr& waiter) noexcept -{ - const auto hr = m_pUsualRoutines->GetConsoleInputImpl(context, outEvents, eventReadCount, readHandleState, IsUnicode, IsPeek, waiter); - _SynchronizeCursor(waiter); - return hr; -} - -[[nodiscard]] HRESULT VtApiRoutines::ReadConsoleImpl(IConsoleInputObject& context, - std::span buffer, - size_t& written, - std::unique_ptr& waiter, - const std::wstring_view initialData, - const std::wstring_view exeName, - INPUT_READ_HANDLE_DATA& readHandleState, - const bool IsUnicode, - const HANDLE clientHandle, - const DWORD controlWakeupMask, - DWORD& controlKeyState) noexcept -{ - const auto hr = m_pUsualRoutines->ReadConsoleImpl(context, buffer, written, waiter, initialData, exeName, readHandleState, IsUnicode, clientHandle, controlWakeupMask, controlKeyState); - // If we're about to tell the caller to wait, let's synchronize the cursor we have with what - // the terminal is presenting in case there's a cooked read going on. - // TODO GH10001: we only need to do this in cooked read mode. - if (clientHandle) - { - m_listeningForDSR = true; - (void)m_pVtEngine->_ListenForDSR(); - (void)m_pVtEngine->RequestCursor(); - } - return hr; -} - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleAImpl(IConsoleOutputObject& context, - const std::string_view buffer, - size_t& read, - bool requiresVtQuirk, - std::unique_ptr& waiter) noexcept -{ - if (CP_UTF8 == m_outputCodepage) - { - (void)m_pVtEngine->WriteTerminalUtf8(buffer); - } - else - { - (void)m_pVtEngine->WriteTerminalW(ConvertToW(m_outputCodepage, buffer)); - } - - (void)m_pVtEngine->_Flush(); - read = buffer.size(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleWImpl(IConsoleOutputObject& context, - const std::wstring_view buffer, - size_t& read, - bool requiresVtQuirk, - std::unique_ptr& waiter) noexcept -{ - (void)m_pVtEngine->WriteTerminalW(buffer); - (void)m_pVtEngine->_Flush(); - read = buffer.size(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleLangIdImpl(LANGID& langId) noexcept -{ - return m_pUsualRoutines->GetConsoleLangIdImpl(langId); -} - -[[nodiscard]] HRESULT VtApiRoutines::FillConsoleOutputAttributeImpl(IConsoleOutputObject& OutContext, - const WORD attribute, - const size_t lengthToWrite, - const til::point startingCoordinate, - size_t& cellsModified) noexcept -{ - (void)m_pVtEngine->_CursorPosition(startingCoordinate); - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(attribute), true); - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(attribute >> 4), false); - (void)m_pVtEngine->_WriteFill(lengthToWrite, s_readBackAscii.Char.AsciiChar); - (void)m_pVtEngine->_Flush(); - cellsModified = lengthToWrite; - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::FillConsoleOutputCharacterAImpl(IConsoleOutputObject& OutContext, - const char character, - const size_t lengthToWrite, - const til::point startingCoordinate, - size_t& cellsModified) noexcept -{ - // I mean... if you get your jollies by using UTF8 for single byte codepoints... - // we may as well skip a lot of conversion work and just write it out. - if (m_outputCodepage == CP_UTF8 && character <= 0x7F) - { - (void)m_pVtEngine->_CursorPosition(startingCoordinate); - (void)m_pVtEngine->_WriteFill(lengthToWrite, character); - (void)m_pVtEngine->_Flush(); - cellsModified = lengthToWrite; - return S_OK; - } - else - { - const auto wstr = ConvertToW(m_outputCodepage, std::string_view{ &character, 1 }); - return FillConsoleOutputCharacterWImpl(OutContext, wstr.front(), lengthToWrite, startingCoordinate, cellsModified); - } -} - -[[nodiscard]] HRESULT VtApiRoutines::FillConsoleOutputCharacterWImpl(IConsoleOutputObject& OutContext, - const wchar_t character, - const size_t lengthToWrite, - const til::point startingCoordinate, - size_t& cellsModified, - const bool enablePowershellShim) noexcept -{ - (void)m_pVtEngine->_CursorPosition(startingCoordinate); - const std::wstring_view sv{ &character, 1 }; - - // TODO GH10001: horrible. it'll WC2MB over and over...we should do that once then emit... and then rep... - // TODO GH10001: there's probably an optimization for if ((character & 0x7F) == character) --> call the UTF8 one. - for (size_t i = 0; i < lengthToWrite; ++i) - { - (void)m_pVtEngine->WriteTerminalW(sv); - } - - (void)m_pVtEngine->_Flush(); - cellsModified = lengthToWrite; - return S_OK; -} - -//// Process based. Restrict in protocol side? -//HRESULT GenerateConsoleCtrlEventImpl(const ULONG ProcessGroupFilter, -// const ULONG ControlEvent); - -void VtApiRoutines::SetConsoleActiveScreenBufferImpl(SCREEN_INFORMATION& newContext) noexcept -{ - return; -} - -void VtApiRoutines::FlushConsoleInputBuffer(InputBuffer& context) noexcept -{ - m_pUsualRoutines->FlushConsoleInputBuffer(context); -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleInputCodePageImpl(const ULONG codepage) noexcept -{ - m_inputCodepage = codepage; - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleOutputCodePageImpl(const ULONG codepage) noexcept -{ - m_outputCodepage = codepage; - return S_OK; -} - -void VtApiRoutines::GetConsoleCursorInfoImpl(const SCREEN_INFORMATION& context, - ULONG& size, - bool& isVisible) noexcept -{ - // TODO GH10001: good luck capturing this out of the input buffer when it comes back in. - //m_pVtEngine->RequestCursor(); - return; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleCursorInfoImpl(SCREEN_INFORMATION& context, - const ULONG size, - const bool isVisible) noexcept -{ - isVisible ? (void)m_pVtEngine->_ShowCursor() : (void)m_pVtEngine->_HideCursor(); - (void)m_pVtEngine->_Flush(); - return S_OK; -} - -//// driver will pare down for non-Ex method -void VtApiRoutines::GetConsoleScreenBufferInfoExImpl(const SCREEN_INFORMATION& context, - CONSOLE_SCREEN_BUFFER_INFOEX& data) noexcept -{ - // TODO GH10001: this is technically full of potentially incorrect data. do we care? should we store it in here with set? - return m_pUsualRoutines->GetConsoleScreenBufferInfoExImpl(context, data); -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleScreenBufferInfoExImpl(SCREEN_INFORMATION& context, - const CONSOLE_SCREEN_BUFFER_INFOEX& data) noexcept -{ - (void)m_pVtEngine->_ResizeWindow(data.srWindow.Right - data.srWindow.Left, data.srWindow.Bottom - data.srWindow.Top); - (void)m_pVtEngine->_CursorPosition(til::wrap_coord(data.dwCursorPosition)); - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(data.wAttributes), true); - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(data.wAttributes >> 4), false); - //color table? - // popup attributes... hold internally? - // TODO GH10001: popups are gonna erase the stuff behind them... deal with that somehow. - (void)m_pVtEngine->_Flush(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleScreenBufferSizeImpl(SCREEN_INFORMATION& context, - const til::size size) noexcept -{ - // Don't transmit. The terminal figures out its own buffer size. - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleCursorPositionImpl(SCREEN_INFORMATION& context, - const til::point position) noexcept -{ - if (m_listeningForDSR) - { - context.GetActiveBuffer().GetTextBuffer().GetCursor().SetPosition(position); - m_pVtEngine->SetTerminalCursorTextPosition(position); - } - else - { - (void)m_pVtEngine->_CursorPosition(position); - (void)m_pVtEngine->_Flush(); - } - return S_OK; -} - -void VtApiRoutines::GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& context, - til::size& size) noexcept -{ - m_pUsualRoutines->GetLargestConsoleWindowSizeImpl(context, size); // This is likely super weird but not weirder than existing ConPTY answers. - return; -} - -[[nodiscard]] HRESULT VtApiRoutines::ScrollConsoleScreenBufferAImpl(SCREEN_INFORMATION& context, - const til::inclusive_rect& source, - const til::point target, - std::optional clip, - const char fillCharacter, - const WORD fillAttribute) noexcept -{ - // TODO GH10001: Use DECCRA - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::ScrollConsoleScreenBufferWImpl(SCREEN_INFORMATION& context, - const til::inclusive_rect& source, - const til::point target, - std::optional clip, - const wchar_t fillCharacter, - const WORD fillAttribute, - const bool enableCmdShim) noexcept -{ - // TODO GH10001: Use DECCRA - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleTextAttributeImpl(SCREEN_INFORMATION& context, - const WORD attribute) noexcept -{ - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(attribute), true); - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(attribute >> 4), false); - (void)m_pVtEngine->_Flush(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleWindowInfoImpl(SCREEN_INFORMATION& context, - const bool isAbsolute, - const til::inclusive_rect& windowRect) noexcept -{ - (void)m_pVtEngine->_ResizeWindow(windowRect.right - windowRect.left + 1, windowRect.bottom - windowRect.top + 1); - (void)m_pVtEngine->_Flush(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::ReadConsoleOutputAttributeImpl(const SCREEN_INFORMATION& context, - const til::point origin, - std::span buffer, - size_t& written) noexcept -{ - std::fill_n(buffer.data(), buffer.size(), s_readBackUnicode.Attributes); // should be same as the ascii one. - written = buffer.size(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::ReadConsoleOutputCharacterAImpl(const SCREEN_INFORMATION& context, - const til::point origin, - std::span buffer, - size_t& written) noexcept -{ - std::fill_n(buffer.data(), buffer.size(), s_readBackAscii.Char.AsciiChar); - written = buffer.size(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::ReadConsoleOutputCharacterWImpl(const SCREEN_INFORMATION& context, - const til::point origin, - std::span buffer, - size_t& written) noexcept -{ - std::fill_n(buffer.data(), buffer.size(), s_readBackUnicode.Char.UnicodeChar); - written = buffer.size(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleInputAImpl(InputBuffer& context, - const std::span buffer, - size_t& written, - const bool append) noexcept -{ - return m_pUsualRoutines->WriteConsoleInputAImpl(context, buffer, written, append); -} - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleInputWImpl(InputBuffer& context, - const std::span buffer, - size_t& written, - const bool append) noexcept -{ - return m_pUsualRoutines->WriteConsoleInputWImpl(context, buffer, written, append); -} - -extern HRESULT _ConvertCellsToWInplace(const UINT codepage, - std::span buffer, - const Viewport& rectangle) noexcept; - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleOutputAImpl(SCREEN_INFORMATION& context, - std::span buffer, - const Microsoft::Console::Types::Viewport& requestRectangle, - Microsoft::Console::Types::Viewport& writtenRectangle) noexcept -{ - // No UTF8 optimization because the entire `CHAR_INFO` grid system doesn't make sense for UTF-8 - // with up to 4 bytes per cell...or more! - - RETURN_IF_FAILED(_ConvertCellsToWInplace(m_outputCodepage, buffer, requestRectangle)); - return WriteConsoleOutputWImpl(context, buffer, requestRectangle, writtenRectangle); -} - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleOutputWImpl(SCREEN_INFORMATION& context, - std::span buffer, - const Microsoft::Console::Types::Viewport& requestRectangle, - Microsoft::Console::Types::Viewport& writtenRectangle) noexcept -{ - auto cursor = requestRectangle.Origin(); - - const size_t width = requestRectangle.Width(); - size_t pos = 0; - - while (pos < buffer.size()) - { - (void)m_pVtEngine->_CursorPosition(cursor); - - const auto subspan = buffer.subspan(pos, width); - - for (const auto& ci : subspan) - { - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(ci.Attributes), true); - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(ci.Attributes >> 4), false); - (void)m_pVtEngine->WriteTerminalW(std::wstring_view{ &ci.Char.UnicodeChar, 1 }); - } - - ++cursor.y; - pos += width; - } - - (void)m_pVtEngine->_Flush(); - - //TODO GH10001: trim to buffer size? - writtenRectangle = requestRectangle; - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleOutputAttributeImpl(IConsoleOutputObject& OutContext, - const std::span attrs, - const til::point target, - size_t& used) noexcept -{ - (void)m_pVtEngine->_CursorPosition(target); - - for (const auto& attr : attrs) - { - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(attr), true); - (void)m_pVtEngine->_SetGraphicsRendition16Color(static_cast(attr >> 4), false); - (void)m_pVtEngine->WriteTerminalUtf8(std::string_view{ &s_readBackAscii.Char.AsciiChar, 1 }); - } - - (void)m_pVtEngine->_Flush(); - - used = attrs.size(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleOutputCharacterAImpl(IConsoleOutputObject& OutContext, - const std::string_view text, - const til::point target, - size_t& used) noexcept -{ - if (m_outputCodepage == CP_UTF8) - { - (void)m_pVtEngine->_CursorPosition(target); - (void)m_pVtEngine->WriteTerminalUtf8(text); - (void)m_pVtEngine->_Flush(); - return S_OK; - } - else - { - return WriteConsoleOutputCharacterWImpl(OutContext, ConvertToW(m_outputCodepage, text), target, used); - } -} - -[[nodiscard]] HRESULT VtApiRoutines::WriteConsoleOutputCharacterWImpl(IConsoleOutputObject& OutContext, - const std::wstring_view text, - const til::point target, - size_t& used) noexcept -{ - (void)m_pVtEngine->_CursorPosition(target); - (void)m_pVtEngine->WriteTerminalW(text); - (void)m_pVtEngine->_Flush(); - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::ReadConsoleOutputAImpl(const SCREEN_INFORMATION& context, - std::span buffer, - const Microsoft::Console::Types::Viewport& sourceRectangle, - Microsoft::Console::Types::Viewport& readRectangle) noexcept -{ - std::fill_n(buffer.data(), buffer.size(), s_readBackAscii); - // TODO GH10001: do we need to constrict readRectangle to within the known buffer size... probably. - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::ReadConsoleOutputWImpl(const SCREEN_INFORMATION& context, - std::span buffer, - const Microsoft::Console::Types::Viewport& sourceRectangle, - Microsoft::Console::Types::Viewport& readRectangle) noexcept -{ - std::fill_n(buffer.data(), buffer.size(), s_readBackUnicode); - // TODO GH10001: do we need to constrict readRectangle to within the known buffer size... probably. - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleTitleAImpl(std::span title, - size_t& written, - size_t& needed) noexcept -{ - written = 0; - needed = 0; - - if (!title.empty()) - { - title.front() = ANSI_NULL; - } - - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleTitleWImpl(std::span title, - size_t& written, - size_t& needed) noexcept -{ - written = 0; - needed = 0; - - if (!title.empty()) - { - title.front() = UNICODE_NULL; - } - - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleOriginalTitleAImpl(std::span title, - size_t& written, - size_t& needed) noexcept -{ - written = 0; - needed = 0; - - if (!title.empty()) - { - title.front() = ANSI_NULL; - } - - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleOriginalTitleWImpl(std::span title, - size_t& written, - size_t& needed) noexcept -{ - written = 0; - needed = 0; - - if (!title.empty()) - { - title.front() = UNICODE_NULL; - } - - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleTitleAImpl(const std::string_view title) noexcept -{ - return SetConsoleTitleWImpl(ConvertToW(m_inputCodepage, title)); -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleTitleWImpl(const std::wstring_view title) noexcept -{ - (void)m_pVtEngine->UpdateTitle(title); - (void)m_pVtEngine->_Flush(); - return S_OK; -} - -void VtApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept -{ - buttons = 2; - return; -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleFontSizeImpl(const SCREEN_INFORMATION& context, - const DWORD index, - til::size& size) noexcept -{ - size.width = 8; - size.height = 12; - return S_OK; -} - -//// driver will pare down for non-Ex method -[[nodiscard]] HRESULT VtApiRoutines::GetCurrentConsoleFontExImpl(const SCREEN_INFORMATION& context, - const bool isForMaximumWindowSize, - CONSOLE_FONT_INFOEX& consoleFontInfoEx) noexcept -{ - return S_OK; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleDisplayModeImpl(SCREEN_INFORMATION& context, - const ULONG flags, - til::size& newSize) noexcept -{ - return S_OK; -} - -void VtApiRoutines::GetConsoleDisplayModeImpl(ULONG& flags) noexcept -{ - flags = 0; - return; -} - -[[nodiscard]] HRESULT VtApiRoutines::AddConsoleAliasAImpl(const std::string_view source, - const std::string_view target, - const std::string_view exeName) noexcept -{ - return m_pUsualRoutines->AddConsoleAliasAImpl(source, target, exeName); -} - -[[nodiscard]] HRESULT VtApiRoutines::AddConsoleAliasWImpl(const std::wstring_view source, - const std::wstring_view target, - const std::wstring_view exeName) noexcept -{ - return m_pUsualRoutines->AddConsoleAliasWImpl(source, target, exeName); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasAImpl(const std::string_view source, - std::span target, - size_t& written, - const std::string_view exeName) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasAImpl(source, target, written, exeName); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasWImpl(const std::wstring_view source, - std::span target, - size_t& written, - const std::wstring_view exeName) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasWImpl(source, target, written, exeName); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasesLengthAImpl(const std::string_view exeName, - size_t& bufferRequired) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasesLengthAImpl(exeName, bufferRequired); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasesLengthWImpl(const std::wstring_view exeName, - size_t& bufferRequired) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasesLengthWImpl(exeName, bufferRequired); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasExesLengthAImpl(size_t& bufferRequired) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasExesLengthAImpl(bufferRequired); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasExesLengthWImpl(size_t& bufferRequired) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasExesLengthWImpl(bufferRequired); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasesAImpl(const std::string_view exeName, - std::span alias, - size_t& written) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasesAImpl(exeName, alias, written); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasesWImpl(const std::wstring_view exeName, - std::span alias, - size_t& written) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasesWImpl(exeName, alias, written); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasExesAImpl(std::span aliasExes, - size_t& written) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasExesAImpl(aliasExes, written); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleAliasExesWImpl(std::span aliasExes, - size_t& written) noexcept -{ - return m_pUsualRoutines->GetConsoleAliasExesWImpl(aliasExes, written); -} - -[[nodiscard]] HRESULT VtApiRoutines::ExpungeConsoleCommandHistoryAImpl(const std::string_view exeName) noexcept -{ - return m_pUsualRoutines->ExpungeConsoleCommandHistoryAImpl(exeName); -} - -[[nodiscard]] HRESULT VtApiRoutines::ExpungeConsoleCommandHistoryWImpl(const std::wstring_view exeName) noexcept -{ - return m_pUsualRoutines->ExpungeConsoleCommandHistoryWImpl(exeName); -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleNumberOfCommandsAImpl(const std::string_view exeName, - const size_t numberOfCommands) noexcept -{ - return m_pUsualRoutines->SetConsoleNumberOfCommandsAImpl(exeName, numberOfCommands); -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleNumberOfCommandsWImpl(const std::wstring_view exeName, - const size_t numberOfCommands) noexcept -{ - return m_pUsualRoutines->SetConsoleNumberOfCommandsWImpl(exeName, numberOfCommands); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleCommandHistoryLengthAImpl(const std::string_view exeName, - size_t& length) noexcept -{ - return m_pUsualRoutines->GetConsoleCommandHistoryLengthAImpl(exeName, length); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleCommandHistoryLengthWImpl(const std::wstring_view exeName, - size_t& length) noexcept -{ - return m_pUsualRoutines->GetConsoleCommandHistoryLengthWImpl(exeName, length); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleCommandHistoryAImpl(const std::string_view exeName, - std::span commandHistory, - size_t& written) noexcept -{ - return m_pUsualRoutines->GetConsoleCommandHistoryAImpl(exeName, commandHistory, written); -} - -[[nodiscard]] HRESULT VtApiRoutines::GetConsoleCommandHistoryWImpl(const std::wstring_view exeName, - std::span commandHistory, - size_t& written) noexcept -{ - return m_pUsualRoutines->GetConsoleCommandHistoryWImpl(exeName, commandHistory, written); -} - -void VtApiRoutines::GetConsoleWindowImpl(HWND& hwnd) noexcept -{ - hwnd = ServiceLocator::LocatePseudoWindow(); - return; -} - -void VtApiRoutines::GetConsoleSelectionInfoImpl(CONSOLE_SELECTION_INFO& consoleSelectionInfo) noexcept -{ - consoleSelectionInfo = { 0 }; - return; -} - -void VtApiRoutines::GetConsoleHistoryInfoImpl(CONSOLE_HISTORY_INFO& consoleHistoryInfo) noexcept -{ - m_pUsualRoutines->GetConsoleHistoryInfoImpl(consoleHistoryInfo); - return; -} - -[[nodiscard]] HRESULT VtApiRoutines::SetConsoleHistoryInfoImpl(const CONSOLE_HISTORY_INFO& consoleHistoryInfo) noexcept -{ - return m_pUsualRoutines->SetConsoleHistoryInfoImpl(consoleHistoryInfo); -} - -[[nodiscard]] HRESULT VtApiRoutines::SetCurrentConsoleFontExImpl(IConsoleOutputObject& context, - const bool isForMaximumWindowSize, - const CONSOLE_FONT_INFOEX& consoleFontInfoEx) noexcept -{ - return S_OK; -} - -#pragma warning(pop) diff --git a/src/host/VtApiRoutines.h b/src/host/VtApiRoutines.h deleted file mode 100644 index 7dc77f78b09..00000000000 --- a/src/host/VtApiRoutines.h +++ /dev/null @@ -1,366 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Module Name: -- VtApiRoutines.h - -Abstract: -- This file defines the interface to respond to all API calls by using VT on behalf of the client - -Author: -- Michael Niksa (miniksa) 26-Jul-2021 - -Revision History: -- Adapted from original items in srvinit.cpp, getset.cpp, directio.cpp, stream.cpp ---*/ - -#pragma once - -#include "../server/IApiRoutines.h" -#include "../renderer/vt/Xterm256Engine.hpp" - -class VtApiRoutines : public IApiRoutines -{ -public: - VtApiRoutines(); - -#pragma region ObjectManagement - /*HRESULT CreateInitialObjects(_Out_ InputBuffer** const ppInputObject, - _Out_ SCREEN_INFORMATION** const ppOutputObject); - */ - -#pragma endregion - -#pragma region L1 - void GetConsoleInputCodePageImpl(ULONG& codepage) noexcept override; - - void GetConsoleOutputCodePageImpl(ULONG& codepage) noexcept override; - - void GetConsoleInputModeImpl(InputBuffer& context, - ULONG& mode) noexcept override; - - void GetConsoleOutputModeImpl(SCREEN_INFORMATION& context, - ULONG& mode) noexcept override; - - [[nodiscard]] HRESULT SetConsoleInputModeImpl(InputBuffer& context, - const ULONG mode) noexcept override; - - [[nodiscard]] HRESULT SetConsoleOutputModeImpl(SCREEN_INFORMATION& context, - const ULONG Mode) noexcept override; - - [[nodiscard]] HRESULT GetNumberOfConsoleInputEventsImpl(const InputBuffer& context, - ULONG& events) noexcept override; - - [[nodiscard]] HRESULT GetConsoleInputImpl(IConsoleInputObject& context, - InputEventQueue& outEvents, - const size_t eventReadCount, - INPUT_READ_HANDLE_DATA& readHandleState, - const bool IsUnicode, - const bool IsPeek, - std::unique_ptr& waiter) noexcept override; - - [[nodiscard]] HRESULT ReadConsoleImpl(IConsoleInputObject& context, - std::span buffer, - size_t& written, - std::unique_ptr& waiter, - const std::wstring_view initialData, - const std::wstring_view exeName, - INPUT_READ_HANDLE_DATA& readHandleState, - const bool IsUnicode, - const HANDLE clientHandle, - const DWORD controlWakeupMask, - DWORD& controlKeyState) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleAImpl(IConsoleOutputObject& context, - const std::string_view buffer, - size_t& read, - bool requiresVtQuirk, - std::unique_ptr& waiter) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleWImpl(IConsoleOutputObject& context, - const std::wstring_view buffer, - size_t& read, - bool requiresVtQuirk, - std::unique_ptr& waiter) noexcept override; - -#pragma region ThreadCreationInfo - [[nodiscard]] HRESULT GetConsoleLangIdImpl(LANGID& langId) noexcept override; -#pragma endregion - -#pragma endregion - -#pragma region L2 - - [[nodiscard]] HRESULT FillConsoleOutputAttributeImpl(IConsoleOutputObject& OutContext, - const WORD attribute, - const size_t lengthToWrite, - const til::point startingCoordinate, - size_t& cellsModified) noexcept override; - - [[nodiscard]] HRESULT FillConsoleOutputCharacterAImpl(IConsoleOutputObject& OutContext, - const char character, - const size_t lengthToWrite, - const til::point startingCoordinate, - size_t& cellsModified) noexcept override; - - [[nodiscard]] HRESULT FillConsoleOutputCharacterWImpl(IConsoleOutputObject& OutContext, - const wchar_t character, - const size_t lengthToWrite, - const til::point startingCoordinate, - size_t& cellsModified, - const bool enablePowershellShim = false) noexcept override; - - //// Process based. Restrict in protocol side? - //HRESULT GenerateConsoleCtrlEventImpl(const ULONG ProcessGroupFilter, - // const ULONG ControlEvent); - - void SetConsoleActiveScreenBufferImpl(SCREEN_INFORMATION& newContext) noexcept override; - - void FlushConsoleInputBuffer(InputBuffer& context) noexcept override; - - [[nodiscard]] HRESULT SetConsoleInputCodePageImpl(const ULONG codepage) noexcept override; - - [[nodiscard]] HRESULT SetConsoleOutputCodePageImpl(const ULONG codepage) noexcept override; - - void GetConsoleCursorInfoImpl(const SCREEN_INFORMATION& context, - ULONG& size, - bool& isVisible) noexcept override; - - [[nodiscard]] HRESULT SetConsoleCursorInfoImpl(SCREEN_INFORMATION& context, - const ULONG size, - const bool isVisible) noexcept override; - - //// driver will pare down for non-Ex method - void GetConsoleScreenBufferInfoExImpl(const SCREEN_INFORMATION& context, - CONSOLE_SCREEN_BUFFER_INFOEX& data) noexcept override; - - [[nodiscard]] HRESULT SetConsoleScreenBufferInfoExImpl(SCREEN_INFORMATION& context, - const CONSOLE_SCREEN_BUFFER_INFOEX& data) noexcept override; - - [[nodiscard]] HRESULT SetConsoleScreenBufferSizeImpl(SCREEN_INFORMATION& context, - const til::size size) noexcept override; - - [[nodiscard]] HRESULT SetConsoleCursorPositionImpl(SCREEN_INFORMATION& context, - const til::point position) noexcept override; - - void GetLargestConsoleWindowSizeImpl(const SCREEN_INFORMATION& context, - til::size& size) noexcept override; - - [[nodiscard]] HRESULT ScrollConsoleScreenBufferAImpl(SCREEN_INFORMATION& context, - const til::inclusive_rect& source, - const til::point target, - std::optional clip, - const char fillCharacter, - const WORD fillAttribute) noexcept override; - - [[nodiscard]] HRESULT ScrollConsoleScreenBufferWImpl(SCREEN_INFORMATION& context, - const til::inclusive_rect& source, - const til::point target, - std::optional clip, - const wchar_t fillCharacter, - const WORD fillAttribute, - const bool enableCmdShim = false) noexcept override; - - [[nodiscard]] HRESULT SetConsoleTextAttributeImpl(SCREEN_INFORMATION& context, - const WORD attribute) noexcept override; - - [[nodiscard]] HRESULT SetConsoleWindowInfoImpl(SCREEN_INFORMATION& context, - const bool isAbsolute, - const til::inclusive_rect& windowRect) noexcept override; - - [[nodiscard]] HRESULT ReadConsoleOutputAttributeImpl(const SCREEN_INFORMATION& context, - const til::point origin, - std::span buffer, - size_t& written) noexcept override; - - [[nodiscard]] HRESULT ReadConsoleOutputCharacterAImpl(const SCREEN_INFORMATION& context, - const til::point origin, - std::span buffer, - size_t& written) noexcept override; - - [[nodiscard]] HRESULT ReadConsoleOutputCharacterWImpl(const SCREEN_INFORMATION& context, - const til::point origin, - std::span buffer, - size_t& written) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleInputAImpl(InputBuffer& context, - const std::span buffer, - size_t& written, - const bool append) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleInputWImpl(InputBuffer& context, - const std::span buffer, - size_t& written, - const bool append) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleOutputAImpl(SCREEN_INFORMATION& context, - std::span buffer, - const Microsoft::Console::Types::Viewport& requestRectangle, - Microsoft::Console::Types::Viewport& writtenRectangle) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleOutputWImpl(SCREEN_INFORMATION& context, - std::span buffer, - const Microsoft::Console::Types::Viewport& requestRectangle, - Microsoft::Console::Types::Viewport& writtenRectangle) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleOutputAttributeImpl(IConsoleOutputObject& OutContext, - const std::span attrs, - const til::point target, - size_t& used) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleOutputCharacterAImpl(IConsoleOutputObject& OutContext, - const std::string_view text, - const til::point target, - size_t& used) noexcept override; - - [[nodiscard]] HRESULT WriteConsoleOutputCharacterWImpl(IConsoleOutputObject& OutContext, - const std::wstring_view text, - const til::point target, - size_t& used) noexcept override; - - [[nodiscard]] HRESULT ReadConsoleOutputAImpl(const SCREEN_INFORMATION& context, - std::span buffer, - const Microsoft::Console::Types::Viewport& sourceRectangle, - Microsoft::Console::Types::Viewport& readRectangle) noexcept override; - - [[nodiscard]] HRESULT ReadConsoleOutputWImpl(const SCREEN_INFORMATION& context, - std::span buffer, - const Microsoft::Console::Types::Viewport& sourceRectangle, - Microsoft::Console::Types::Viewport& readRectangle) noexcept override; - - [[nodiscard]] HRESULT GetConsoleTitleAImpl(std::span title, - size_t& written, - size_t& needed) noexcept override; - - [[nodiscard]] HRESULT GetConsoleTitleWImpl(std::span title, - size_t& written, - size_t& needed) noexcept override; - - [[nodiscard]] HRESULT GetConsoleOriginalTitleAImpl(std::span title, - size_t& written, - size_t& needed) noexcept override; - - [[nodiscard]] HRESULT GetConsoleOriginalTitleWImpl(std::span title, - size_t& written, - size_t& needed) noexcept override; - - [[nodiscard]] HRESULT SetConsoleTitleAImpl(const std::string_view title) noexcept override; - - [[nodiscard]] HRESULT SetConsoleTitleWImpl(const std::wstring_view title) noexcept override; - -#pragma endregion - -#pragma region L3 - void GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept override; - - [[nodiscard]] HRESULT GetConsoleFontSizeImpl(const SCREEN_INFORMATION& context, - const DWORD index, - til::size& size) noexcept override; - - //// driver will pare down for non-Ex method - [[nodiscard]] HRESULT GetCurrentConsoleFontExImpl(const SCREEN_INFORMATION& context, - const bool isForMaximumWindowSize, - CONSOLE_FONT_INFOEX& consoleFontInfoEx) noexcept override; - - [[nodiscard]] HRESULT SetConsoleDisplayModeImpl(SCREEN_INFORMATION& context, - const ULONG flags, - til::size& newSize) noexcept override; - - void GetConsoleDisplayModeImpl(ULONG& flags) noexcept override; - - [[nodiscard]] HRESULT AddConsoleAliasAImpl(const std::string_view source, - const std::string_view target, - const std::string_view exeName) noexcept override; - - [[nodiscard]] HRESULT AddConsoleAliasWImpl(const std::wstring_view source, - const std::wstring_view target, - const std::wstring_view exeName) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasAImpl(const std::string_view source, - std::span target, - size_t& written, - const std::string_view exeName) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasWImpl(const std::wstring_view source, - std::span target, - size_t& written, - const std::wstring_view exeName) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasesLengthAImpl(const std::string_view exeName, - size_t& bufferRequired) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasesLengthWImpl(const std::wstring_view exeName, - size_t& bufferRequired) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasExesLengthAImpl(size_t& bufferRequired) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasExesLengthWImpl(size_t& bufferRequired) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasesAImpl(const std::string_view exeName, - std::span alias, - size_t& written) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasesWImpl(const std::wstring_view exeName, - std::span alias, - size_t& written) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasExesAImpl(std::span aliasExes, - size_t& written) noexcept override; - - [[nodiscard]] HRESULT GetConsoleAliasExesWImpl(std::span aliasExes, - size_t& written) noexcept override; - -#pragma region CMDext Private API - - [[nodiscard]] HRESULT ExpungeConsoleCommandHistoryAImpl(const std::string_view exeName) noexcept override; - - [[nodiscard]] HRESULT ExpungeConsoleCommandHistoryWImpl(const std::wstring_view exeName) noexcept override; - - [[nodiscard]] HRESULT SetConsoleNumberOfCommandsAImpl(const std::string_view exeName, - const size_t numberOfCommands) noexcept override; - - [[nodiscard]] HRESULT SetConsoleNumberOfCommandsWImpl(const std::wstring_view exeName, - const size_t numberOfCommands) noexcept override; - - [[nodiscard]] HRESULT GetConsoleCommandHistoryLengthAImpl(const std::string_view exeName, - size_t& length) noexcept override; - - [[nodiscard]] HRESULT GetConsoleCommandHistoryLengthWImpl(const std::wstring_view exeName, - size_t& length) noexcept override; - - [[nodiscard]] HRESULT GetConsoleCommandHistoryAImpl(const std::string_view exeName, - std::span commandHistory, - size_t& written) noexcept override; - - [[nodiscard]] HRESULT GetConsoleCommandHistoryWImpl(const std::wstring_view exeName, - std::span commandHistory, - size_t& written) noexcept override; - -#pragma endregion - - void GetConsoleWindowImpl(HWND& hwnd) noexcept override; - - void GetConsoleSelectionInfoImpl(CONSOLE_SELECTION_INFO& consoleSelectionInfo) noexcept override; - - void GetConsoleHistoryInfoImpl(CONSOLE_HISTORY_INFO& consoleHistoryInfo) noexcept override; - - [[nodiscard]] HRESULT SetConsoleHistoryInfoImpl(const CONSOLE_HISTORY_INFO& consoleHistoryInfo) noexcept override; - - [[nodiscard]] HRESULT SetCurrentConsoleFontExImpl(IConsoleOutputObject& context, - const bool isForMaximumWindowSize, - const CONSOLE_FONT_INFOEX& consoleFontInfoEx) noexcept override; - -#pragma endregion - - IApiRoutines* m_pUsualRoutines; - UINT& m_inputCodepage; - UINT& m_outputCodepage; - ULONG m_inputMode; - ULONG m_outputMode; - bool m_listeningForDSR; - Microsoft::Console::Render::Xterm256Engine* m_pVtEngine; - -private: - void _SynchronizeCursor(std::unique_ptr& waiter) noexcept; -}; diff --git a/src/host/VtIo.cpp b/src/host/VtIo.cpp index f9a6b722767..3d6412add00 100644 --- a/src/host/VtIo.cpp +++ b/src/host/VtIo.cpp @@ -14,8 +14,6 @@ #include "input.h" // ProcessCtrlEvents #include "output.h" // CloseConsoleProcessState -#include "VtApiRoutines.h" - using namespace Microsoft::Console; using namespace Microsoft::Console::Render; using namespace Microsoft::Console::VirtualTerminal; @@ -71,7 +69,6 @@ VtIo::VtIo() : { _lookingForCursorPosition = pArgs->GetInheritCursor(); _resizeQuirk = pArgs->IsResizeQuirkEnabled(); - _passthroughMode = pArgs->IsPassthroughMode(); // If we were already given VT handles, set up the VT IO engine to use those. if (pArgs->InConptyMode()) @@ -162,26 +159,6 @@ VtIo::VtIo() : { auto xterm256Engine = std::make_unique(std::move(_hOutput), initialViewport); - if constexpr (Feature_VtPassthroughMode::IsEnabled()) - { - if (_passthroughMode) - { - auto vtapi = new VtApiRoutines(); - vtapi->m_pVtEngine = xterm256Engine.get(); - vtapi->m_pUsualRoutines = globals.api; - - xterm256Engine->SetPassthroughMode(true); - - if (_pVtInputThread) - { - auto pfnSetListenForDSR = std::bind(&VtInputThread::SetLookingForDSR, _pVtInputThread.get(), std::placeholders::_1); - xterm256Engine->SetLookingForDSRCallback(pfnSetListenForDSR); - } - - globals.api = vtapi; - } - } - _pVtRenderEngine = std::move(xterm256Engine); break; } @@ -190,10 +167,6 @@ VtIo::VtIo() : _pVtRenderEngine = std::make_unique(std::move(_hOutput), initialViewport, false); - if (_passthroughMode) - { - return E_NOTIMPL; - } break; } case VtIoMode::XTERM_ASCII: @@ -201,11 +174,6 @@ VtIo::VtIo() : _pVtRenderEngine = std::make_unique(std::move(_hOutput), initialViewport, true); - - if (_passthroughMode) - { - return E_NOTIMPL; - } break; } default: diff --git a/src/host/VtIo.hpp b/src/host/VtIo.hpp index 2ecc0d51754..7cd12036f5d 100644 --- a/src/host/VtIo.hpp +++ b/src/host/VtIo.hpp @@ -67,7 +67,6 @@ namespace Microsoft::Console::VirtualTerminal bool _lookingForCursorPosition; bool _resizeQuirk{ false }; - bool _passthroughMode{ false }; bool _closeEventSent{ false }; std::unique_ptr _pVtRenderEngine; diff --git a/src/host/host-common.vcxitems b/src/host/host-common.vcxitems index 5ae8d7a0f3b..3456180ff1f 100644 --- a/src/host/host-common.vcxitems +++ b/src/host/host-common.vcxitems @@ -45,7 +45,6 @@ - @@ -97,7 +96,6 @@ - diff --git a/src/host/lib/hostlib.vcxproj.filters b/src/host/lib/hostlib.vcxproj.filters index 0e8177d4bc4..c70ea1a4d9f 100644 --- a/src/host/lib/hostlib.vcxproj.filters +++ b/src/host/lib/hostlib.vcxproj.filters @@ -156,9 +156,6 @@ Source Files - - Source Files - @@ -311,12 +308,9 @@ Header Files - - Header Files - - \ No newline at end of file + diff --git a/src/host/sources.inc b/src/host/sources.inc index f17c5191ac8..0c6b8fd14d2 100644 --- a/src/host/sources.inc +++ b/src/host/sources.inc @@ -86,7 +86,6 @@ SOURCES = \ ..\conareainfo.cpp \ ..\conimeinfo.cpp \ ..\ConsoleArguments.cpp \ - ..\VtApiRoutines.cpp \ # ------------------------------------- diff --git a/src/host/ut_host/ConsoleArgumentsTests.cpp b/src/host/ut_host/ConsoleArgumentsTests.cpp index 2da3663b7c2..d640469f236 100644 --- a/src/host/ut_host/ConsoleArgumentsTests.cpp +++ b/src/host/ut_host/ConsoleArgumentsTests.cpp @@ -83,8 +83,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe \"this is the commandline\""; @@ -106,8 +105,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless \"--vtmode bar this is the commandline\""; @@ -129,8 +127,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless --server 0x4 this is the commandline"; @@ -152,8 +149,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0x4, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless\t--vtmode\txterm\tthis\tis\tthe\tcommandline"; @@ -175,8 +171,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless\\ foo\\ --outpipe\\ bar\\ this\\ is\\ the\\ commandline"; @@ -198,8 +193,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless\\\tfoo\\\t--outpipe\\\tbar\\\tthis\\\tis\\\tthe\\\tcommandline"; @@ -221,8 +215,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode a\\\\\\\\\"b c\" d e"; @@ -244,8 +237,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe this is the commandline"; @@ -267,8 +259,7 @@ void ConsoleArgumentsTests::ArgSplittingTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? } @@ -295,8 +286,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe foo"; @@ -318,8 +308,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe foo -- bar"; @@ -341,8 +330,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode foo foo -- bar"; @@ -364,8 +352,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe console --vtmode foo foo -- bar"; @@ -387,8 +374,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe console --vtmode foo --outpipe foo -- bar"; @@ -410,8 +396,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode foo -- --outpipe foo bar"; @@ -433,8 +418,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode -- --headless bar"; @@ -456,8 +440,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --"; @@ -479,8 +462,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe"; @@ -502,8 +484,7 @@ void ConsoleArgumentsTests::ClientCommandlineTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? } @@ -530,8 +511,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --server 0x4"; @@ -553,8 +533,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe 0x4 0x8"; @@ -576,8 +555,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --server 0x4 0x8"; @@ -599,8 +577,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe 0x4 --server 0x8"; @@ -622,8 +599,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --server 0x4 --server 0x8"; @@ -645,8 +621,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe 0x4 -ForceV1"; @@ -668,8 +643,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe -ForceV1"; @@ -691,8 +665,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe 0x4 -ForceNoHandoff"; @@ -714,8 +687,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe -ForceNoHandoff"; @@ -737,8 +709,7 @@ void ConsoleArgumentsTests::LegacyFormatsTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? } @@ -789,8 +760,7 @@ void ConsoleArgumentsTests::CombineVtPipeHandleTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode xterm-256color"; @@ -812,8 +782,7 @@ void ConsoleArgumentsTests::CombineVtPipeHandleTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? } @@ -850,8 +819,7 @@ void ConsoleArgumentsTests::InitialSizeTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --width 120"; @@ -873,8 +841,7 @@ void ConsoleArgumentsTests::InitialSizeTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --height 30"; @@ -896,8 +863,7 @@ void ConsoleArgumentsTests::InitialSizeTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --width 0"; @@ -919,8 +885,7 @@ void ConsoleArgumentsTests::InitialSizeTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --width -1"; @@ -942,8 +907,7 @@ void ConsoleArgumentsTests::InitialSizeTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --width foo"; @@ -965,8 +929,7 @@ void ConsoleArgumentsTests::InitialSizeTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --width 2foo"; @@ -988,8 +951,7 @@ void ConsoleArgumentsTests::InitialSizeTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --width 65535"; @@ -1011,8 +973,7 @@ void ConsoleArgumentsTests::InitialSizeTests() 0ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? } @@ -1039,8 +1000,7 @@ void ConsoleArgumentsTests::HeadlessArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless 0x4"; @@ -1062,8 +1022,7 @@ void ConsoleArgumentsTests::HeadlessArgTests() 4ul, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless --headless"; @@ -1085,8 +1044,7 @@ void ConsoleArgumentsTests::HeadlessArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe -- foo.exe --headless"; @@ -1108,8 +1066,7 @@ void ConsoleArgumentsTests::HeadlessArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? } @@ -1140,8 +1097,7 @@ void ConsoleArgumentsTests::SignalHandleTests() 4ul, // serverHandle 8ul, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --server 0x4 --signal ASDF"; @@ -1163,8 +1119,7 @@ void ConsoleArgumentsTests::SignalHandleTests() 4ul, // serverHandle 0ul, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --signal --server 0x4"; @@ -1186,8 +1141,7 @@ void ConsoleArgumentsTests::SignalHandleTests() 0ul, // serverHandle 0ul, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? } @@ -1218,8 +1172,7 @@ void ConsoleArgumentsTests::FeatureArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --feature tty"; ArgTestsRunner(L"#2 Error case, pass an unsupported feature", @@ -1240,8 +1193,7 @@ void ConsoleArgumentsTests::FeatureArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --feature pty --feature pty"; @@ -1263,8 +1215,7 @@ void ConsoleArgumentsTests::FeatureArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --feature pty --feature tty"; @@ -1286,8 +1237,7 @@ void ConsoleArgumentsTests::FeatureArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --feature pty --feature"; @@ -1309,8 +1259,7 @@ void ConsoleArgumentsTests::FeatureArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --feature pty --feature --signal foo"; @@ -1332,7 +1281,6 @@ void ConsoleArgumentsTests::FeatureArgTests() 0, // serverHandle 0, // signalHandle false, // inheritCursor - false, // runAsComServer - false), // passthroughMode + false), // runAsComServer false); // successful parse? } diff --git a/src/inc/conpty-static.h b/src/inc/conpty-static.h index 4d22048868c..1dd9a4123e2 100644 --- a/src/inc/conpty-static.h +++ b/src/inc/conpty-static.h @@ -24,7 +24,6 @@ #endif #define PSEUDOCONSOLE_RESIZE_QUIRK (2u) -#define PSEUDOCONSOLE_PASSTHROUGH_MODE (8u) CONPTY_EXPORT HRESULT WINAPI ConptyCreatePseudoConsole(COORD size, HANDLE hInput, HANDLE hOutput, DWORD dwFlags, HPCON* phPC); CONPTY_EXPORT HRESULT WINAPI ConptyCreatePseudoConsoleAsUser(HANDLE hToken, COORD size, HANDLE hInput, HANDLE hOutput, DWORD dwFlags, HPCON* phPC); diff --git a/src/renderer/vt/Xterm256Engine.hpp b/src/renderer/vt/Xterm256Engine.hpp index 9d704c34dd8..5c8cde61831 100644 --- a/src/renderer/vt/Xterm256Engine.hpp +++ b/src/renderer/vt/Xterm256Engine.hpp @@ -18,8 +18,6 @@ Author(s): #include "XtermEngine.hpp" -class VtApiRoutines; - namespace Microsoft::Console::Render { class Xterm256Engine : public XtermEngine @@ -38,8 +36,6 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT ManuallyClearScrollback() noexcept override; - friend class ::VtApiRoutines; - private: [[nodiscard]] HRESULT _UpdateExtendedAttrs(const TextAttribute& textAttributes) noexcept; [[nodiscard]] HRESULT _UpdateHyperlinkAttr(const TextAttribute& textAttributes, diff --git a/src/renderer/vt/state.cpp b/src/renderer/vt/state.cpp index 5bb6b7d694d..9749bf63d32 100644 --- a/src/renderer/vt/state.cpp +++ b/src/renderer/vt/state.cpp @@ -475,19 +475,6 @@ void VtEngine::SetResizeQuirk(const bool resizeQuirk) _resizeQuirk = resizeQuirk; } -// Method Description: -// - Configure the renderer to understand that we're operating in limited-draw -// passthrough mode. We do not need to handle full responsibility for replicating -// buffer state to the attached terminal. -// Arguments: -// - passthrough - True to turn on passthrough mode. False otherwise. -// Return Value: -// - true iff we were started with an output mode for passthrough. false otherwise. -void VtEngine::SetPassthroughMode(const bool passthrough) noexcept -{ - _passthrough = passthrough; -} - void VtEngine::SetLookingForDSRCallback(std::function pfnLooking) noexcept { _pfnSetLookingForDSR = pfnLooking; diff --git a/src/renderer/vt/vtrenderer.hpp b/src/renderer/vt/vtrenderer.hpp index 7a974850afc..1a7c25316fd 100644 --- a/src/renderer/vt/vtrenderer.hpp +++ b/src/renderer/vt/vtrenderer.hpp @@ -82,7 +82,6 @@ namespace Microsoft::Console::Render [[nodiscard]] virtual HRESULT WriteTerminalW(const std::wstring_view str) noexcept = 0; void SetTerminalOwner(Microsoft::Console::VirtualTerminal::VtIo* const terminalOwner); void SetResizeQuirk(const bool resizeQuirk); - void SetPassthroughMode(const bool passthrough) noexcept; void SetLookingForDSRCallback(std::function pfnLooking) noexcept; void SetTerminalCursorTextPosition(const til::point coordCursor) noexcept; [[nodiscard]] virtual HRESULT ManuallyClearScrollback() noexcept; diff --git a/src/server/ApiSorter.cpp b/src/server/ApiSorter.cpp index 39cf676e497..7e20b290f59 100644 --- a/src/server/ApiSorter.cpp +++ b/src/server/ApiSorter.cpp @@ -168,14 +168,25 @@ PCONSOLE_API_MSG ApiSorter::ConsoleDispatchRequest(_Inout_ PCONSOLE_API_MSG Mess Message->State.WriteOffset = Message->msgHeader.ApiDescriptorSize; Message->State.ReadOffset = Message->msgHeader.ApiDescriptorSize + sizeof(CONSOLE_MSG_HEADER); + HRESULT hr = S_OK; + try + { + hr = (*Descriptor->Routine)(Message, &ReplyPending); + } + catch (const wil::ResultException& e) + { + hr = e.GetStatusCode(); + } + catch (...) + { + hr = E_UNEXPECTED; + } + // Unfortunately, we can't be as clear-cut with our error codes as we'd like since we have some callers that take // hard dependencies on NTSTATUS codes that aren't readily expressible as an HRESULT. There's currently only one // such known code -- STATUS_BUFFER_TOO_SMALL. There's a conlibk dependency on this being returned from the console // alias API. - NTSTATUS Status = S_OK; - { - Status = (*Descriptor->Routine)(Message, &ReplyPending); - } + NTSTATUS Status = hr; if (Status != STATUS_BUFFER_TOO_SMALL) { Status = NTSTATUS_FROM_HRESULT(Status); diff --git a/src/server/IApiRoutines.h b/src/server/IApiRoutines.h index 87830795c6c..9c99136c2c3 100644 --- a/src/server/IApiRoutines.h +++ b/src/server/IApiRoutines.h @@ -28,22 +28,13 @@ typedef InputBuffer IConsoleInputObject; class INPUT_READ_HANDLE_DATA; #include "IWaitRoutine.h" -#include -#include #include "../types/inc/IInputEvent.hpp" #include "../types/inc/viewport.hpp" -class IApiRoutines +class __declspec(novtable) IApiRoutines { public: -#pragma region ObjectManagement - // TODO: 9115192 - We will need to make the objects via an interface eventually. This represents that idea. - /*virtual HRESULT CreateInitialObjects(_Out_ IConsoleInputObject** const ppInputObject, - _Out_ IConsoleOutputObject** const ppOutputObject); -*/ - -#pragma endregion - +#pragma warning(suppress : 26432) // If you define or delete any default operation in the type '...', define or delete them all (c.21). virtual ~IApiRoutines() = default; #pragma region L1 diff --git a/src/winconpty/winconpty.cpp b/src/winconpty/winconpty.cpp index 323e4f788f9..16bb278b7da 100644 --- a/src/winconpty/winconpty.cpp +++ b/src/winconpty/winconpty.cpp @@ -133,23 +133,20 @@ HRESULT _CreatePseudoConsole(const HANDLE hToken, RETURN_IF_WIN32_BOOL_FALSE(SetHandleInformation(signalPipeConhostSide.get(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)); // GH4061: Ensure that the path to executable in the format is escaped so C:\Program.exe cannot collide with C:\Program Files - auto pwszFormat = L"\"%s\" --headless %s%s%s--width %hu --height %hu --signal 0x%x --server 0x%x"; // This is plenty of space to hold the formatted string wchar_t cmd[MAX_PATH]{}; const BOOL bInheritCursor = (dwFlags & PSEUDOCONSOLE_INHERIT_CURSOR) == PSEUDOCONSOLE_INHERIT_CURSOR; const BOOL bResizeQuirk = (dwFlags & PSEUDOCONSOLE_RESIZE_QUIRK) == PSEUDOCONSOLE_RESIZE_QUIRK; - const BOOL bPassthroughMode = (dwFlags & PSEUDOCONSOLE_PASSTHROUGH_MODE) == PSEUDOCONSOLE_PASSTHROUGH_MODE; swprintf_s(cmd, MAX_PATH, - pwszFormat, + L"\"%s\" --headless %s%s--width %hd --height %hd --signal 0x%tx --server 0x%tx", _ConsoleHostPath(), bInheritCursor ? L"--inheritcursor " : L"", bResizeQuirk ? L"--resizeQuirk " : L"", - bPassthroughMode ? L"--passthrough " : L"", size.X, size.Y, - signalPipeConhostSide.get(), - serverHandle.get()); + std::bit_cast(signalPipeConhostSide.get()), + std::bit_cast(serverHandle.get())); STARTUPINFOEXW siEx{ 0 }; siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW); diff --git a/src/winconpty/winconpty.h b/src/winconpty/winconpty.h index 744ec09916d..a38fdef8594 100644 --- a/src/winconpty/winconpty.h +++ b/src/winconpty/winconpty.h @@ -58,9 +58,6 @@ typedef struct _PseudoConsole #ifndef PSEUDOCONSOLE_WIN32_INPUT_MODE #define PSEUDOCONSOLE_WIN32_INPUT_MODE (0x4) #endif -#ifndef PSEUDOCONSOLE_PASSTHROUGH_MODE -#define PSEUDOCONSOLE_PASSTHROUGH_MODE (0x8) -#endif // Implementations of the various PseudoConsole functions. HRESULT _CreatePseudoConsole(const HANDLE hToken, From 0f81ac43b6f9834f9dd251e7bda4560e522ca985 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Thu, 28 Mar 2024 19:45:36 +0100 Subject: [PATCH 11/16] Replace til::bit_cast with std::bit_cast (#16948) The former was introduced when we were still using C++17. We're using C++20 now so it's not needed anymore. --- src/buffer/out/TextColor.cpp | 4 ++-- src/buffer/out/textBuffer.cpp | 2 +- src/host/directio.cpp | 6 +++--- src/host/inputBuffer.cpp | 2 +- src/inc/consoletaeftemplates.hpp | 2 +- src/inc/til/bit.h | 10 +--------- 6 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/buffer/out/TextColor.cpp b/src/buffer/out/TextColor.cpp index 2e2e6f9fa0b..fa84adfac8d 100644 --- a/src/buffer/out/TextColor.cpp +++ b/src/buffer/out/TextColor.cpp @@ -202,7 +202,7 @@ COLORREF TextColor::GetColor(const std::array& // the result will be something like 0b00100000. // 5. Use BitScanForward (bsf) to find the index of the most significant 1 bit. const auto haystack = _mm256_loadu_si256(reinterpret_cast(colorTable.data())); // 1. - const auto needle = _mm256_set1_epi32(til::bit_cast(defaultColor)); // 2. + const auto needle = _mm256_set1_epi32(std::bit_cast(defaultColor)); // 2. const auto result = _mm256_cmpeq_epi32(haystack, needle); // 3. const auto mask = _mm256_movemask_ps(_mm256_castsi256_ps(result)); // 4. unsigned long index; @@ -219,7 +219,7 @@ COLORREF TextColor::GetColor(const std::array& // --> the index returned by _BitScanForward must be divided by 2. const auto haystack1 = _mm_loadu_si128(reinterpret_cast(colorTable.data() + 0)); const auto haystack2 = _mm_loadu_si128(reinterpret_cast(colorTable.data() + 4)); - const auto needle = _mm_set1_epi32(til::bit_cast(defaultColor)); + const auto needle = _mm_set1_epi32(std::bit_cast(defaultColor)); const auto result1 = _mm_cmpeq_epi32(haystack1, needle); const auto result2 = _mm_cmpeq_epi32(haystack2, needle); const auto result = _mm_packs_epi32(result1, result2); // 3.5 diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index 5c71dd1d398..5530dedb739 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -2502,7 +2502,7 @@ void TextBuffer::_AppendRTFText(std::string& contentBuilder, const std::wstring_ { // Windows uses unsigned wchar_t - RTF uses signed ones. // '?' is the fallback ascii character. - const auto codeUnitRTFStr = std::to_string(til::bit_cast(codeUnit)); + const auto codeUnitRTFStr = std::to_string(std::bit_cast(codeUnit)); fmt::format_to(std::back_inserter(contentBuilder), FMT_COMPILE("\\u{}?"), codeUnitRTFStr); } } diff --git a/src/host/directio.cpp b/src/host/directio.cpp index 0a00fa25f82..b93252ad1ef 100644 --- a/src/host/directio.cpp +++ b/src/host/directio.cpp @@ -306,8 +306,8 @@ CATCH_RETURN(); // Fill the 1 byte (AsciiChar) portion of the leading and trailing cells with each of the bytes returned. // We have to be bit careful here not to directly write the CHARs, because CHARs are signed whereas wchar_t isn't // and we don't want any sign-extension. We want a 1:1 copy instead, so cast it to an unsigned char first. - in1.Char.UnicodeChar = til::bit_cast(AsciiDbcs[0]); - in2.Char.UnicodeChar = til::bit_cast(AsciiDbcs[1]); + in1.Char.UnicodeChar = std::bit_cast(AsciiDbcs[0]); + in2.Char.UnicodeChar = std::bit_cast(AsciiDbcs[1]); } else { @@ -323,7 +323,7 @@ CATCH_RETURN(); // 2 byte UTF-16 character into. Give it a go. CHAR asciiChar{}; ConvertToOem(codepage, &in1.Char.UnicodeChar, 1, &asciiChar, 1); - in1.Char.UnicodeChar = til::bit_cast(asciiChar); + in1.Char.UnicodeChar = std::bit_cast(asciiChar); } } } diff --git a/src/host/inputBuffer.cpp b/src/host/inputBuffer.cpp index 184670ffb1d..2e28a17ef67 100644 --- a/src/host/inputBuffer.cpp +++ b/src/host/inputBuffer.cpp @@ -434,7 +434,7 @@ try { // char is signed and assigning it to UnicodeChar would cause sign-extension. // unsigned char doesn't have this problem. - event.Event.KeyEvent.uChar.UnicodeChar = til::bit_cast(ch); + event.Event.KeyEvent.uChar.UnicodeChar = std::bit_cast(ch); OutEvents.push_back(event); } repeat--; diff --git a/src/inc/consoletaeftemplates.hpp b/src/inc/consoletaeftemplates.hpp index 752e21ffed6..2a98851ecab 100644 --- a/src/inc/consoletaeftemplates.hpp +++ b/src/inc/consoletaeftemplates.hpp @@ -61,7 +61,7 @@ namespace WEX::TestExecution return true; } - const auto nDiff = static_cast>(til::bit_cast(a) - til::bit_cast(b)); + const auto nDiff = static_cast>(std::bit_cast(a) - std::bit_cast(b)); const auto uDiff = static_cast(nDiff < 0 ? -nDiff : nDiff); return uDiff <= 4; } diff --git a/src/inc/til/bit.h b/src/inc/til/bit.h index a3ce7775a3b..46f4747f276 100644 --- a/src/inc/til/bit.h +++ b/src/inc/til/bit.h @@ -5,20 +5,12 @@ namespace til { - // bit_cast is a backport of the STL's std::bit_cast to C++17. - template, std::is_trivially_copyable, std::is_trivially_copyable>, int> = 0> - [[nodiscard]] constexpr To bit_cast(const From& _Val) noexcept - { - // TODO: Replace til::bit_cast and __builtin_bit_cast with std::bit_cast - return __builtin_bit_cast(To, _Val); - } - // When you cast a signed integer to an unsigned one, the compiler will use "sign extension" // so that -1 translates to all bits being set, no matter the size of the target type. // Sometimes you don't need or want that, which is when you can use this function. template [[nodiscard]] constexpr auto as_unsigned(const T& v) noexcept { - return bit_cast>(v); + return std::bit_cast>(v); } } From 36c81f24fbbc3473a3b1bbb214b8234a52740a1a Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 28 Mar 2024 13:11:36 -0700 Subject: [PATCH 12/16] Add a WT_SETTINGS_DIR env variable that portable profiles can use (#16949) Basically, title. It'd be a neat idea for portable installs of the Terminal to reference files that are right there in the portable install. This PR adds a `WT_SETTINGS_DIR` var to Terminal's own env block. This allows us to resolve profiles relative to our own settings folder. Closes #16295 --- src/cascadia/TerminalApp/AppLogic.cpp | 15 +++++++++++++++ src/cascadia/TerminalApp/AppLogic.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 29c13fdb13f..0b3ada01efa 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -149,6 +149,11 @@ namespace winrt::TerminalApp::implementation _languageProfileNotifier = winrt::make_self([this]() { _reloadSettings->Run(); }); + + // Do this here, rather than at the top of main. This will prevent us from + // including this variable in the vars we serialize in the + // Remoting::CommandlineArgs up in HandleCommandlineArgs. + _setupFolderPathEnvVar(); } // Method Description: @@ -720,4 +725,14 @@ namespace winrt::TerminalApp::implementation return TerminalApp::ParseCommandlineResult{ winrt::to_hstring(_appArgs.GetExitMessage()), r }; } + // Function Description + // * Adds a `WT_SETTINGS_DIR` env var to our own environment block, that + // points at our settings directory. This allows portable installs to + // refer to files in the portable install using %WT_SETTINGS_DIR% + void AppLogic::_setupFolderPathEnvVar() + { + std::wstring path{ CascadiaSettings::SettingsPath() }; + auto folderPath = path.substr(0, path.find_last_of(L"\\")); + SetEnvironmentVariableW(L"WT_SETTINGS_DIR", folderPath.c_str()); + } } diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 4f735dc9b29..3c14a4bca41 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -112,6 +112,8 @@ namespace winrt::TerminalApp::implementation void _RegisterSettingsChange(); fire_and_forget _DispatchReloadSettings(); + void _setupFolderPathEnvVar(); + #ifdef UNIT_TESTING friend class TerminalAppLocalTests::CommandlineTest; #endif From 1ede0233318088d4a1797c9c5d38904cc3f02e95 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Thu, 28 Mar 2024 21:12:10 +0100 Subject: [PATCH 13/16] Properly fix ConPTY buffer corking (#16793) I've found that #16079 was never properly addressed (it still randomly occurred after even after PR #16349), which later led to the issues described in #16769 (nushell flickering due to too many flushes). The crux of the fix is that this brings back the `_noFlushOnEnd` flag that was removed in PR #15991. This is then combined with a change to the cork API: An `uncork` on `VtEngine` now only flushes if `_Flush` got called while it was corked in the first place. `_noFlushOnEnd` prevents us from flushing in between two "unknown" VT sequences (like soft fonts or FTCS) which prevents them from being corrupted. The corking prevents the remaining cases of flushing too often. Long-term, a proper fix would be to pass through VT unmodified. Closes #16769 --- src/renderer/vt/invalidate.cpp | 4 ++++ src/renderer/vt/paint.cpp | 14 +++++++++++++- src/renderer/vt/state.cpp | 19 +++++++++++++++++-- src/renderer/vt/vtrenderer.hpp | 2 ++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/renderer/vt/invalidate.cpp b/src/renderer/vt/invalidate.cpp index 8f80d3eb8ea..489a6b50bc1 100644 --- a/src/renderer/vt/invalidate.cpp +++ b/src/renderer/vt/invalidate.cpp @@ -112,6 +112,10 @@ CATCH_RETURN(); // end paint to specifically handle this. _circled = circled; + // If we flushed for any reason other than circling (i.e, a sequence that we + // didn't understand), we don't need to push the buffer out on EndPaint. + _noFlushOnEnd = !circled; + _trace.TraceTriggerCircling(*pForcePaint); return S_OK; } diff --git a/src/renderer/vt/paint.cpp b/src/renderer/vt/paint.cpp index 4e5d3ec5389..6dc611252c4 100644 --- a/src/renderer/vt/paint.cpp +++ b/src/renderer/vt/paint.cpp @@ -94,7 +94,19 @@ using namespace Microsoft::Console::Types; RETURN_IF_FAILED(_MoveCursor(_deferredCursorPos)); } - _Flush(); + // If this frame was triggered because we encountered a VT sequence which + // required the buffered state to get printed, we don't want to flush this + // frame to the pipe. That might result in us rendering half the output of a + // particular frame (as emitted by the client). + // + // Instead, we'll leave this frame in _buffer, and just keep appending to + // it as needed. + if (!_noFlushOnEnd) + { + _Flush(); + } + + _noFlushOnEnd = false; return S_OK; } diff --git a/src/renderer/vt/state.cpp b/src/renderer/vt/state.cpp index 9749bf63d32..ea176e42f37 100644 --- a/src/renderer/vt/state.cpp +++ b/src/renderer/vt/state.cpp @@ -136,10 +136,19 @@ CATCH_RETURN(); void VtEngine::_Flush() noexcept { - if (!_corked && !_buffer.empty()) + if (_buffer.empty()) + { + return; + } + + if (!_corked) { _flushImpl(); + return; } + + // Defer the flush until someone calls Cork(false). + _flushRequested = true; } // _corked is often true and separating _flushImpl() out allows _flush() to be inlined. @@ -167,7 +176,13 @@ void VtEngine::_flushImpl() noexcept void VtEngine::Cork(bool corked) noexcept { _corked = corked; - _Flush(); + + // Now do the deferred flush from a previous call to _Flush(). + if (!corked && _flushRequested) + { + _flushRequested = false; + _flushImpl(); + } } // Method Description: diff --git a/src/renderer/vt/vtrenderer.hpp b/src/renderer/vt/vtrenderer.hpp index 1a7c25316fd..3bea4528ac5 100644 --- a/src/renderer/vt/vtrenderer.hpp +++ b/src/renderer/vt/vtrenderer.hpp @@ -137,7 +137,9 @@ namespace Microsoft::Console::Render bool _resizeQuirk{ false }; bool _passthrough{ false }; + bool _noFlushOnEnd{ false }; bool _corked{ false }; + bool _flushRequested{ false }; std::optional _newBottomLineBG{ std::nullopt }; [[nodiscard]] HRESULT _WriteFill(const size_t n, const char c) noexcept; From c4c52061d54694d183b264b6f71e350114b5d715 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Fri, 29 Mar 2024 12:48:58 +0100 Subject: [PATCH 14/16] Implement buffer restore (#16598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This changeset allows Windows Terminal to dump its buffer contents as UTF-16LE VT text onto disk and restore it later. This functionality is enabled whenever `persistedWindowLayout` is being used. Closes #961 Closes #16741 ## Validation Steps Performed * Open multiple windows with multiple tabs and restart the app Everything's restored ✅ * Reopen a tab with output from `RenderingTests.exe` Everything's restored ✅ * Closing tabs and windows with Ctrl+W deletes their buffer dumps ✅ * Closing tabs doesn't create buffer dumps ✅ --- .github/actions/spelling/expect/expect.txt | 2 + src/buffer/out/TextColor.cpp | 17 +- src/buffer/out/TextColor.h | 12 +- src/buffer/out/textBuffer.cpp | 232 +++++++++++++++++- src/buffer/out/textBuffer.hpp | 2 + src/cascadia/Remoting/GetWindowLayoutArgs.cpp | 5 - src/cascadia/Remoting/GetWindowLayoutArgs.h | 31 --- .../Microsoft.Terminal.RemotingLib.vcxproj | 12 - src/cascadia/Remoting/Monarch.cpp | 41 +--- src/cascadia/Remoting/Monarch.h | 6 +- src/cascadia/Remoting/Monarch.idl | 7 - src/cascadia/Remoting/Peasant.cpp | 21 -- src/cascadia/Remoting/Peasant.h | 2 - src/cascadia/Remoting/Peasant.idl | 8 - .../Remoting/QuitAllRequestedArgs.cpp | 5 - src/cascadia/Remoting/QuitAllRequestedArgs.h | 29 --- src/cascadia/Remoting/WindowManager.cpp | 36 --- src/cascadia/Remoting/WindowManager.h | 6 - src/cascadia/Remoting/WindowManager.idl | 4 - .../TerminalApp/AppCommandlineArgs.cpp | 11 + src/cascadia/TerminalApp/AppCommandlineArgs.h | 2 + src/cascadia/TerminalApp/AppLogic.cpp | 16 -- src/cascadia/TerminalApp/AppLogic.h | 2 - src/cascadia/TerminalApp/AppLogic.idl | 1 - src/cascadia/TerminalApp/IPaneContent.idl | 9 +- src/cascadia/TerminalApp/Pane.cpp | 40 +-- src/cascadia/TerminalApp/Pane.h | 4 +- .../Resources/en-US/Resources.resw | 6 +- .../TerminalApp/ScratchpadContent.cpp | 2 +- src/cascadia/TerminalApp/ScratchpadContent.h | 2 +- src/cascadia/TerminalApp/SettingsTab.cpp | 2 +- src/cascadia/TerminalApp/SettingsTab.h | 2 +- src/cascadia/TerminalApp/TabBase.h | 2 +- src/cascadia/TerminalApp/TabManagement.cpp | 16 +- src/cascadia/TerminalApp/TerminalPage.cpp | 65 +++-- src/cascadia/TerminalApp/TerminalPage.h | 20 +- src/cascadia/TerminalApp/TerminalPage.idl | 7 +- .../TerminalApp/TerminalPaneContent.cpp | 37 ++- .../TerminalApp/TerminalPaneContent.h | 2 +- src/cascadia/TerminalApp/TerminalTab.cpp | 6 +- src/cascadia/TerminalApp/TerminalTab.h | 2 +- src/cascadia/TerminalApp/TerminalWindow.cpp | 40 +-- src/cascadia/TerminalApp/TerminalWindow.h | 9 +- src/cascadia/TerminalApp/TerminalWindow.idl | 7 +- .../TerminalConnection.vcxproj | 3 +- src/cascadia/TerminalControl/ControlCore.cpp | 52 +++- src/cascadia/TerminalControl/ControlCore.h | 2 + .../TerminalControl/IControlSettings.idl | 3 +- src/cascadia/TerminalControl/TermControl.cpp | 21 ++ src/cascadia/TerminalControl/TermControl.h | 3 + src/cascadia/TerminalControl/TermControl.idl | 2 + src/cascadia/TerminalCore/Terminal.cpp | 5 + src/cascadia/TerminalCore/Terminal.hpp | 1 + .../TerminalSettingsModel/ActionArgs.cpp | 7 + .../TerminalSettingsModel/ActionArgs.h | 5 + .../TerminalSettingsModel/ActionArgs.idl | 1 + .../ApplicationState.cpp | 17 +- .../TerminalSettingsModel/ApplicationState.h | 2 + .../ApplicationState.idl | 2 + .../TerminalSettingsModel/CascadiaSettings.h | 1 + .../CascadiaSettings.idl | 1 + .../CascadiaSettingsSerialization.cpp | 7 + .../TerminalSettings.cpp | 5 + .../TerminalSettingsModel/TerminalSettings.h | 1 + .../TerminalSettings.idl | 1 + .../UnitTests_Remoting/RemotingTests.cpp | 4 - src/cascadia/WindowsTerminal/AppHost.cpp | 211 ++++++---------- src/cascadia/WindowsTerminal/AppHost.h | 15 +- .../WindowsTerminal/WindowEmperor.cpp | 173 ++++++------- src/cascadia/WindowsTerminal/WindowEmperor.h | 8 - src/cascadia/inc/ControlProperties.h | 1 + src/inc/til/small_vector.h | 14 +- 72 files changed, 670 insertions(+), 688 deletions(-) delete mode 100644 src/cascadia/Remoting/GetWindowLayoutArgs.cpp delete mode 100644 src/cascadia/Remoting/GetWindowLayoutArgs.h delete mode 100644 src/cascadia/Remoting/QuitAllRequestedArgs.cpp delete mode 100644 src/cascadia/Remoting/QuitAllRequestedArgs.h diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 28b9b790d7b..1ce77a78ad5 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -597,6 +597,7 @@ FECF FEEF fesb FFAF +ffd FFDE FFFDb fgbg @@ -757,6 +758,7 @@ hdr HDROP hdrstop HEIGHTSCROLL +hfind hfont hfontresource hglobal diff --git a/src/buffer/out/TextColor.cpp b/src/buffer/out/TextColor.cpp index fa84adfac8d..0840ec19f5f 100644 --- a/src/buffer/out/TextColor.cpp +++ b/src/buffer/out/TextColor.cpp @@ -62,6 +62,11 @@ bool TextColor::CanBeBrightened() const noexcept return IsIndex16() || IsDefault(); } +ColorType TextColor::GetType() const noexcept +{ + return _meta; +} + bool TextColor::IsLegacy() const noexcept { return (IsIndex16() || IsIndex256()) && _index < 16; @@ -280,15 +285,3 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept return til::at(CompressedRgbToIndex16, compressedRgb); } } - -// Method Description: -// - Return a COLORREF containing our stored value. Will return garbage if this -//attribute is not a RGB attribute. -// Arguments: -// - -// Return Value: -// - a COLORREF containing our stored value -COLORREF TextColor::GetRGB() const noexcept -{ - return RGB(_red, _green, _blue); -} diff --git a/src/buffer/out/TextColor.h b/src/buffer/out/TextColor.h index 0b71078fbf1..3070f816974 100644 --- a/src/buffer/out/TextColor.h +++ b/src/buffer/out/TextColor.h @@ -119,6 +119,7 @@ struct TextColor } bool CanBeBrightened() const noexcept; + ColorType GetType() const noexcept; bool IsLegacy() const noexcept; bool IsIndex16() const noexcept; bool IsIndex256() const noexcept; @@ -133,12 +134,11 @@ struct TextColor COLORREF GetColor(const std::array& colorTable, const size_t defaultIndex, bool brighten = false) const noexcept; BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept; - constexpr BYTE GetIndex() const noexcept - { - return _index; - } - - COLORREF GetRGB() const noexcept; + constexpr BYTE GetIndex() const noexcept { return _index; } + constexpr BYTE GetR() const noexcept { return _red; } + constexpr BYTE GetG() const noexcept { return _green; } + constexpr BYTE GetB() const noexcept { return _blue; } + constexpr COLORREF GetRGB() const noexcept { return RGB(_red, _green, _blue); } static constexpr BYTE TransposeLegacyIndex(const size_t index) { diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index 5530dedb739..62371474adc 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -11,7 +11,6 @@ #include "UTextAdapter.h" #include "../../types/inc/GlyphWidth.hpp" #include "../renderer/base/renderer.hpp" -#include "../types/inc/convert.hpp" #include "../types/inc/utils.hpp" using namespace Microsoft::Console; @@ -2508,6 +2507,237 @@ void TextBuffer::_AppendRTFText(std::string& contentBuilder, const std::wstring_ } } +void TextBuffer::Serialize(const wchar_t* destination) const +{ + const wil::unique_handle file{ CreateFileW(destination, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr) }; + THROW_LAST_ERROR_IF(!file); + + static constexpr size_t writeThreshold = 32 * 1024; + std::wstring buffer; + buffer.reserve(writeThreshold + writeThreshold / 2); + buffer.push_back(L'\uFEFF'); + + const til::CoordType lastRowWithText = GetLastNonSpaceCharacter(nullptr).y; + CharacterAttributes previousAttr = CharacterAttributes::Unused1; + TextColor previousFg; + TextColor previousBg; + TextColor previousUl; + uint16_t previousHyperlinkId = 0; + + // This iterates through each row. The exit condition is at the end + // of the for() loop so that we can properly handle file flushing. + for (til::CoordType currentRow = 0;; currentRow++) + { + const auto& row = GetRowByOffset(currentRow); + + if (const auto lr = row.GetLineRendition(); lr != LineRendition::SingleWidth) + { + static constexpr std::wstring_view mappings[] = { + L"\x1b#6", // LineRendition::DoubleWidth + L"\x1b#3", // LineRendition::DoubleHeightTop + L"\x1b#4", // LineRendition::DoubleHeightBottom + }; + const auto idx = std::clamp(static_cast(lr) - 1, 0, 2); + buffer.append(til::at(mappings, idx)); + } + + const auto& runs = row.Attributes().runs(); + auto it = runs.begin(); + const auto end = runs.end(); + const auto last = end - 1; + til::CoordType oldX = 0; + + for (; it != end; ++it) + { + const auto attr = it->value.GetCharacterAttributes(); + const auto hyperlinkId = it->value.GetHyperlinkId(); + const auto fg = it->value.GetForeground(); + const auto bg = it->value.GetBackground(); + const auto ul = it->value.GetUnderlineColor(); + + if (previousAttr != attr) + { + const auto attrDelta = attr ^ previousAttr; + + { + struct Mapping + { + CharacterAttributes attr; + uint8_t change[2]; // [0] = off, [1] = on + }; + static constexpr Mapping mappings[] = { + { CharacterAttributes::Intense, { 22, 1 } }, + { CharacterAttributes::Italics, { 23, 3 } }, + { CharacterAttributes::Blinking, { 25, 5 } }, + { CharacterAttributes::Invisible, { 28, 8 } }, + { CharacterAttributes::CrossedOut, { 29, 9 } }, + { CharacterAttributes::Faint, { 22, 2 } }, + { CharacterAttributes::TopGridline, { 55, 53 } }, + { CharacterAttributes::ReverseVideo, { 27, 7 } }, + { CharacterAttributes::BottomGridline, { 24, 4 } }, + }; + for (const auto& mapping : mappings) + { + if (WI_IsAnyFlagSet(attrDelta, mapping.attr)) + { + const auto n = til::at(mapping.change, WI_IsAnyFlagSet(attr, mapping.attr)); + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[{}m"), n); + } + } + } + + if (WI_IsAnyFlagSet(attrDelta, CharacterAttributes::UnderlineStyle)) + { + static constexpr std::wstring_view mappings[] = { + L"\x1b[24m", // UnderlineStyle::NoUnderline + L"\x1b[4m", // UnderlineStyle::SinglyUnderlined + L"\x1b[21m", // UnderlineStyle::DoublyUnderlined + L"\x1b[4:3m", // UnderlineStyle::CurlyUnderlined + L"\x1b[4:4m", // UnderlineStyle::DottedUnderlined + L"\x1b[4:5m", // UnderlineStyle::DashedUnderlined + }; + + auto idx = WI_EnumValue(it->value.GetUnderlineStyle()); + if (idx >= std::size(mappings)) + { + idx = 1; // UnderlineStyle::SinglyUnderlined + } + + buffer.append(til::at(mappings, idx)); + } + + previousAttr = attr; + } + + if (previousFg != fg) + { + switch (fg.GetType()) + { + case ColorType::IsDefault: + buffer.append(L"\x1b[39m"); + break; + case ColorType::IsIndex16: + { + uint8_t index = WI_IsFlagSet(fg.GetIndex(), 8) ? 90 : 30; + index += fg.GetIndex() & 7; + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[{}m"), index); + break; + } + case ColorType::IsIndex256: + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[38;5;{}m"), fg.GetIndex()); + break; + case ColorType::IsRgb: + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[38;2;{};{};{}m"), fg.GetR(), fg.GetG(), fg.GetB()); + break; + default: + break; + } + previousFg = fg; + } + + if (previousBg != bg) + { + switch (bg.GetType()) + { + case ColorType::IsDefault: + buffer.append(L"\x1b[49m"); + break; + case ColorType::IsIndex16: + { + uint8_t index = WI_IsFlagSet(bg.GetIndex(), 8) ? 100 : 40; + index += bg.GetIndex() & 7; + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[{}m"), index); + break; + } + case ColorType::IsIndex256: + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[48;5;{}m"), bg.GetIndex()); + break; + case ColorType::IsRgb: + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[48;2;{};{};{}m"), bg.GetR(), bg.GetG(), bg.GetB()); + break; + default: + break; + } + previousBg = bg; + } + + if (previousUl != ul) + { + switch (fg.GetType()) + { + case ColorType::IsDefault: + buffer.append(L"\x1b[59m"); + break; + case ColorType::IsIndex256: + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[58:5:{}m"), ul.GetIndex()); + break; + case ColorType::IsRgb: + fmt::format_to(std::back_inserter(buffer), FMT_COMPILE(L"\x1b[58:2::{}:{}:{}m"), ul.GetR(), ul.GetG(), ul.GetB()); + break; + default: + break; + } + previousUl = ul; + } + + if (previousHyperlinkId != hyperlinkId) + { + if (hyperlinkId) + { + const auto uri = GetHyperlinkUriFromId(hyperlinkId); + if (!uri.empty()) + { + buffer.append(L"\x1b]8;;"); + buffer.append(uri); + buffer.append(L"\x1b\\"); + previousHyperlinkId = hyperlinkId; + } + } + else + { + buffer.append(L"\x1b]8;;\x1b\\"); + previousHyperlinkId = 0; + } + } + + auto newX = oldX + it->length; + // Trim whitespace with default attributes from the end of each line. + if (it == last && it->value == TextAttribute{}) + { + // This can result in oldX > newX, but that's okay because GetText() + // is robust against that and returns an empty string. + newX = row.MeasureRight(); + } + + buffer.append(row.GetText(oldX, newX)); + oldX = newX; + } + + const auto moreRowsRemaining = currentRow < lastRowWithText; + + if (!row.WasWrapForced() || !moreRowsRemaining) + { + buffer.append(L"\r\n"); + } + + if (buffer.size() >= writeThreshold || !moreRowsRemaining) + { + const auto fileSize = gsl::narrow(buffer.size() * sizeof(wchar_t)); + DWORD bytesWritten = 0; + THROW_IF_WIN32_BOOL_FALSE(WriteFile(file.get(), buffer.data(), fileSize, &bytesWritten, nullptr)); + if (bytesWritten != fileSize) + { + THROW_WIN32_MSG(ERROR_WRITE_FAULT, "failed to write"); + } + } + + if (!moreRowsRemaining) + { + break; + } + } +} + // Function Description: // - Reflow the contents from the old buffer into the new buffer. The new buffer // can have different dimensions than the old buffer. If it does, then this diff --git a/src/buffer/out/textBuffer.hpp b/src/buffer/out/textBuffer.hpp index 419e01471e5..8093aea9af8 100644 --- a/src/buffer/out/textBuffer.hpp +++ b/src/buffer/out/textBuffer.hpp @@ -319,6 +319,8 @@ class TextBuffer final const bool isIntenseBold, std::function(const TextAttribute&)> GetAttributeColors) const noexcept; + void Serialize(const wchar_t* destination) const; + struct PositionInformation { til::CoordType mutableViewportTop{ 0 }; diff --git a/src/cascadia/Remoting/GetWindowLayoutArgs.cpp b/src/cascadia/Remoting/GetWindowLayoutArgs.cpp deleted file mode 100644 index f2cc01df40c..00000000000 --- a/src/cascadia/Remoting/GetWindowLayoutArgs.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#include "pch.h" -#include "GetWindowLayoutArgs.h" -#include "GetWindowLayoutArgs.g.cpp" diff --git a/src/cascadia/Remoting/GetWindowLayoutArgs.h b/src/cascadia/Remoting/GetWindowLayoutArgs.h deleted file mode 100644 index 097e375bc70..00000000000 --- a/src/cascadia/Remoting/GetWindowLayoutArgs.h +++ /dev/null @@ -1,31 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Class Name: -- GetWindowLayoutArgs.h - -Abstract: -- This is a helper class for getting the window layout from a peasant. - Depending on if we are running on the monarch or on a peasant we might need - to switch what thread we are executing on. This gives us the option of - either returning the json result synchronously, or as a promise. ---*/ - -#pragma once - -#include "GetWindowLayoutArgs.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct GetWindowLayoutArgs : public GetWindowLayoutArgsT - { - WINRT_PROPERTY(winrt::hstring, WindowLayoutJson, L""); - WINRT_PROPERTY(winrt::Windows::Foundation::IAsyncOperation, WindowLayoutJsonAsync, nullptr) - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(GetWindowLayoutArgs); -} diff --git a/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj b/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj index ce78fc9c4b2..b5c7ada4790 100644 --- a/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj +++ b/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj @@ -37,12 +37,6 @@ Peasant.idl - - Peasant.idl - - - Monarch.idl - @@ -78,12 +72,6 @@ Peasant.idl - - Peasant.idl - - - Monarch.idl - Create diff --git a/src/cascadia/Remoting/Monarch.cpp b/src/cascadia/Remoting/Monarch.cpp index 6b48650c5f2..63e74b0fae1 100644 --- a/src/cascadia/Remoting/Monarch.cpp +++ b/src/cascadia/Remoting/Monarch.cpp @@ -6,7 +6,6 @@ #include "Monarch.h" #include "CommandlineArgs.h" #include "FindTargetWindowArgs.h" -#include "QuitAllRequestedArgs.h" #include "ProposeCommandlineResult.h" #include "Monarch.g.cpp" @@ -135,21 +134,13 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation // - used // Return Value: // - - winrt::fire_and_forget Monarch::_handleQuitAll(const winrt::Windows::Foundation::IInspectable& /*sender*/, - const winrt::Windows::Foundation::IInspectable& /*args*/) + void Monarch::_handleQuitAll(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/) { - // Let the process hosting the monarch run any needed logic before - // closing all windows. - auto args = winrt::make_self(); - QuitAllRequested.raise(*this, *args); - - if (const auto action = args->BeforeQuitAllAction()) + if (_quitting.exchange(true, std::memory_order_relaxed)) { - co_await action; + return; } - _quitting.store(true); - // Tell all peasants to exit. const auto callback = [&](const auto& id, const auto& p) { // We want to tell our peasant to quit last, so that we don't try // to perform a bunch of elections on quit. @@ -197,7 +188,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation // If we are quitting we don't care about maintaining our list of // peasants anymore, and don't need to notify the host that something // changed. - if (_quitting.load(std::memory_order_acquire)) + if (_quitting.load(std::memory_order_relaxed)) { return; } @@ -1036,30 +1027,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation _forEachPeasant(func, onError); } - // Method Description: - // - Ask all peasants to return their window layout as json - // Arguments: - // - - // Return Value: - // - The collection of window layouts from each peasant. - Windows::Foundation::Collections::IVector Monarch::GetAllWindowLayouts() - { - std::vector vec; - auto callback = [&](const auto& /*id*/, const auto& p) { - vec.emplace_back(p.GetWindowLayout()); - }; - auto onError = [](auto&& id) { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_GetAllWindowLayouts_Failed", - TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not get a window layout from"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - }; - _forEachPeasant(callback, onError); - - return winrt::single_threaded_vector(std::move(vec)); - } - void Monarch::RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, diff --git a/src/cascadia/Remoting/Monarch.h b/src/cascadia/Remoting/Monarch.h index 48619ac47b8..299932d9610 100644 --- a/src/cascadia/Remoting/Monarch.h +++ b/src/cascadia/Remoting/Monarch.h @@ -96,7 +96,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation void SummonAllWindows(); bool DoesQuakeWindowExist(); Windows::Foundation::Collections::IVectorView GetPeasantInfos(); - Windows::Foundation::Collections::IVector GetAllWindowLayouts(); void RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, const Windows::Foundation::IReference& windowBounds); void RequestSendContent(const Remoting::RequestReceiveContentArgs& args); @@ -106,7 +105,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation til::typed_event<> HideNotificationIconRequested; til::typed_event<> WindowCreated; til::typed_event<> WindowClosed; - til::typed_event QuitAllRequested; til::typed_event RequestNewWindow; @@ -146,8 +144,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation void _renameRequested(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args); - winrt::fire_and_forget _handleQuitAll(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Windows::Foundation::IInspectable& args); + void _handleQuitAll(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::Windows::Foundation::IInspectable& args); // Method Description: // - Helper for doing something on each and every peasant. diff --git a/src/cascadia/Remoting/Monarch.idl b/src/cascadia/Remoting/Monarch.idl index f57bd6b59b2..c81837e96b5 100644 --- a/src/cascadia/Remoting/Monarch.idl +++ b/src/cascadia/Remoting/Monarch.idl @@ -46,11 +46,6 @@ namespace Microsoft.Terminal.Remoting Windows.Foundation.IReference WindowID; } - [default_interface] runtimeclass QuitAllRequestedArgs { - QuitAllRequestedArgs(); - Windows.Foundation.IAsyncAction BeforeQuitAllAction; - } - struct PeasantInfo { UInt64 Id; @@ -72,7 +67,6 @@ namespace Microsoft.Terminal.Remoting void SummonAllWindows(); Boolean DoesQuakeWindowExist(); Windows.Foundation.Collections.IVectorView GetPeasantInfos { get; }; - Windows.Foundation.Collections.IVector GetAllWindowLayouts(); void RequestMoveContent(String window, String content, UInt32 tabIndex, Windows.Foundation.IReference bounds); void RequestSendContent(RequestReceiveContentArgs args); @@ -82,7 +76,6 @@ namespace Microsoft.Terminal.Remoting event Windows.Foundation.TypedEventHandler HideNotificationIconRequested; event Windows.Foundation.TypedEventHandler WindowCreated; event Windows.Foundation.TypedEventHandler WindowClosed; - event Windows.Foundation.TypedEventHandler QuitAllRequested; event Windows.Foundation.TypedEventHandler RequestNewWindow; }; diff --git a/src/cascadia/Remoting/Peasant.cpp b/src/cascadia/Remoting/Peasant.cpp index 5d2b54f85af..6378854d199 100644 --- a/src/cascadia/Remoting/Peasant.cpp +++ b/src/cascadia/Remoting/Peasant.cpp @@ -5,7 +5,6 @@ #include "Peasant.h" #include "CommandlineArgs.h" #include "SummonWindowBehavior.h" -#include "GetWindowLayoutArgs.h" #include "Peasant.g.cpp" #include "../../types/inc/utils.hpp" #include "AttachRequest.g.cpp" @@ -309,26 +308,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation TraceLoggingKeyword(TIL_KEYWORD_TRACE)); } - // Method Description: - // - Request and return the window layout from the current TerminalPage - // Arguments: - // - - // Return Value: - // - the window layout as a json string - hstring Peasant::GetWindowLayout() - { - auto args = winrt::make_self(); - GetWindowLayoutRequested.raise(nullptr, *args); - if (const auto op = args->WindowLayoutJsonAsync()) - { - // This will fail if called on the UI thread, so the monarch should - // never set WindowLayoutJsonAsync. - auto str = op.get(); - return str; - } - return args->WindowLayoutJson(); - } - void Peasant::SendContent(const Remoting::RequestReceiveContentArgs& args) { SendContentRequested.raise(*this, args); diff --git a/src/cascadia/Remoting/Peasant.h b/src/cascadia/Remoting/Peasant.h index 67d407e599a..dc860ba907d 100644 --- a/src/cascadia/Remoting/Peasant.h +++ b/src/cascadia/Remoting/Peasant.h @@ -65,7 +65,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs(); - winrt::hstring GetWindowLayout(); void SendContent(const winrt::Microsoft::Terminal::Remoting::RequestReceiveContentArgs& args); til::typed_event WindowActivated; @@ -79,7 +78,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation til::typed_event<> HideNotificationIconRequested; til::typed_event<> QuitAllRequested; til::typed_event<> QuitRequested; - til::typed_event GetWindowLayoutRequested; til::typed_event AttachRequested; til::typed_event SendContentRequested; diff --git a/src/cascadia/Remoting/Peasant.idl b/src/cascadia/Remoting/Peasant.idl index f02d22da9c4..3463d561f07 100644 --- a/src/cascadia/Remoting/Peasant.idl +++ b/src/cascadia/Remoting/Peasant.idl @@ -32,12 +32,6 @@ namespace Microsoft.Terminal.Remoting Windows.Foundation.DateTime ActivatedTime { get; }; }; - [default_interface] runtimeclass GetWindowLayoutArgs { - GetWindowLayoutArgs(); - String WindowLayoutJson; - Windows.Foundation.IAsyncOperation WindowLayoutJsonAsync; - } - enum MonitorBehavior { InPlace, @@ -88,7 +82,6 @@ namespace Microsoft.Terminal.Remoting void RequestHideNotificationIcon(); void RequestQuitAll(); void Quit(); - String GetWindowLayout(); void AttachContentToWindow(AttachRequest request); void SendContent(RequestReceiveContentArgs args); @@ -102,7 +95,6 @@ namespace Microsoft.Terminal.Remoting event Windows.Foundation.TypedEventHandler ShowNotificationIconRequested; event Windows.Foundation.TypedEventHandler HideNotificationIconRequested; - event Windows.Foundation.TypedEventHandler GetWindowLayoutRequested; event Windows.Foundation.TypedEventHandler QuitAllRequested; event Windows.Foundation.TypedEventHandler QuitRequested; diff --git a/src/cascadia/Remoting/QuitAllRequestedArgs.cpp b/src/cascadia/Remoting/QuitAllRequestedArgs.cpp deleted file mode 100644 index ed5c39dcf4f..00000000000 --- a/src/cascadia/Remoting/QuitAllRequestedArgs.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#include "pch.h" -#include "QuitAllRequestedArgs.h" -#include "QuitAllRequestedArgs.g.cpp" diff --git a/src/cascadia/Remoting/QuitAllRequestedArgs.h b/src/cascadia/Remoting/QuitAllRequestedArgs.h deleted file mode 100644 index 4fba59cd141..00000000000 --- a/src/cascadia/Remoting/QuitAllRequestedArgs.h +++ /dev/null @@ -1,29 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Class Name: -- QuitAllRequestedArgs.h - -Abstract: -- This is a helper class for allowing the monarch to run code before telling all - peasants to quit. This way the monarch can raise an event and get back a future - to wait for before continuing. ---*/ - -#pragma once - -#include "QuitAllRequestedArgs.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct QuitAllRequestedArgs : public QuitAllRequestedArgsT - { - WINRT_PROPERTY(winrt::Windows::Foundation::IAsyncAction, BeforeQuitAllAction, nullptr) - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(QuitAllRequestedArgs); -} diff --git a/src/cascadia/Remoting/WindowManager.cpp b/src/cascadia/Remoting/WindowManager.cpp index 57c110cd37d..a9d3a42e018 100644 --- a/src/cascadia/Remoting/WindowManager.cpp +++ b/src/cascadia/Remoting/WindowManager.cpp @@ -92,7 +92,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation _monarch.WindowCreated({ get_weak(), &WindowManager::_bubbleWindowCreated }); _monarch.WindowClosed({ get_weak(), &WindowManager::_bubbleWindowClosed }); _monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested }); - _monarch.QuitAllRequested({ get_weak(), &WindowManager::_bubbleQuitAllRequested }); _monarch.RequestNewWindow({ get_weak(), &WindowManager::_raiseRequestNewWindow }); } @@ -356,8 +355,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation _monarch.AddPeasant(*p); - p->GetWindowLayoutRequested({ get_weak(), &WindowManager::_bubbleGetWindowLayoutRequested }); - TraceLoggingWrite(g_hRemotingProvider, "WindowManager_CreateOurPeasant", TraceLoggingUInt64(p->GetID(), "peasantID", "The ID of our new peasant"), @@ -367,10 +364,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation return *p; } - void WindowManager::_bubbleGetWindowLayoutRequested(const winrt::Windows::Foundation::IInspectable& s, const winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs& e) - { - GetWindowLayoutRequested.raise(s, e); - } void WindowManager::_bubbleWindowCreated(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e) { WindowCreated.raise(s, e); @@ -379,10 +372,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation { WindowClosed.raise(s, e); } - void WindowManager::_bubbleQuitAllRequested(const winrt::Windows::Foundation::IInspectable& s, const winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs& e) - { - QuitAllRequested.raise(s, e); - } void WindowManager::SignalClose(const Remoting::Peasant& peasant) { @@ -429,18 +418,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation return 0; } - // Method Description: - // - Ask the monarch to quit all windows. - // Arguments: - // - - // Return Value: - // - - winrt::fire_and_forget WindowManager::RequestQuitAll(Remoting::Peasant peasant) - { - co_await winrt::resume_background(); - peasant.RequestQuitAll(); - } - bool WindowManager::DoesQuakeWindowExist() { return _monarch.DoesQuakeWindowExist(); @@ -451,19 +428,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation winrt::get_self(peasant)->ActiveTabTitle(title); } - Windows::Foundation::Collections::IVector WindowManager::GetAllWindowLayouts() - { - if (_monarch) - { - try - { - return _monarch.GetAllWindowLayouts(); - } - CATCH_LOG() - } - return nullptr; - } - winrt::fire_and_forget WindowManager::RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, diff --git a/src/cascadia/Remoting/WindowManager.h b/src/cascadia/Remoting/WindowManager.h index 96946f1d3cc..6dd935e8a65 100644 --- a/src/cascadia/Remoting/WindowManager.h +++ b/src/cascadia/Remoting/WindowManager.h @@ -38,10 +38,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation uint64_t GetNumberOfPeasants(); - static winrt::fire_and_forget RequestQuitAll(Remoting::Peasant peasant); void UpdateActiveTabTitle(const winrt::hstring& title, const Remoting::Peasant& peasant); - Windows::Foundation::Collections::IVector GetAllWindowLayouts(); bool DoesQuakeWindowExist(); winrt::fire_and_forget RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, Windows::Foundation::IReference windowBounds); @@ -51,8 +49,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation til::typed_event<> WindowCreated; til::typed_event<> WindowClosed; - til::typed_event QuitAllRequested; - til::typed_event GetWindowLayoutRequested; til::typed_event RequestNewWindow; private: @@ -71,8 +67,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args); void _bubbleWindowCreated(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e); void _bubbleWindowClosed(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e); - void _bubbleQuitAllRequested(const winrt::Windows::Foundation::IInspectable& s, const winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs& e); - void _bubbleGetWindowLayoutRequested(const winrt::Windows::Foundation::IInspectable& s, const winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs& e); }; } diff --git a/src/cascadia/Remoting/WindowManager.idl b/src/cascadia/Remoting/WindowManager.idl index 5dd72b7f19a..deaf2b7489e 100644 --- a/src/cascadia/Remoting/WindowManager.idl +++ b/src/cascadia/Remoting/WindowManager.idl @@ -14,12 +14,10 @@ namespace Microsoft.Terminal.Remoting void SignalClose(Peasant p); void UpdateActiveTabTitle(String title, Peasant p); - static void RequestQuitAll(Peasant p); void SummonWindow(SummonWindowSelectionArgs args); void SummonAllWindows(); - Windows.Foundation.Collections.IVector GetAllWindowLayouts(); Windows.Foundation.Collections.IVectorView GetPeasantInfos(); UInt64 GetNumberOfPeasants(); @@ -33,8 +31,6 @@ namespace Microsoft.Terminal.Remoting event Windows.Foundation.TypedEventHandler WindowCreated; event Windows.Foundation.TypedEventHandler WindowClosed; - event Windows.Foundation.TypedEventHandler QuitAllRequested; - event Windows.Foundation.TypedEventHandler GetWindowLayoutRequested; event Windows.Foundation.TypedEventHandler RequestNewWindow; diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 5060b4ff2f7..b7a6b581a05 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -549,6 +549,9 @@ void AppCommandlineArgs::_addNewTerminalArgs(AppCommandlineArgs::NewTerminalSubc subcommand.profileNameOption = subcommand.subcommand->add_option("-p,--profile", _profileName, RS_A(L"CmdProfileArgDesc")); + subcommand.sessionIdOption = subcommand.subcommand->add_option("--sessionId", + _sessionId, + RS_A(L"CmdSessionIdArgDesc")); subcommand.startingDirectoryOption = subcommand.subcommand->add_option("-d,--startingDirectory", _startingDirectory, RS_A(L"CmdStartingDirArgDesc")); @@ -628,6 +631,13 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT args.Profile(winrt::to_hstring(_profileName)); } + if (*subcommand.sessionIdOption) + { + const auto str = winrt::to_hstring(_sessionId); + const auto id = ::Microsoft::Console::Utils::GuidFromString(str.c_str()); + args.SessionId(id); + } + if (*subcommand.startingDirectoryOption) { args.StartingDirectory(winrt::to_hstring(_startingDirectory)); @@ -714,6 +724,7 @@ bool AppCommandlineArgs::_noCommandsProvided() void AppCommandlineArgs::_resetStateToDefault() { _profileName.clear(); + _sessionId.clear(); _startingDirectory.clear(); _startingTitle.clear(); _startingTabColor.clear(); diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index 9145697f453..7eb5a34f93d 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -62,6 +62,7 @@ class TerminalApp::AppCommandlineArgs final CLI::App* subcommand; CLI::Option* commandlineOption; CLI::Option* profileNameOption; + CLI::Option* sessionIdOption; CLI::Option* startingDirectoryOption; CLI::Option* titleOption; CLI::Option* tabColorOption; @@ -96,6 +97,7 @@ class TerminalApp::AppCommandlineArgs final // Are you adding a new sub-command? Make sure to update _noCommandsProvided! std::string _profileName; + std::string _sessionId; std::string _startingDirectory; std::string _startingTitle; std::string _startingTabColor; diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 0b3ada01efa..dc11b506449 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -702,22 +702,6 @@ namespace winrt::TerminalApp::implementation return _settings.GlobalSettings().ShouldUsePersistedLayout(); } - void AppLogic::SaveWindowLayoutJsons(const Windows::Foundation::Collections::IVector& layouts) - { - std::vector converted; - converted.reserve(layouts.Size()); - - for (const auto& json : layouts) - { - if (json != L"") - { - converted.emplace_back(WindowLayout::FromJson(json)); - } - } - - ApplicationState::SharedInstance().PersistedWindowLayouts(winrt::single_threaded_vector(std::move(converted))); - } - TerminalApp::ParseCommandlineResult AppLogic::GetParseCommandlineMessage(array_view args) { ::TerminalApp::AppCommandlineArgs _appArgs; diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 3c14a4bca41..43d64184deb 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -53,9 +53,7 @@ namespace winrt::TerminalApp::implementation void NotifyRootInitialized(); bool HasSettingsStartupActions() const noexcept; - bool ShouldUsePersistedLayout() const; - void SaveWindowLayoutJsons(const Windows::Foundation::Collections::IVector& layouts); [[nodiscard]] Microsoft::Terminal::Settings::Model::CascadiaSettings GetSettings() const noexcept; diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 1021e61b99a..362c7405644 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -37,7 +37,6 @@ namespace TerminalApp Boolean HasSettingsStartupActions(); Boolean ShouldUsePersistedLayout(); - void SaveWindowLayoutJsons(Windows.Foundation.Collections.IVector layouts); void ReloadSettings(); diff --git a/src/cascadia/TerminalApp/IPaneContent.idl b/src/cascadia/TerminalApp/IPaneContent.idl index ebe0914ea9c..a26d1a05477 100644 --- a/src/cascadia/TerminalApp/IPaneContent.idl +++ b/src/cascadia/TerminalApp/IPaneContent.idl @@ -3,6 +3,13 @@ namespace TerminalApp { + enum BuildStartupKind + { + None, + Content, + MovePane, + Persist, + }; runtimeclass BellEventArgs { @@ -20,7 +27,7 @@ namespace TerminalApp UInt64 TaskbarProgress { get; }; Boolean ReadOnly { get; }; - Microsoft.Terminal.Settings.Model.NewTerminalArgs GetNewTerminalArgs(Boolean asContent); + Microsoft.Terminal.Settings.Model.NewTerminalArgs GetNewTerminalArgs(BuildStartupKind kind); void Focus(Windows.UI.Xaml.FocusState reason); diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 9ed53d49204..45950e2c776 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -4,12 +4,6 @@ #include "pch.h" #include "Pane.h" -#include "AppLogic.h" - -#include "Utils.h" - -#include - using namespace winrt::Windows::Foundation; using namespace winrt::Windows::Graphics::Display; using namespace winrt::Windows::UI; @@ -20,7 +14,6 @@ using namespace winrt::Microsoft::Terminal::Settings::Model; using namespace winrt::Microsoft::Terminal::Control; using namespace winrt::Microsoft::Terminal::TerminalConnection; using namespace winrt::TerminalApp; -using namespace TerminalApp; static const int PaneBorderSize = 2; static const int CombinedPaneBorderSize = 2 * PaneBorderSize; @@ -105,21 +98,13 @@ Pane::Pane(std::shared_ptr first, }); } -// Method Description: -// - Extract the terminal settings from the current (leaf) pane's control -// to be used to create an equivalent control -// Arguments: -// - asContent: when true, we're trying to serialize this pane for moving across -// windows. In that case, we'll need to fill in the content guid for our new -// terminal args. -// Return Value: -// - Arguments appropriate for a SplitPane or NewTab action -NewTerminalArgs Pane::GetTerminalArgsForPane(const bool asContent) const +// Extract the terminal settings from the current (leaf) pane's control +// to be used to create an equivalent control +NewTerminalArgs Pane::GetTerminalArgsForPane(BuildStartupKind kind) const { // Leaves are the only things that have controls assert(_IsLeaf()); - - return _content.GetNewTerminalArgs(asContent); + return _content.GetNewTerminalArgs(kind); } // Method Description: @@ -142,16 +127,13 @@ NewTerminalArgs Pane::GetTerminalArgsForPane(const bool asContent) const // - The state from building the startup actions, includes a vector of commands, // the original root pane, the id of the focused pane, and the number of panes // created. -Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, - uint32_t nextId, - const bool asContent, - const bool asMovePane) +Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t nextId, BuildStartupKind kind) { // Normally, if we're a leaf, return an empt set of actions, because the // parent pane will build the SplitPane action for us. If we're building // actions for a movePane action though, we'll still need to include // ourselves. - if (!asMovePane && _IsLeaf()) + if (kind != BuildStartupKind::MovePane && _IsLeaf()) { if (_lastActive) { @@ -165,18 +147,18 @@ Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, auto buildSplitPane = [&](auto newPane) { ActionAndArgs actionAndArgs; actionAndArgs.Action(ShortcutAction::SplitPane); - const auto terminalArgs{ newPane->GetTerminalArgsForPane(asContent) }; + const auto terminalArgs{ newPane->GetTerminalArgsForPane(kind) }; // When creating a pane the split size is the size of the new pane // and not position. const auto splitDirection = _splitState == SplitState::Horizontal ? SplitDirection::Down : SplitDirection::Right; - const auto splitSize = (asContent && _IsLeaf() ? .5 : 1. - _desiredSplitPosition); + const auto splitSize = (kind != BuildStartupKind::None && _IsLeaf() ? .5 : 1. - _desiredSplitPosition); SplitPaneArgs args{ SplitType::Manual, splitDirection, splitSize, terminalArgs }; actionAndArgs.Args(args); return actionAndArgs; }; - if (asContent && _IsLeaf()) + if (kind != BuildStartupKind::None && _IsLeaf()) { return { .args = { buildSplitPane(shared_from_this()) }, @@ -223,10 +205,10 @@ Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, // We now need to execute the commands for each side of the tree // We've done one split, so the first-most child will have currentId, and the // one after it will be incremented. - auto firstState = _firstChild->BuildStartupActions(currentId, nextId + 1); + auto firstState = _firstChild->BuildStartupActions(currentId, nextId + 1, kind); // the next id for the second branch depends on how many splits were in the // first child. - auto secondState = _secondChild->BuildStartupActions(nextId, nextId + firstState.panesCreated + 1); + auto secondState = _secondChild->BuildStartupActions(nextId, nextId + firstState.panesCreated + 1, kind); std::vector actions{}; actions.reserve(firstState.args.size() + secondState.args.size() + 3); diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index 1f237f83190..0f4a5c907dc 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -104,8 +104,8 @@ class Pane : public std::enable_shared_from_this std::optional focusedPaneId; uint32_t panesCreated; }; - BuildStartupState BuildStartupActions(uint32_t currentId, uint32_t nextId, const bool asContent = false, const bool asMovePane = false); - winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetTerminalArgsForPane(const bool asContent = false) const; + BuildStartupState BuildStartupActions(uint32_t currentId, uint32_t nextId, winrt::TerminalApp::BuildStartupKind kind); + winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetTerminalArgsForPane(winrt::TerminalApp::BuildStartupKind kind) const; void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, const winrt::Microsoft::Terminal::Settings::Model::Profile& profile); diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 3f91408815f..54cd9e9bc30 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -187,9 +187,6 @@ Quit - - Do you want to close all tabs? - Multiple panes @@ -340,6 +337,9 @@ Open with the given profile. Accepts either the name or GUID of a profile + + Sets the WT_SESSION variable; must be a GUID + Create a new split pane diff --git a/src/cascadia/TerminalApp/ScratchpadContent.cpp b/src/cascadia/TerminalApp/ScratchpadContent.cpp index dcb13697b54..0ed99203391 100644 --- a/src/cascadia/TerminalApp/ScratchpadContent.cpp +++ b/src/cascadia/TerminalApp/ScratchpadContent.cpp @@ -43,7 +43,7 @@ namespace winrt::TerminalApp::implementation CloseRequested.raise(*this, nullptr); } - NewTerminalArgs ScratchpadContent::GetNewTerminalArgs(const bool /* asContent */) const + NewTerminalArgs ScratchpadContent::GetNewTerminalArgs(const BuildStartupKind /* kind */) const { return nullptr; } diff --git a/src/cascadia/TerminalApp/ScratchpadContent.h b/src/cascadia/TerminalApp/ScratchpadContent.h index 10aa36b6b85..a2b76e47934 100644 --- a/src/cascadia/TerminalApp/ScratchpadContent.h +++ b/src/cascadia/TerminalApp/ScratchpadContent.h @@ -17,7 +17,7 @@ namespace winrt::TerminalApp::implementation void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic); void Close(); - winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetNewTerminalArgs(const bool asContent) const; + winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetNewTerminalArgs(BuildStartupKind kind) const; winrt::hstring Title() { return L"Scratchpad"; } uint64_t TaskbarState() { return 0; } diff --git a/src/cascadia/TerminalApp/SettingsTab.cpp b/src/cascadia/TerminalApp/SettingsTab.cpp index 12107e8efea..483f4f30475 100644 --- a/src/cascadia/TerminalApp/SettingsTab.cpp +++ b/src/cascadia/TerminalApp/SettingsTab.cpp @@ -57,7 +57,7 @@ namespace winrt::TerminalApp::implementation // re-evaluate including that arg in this action then. // Return Value: // - The list of actions. - std::vector SettingsTab::BuildStartupActions(const bool /*asContent*/) const + std::vector SettingsTab::BuildStartupActions(BuildStartupKind) const { ASSERT_UI_THREAD(); diff --git a/src/cascadia/TerminalApp/SettingsTab.h b/src/cascadia/TerminalApp/SettingsTab.h index 657c8387661..e5d7df92faf 100644 --- a/src/cascadia/TerminalApp/SettingsTab.h +++ b/src/cascadia/TerminalApp/SettingsTab.h @@ -30,7 +30,7 @@ namespace winrt::TerminalApp::implementation void UpdateSettings(Microsoft::Terminal::Settings::Model::CascadiaSettings settings); void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override; - std::vector BuildStartupActions(const bool asContent = false) const override; + std::vector BuildStartupActions(BuildStartupKind kind) const override; private: winrt::Windows::UI::Xaml::ElementTheme _requestedTheme; diff --git a/src/cascadia/TerminalApp/TabBase.h b/src/cascadia/TerminalApp/TabBase.h index 8a0190ad3c3..9a538550b8d 100644 --- a/src/cascadia/TerminalApp/TabBase.h +++ b/src/cascadia/TerminalApp/TabBase.h @@ -22,7 +22,7 @@ namespace winrt::TerminalApp::implementation void UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs); void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap); - virtual std::vector BuildStartupActions(const bool asContent = false) const = 0; + virtual std::vector BuildStartupActions(BuildStartupKind kind) const = 0; virtual std::optional GetTabColor(); void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index b407c6107c1..8d99ac600f5 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -429,7 +429,7 @@ namespace winrt::TerminalApp::implementation } auto t = winrt::get_self(tab); - auto actions = t->BuildStartupActions(); + auto actions = t->BuildStartupActions(BuildStartupKind::None); _AddPreviouslyClosedPaneOrTab(std::move(actions)); _RemoveTab(tab); @@ -486,7 +486,7 @@ namespace winrt::TerminalApp::implementation // if the user manually closed all tabs. // Do this only if we are the last window; the monarch will notice // we are missing and remove us that way otherwise. - LastTabClosed.raise(*this, winrt::make(!_maintainStateOnTabClose)); + CloseWindowRequested.raise(*this, nullptr); } else if (focusedTabIndex.has_value() && focusedTabIndex.value() == gsl::narrow_cast(tabIndex)) { @@ -767,11 +767,11 @@ namespace winrt::TerminalApp::implementation // This doesn't handle refocusing anything in particular, the // result will be that the last pane created is focused. In the // case of a single pane that is the desired behavior anyways. - auto state = pane->BuildStartupActions(0, 1); + auto state = pane->BuildStartupActions(0, 1, BuildStartupKind::None); { ActionAndArgs splitPaneAction{}; splitPaneAction.Action(ShortcutAction::SplitPane); - SplitPaneArgs splitPaneArgs{ SplitDirection::Automatic, state.firstPane->GetTerminalArgsForPane() }; + SplitPaneArgs splitPaneArgs{ SplitDirection::Automatic, state.firstPane->GetTerminalArgsForPane(BuildStartupKind::None) }; splitPaneAction.Args(splitPaneArgs); state.args.emplace(state.args.begin(), std::move(splitPaneAction)); @@ -1139,12 +1139,4 @@ namespace winrt::TerminalApp::implementation { return _tabs.Size() > 1; } - - void TerminalPage::_RemoveAllTabs() - { - // Since _RemoveTabs is asynchronous, create a snapshot of the tabs we want to remove - std::vector tabsToRemove; - std::copy(begin(_tabs), end(_tabs), std::back_inserter(tabsToRemove)); - _RemoveTabs(tabsToRemove); - } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index d3fc7a2dc25..591fc6906a0 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -5,7 +5,6 @@ #include "pch.h" #include "TerminalPage.h" #include "TerminalPage.g.cpp" -#include "LastTabClosedEventArgs.g.cpp" #include "RenameWindowRequestedArgs.g.cpp" #include "RequestMoveContentArgs.g.cpp" #include "RequestReceiveContentArgs.g.cpp" @@ -654,9 +653,9 @@ namespace winrt::TerminalApp::implementation // GH#12267: Make sure that we don't instantly close ourselves when // we're readying to accept a defterm connection. In that case, we don't // have a tab yet, but will once we're initialized. - if (_tabs.Size() == 0 && !(_shouldStartInboundListener || _isEmbeddingInboundListener)) + if (_tabs.Size() == 0 && !_shouldStartInboundListener && !_isEmbeddingInboundListener) { - LastTabClosed.raise(*this, winrt::make(false)); + CloseWindowRequested.raise(*this, nullptr); co_return; } else @@ -1277,6 +1276,11 @@ namespace winrt::TerminalApp::implementation } } + if (const auto id = settings.SessionId(); id != winrt::guid{}) + { + valueSet.Insert(L"sessionId", Windows::Foundation::PropertyValue::CreateGuid(id)); + } + connection.Initialize(valueSet); TraceLoggingWrite( @@ -1891,19 +1895,11 @@ namespace winrt::TerminalApp::implementation } } - // Method Description: - // - Saves the window position and tab layout to the application state - // - This does not create the InitialPosition field, that needs to be - // added externally. - // Arguments: - // - - // Return Value: - // - the window layout - WindowLayout TerminalPage::GetWindowLayout() + void TerminalPage::PersistState() { if (_startupState != StartupState::Initialized) { - return nullptr; + return; } std::vector actions; @@ -1911,7 +1907,7 @@ namespace winrt::TerminalApp::implementation for (auto tab : _tabs) { auto t = winrt::get_self(tab); - auto tabActions = t->BuildStartupActions(); + auto tabActions = t->BuildStartupActions(BuildStartupKind::Persist); actions.insert(actions.end(), std::make_move_iterator(tabActions.begin()), std::make_move_iterator(tabActions.end())); } @@ -1938,7 +1934,7 @@ namespace winrt::TerminalApp::implementation actions.emplace_back(std::move(action)); } - WindowLayout layout{}; + WindowLayout layout; layout.TabLayout(winrt::single_threaded_vector(std::move(actions))); auto mode = LaunchMode::DefaultMode; @@ -1955,20 +1951,15 @@ namespace winrt::TerminalApp::implementation layout.InitialSize(windowSize); - return layout; + ApplicationState::SharedInstance().AppendPersistedWindowLayout(layout); } // Method Description: // - Close the terminal app. If there is more // than one tab opened, show a warning dialog. - // Arguments: - // - bypassDialog: if true a dialog won't be shown even if the user would - // normally get confirmation. This is used in the case where the user - // has already been prompted by the Quit action. - fire_and_forget TerminalPage::CloseWindow(bool bypassDialog) + fire_and_forget TerminalPage::CloseWindow() { - if (!bypassDialog && - _HasMultipleTabs() && + if (_HasMultipleTabs() && _settings.GlobalSettings().ConfirmCloseAllTabs() && !_displayingCloseDialog) { @@ -1987,15 +1978,7 @@ namespace winrt::TerminalApp::implementation } } - if (_settings.GlobalSettings().ShouldUsePersistedLayout()) - { - // Don't delete the ApplicationState when all of the tabs are removed. - // If there is still a monarch living they will get the event that - // a window closed and trigger a new save without this window. - _maintainStateOnTabClose = true; - } - - _RemoveAllTabs(); + CloseWindowRequested.raise(*this, nullptr); } // Method Description: @@ -2057,7 +2040,7 @@ namespace winrt::TerminalApp::implementation { if (const auto pane{ terminalTab->GetActivePane() }) { - auto startupActions = pane->BuildStartupActions(0, 1, true, true); + auto startupActions = pane->BuildStartupActions(0, 1, BuildStartupKind::MovePane); _DetachPaneFromWindow(pane); _MoveContent(std::move(startupActions.args), windowId, tabIdx); focusedTab->DetachPane(); @@ -2199,7 +2182,7 @@ namespace winrt::TerminalApp::implementation if (tab) { - auto startupActions = tab->BuildStartupActions(true); + auto startupActions = tab->BuildStartupActions(BuildStartupKind::Content); _DetachTabFromWindow(tab); _MoveContent(std::move(startupActions), windowId, 0); _RemoveTab(*tab); @@ -3041,7 +3024,17 @@ namespace winrt::TerminalApp::implementation // TermControl will copy the settings out of the settings passed to it. const auto content = _manager.CreateCore(settings.DefaultSettings(), settings.UnfocusedSettings(), connection); - return _SetupControl(TermControl{ content }); + const TermControl control{ content }; + + if (const auto id = settings.DefaultSettings().SessionId(); id != winrt::guid{}) + { + const auto settingsDir = CascadiaSettings::SettingsDirectory(); + const auto idStr = Utils::GuidToPlainString(id); + const auto path = fmt::format(FMT_COMPILE(L"{}\\buffer_{}.txt"), settingsDir, idStr); + control.RestoreFromPath(path); + } + + return _SetupControl(control); } TermControl TerminalPage::_AttachControlToContent(const uint64_t& contentId) @@ -5124,7 +5117,7 @@ namespace winrt::TerminalApp::implementation const uint32_t tabIndex, std::optional dragPoint) { - auto startupActions = _stashed.draggedTab->BuildStartupActions(true); + auto startupActions = _stashed.draggedTab->BuildStartupActions(BuildStartupKind::Content); _DetachTabFromWindow(_stashed.draggedTab); _MoveContent(std::move(startupActions), windowId, tabIndex, dragPoint); diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 639165d1730..227f28edbb5 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -7,7 +7,6 @@ #include "TerminalTab.h" #include "AppKeyBindings.h" #include "AppCommandlineArgs.h" -#include "LastTabClosedEventArgs.g.h" #include "RenameWindowRequestedArgs.g.h" #include "RequestMoveContentArgs.g.h" #include "RequestReceiveContentArgs.g.h" @@ -44,15 +43,6 @@ namespace winrt::TerminalApp::implementation ScrollDown = 1 }; - struct LastTabClosedEventArgs : LastTabClosedEventArgsT - { - WINRT_PROPERTY(bool, ClearPersistedState); - - public: - LastTabClosedEventArgs(const bool& shouldClear) : - _ClearPersistedState{ shouldClear } {}; - }; - struct RenameWindowRequestedArgs : RenameWindowRequestedArgsT { WINRT_PROPERTY(winrt::hstring, ProposedName); @@ -105,7 +95,6 @@ namespace winrt::TerminalApp::implementation bool ShouldImmediatelyHandoffToElevated(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const; void HandoffToElevated(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings); - Microsoft::Terminal::Settings::Model::WindowLayout GetWindowLayout(); hstring Title(); @@ -121,7 +110,8 @@ namespace winrt::TerminalApp::implementation SuggestionsControl LoadSuggestionsUI(); winrt::fire_and_forget RequestQuit(); - winrt::fire_and_forget CloseWindow(bool bypassDialog); + winrt::fire_and_forget CloseWindow(); + void PersistState(); void ToggleFocusMode(); void ToggleFullscreen(); @@ -175,7 +165,7 @@ namespace winrt::TerminalApp::implementation // -------------------------------- WinRT Events --------------------------------- til::typed_event TitleChanged; - til::typed_event LastTabClosed; + til::typed_event CloseWindowRequested; til::typed_event SetTitleBarContent; til::typed_event FocusModeChanged; til::typed_event FullscreenChanged; @@ -185,7 +175,7 @@ namespace winrt::TerminalApp::implementation til::typed_event SetTaskbarProgress; til::typed_event Initialized; til::typed_event IdentifyWindowsRequested; - til::typed_event RenameWindowRequested; + til::typed_event RenameWindowRequested; til::typed_event SummonWindowRequested; til::typed_event CloseRequested; @@ -232,7 +222,6 @@ namespace winrt::TerminalApp::implementation std::optional _loadFromPersistedLayoutIdx{}; - bool _maintainStateOnTabClose{ false }; bool _rearranging{ false }; std::optional _rearrangeFrom{}; std::optional _rearrangeTo{}; @@ -348,7 +337,6 @@ namespace winrt::TerminalApp::implementation void _DismissTabContextMenus(); void _FocusCurrentTab(const bool focusAlways); bool _HasMultipleTabs() const; - void _RemoveAllTabs(); void _SelectNextTab(const bool bMoveRight, const Windows::Foundation::IReference& customTabSwitcherMode); bool _SelectTab(uint32_t tabIndex); diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index f322c0d527e..8ec4fa1dc9c 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -14,11 +14,6 @@ namespace TerminalApp void Detach(Microsoft.Terminal.Control.TermControl control); } - [default_interface] runtimeclass LastTabClosedEventArgs - { - Boolean ClearPersistedState { get; }; - }; - [default_interface] runtimeclass RenameWindowRequestedArgs { String ProposedName { get; }; @@ -86,7 +81,7 @@ namespace TerminalApp void SendContentToOther(RequestReceiveContentArgs args); event Windows.Foundation.TypedEventHandler TitleChanged; - event Windows.Foundation.TypedEventHandler LastTabClosed; + event Windows.Foundation.TypedEventHandler CloseWindowRequested; event Windows.Foundation.TypedEventHandler SetTitleBarContent; event Windows.Foundation.TypedEventHandler FocusModeChanged; event Windows.Foundation.TypedEventHandler FullscreenChanged; diff --git a/src/cascadia/TerminalApp/TerminalPaneContent.cpp b/src/cascadia/TerminalApp/TerminalPaneContent.cpp index 597631d8fdc..49bbe3ff355 100644 --- a/src/cascadia/TerminalApp/TerminalPaneContent.cpp +++ b/src/cascadia/TerminalApp/TerminalPaneContent.cpp @@ -3,11 +3,14 @@ #include "pch.h" #include "TerminalPaneContent.h" -#include "TerminalPaneContent.g.cpp" + +#include + +#include "../../types/inc/utils.hpp" #include "BellEventArgs.g.cpp" +#include "TerminalPaneContent.g.cpp" -#include using namespace winrt::Windows::Foundation; using namespace winrt::Windows::UI::Xaml; using namespace winrt::Microsoft::Terminal::Settings::Model; @@ -77,7 +80,7 @@ namespace winrt::TerminalApp::implementation CloseRequested.raise(*this, nullptr); } - NewTerminalArgs TerminalPaneContent::GetNewTerminalArgs(const bool asContent) const + NewTerminalArgs TerminalPaneContent::GetNewTerminalArgs(const BuildStartupKind kind) const { NewTerminalArgs args{}; const auto& controlSettings = _control.Settings(); @@ -119,12 +122,32 @@ namespace winrt::TerminalApp::implementation // object. That would work for schemes set by the Terminal, but not ones set // by VT, but that seems good enough. - // Only fill in the ContentId if absolutely needed. If you fill in a number - // here (even 0), we'll serialize that number, AND treat that action as an - // "attach existing" rather than a "create" - if (asContent) + switch (kind) { + case BuildStartupKind::Content: + case BuildStartupKind::MovePane: + // Only fill in the ContentId if absolutely needed. If you fill in a number + // here (even 0), we'll serialize that number, AND treat that action as an + // "attach existing" rather than a "create" args.ContentId(_control.ContentId()); + break; + case BuildStartupKind::Persist: + { + const auto connection = _control.Connection(); + const auto id = connection ? connection.SessionId() : winrt::guid{}; + + if (id != winrt::guid{}) + { + const auto settingsDir = CascadiaSettings::SettingsDirectory(); + const auto idStr = ::Microsoft::Console::Utils::GuidToPlainString(id); + const auto path = fmt::format(FMT_COMPILE(L"{}\\buffer_{}.txt"), settingsDir, idStr); + _control.PersistToPath(path); + args.SessionId(id); + } + break; + } + default: + break; } return args; diff --git a/src/cascadia/TerminalApp/TerminalPaneContent.h b/src/cascadia/TerminalApp/TerminalPaneContent.h index 2c2deee0124..11ad0425379 100644 --- a/src/cascadia/TerminalApp/TerminalPaneContent.h +++ b/src/cascadia/TerminalApp/TerminalPaneContent.h @@ -27,7 +27,7 @@ namespace winrt::TerminalApp::implementation void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic); void Close(); - winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetNewTerminalArgs(const bool asContent) const; + winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetNewTerminalArgs(BuildStartupKind kind) const; void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, const winrt::Microsoft::Terminal::Settings::Model::Profile& profile); diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index c5cb7f5b5f2..247601e21d1 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -432,18 +432,18 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - A vector of commands - std::vector TerminalTab::BuildStartupActions(const bool asContent) const + std::vector TerminalTab::BuildStartupActions(BuildStartupKind kind) const { ASSERT_UI_THREAD(); // Give initial ids (0 for the child created with this tab, // 1 for the child after the first split. - auto state = _rootPane->BuildStartupActions(0, 1, asContent); + auto state = _rootPane->BuildStartupActions(0, 1, kind); { ActionAndArgs newTabAction{}; newTabAction.Action(ShortcutAction::NewTab); - NewTabArgs newTabArgs{ state.firstPane->GetTerminalArgsForPane(asContent) }; + NewTabArgs newTabArgs{ state.firstPane->GetTerminalArgsForPane(kind) }; newTabAction.Args(newTabArgs); state.args.emplace(state.args.begin(), std::move(newTabAction)); diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index df9e4cae825..3ae1a3cc2fa 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -79,7 +79,7 @@ namespace winrt::TerminalApp::implementation void EnterZoom(); void ExitZoom(); - std::vector BuildStartupActions(const bool asContent = false) const override; + std::vector BuildStartupActions(BuildStartupKind kind) const override; int GetLeafPaneCount() const noexcept; diff --git a/src/cascadia/TerminalApp/TerminalWindow.cpp b/src/cascadia/TerminalApp/TerminalWindow.cpp index 0ca513a064a..4a37b0a733e 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.cpp +++ b/src/cascadia/TerminalApp/TerminalWindow.cpp @@ -267,7 +267,7 @@ namespace winrt::TerminalApp::implementation { if (_root) { - _root->CloseWindow(true); + _root->PersistState(); } } @@ -916,32 +916,11 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalWindow::CloseWindow(LaunchPosition pos, const bool isLastWindow) + void TerminalWindow::CloseWindow() { if (_root) { - // If persisted layout is enabled and we are the last window closing - // we should save our state. - if (_settings.GlobalSettings().ShouldUsePersistedLayout() && isLastWindow) - { - if (const auto layout = _root->GetWindowLayout()) - { - layout.InitialPosition(pos); - const auto state = ApplicationState::SharedInstance(); - state.PersistedWindowLayouts(winrt::single_threaded_vector({ layout })); - } - } - - _root->CloseWindow(false); - } - } - - void TerminalWindow::ClearPersistedWindowState() - { - if (_settings.GlobalSettings().ShouldUsePersistedLayout()) - { - auto state = ApplicationState::SharedInstance(); - state.PersistedWindowLayouts(nullptr); + _root->CloseWindow(); } } @@ -1134,19 +1113,6 @@ namespace winrt::TerminalApp::implementation return winrt::to_hstring(_appArgs.GetExitMessage()); } - hstring TerminalWindow::GetWindowLayoutJson(LaunchPosition position) - { - if (_root != nullptr) - { - if (const auto layout = _root->GetWindowLayout()) - { - layout.InitialPosition(position); - return WindowLayout::ToJson(layout); - } - } - return L""; - } - void TerminalWindow::SetPersistedLayoutIdx(const uint32_t idx) { _loadFromPersistedLayoutIdx = idx; diff --git a/src/cascadia/TerminalApp/TerminalWindow.h b/src/cascadia/TerminalApp/TerminalWindow.h index 8bf04971afb..d48d8d4f242 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.h +++ b/src/cascadia/TerminalApp/TerminalWindow.h @@ -95,8 +95,6 @@ namespace winrt::TerminalApp::implementation bool AlwaysOnTop() const; bool AutoHideWindow(); - hstring GetWindowLayoutJson(Microsoft::Terminal::Settings::Model::LaunchPosition position); - void IdentifyWindow(); void RenameFailed(); @@ -104,9 +102,6 @@ namespace winrt::TerminalApp::implementation winrt::Microsoft::Terminal::Settings::Model::WindowLayout LoadPersistedLayout(); void SetPersistedLayoutIdx(const uint32_t idx); - void SetNumberOfOpenWindows(const uint64_t num); - bool ShouldUsePersistedLayout() const; - void ClearPersistedWindowState(); void RequestExitFullscreen(); @@ -125,7 +120,7 @@ namespace winrt::TerminalApp::implementation void TitlebarClicked(); bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down); - void CloseWindow(Microsoft::Terminal::Settings::Model::LaunchPosition position, const bool isLastWindow); + void CloseWindow(); void WindowVisibilityChanged(const bool showOrHide); winrt::TerminalApp::TaskbarState TaskbarState(); @@ -218,7 +213,7 @@ namespace winrt::TerminalApp::implementation FORWARDED_TYPED_EVENT(SetTitleBarContent, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement, _root, SetTitleBarContent); FORWARDED_TYPED_EVENT(TitleChanged, winrt::Windows::Foundation::IInspectable, winrt::hstring, _root, TitleChanged); - FORWARDED_TYPED_EVENT(LastTabClosed, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs, _root, LastTabClosed); + FORWARDED_TYPED_EVENT(CloseWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, CloseWindowRequested); FORWARDED_TYPED_EVENT(FocusModeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FocusModeChanged); FORWARDED_TYPED_EVENT(FullscreenChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FullscreenChanged); FORWARDED_TYPED_EVENT(ChangeMaximizeRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, ChangeMaximizeRequested); diff --git a/src/cascadia/TerminalApp/TerminalWindow.idl b/src/cascadia/TerminalApp/TerminalWindow.idl index a1e84211542..1700686e1db 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.idl +++ b/src/cascadia/TerminalApp/TerminalWindow.idl @@ -74,7 +74,6 @@ namespace TerminalApp void IdentifyWindow(); void SetPersistedLayoutIdx(UInt32 idx); - void ClearPersistedWindowState(); void RenameFailed(); void RequestExitFullscreen(); @@ -89,7 +88,7 @@ namespace TerminalApp Boolean GetInitialAlwaysOnTop(); Single CalcSnappedDimension(Boolean widthOrHeight, Single dimension); void TitlebarClicked(); - void CloseWindow(Microsoft.Terminal.Settings.Model.LaunchPosition position, Boolean isLastWindow); + void CloseWindow(); void WindowVisibilityChanged(Boolean showOrHide); TaskbarState TaskbarState{ get; }; @@ -97,8 +96,6 @@ namespace TerminalApp Windows.UI.Xaml.Media.Brush FrameBrush { get; }; void WindowActivated(Boolean activated); - String GetWindowLayoutJson(Microsoft.Terminal.Settings.Model.LaunchPosition position); - Boolean GetMinimizeToNotificationArea(); Boolean GetAlwaysShowNotificationIcon(); Boolean GetShowTitleInTitlebar(); @@ -118,7 +115,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler SetTitleBarContent; event Windows.Foundation.TypedEventHandler TitleChanged; - event Windows.Foundation.TypedEventHandler LastTabClosed; + event Windows.Foundation.TypedEventHandler CloseWindowRequested; event Windows.Foundation.TypedEventHandler RequestedThemeChanged; event Windows.Foundation.TypedEventHandler FocusModeChanged; event Windows.Foundation.TypedEventHandler FullscreenChanged; diff --git a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj index f0a2e4e6b49..8eda9937725 100644 --- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj +++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj @@ -96,7 +96,6 @@ - - + \ No newline at end of file diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 95c80e4e9ad..4c36320d9b2 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -9,8 +9,10 @@ #include #include -#include #include +#include +#include +#include #include "EventArgs.h" #include "../../renderer/atlas/AtlasEngine.h" @@ -399,10 +401,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _initializedTerminal.store(true, std::memory_order_relaxed); } // scope for TerminalLock - // Start the connection outside of lock, because it could - // start writing output immediately. - _connection.Start(); - return true; } @@ -1711,6 +1709,50 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } + void ControlCore::PersistToPath(const wchar_t* path) const + { + const auto lock = _terminal->LockForReading(); + _terminal->SerializeMainBuffer(path); + } + + void ControlCore::RestoreFromPath(const wchar_t* path) const + { + const wil::unique_handle file{ CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr) }; + if (!file) + { + return; + } + + wchar_t buffer[32 * 1024]; + DWORD read = 0; + + // Ensure the text file starts with a UTF-16 BOM. + if (!ReadFile(file.get(), &buffer[0], 2, &read, nullptr) || read < 2 || buffer[0] != L'\uFEFF') + { + return; + } + + for (;;) + { + if (!ReadFile(file.get(), &buffer[0], sizeof(buffer), &read, nullptr)) + { + break; + } + + const auto lock = _terminal->LockForWriting(); + _terminal->Write({ &buffer[0], read / 2 }); + + if (read < sizeof(buffer)) + { + break; + } + } + + // This pushes the restored contents up into the scrollback. + const auto lock = _terminal->LockForWriting(); + _terminal->Write(L"\x1b[2J"); + } + void ControlCore::_rendererWarning(const HRESULT hr, wil::zwstring_view parameter) { RendererWarning.raise(*this, winrt::make(hr, winrt::hstring{ parameter })); diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 7dbf228cd26..ee0d68f6a8a 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -150,6 +150,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ColorSelection(const Control::SelectionColor& fg, const Control::SelectionColor& bg, Core::MatchMode matchMode); void Close(); + void PersistToPath(const wchar_t* path) const; + void RestoreFromPath(const wchar_t* path) const; #pragma region ICoreState const size_t TaskbarState() const noexcept; diff --git a/src/cascadia/TerminalControl/IControlSettings.idl b/src/cascadia/TerminalControl/IControlSettings.idl index 2db92a86a83..29cd96b6f8e 100644 --- a/src/cascadia/TerminalControl/IControlSettings.idl +++ b/src/cascadia/TerminalControl/IControlSettings.idl @@ -32,7 +32,8 @@ namespace Microsoft.Terminal.Control String ProfileName; String ProfileSource; - Boolean EnableUnfocusedAcrylic; + Boolean EnableUnfocusedAcrylic { get; }; + Guid SessionId { get; }; ScrollbarState ScrollState { get; }; String FontFace { get; }; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 303d6d61482..0e459e9238b 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -5,6 +5,7 @@ #include "TermControl.h" #include +#include #include "TermControlAutomationPeer.h" #include "../../renderer/atlas/AtlasEngine.h" @@ -1068,7 +1069,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation { return false; } + _interactivity.Initialize(); + + if (!_restorePath.empty()) + { + winrt::get_self(_core)->RestoreFromPath(_restorePath.c_str()); + _restorePath = {}; + } + + _core.Connection().Start(); } else { @@ -2259,6 +2269,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _core.ExpandSelectionToWord(); } + void TermControl::RestoreFromPath(winrt::hstring path) + { + _restorePath = std::move(path); + } + + void TermControl::PersistToPath(const winrt::hstring& path) const + { + winrt::get_self(_core)->PersistToPath(path.c_str()); + } + void TermControl::Close() { if (!_IsClosing()) @@ -2293,6 +2313,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } } + void TermControl::Detach() { _revokers = {}; diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 2a8b28567ec..a12aa964664 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -45,6 +45,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation void ToggleMarkMode(); bool SwitchSelectionEndpoint(); bool ExpandSelectionToWord(); + void RestoreFromPath(winrt::hstring path); + void PersistToPath(const winrt::hstring& path) const; void Close(); Windows::Foundation::Size CharacterDimensions() const; Windows::Foundation::Size MinimumSize(); @@ -249,6 +251,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation SafeDispatcherTimer _blinkTimer; winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; + winrt::hstring _restorePath; bool _showMarksInScrollbar{ false }; bool _isBackgroundLight{ false }; diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index b105748ff64..8a91707c3af 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -93,6 +93,8 @@ namespace Microsoft.Terminal.Control Boolean SwitchSelectionEndpoint(); Boolean ExpandSelectionToWord(); void ClearBuffer(ClearBufferType clearType); + void RestoreFromPath(String path); + void PersistToPath(String path); void Close(); Windows.Foundation.Size CharacterDimensions { get; }; Windows.Foundation.Size MinimumSize { get; }; diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 6eabcdab072..4a6c1187da5 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -1549,6 +1549,11 @@ std::wstring_view Terminal::CurrentCommand() const return _activeBuffer().CurrentCommand(); } +void Terminal::SerializeMainBuffer(const wchar_t* destination) const +{ + _mainBuffer->Serialize(destination); +} + void Terminal::ColorSelection(const TextAttribute& attr, winrt::Microsoft::Terminal::Core::MatchMode matchMode) { const auto colorSelection = [this](const til::point coordStart, const til::point coordEnd, const TextAttribute& attr) { diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 80c5e3cc905..b10c0d893ac 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -126,6 +126,7 @@ class Microsoft::Terminal::Core::Terminal final : til::property AlwaysNotifyOnBufferRotation; std::wstring_view CurrentCommand() const; + void SerializeMainBuffer(const wchar_t* destination) const; #pragma region ITerminalApi // These methods are defined in TerminalApi.cpp diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionArgs.cpp index a276ebeff2b..598b77a4051 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.cpp @@ -129,6 +129,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { ss << fmt::format(L"--profile \"{}\" ", Profile()); } + + if (const auto id = SessionId(); id != winrt::guid{}) + { + const auto str = ::Microsoft::Console::Utils::GuidToString(id); + ss << fmt::format(L"--sessionId \"{}\" ", str); + } + // The caller is always expected to provide the evaluated profile in the // NewTerminalArgs, not the index // diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index 6d83964cbbc..4062cee426c 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -309,6 +309,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation ACTION_ARG(Windows::Foundation::IReference, TabColor, nullptr); ACTION_ARG(Windows::Foundation::IReference, ProfileIndex, nullptr); ACTION_ARG(winrt::hstring, Profile, L""); + ACTION_ARG(winrt::guid, SessionId, winrt::guid{}); ACTION_ARG(bool, AppendCommandLine, false); ACTION_ARG(Windows::Foundation::IReference, SuppressApplicationTitle, nullptr); ACTION_ARG(winrt::hstring, ColorScheme); @@ -322,6 +323,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static constexpr std::string_view TabColorKey{ "tabColor" }; static constexpr std::string_view ProfileIndexKey{ "index" }; static constexpr std::string_view ProfileKey{ "profile" }; + static constexpr std::string_view SessionIdKey{ "sessionId" }; static constexpr std::string_view AppendCommandLineKey{ "appendCommandLine" }; static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" }; static constexpr std::string_view ColorSchemeKey{ "colorScheme" }; @@ -362,6 +364,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation JsonUtils::GetValueForKey(json, TabTitleKey, args->_TabTitle); JsonUtils::GetValueForKey(json, ProfileIndexKey, args->_ProfileIndex); JsonUtils::GetValueForKey(json, ProfileKey, args->_Profile); + JsonUtils::GetValueForKey(json, SessionIdKey, args->_SessionId); JsonUtils::GetValueForKey(json, TabColorKey, args->_TabColor); JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, args->_SuppressApplicationTitle); JsonUtils::GetValueForKey(json, ColorSchemeKey, args->_ColorScheme); @@ -383,6 +386,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation JsonUtils::SetValueForKey(json, TabTitleKey, args->_TabTitle); JsonUtils::SetValueForKey(json, ProfileIndexKey, args->_ProfileIndex); JsonUtils::SetValueForKey(json, ProfileKey, args->_Profile); + JsonUtils::SetValueForKey(json, SessionIdKey, args->_SessionId); JsonUtils::SetValueForKey(json, TabColorKey, args->_TabColor); JsonUtils::SetValueForKey(json, SuppressApplicationTitleKey, args->_SuppressApplicationTitle); JsonUtils::SetValueForKey(json, ColorSchemeKey, args->_ColorScheme); @@ -400,6 +404,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation copy->_TabColor = _TabColor; copy->_ProfileIndex = _ProfileIndex; copy->_Profile = _Profile; + copy->_SessionId = _SessionId; copy->_SuppressApplicationTitle = _SuppressApplicationTitle; copy->_ColorScheme = _ColorScheme; copy->_Elevate = _Elevate; diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index 32f9005fdee..f8e6f4eb9cd 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -132,6 +132,7 @@ namespace Microsoft.Terminal.Settings.Model String TabTitle; Windows.Foundation.IReference TabColor; String Profile; // Either a GUID or a profile's name if the GUID isn't a match + Guid SessionId; Boolean AppendCommandLine; // We use IReference<> to treat some args as nullable where null means diff --git a/src/cascadia/TerminalSettingsModel/ApplicationState.cpp b/src/cascadia/TerminalSettingsModel/ApplicationState.cpp index 347a180b708..30b44a55b21 100644 --- a/src/cascadia/TerminalSettingsModel/ApplicationState.cpp +++ b/src/cascadia/TerminalSettingsModel/ApplicationState.cpp @@ -240,8 +240,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // Returns the application-global ApplicationState object. Microsoft::Terminal::Settings::Model::ApplicationState ApplicationState::SharedInstance() { - auto root{ GetBaseSettingsPath() }; - static auto state = winrt::make_self(root); + static auto state = winrt::make_self(GetBaseSettingsPath()); return *state; } @@ -294,6 +293,20 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation return root; } + void ApplicationState::AppendPersistedWindowLayout(Model::WindowLayout layout) + { + { + const auto state = _state.lock(); + if (!state->PersistedWindowLayouts || !*state->PersistedWindowLayouts) + { + state->PersistedWindowLayouts = winrt::single_threaded_vector(); + } + state->PersistedWindowLayouts->Append(std::move(layout)); + } + + _throttler(); + } + // Generate all getter/setters #define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \ type ApplicationState::name() const noexcept \ diff --git a/src/cascadia/TerminalSettingsModel/ApplicationState.h b/src/cascadia/TerminalSettingsModel/ApplicationState.h index bacffdba2f7..df7fd803e70 100644 --- a/src/cascadia/TerminalSettingsModel/ApplicationState.h +++ b/src/cascadia/TerminalSettingsModel/ApplicationState.h @@ -69,6 +69,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation void FromJson(const Json::Value& root, FileSource parseSource) const noexcept; Json::Value ToJson(FileSource parseSource) const noexcept; + void AppendPersistedWindowLayout(Model::WindowLayout layout); + // State getters/setters #define MTSM_APPLICATION_STATE_GEN(source, type, name, key, ...) \ type name() const noexcept; \ diff --git a/src/cascadia/TerminalSettingsModel/ApplicationState.idl b/src/cascadia/TerminalSettingsModel/ApplicationState.idl index e48c1e7f86b..e35447773a6 100644 --- a/src/cascadia/TerminalSettingsModel/ApplicationState.idl +++ b/src/cascadia/TerminalSettingsModel/ApplicationState.idl @@ -32,6 +32,8 @@ namespace Microsoft.Terminal.Settings.Model void Flush(); void Reset(); + void AppendPersistedWindowLayout(WindowLayout layout); + String SettingsHash; Windows.Foundation.Collections.IVector PersistedWindowLayouts; Windows.Foundation.Collections.IVector RecentCommands; diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h index 03f3ea071ec..03553c8b73d 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h @@ -106,6 +106,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static Model::CascadiaSettings LoadDefaults(); static Model::CascadiaSettings LoadAll(); + static winrt::hstring SettingsDirectory(); static winrt::hstring SettingsPath(); static winrt::hstring DefaultSettingsPath(); static winrt::hstring ApplicationDisplayName(); diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl index 1889871bb3e..165a7fed9fa 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl @@ -12,6 +12,7 @@ namespace Microsoft.Terminal.Settings.Model static CascadiaSettings LoadDefaults(); static CascadiaSettings LoadAll(); + static String SettingsDirectory { get; }; static String SettingsPath { get; }; static String DefaultSettingsPath { get; }; static Boolean IsPortableMode { get; }; diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp index 244c200dad8..93af43319bc 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp @@ -1244,6 +1244,13 @@ winrt::hstring CascadiaSettings::_calculateHash(std::string_view settings, const return winrt::hstring{ hash }; } +// This returns something akin to %LOCALAPPDATA%\Packages\WindowsTerminalDev_8wekyb3d8bbwe\LocalState +// just like SettingsPath(), but without the trailing \settings.json. +winrt::hstring CascadiaSettings::SettingsDirectory() +{ + return winrt::hstring{ GetBaseSettingsPath().native() }; +} + // function Description: // - Returns the full path to the settings file, either within the application // package, or in its unpackaged location. This path is under the "Local diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp index 6f1d2932699..29b9bb811fe 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp @@ -126,6 +126,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation if (newTerminalArgs) { + if (const auto id = newTerminalArgs.SessionId(); id != winrt::guid{}) + { + defaultSettings.SessionId(id); + } + // Override commandline, starting directory if they exist in newTerminalArgs if (!newTerminalArgs.Commandline().empty()) { diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.h b/src/cascadia/TerminalSettingsModel/TerminalSettings.h index d3410ba2628..57ec8659fd6 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.h @@ -118,6 +118,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileName); INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileSource); + INHERITABLE_SETTING(Model::TerminalSettings, guid, SessionId); INHERITABLE_SETTING(Model::TerminalSettings, bool, EnableUnfocusedAcrylic, false); INHERITABLE_SETTING(Model::TerminalSettings, bool, UseAcrylic, false); INHERITABLE_SETTING(Model::TerminalSettings, double, Opacity, UseAcrylic() ? 0.5 : 1.0); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.idl b/src/cascadia/TerminalSettingsModel/TerminalSettings.idl index 23c305ee4e0..32bf6111909 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.idl +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.idl @@ -41,6 +41,7 @@ namespace Microsoft.Terminal.Settings.Model // The getters for these are already defined in IControlSettings. So // we're just adding the setters here, because TerminalApp likes to be // able to change these at runtime (e.g. when duplicating a pane). + Guid SessionId { set; }; String Commandline { set; }; String StartingDirectory { set; }; diff --git a/src/cascadia/UnitTests_Remoting/RemotingTests.cpp b/src/cascadia/UnitTests_Remoting/RemotingTests.cpp index 8be39b44ca6..8fc12f493db 100644 --- a/src/cascadia/UnitTests_Remoting/RemotingTests.cpp +++ b/src/cascadia/UnitTests_Remoting/RemotingTests.cpp @@ -82,7 +82,6 @@ namespace RemotingUnitTests void Summon(const Remoting::SummonWindowBehavior& /*args*/) DIE; void RequestShowNotificationIcon() DIE; void RequestHideNotificationIcon() DIE; - winrt::hstring GetWindowLayout() DIE; void RequestQuitAll() DIE; void Quit() DIE; void AttachContentToWindow(Remoting::AttachRequest) DIE; @@ -97,7 +96,6 @@ namespace RemotingUnitTests til::typed_event<> HideNotificationIconRequested; til::typed_event<> QuitAllRequested; til::typed_event<> QuitRequested; - til::typed_event GetWindowLayoutRequested; til::typed_event AttachRequested; til::typed_event SendContentRequested; }; @@ -117,7 +115,6 @@ namespace RemotingUnitTests void SummonAllWindows() DIE; bool DoesQuakeWindowExist() DIE; winrt::Windows::Foundation::Collections::IVectorView GetPeasantInfos() DIE; - winrt::Windows::Foundation::Collections::IVector GetAllWindowLayouts() DIE; void RequestMoveContent(winrt::hstring, winrt::hstring, uint32_t, winrt::Windows::Foundation::IReference) DIE; void RequestSendContent(Remoting::RequestReceiveContentArgs) DIE; @@ -126,7 +123,6 @@ namespace RemotingUnitTests til::typed_event<> HideNotificationIconRequested; til::typed_event<> WindowCreated; til::typed_event<> WindowClosed; - til::typed_event QuitAllRequested; til::typed_event RequestNewWindow; }; diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 816e4cda6e4..0fe39c1cc56 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -215,49 +215,51 @@ void AppHost::_HandleSessionRestore(const bool startedForContent) // we'll leave it here. const auto numPeasants = _windowManager.GetNumberOfPeasants(); // Don't attempt to session restore if we're just making a window for tear-out - if (!startedForContent && numPeasants == 1) + if (startedForContent || numPeasants != 1 || !_appLogic.ShouldUsePersistedLayout()) { - const auto layouts = ApplicationState::SharedInstance().PersistedWindowLayouts(); - if (_appLogic.ShouldUsePersistedLayout() && - layouts && - layouts.Size() > 0) + return; + } + + const auto state = ApplicationState::SharedInstance(); + const auto layouts = state.PersistedWindowLayouts(); + + if (layouts && layouts.Size() > 0) + { + uint32_t startIdx = 0; + // We want to create a window for every saved layout. + // If we are the only window, and no commandline arguments were provided + // then we should just use the current window to load the first layout. + // Otherwise create this window normally with its commandline, and create + // a new window using the first saved layout information. + // The 2nd+ layout will always get a new window. + if (!_windowLogic.HasCommandlineArguments() && + !_appLogic.HasSettingsStartupActions()) { - uint32_t startIdx = 0; - // We want to create a window for every saved layout. - // If we are the only window, and no commandline arguments were provided - // then we should just use the current window to load the first layout. - // Otherwise create this window normally with its commandline, and create - // a new window using the first saved layout information. - // The 2nd+ layout will always get a new window. - if (!_windowLogic.HasCommandlineArguments() && - !_appLogic.HasSettingsStartupActions()) - { - _windowLogic.SetPersistedLayoutIdx(startIdx); - startIdx += 1; - } + _windowLogic.SetPersistedLayoutIdx(startIdx); + startIdx += 1; + } - // Create new windows for each of the other saved layouts. - for (const auto size = layouts.Size(); startIdx < size; startIdx += 1) - { - auto newWindowArgs = fmt::format(L"{0} -w new -s {1}", args.Commandline()[0], startIdx); - - STARTUPINFO si; - memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); - wil::unique_process_information pi; - - LOG_IF_WIN32_BOOL_FALSE(CreateProcessW(nullptr, - newWindowArgs.data(), - nullptr, // lpProcessAttributes - nullptr, // lpThreadAttributes - false, // bInheritHandles - DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT, // doCreationFlags - nullptr, // lpEnvironment - nullptr, // lpStartingDirectory - &si, // lpStartupInfo - &pi // lpProcessInformation - )); - } + // Create new windows for each of the other saved layouts. + for (const auto size = layouts.Size(); startIdx < size; startIdx += 1) + { + auto newWindowArgs = fmt::format(L"{0} -w new -s {1}", args.Commandline()[0], startIdx); + + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + wil::unique_process_information pi; + + LOG_IF_WIN32_BOOL_FALSE(CreateProcessW(nullptr, + newWindowArgs.data(), + nullptr, // lpProcessAttributes + nullptr, // lpThreadAttributes + false, // bInheritHandles + DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT, // doCreationFlags + nullptr, // lpEnvironment + nullptr, // lpStartingDirectory + &si, // lpStartupInfo + &pi // lpProcessInformation + )); } } } @@ -317,7 +319,7 @@ void AppHost::Initialize() // Register the 'X' button of the window for a warning experience of multiple // tabs opened, this is consistent with Alt+F4 closing _windowCallbacks.WindowCloseButtonClicked = _window->WindowCloseButtonClicked([this]() { - _CloseRequested(nullptr, nullptr); + _windowLogic.CloseWindow(); }); // If the user requests a close in another way handle the same as if the 'X' // was clicked. @@ -350,7 +352,7 @@ void AppHost::Initialize() _windowCallbacks.AutomaticShutdownRequested = _window->AutomaticShutdownRequested([this]() { // Raised when the OS is beginning an update of the app. We will quit, // to save our state, before the OS manually kills us. - Remoting::WindowManager::RequestQuitAll(_peasant); + _quit(); }); // Load bearing: make sure the PropertyChanged handler is added before we @@ -362,7 +364,7 @@ void AppHost::Initialize() _windowLogic.Create(); _revokers.TitleChanged = _windowLogic.TitleChanged(winrt::auto_revoke, { this, &AppHost::AppTitleChanged }); - _revokers.LastTabClosed = _windowLogic.LastTabClosed(winrt::auto_revoke, { this, &AppHost::LastTabClosed }); + _revokers.CloseWindowRequested = _windowLogic.CloseWindowRequested(winrt::auto_revoke, { this, &AppHost::_CloseRequested }); _revokers.SetTaskbarProgress = _windowLogic.SetTaskbarProgress(winrt::auto_revoke, { this, &AppHost::SetTaskbarProgress }); _revokers.IdentifyWindowsRequested = _windowLogic.IdentifyWindowsRequested(winrt::auto_revoke, { this, &AppHost::_IdentifyWindowsRequested }); _revokers.RenameWindowRequested = _windowLogic.RenameWindowRequested(winrt::auto_revoke, { this, &AppHost::_RenameWindowRequested }); @@ -382,22 +384,6 @@ void AppHost::Initialize() _revokers.RequestReceiveContent = _windowLogic.RequestReceiveContent(winrt::auto_revoke, { this, &AppHost::_handleReceiveContent }); _revokers.SendContentRequested = _peasant.SendContentRequested(winrt::auto_revoke, { this, &AppHost::_handleSendContent }); - // Add our GetWindowLayoutRequested handler AFTER the xaml island is - // started. Our _GetWindowLayoutAsync handler requires us to be able to work - // on our UI thread, which requires that we have a Dispatcher ready for us - // to move to. If we set up this callback in the ctor, then it is possible - // for there to be a time slice where - // * the monarch creates the peasant for us, - // * we get constructed (registering the callback) - // * then the monarch attempts to query all _peasants_ for their layout, - // coming back to ask us even before XAML has been created. - _GetWindowLayoutRequestedToken = _peasant.GetWindowLayoutRequested([this](auto&&, - const Remoting::GetWindowLayoutArgs& args) { - // The peasants are running on separate threads, so they'll need to - // swap what context they are in to the ui thread to get the actual layout. - args.WindowLayoutJsonAsync(_GetWindowLayoutAsync()); - }); - // BODGY // On certain builds of Windows, when Terminal is set as the default // it will accumulate an unbounded amount of queued animations while @@ -452,6 +438,16 @@ void AppHost::Close() } } +winrt::fire_and_forget AppHost::_quit() +{ + const auto peasant = _peasant; + + co_await winrt::resume_background(); + + ApplicationState::SharedInstance().PersistedWindowLayouts(nullptr); + peasant.RequestQuitAll(); +} + void AppHost::_revokeWindowCallbacks() { // You'll recall, IslandWindow isn't a WinRT type so it can't have auto-revokers. @@ -514,42 +510,6 @@ void AppHost::AppTitleChanged(const winrt::Windows::Foundation::IInspectable& /* _windowManager.UpdateActiveTabTitle(newTitle, _peasant); } -// Method Description: -// - Called when no tab is remaining to close the window. -// Arguments: -// - sender: unused -// - LastTabClosedEventArgs: unused -// Return Value: -// - -void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::TerminalApp::LastTabClosedEventArgs& args) -{ - // We don't want to try to save layouts if we are about to close. - _peasant.GetWindowLayoutRequested(_GetWindowLayoutRequestedToken); - - // If the user closes the last tab, in the last window, _by closing the tab_ - // (not by closing the whole window), we need to manually persist an empty - // window state here. That will cause the terminal to re-open with the usual - // settings (not the persisted state) - if (args.ClearPersistedState() && - _windowManager.GetNumberOfPeasants() == 1) - { - _windowLogic.ClearPersistedWindowState(); - } - // Remove ourself from the list of peasants so that we aren't included in - // any future requests. This will also mean we block until any existing - // event handler finishes. - _windowManager.SignalClose(_peasant); - - if (Utils::IsWindows11()) - { - PostQuitMessage(0); - } - else - { - PostMessageW(_window->GetInteropHandle(), WM_REFRIGERATE, 0, 0); - } -} - LaunchPosition AppHost::_GetWindowLaunchPosition() { LaunchPosition pos{}; @@ -952,42 +912,6 @@ winrt::fire_and_forget AppHost::_peasantNotifyActivateWindow() }); } -// Method Description: -// - Asynchronously get the window layout from the current page. This is -// done async because we need to switch between the ui thread and the calling -// thread. -// - NB: The peasant calling this must not be running on the UI thread, otherwise -// they will crash since they just call .get on the async operation. -// Arguments: -// - -// Return Value: -// - The window layout as a json string. -winrt::Windows::Foundation::IAsyncOperation AppHost::_GetWindowLayoutAsync() -{ - winrt::hstring layoutJson = L""; - - auto weakThis{ weak_from_this() }; - - // Use the main thread since we are accessing controls. - co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher()); - - const auto strongThis = weakThis.lock(); - // GH #16235: If we don't have a window logic, we're already refrigerating, and won't have our _window either. - if (!strongThis || _windowLogic == nullptr) - { - co_return layoutJson; - } - - try - { - const auto pos = _GetWindowLaunchPosition(); - layoutJson = _windowLogic.GetWindowLayoutJson(pos); - } - CATCH_LOG() - - co_return layoutJson; -} - void AppHost::_HandleSummon(const winrt::Windows::Foundation::IInspectable& /*sender*/, const Remoting::SummonWindowBehavior& args) { @@ -1264,13 +1188,14 @@ winrt::fire_and_forget AppHost::_QuitRequested(const winrt::Windows::Foundation: } _windowLogic.Quit(); + PostQuitMessage(0); } // Raised from TerminalWindow. We handle by bubbling the request to the window manager. void AppHost::_RequestQuitAll(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&) { - Remoting::WindowManager::RequestQuitAll(_peasant); + _quit(); } void AppHost::_ShowWindowChanged(const winrt::Windows::Foundation::IInspectable&, @@ -1370,9 +1295,25 @@ void AppHost::_WindowMoved() void AppHost::_CloseRequested(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/) { - const auto pos = _GetWindowLaunchPosition(); - const bool isLastWindow = _windowManager.GetNumberOfPeasants() == 1; - _windowLogic.CloseWindow(pos, isLastWindow); + if (_windowManager.GetNumberOfPeasants() <= 1) + { + _quit(); + return; + } + + // Remove ourself from the list of peasants so that we aren't included in + // any future requests. This will also mean we block until any existing + // event handler finishes. + _windowManager.SignalClose(_peasant); + + if (Utils::IsWindows11()) + { + PostQuitMessage(0); + } + else + { + PostMessageW(_window->GetInteropHandle(), WM_REFRIGERATE, 0, 0); + } } void AppHost::_PropertyChangedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/, diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 25cf599af74..a22fc85a948 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -20,7 +20,6 @@ class AppHost : public std::enable_shared_from_this std::unique_ptr window = nullptr) noexcept; void AppTitleChanged(const winrt::Windows::Foundation::IInspectable& sender, winrt::hstring newTitle); - void LastTabClosed(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::LastTabClosedEventArgs& args); void Initialize(); void Close(); @@ -64,8 +63,7 @@ class AppHost : public std::enable_shared_from_this uint32_t _launchShowWindowCommand{ SW_NORMAL }; - void _preInit(); - + winrt::fire_and_forget _quit(); void _revokeWindowCallbacks(); void _HandleCommandlineArgs(const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args); @@ -100,8 +98,6 @@ class AppHost : public std::enable_shared_from_this void _DispatchCommandline(winrt::Windows::Foundation::IInspectable sender, winrt::Microsoft::Terminal::Remoting::CommandlineArgs args); - winrt::Windows::Foundation::IAsyncOperation _GetWindowLayoutAsync(); - void _HandleSummon(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior& args); @@ -112,10 +108,6 @@ class AppHost : public std::enable_shared_from_this winrt::fire_and_forget _RenameWindowRequested(const winrt::Windows::Foundation::IInspectable sender, const winrt::TerminalApp::RenameWindowRequestedArgs args); - GUID _CurrentDesktopGuid(); - - bool _LazyLoadDesktopManager(); - void _HandleSettingsChanged(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::SettingsLoadEventArgs& args); @@ -168,8 +160,6 @@ class AppHost : public std::enable_shared_from_this void _stopFrameTimer(); void _updateFrameColor(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&); - winrt::event_token _GetWindowLayoutRequestedToken; - // Helper struct. By putting these all into one struct, we can revoke them // all at once, by assigning _revokers to a fresh Revokers instance. That'll // cause us to dtor the old one, which will immediately call revoke on all @@ -194,7 +184,7 @@ class AppHost : public std::enable_shared_from_this winrt::TerminalApp::TerminalWindow::SystemMenuChangeRequested_revoker SystemMenuChangeRequested; winrt::TerminalApp::TerminalWindow::ChangeMaximizeRequested_revoker ChangeMaximizeRequested; winrt::TerminalApp::TerminalWindow::TitleChanged_revoker TitleChanged; - winrt::TerminalApp::TerminalWindow::LastTabClosed_revoker LastTabClosed; + winrt::TerminalApp::TerminalWindow::CloseWindowRequested_revoker CloseWindowRequested; winrt::TerminalApp::TerminalWindow::SetTaskbarProgress_revoker SetTaskbarProgress; winrt::TerminalApp::TerminalWindow::IdentifyWindowsRequested_revoker IdentifyWindowsRequested; winrt::TerminalApp::TerminalWindow::RenameWindowRequested_revoker RenameWindowRequested; @@ -208,7 +198,6 @@ class AppHost : public std::enable_shared_from_this winrt::TerminalApp::TerminalWindow::PropertyChanged_revoker PropertyChanged; winrt::TerminalApp::TerminalWindow::SettingsChanged_revoker SettingsChanged; - winrt::Microsoft::Terminal::Remoting::WindowManager::QuitAllRequested_revoker QuitAllRequested; winrt::Microsoft::Terminal::Remoting::Peasant::SendContentRequested_revoker SendContentRequested; } _revokers{}; diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp index 36d49e2c09f..0fc28a20433 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp +++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp @@ -348,116 +348,17 @@ void WindowEmperor::_becomeMonarch() _revokers.WindowCreated = _manager.WindowCreated(winrt::auto_revoke, { this, &WindowEmperor::_numberOfWindowsChanged }); _revokers.WindowClosed = _manager.WindowClosed(winrt::auto_revoke, { this, &WindowEmperor::_numberOfWindowsChanged }); - - // If the monarch receives a QuitAll event it will signal this event to be - // ran before each peasant is closed. - _revokers.QuitAllRequested = _manager.QuitAllRequested(winrt::auto_revoke, { this, &WindowEmperor::_quitAllRequested }); - - // The monarch should be monitoring if it should save the window layout. - // We want at least some delay to prevent the first save from overwriting - _getWindowLayoutThrottler.emplace(std::chrono::seconds(10), [this]() { _saveWindowLayoutsRepeat(); }); - _getWindowLayoutThrottler.value()(); } // sender and args are always nullptr void WindowEmperor::_numberOfWindowsChanged(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&) { - if (_getWindowLayoutThrottler) - { - _getWindowLayoutThrottler.value()(); - } - // If we closed out the quake window, and don't otherwise need the tray // icon, let's get rid of it. _checkWindowsForNotificationIcon(); } -// Raised from our windowManager (on behalf of the monarch). We respond by -// giving the monarch an async function that the manager should wait on before -// completing the quit. -void WindowEmperor::_quitAllRequested(const winrt::Windows::Foundation::IInspectable&, - const winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs& args) -{ - _quitting = true; - - // Make sure that the current timer is destroyed so that it doesn't attempt - // to run while we are in the middle of quitting. - if (_getWindowLayoutThrottler.has_value()) - { - _getWindowLayoutThrottler.reset(); - } - - // Tell the monarch to wait for the window layouts to save before - // everyone quits. - args.BeforeQuitAllAction(_saveWindowLayouts()); -} - -#pragma region LayoutPersistence - -winrt::Windows::Foundation::IAsyncAction WindowEmperor::_saveWindowLayouts() -{ - // Make sure we run on a background thread to not block anything. - co_await winrt::resume_background(); - - if (_app.Logic().ShouldUsePersistedLayout()) - { - try - { - TraceLoggingWrite(g_hWindowsTerminalProvider, - "AppHost_SaveWindowLayouts_Collect", - TraceLoggingDescription("Logged when collecting window state"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - const auto layoutJsons = _manager.GetAllWindowLayouts(); - - TraceLoggingWrite(g_hWindowsTerminalProvider, - "AppHost_SaveWindowLayouts_Save", - TraceLoggingDescription("Logged when writing window state"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - _app.Logic().SaveWindowLayoutJsons(layoutJsons); - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - TraceLoggingWrite(g_hWindowsTerminalProvider, - "AppHost_SaveWindowLayouts_Failed", - TraceLoggingDescription("An error occurred when collecting or writing window state"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - } - - co_return; -} - -winrt::fire_and_forget WindowEmperor::_saveWindowLayoutsRepeat() -{ - // Make sure we run on a background thread to not block anything. - co_await winrt::resume_background(); - - co_await _saveWindowLayouts(); - - // Don't need to save too frequently. - co_await winrt::resume_after(30s); - - // As long as we are supposed to keep saving, request another save. - // This will be delayed by the throttler so that at most one save happens - // per 10 seconds, if a save is requested by another source simultaneously. - if (_getWindowLayoutThrottler.has_value()) - { - TraceLoggingWrite(g_hWindowsTerminalProvider, - "AppHost_requestGetLayout", - TraceLoggingDescription("Logged when triggering a throttled write of the window state"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - _getWindowLayoutThrottler.value()(); - } -} #pragma endregion #pragma region WindowProc @@ -584,6 +485,80 @@ void WindowEmperor::_finalizeSessionPersistence() const // Ensure to write the state.json before we TerminateProcess() state.Flush(); + + if (!_app.Logic().ShouldUsePersistedLayout()) + { + return; + } + + // Get the "buffer_{guid}.txt" files that we expect to be there + std::unordered_set sessionIds; + if (const auto layouts = state.PersistedWindowLayouts()) + { + for (const auto& windowLayout : layouts) + { + for (const auto& actionAndArgs : windowLayout.TabLayout()) + { + const auto args = actionAndArgs.Args(); + NewTerminalArgs terminalArgs{ nullptr }; + + if (const auto tabArgs = args.try_as()) + { + terminalArgs = tabArgs.TerminalArgs(); + } + else if (const auto paneArgs = args.try_as()) + { + terminalArgs = paneArgs.TerminalArgs(); + } + + if (terminalArgs) + { + sessionIds.emplace(terminalArgs.SessionId()); + } + } + } + } + + // Remove the "buffer_{guid}.txt" files that shouldn't be there + // e.g. "buffer_FD40D746-163E-444C-B9B2-6A3EA2B26722.txt" + { + const std::filesystem::path settingsDirectory{ std::wstring_view{ CascadiaSettings::SettingsDirectory() } }; + const auto filter = settingsDirectory / L"buffer_*"; + WIN32_FIND_DATAW ffd; + + // This could also use std::filesystem::directory_iterator. + // I was just slightly bothered by how it doesn't have a O(1) .filename() + // function, even though the underlying Win32 APIs provide it for free. + // Both work fine. + const wil::unique_hfind handle{ FindFirstFileExW(filter.c_str(), FindExInfoBasic, &ffd, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH) }; + if (!handle) + { + return; + } + + do + { + const auto nameLen = wcsnlen_s(&ffd.cFileName[0], ARRAYSIZE(ffd.cFileName)); + const std::wstring_view name{ &ffd.cFileName[0], nameLen }; + + if (nameLen != 47) + { + continue; + } + + wchar_t guidStr[39]; + guidStr[0] = L'{'; + memcpy(&guidStr[1], name.data() + 7, 36 * sizeof(wchar_t)); + guidStr[37] = L'}'; + guidStr[38] = L'\0'; + + const auto id = Utils::GuidFromString(&guidStr[0]); + if (!sessionIds.contains(id)) + { + std::filesystem::remove(settingsDirectory / name); + } + } while (FindNextFileW(handle.get(), &ffd)); + } } #pragma endregion diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.h b/src/cascadia/WindowsTerminal/WindowEmperor.h index 9f44a276c3c..a35032e6d5e 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.h +++ b/src/cascadia/WindowsTerminal/WindowEmperor.h @@ -44,8 +44,6 @@ class WindowEmperor : public std::enable_shared_from_this til::shared_mutex>> _oldThreads; - std::optional> _getWindowLayoutThrottler; - winrt::event_token _WindowCreatedToken; winrt::event_token _WindowClosedToken; @@ -61,15 +59,10 @@ class WindowEmperor : public std::enable_shared_from_this void _becomeMonarch(); void _numberOfWindowsChanged(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&); - void _quitAllRequested(const winrt::Windows::Foundation::IInspectable&, - const winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs&); winrt::fire_and_forget _windowIsQuakeWindowChanged(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::Foundation::IInspectable args); winrt::fire_and_forget _windowRequestUpdateSettings(); - winrt::Windows::Foundation::IAsyncAction _saveWindowLayouts(); - winrt::fire_and_forget _saveWindowLayoutsRepeat(); - void _createMessageWindow(); void _hotkeyPressed(const long hotkeyIndex); @@ -90,6 +83,5 @@ class WindowEmperor : public std::enable_shared_from_this { winrt::Microsoft::Terminal::Remoting::WindowManager::WindowCreated_revoker WindowCreated; winrt::Microsoft::Terminal::Remoting::WindowManager::WindowClosed_revoker WindowClosed; - winrt::Microsoft::Terminal::Remoting::WindowManager::QuitAllRequested_revoker QuitAllRequested; } _revokers{}; }; diff --git a/src/cascadia/inc/ControlProperties.h b/src/cascadia/inc/ControlProperties.h index a882cd8b0cf..0c4a50308d3 100644 --- a/src/cascadia/inc/ControlProperties.h +++ b/src/cascadia/inc/ControlProperties.h @@ -56,6 +56,7 @@ #define CONTROL_SETTINGS(X) \ X(winrt::hstring, ProfileName) \ X(winrt::hstring, ProfileSource) \ + X(winrt::guid, SessionId) \ X(bool, EnableUnfocusedAcrylic, false) \ X(winrt::hstring, Padding, DEFAULT_PADDING) \ X(winrt::hstring, FontFace, L"Consolas") \ diff --git a/src/inc/til/small_vector.h b/src/inc/til/small_vector.h index a88927e7159..f078d37fbe4 100644 --- a/src/inc/til/small_vector.h +++ b/src/inc/til/small_vector.h @@ -577,18 +577,26 @@ namespace til void resize(size_type new_size) { - _generic_resize(new_size, [](auto&& beg, auto&& end) { + _generic_resize(new_size, [](iterator&& beg, iterator&& end) { std::uninitialized_value_construct(beg, end); }); } void resize(size_type new_size, const_reference value) { - _generic_resize(new_size, [&](auto&& beg, auto&& end) { + _generic_resize(new_size, [&](iterator&& beg, iterator&& end) { std::uninitialized_fill(beg, end, value); }); } + void resize_and_overwrite(size_type new_size, auto op) + requires std::is_trivial_v + { + _size = 0; + reserve(new_size); + _size = std::move(op)(_data, new_size); + } + void shrink_to_fit() { if (_capacity == N || _size == _capacity) @@ -863,7 +871,7 @@ namespace til // An optimization for the most common vector type which is trivially constructible, destructible and copyable. // This allows us to drop exception handlers (= no need to push onto the stack) and replace two moves with just one. - if constexpr (noexcept(func(begin())) && std::is_trivially_destructible_v && std::is_trivially_copyable_v) + if constexpr (noexcept(func(begin())) && std::is_trivial_v) { _size = new_size; From 9f08ee7af9056dfcf244d8d1c4619a17558fd11d Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Fri, 29 Mar 2024 15:46:51 +0100 Subject: [PATCH 15/16] Buffer Restore: Fix turning off intense/faint (#16970) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This takes care of an edge case in regards to SGR 22: It turns off both intense and faint attributes which means that we may need to turn on one of the two if only one of them turned off. Additionally, this removes the mapping for `BottomGridline` which has no real VT equivalent anyway. ## Validation Steps Performed * Turn session restore on * In pwsh write: ```pwsh "`e[1;2mboth`e[0;1mintense`e[m`n`e[1;2mboth`e[0;2mfaint`e[m" ``` * Close the app and open the `buffer_*.txt` file next to settings.json * It contains... ✅ ``` ␛[1m␛[2mboth␛[22;1mintense␛[22m ␛[1m␛[2mboth␛[22;2mfaint␛[22m ``` --- src/buffer/out/textBuffer.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index 62371474adc..40cfc6b17ad 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -2557,7 +2557,32 @@ void TextBuffer::Serialize(const wchar_t* destination) const if (previousAttr != attr) { - const auto attrDelta = attr ^ previousAttr; + auto attrDelta = attr ^ previousAttr; + + // There's no escape sequence that only turns off either bold/intense or dim/faint. SGR 22 turns off both. + // This results in two issues in our generic "Mapping" code below. Assuming, both Intense and Faint were on... + // * ...and either turned off, it would emit SGR 22 which turns both attributes off = Wrong. + // * ...and both are now off, it would emit SGR 22 twice. + // + // This extra branch takes care of both issues. If both attributes turned off it'll emit a single \x1b[22m, + // if faint turned off \x1b[22;1m (intense is still on), and \x1b[22;2m if intense turned off (vice versa). + if (WI_AreAllFlagsSet(previousAttr, CharacterAttributes::Intense | CharacterAttributes::Faint) && + WI_IsAnyFlagSet(attrDelta, CharacterAttributes::Intense | CharacterAttributes::Faint)) + { + wchar_t buf[8] = L"\x1b[22m"; + size_t len = 5; + + if (WI_IsAnyFlagSet(attr, CharacterAttributes::Intense | CharacterAttributes::Faint)) + { + buf[4] = L';'; + buf[5] = WI_IsAnyFlagSet(attr, CharacterAttributes::Intense) ? L'1' : L'2'; + buf[6] = L'm'; + len = 7; + } + + buffer.append(&buf[0], len); + WI_ClearAllFlags(attrDelta, CharacterAttributes::Intense | CharacterAttributes::Faint); + } { struct Mapping @@ -2574,7 +2599,6 @@ void TextBuffer::Serialize(const wchar_t* destination) const { CharacterAttributes::Faint, { 22, 2 } }, { CharacterAttributes::TopGridline, { 55, 53 } }, { CharacterAttributes::ReverseVideo, { 27, 7 } }, - { CharacterAttributes::BottomGridline, { 24, 4 } }, }; for (const auto& mapping : mappings) { From 75dea24d6b656460f83369850fa69d1c9c7a0f8d Mon Sep 17 00:00:00 2001 From: Windows Console Service Bot <14666831+consvc@users.noreply.github.com> Date: Fri, 29 Mar 2024 09:47:11 -0500 Subject: [PATCH 16/16] Localization Updates - main - 03/29/2024 03:04:36 (#16967) --- .../Resources/es-ES/Resources.resw | 4 ++ .../Resources/de-DE/Resources.resw | 8 ---- .../Resources/es-ES/Resources.resw | 34 ++++++++++---- .../Resources/fr-FR/Resources.resw | 45 +++++++++++++++---- .../Resources/it-IT/Resources.resw | 34 ++++++++++---- .../Resources/ja-JP/Resources.resw | 8 ---- .../Resources/ko-KR/Resources.resw | 8 ---- .../Resources/pt-BR/Resources.resw | 8 ---- .../Resources/qps-ploc/Resources.resw | 6 +-- .../Resources/qps-ploca/Resources.resw | 6 +-- .../Resources/qps-plocm/Resources.resw | 6 +-- .../Resources/ru-RU/Resources.resw | 8 ---- .../Resources/zh-CN/Resources.resw | 34 ++++++++++---- .../Resources/zh-TW/Resources.resw | 8 ---- .../Resources/es-ES/Resources.resw | 3 ++ .../Resources/fr-FR/Resources.resw | 3 ++ .../Resources/it-IT/Resources.resw | 3 ++ .../Resources/zh-CN/Resources.resw | 3 ++ 18 files changed, 134 insertions(+), 95 deletions(-) diff --git a/src/cascadia/TerminalControl/Resources/es-ES/Resources.resw b/src/cascadia/TerminalControl/Resources/es-ES/Resources.resw index 30231e7f63e..7ecef8b9222 100644 --- a/src/cascadia/TerminalControl/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalControl/Resources/es-ES/Resources.resw @@ -213,6 +213,10 @@ Instale la fuente que falta o elija otra. El representador encontró un error inesperado: {0} {0} is an error code. + + No se pueden encontrar las siguientes fuentes: {0}. Instálelas o elija fuentes diferentes. + {Locked="{0}"} This is a warning dialog shown when the user selects a font that isn't installed. + El representador encontró un error inesperado: {0:#010x} {1} {Locked="{0:#010x}","{1}"} {0:#010x} is a placeholder for a Windows error code (e.g. 0x88985002). {1} is the corresponding message. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw index 9214556f77b..96d50e58db8 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/de-DE/Resources.resw @@ -989,10 +989,6 @@ Dieses Profil als Administrator ausführen Header for a control to toggle whether the profile should always open elevated (in an admin window) - - Wenn diese Option aktiviert ist, wird das Profil automatisch als Administrator in einem Terminalfenster geöffnet. Wenn das aktuelle Fenster bereits als Administrator ausgeführt wird, wird es in diesem Fenster geöffnet. - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - Größe des Verlaufs Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1225,10 +1221,6 @@ Wenn diese Option aktiviert ist, generiert das Terminal beim Erstellen neuer Registerkarten oder Bereiche mit diesem Profil einen neuen Umgebungsblock. Wenn diese Option deaktiviert ist, erbt die Registerkarte/der Bereich stattdessen die Variablen, mit denen das Terminal gestartet wurde. A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Experimentellen Passthrough für virtuelles Terminal aktivieren - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Menü bei Rechtsklick anzeigen This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw index e4574ab1f35..db4abb81b4f 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw @@ -309,6 +309,10 @@ Aplicación de terminal que se inicia cuando se ejecuta una aplicación de línea de comandos sin una sesión existente, como en el menú Inicio o en el cuadro de diálogo Ejecutar. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + API de gráficos + This text is shown next to a list of choices. + Direct3D 11 proporciona una experiencia con más rendimiento y características, mientras que Direct2D es más estable. La opción predeterminada "Automático" seleccionará la API que mejor se adapte a su hardware gráfico. Si experimenta problemas importantes, considere la posibilidad de usar Direct2D. @@ -316,10 +320,24 @@ Automático The default choice between multiple graphics APIs. + + Direct2D + + + Direct3D 11 + + + Deshabilitar la invalidación parcial de la cadena de intercambio + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + De forma predeterminada, el representador de texto usa una cadena de intercambio de FLIP_SEQUENTIAL y declara rectángulos modificados a través de la API de Present1. Cuando esta configuración está habilitada, se usará una cadena de intercambio de FLIP_DISCARD y no se declarará ningún rectángulo con modificaciones. Si uno u otro es mejor depende de su hardware y de otros factores. {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + Uso de la representación de software (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + Cuando está habilitado, el terminal usará un rasterizador de software (WARP). Esta configuración debe dejarse deshabilitada en casi todas las circunstancias. {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". @@ -971,10 +989,6 @@ Ejecutar este perfil como Administrador Header for a control to toggle whether the profile should always open elevated (in an admin window) - - Si se habilita, el perfil se abrirá automáticamente en una ventana de terminal de administración. Si la ventana actual ya se está ejecutando como administrador, se abrirá en esta ventana. - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - Tamaño del historial Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1207,10 +1221,6 @@ Cuando está habilitado, el terminal generará un nuevo bloque de entorno al crear nuevas pestañas o paneles con este perfil. Cuando se deshabilita, la pestaña o el panel heredarán las variables con las que se inició el terminal. A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Habilitar paso a través de terminal virtual experimental - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Mostrar un menú al hacer clic con el botón derecho This controls how a right-click behaves in the terminal @@ -1786,4 +1796,12 @@ Más información. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + Fuentes que faltan: + This is a label that is followed by a list of missing fonts. + + + Fuentes no monoespaciadas: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw index 2f56f3ebd4c..f14f47e5848 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/fr-FR/Resources.resw @@ -309,10 +309,39 @@ L’application Terminal qui se lance lorsqu’une application de ligne de commande est exécutée sans session existante, par exemple à partir du menu Démarrer ou de la boîte de dialogue Exécuter. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + Graphics API + This text is shown next to a list of choices. + + + Direct3D 11 offre une expérience plus performante et riche en fonctionnalités, tandis que Direct2D est plus stable. L’option par défaut « Automatique » sélectionne l’API qui correspond le mieux à votre matériel graphique. Si vous rencontrez des problèmes importants, envisagez d’utiliser Direct2D. + Automatique The default choice between multiple graphics APIs. + + Direct2D + + + Direct3D 11 + + + Désactiver l’invalidation partielle de la chaîne d’échange + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + + + Par défaut, le moteur de rendu de texte utilise une chaîne de permutation FLIP_SEQUENTIAL et déclare les rectangles sales via l’API Present1. Lorsque ce paramètre est activé, une chaîne d’échange FLIP_DISCARD est utilisée à la place, et aucun rectangle sale n’est déclaré. La supériorité de l’un ou de l’autre dépend de votre matériel et de divers autres facteurs. + {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + + Utiliser le rendu logiciel (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + + + Lorsque cette option est activée, le terminal utilise un logiciel de tramage (WARP). Ce paramètre doit être désactivé dans presque toutes les circonstances. + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". + Colonnes Header for a control to choose the number of columns in the terminal's text grid. @@ -960,10 +989,6 @@ Exécuter ce profil en tant qu’administrateur Header for a control to toggle whether the profile should always open elevated (in an admin window) - - Si l’option est activée, le profil s’ouvre automatiquement dans une fenêtre de terminal d’administration. Si la fenêtre active est déjà en cours d’exécution en tant qu’administrateur, elle s’ouvre dans cette fenêtre. - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - Taille de l’historique Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1196,10 +1221,6 @@ Lorsqu’il est activé, le terminal génère un nouveau bloc d’environnement lors de la création de nouveaux onglets ou volets avec ce profil. Lorsqu’il est désactivé, l’onglet/volet hérite à la place des variables avec laquelle le terminal a été démarré. A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Activer le relais de terminal virtuel expérimental - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Afficher un menu en cliquant avec le bouton droit This controls how a right-click behaves in the terminal @@ -1775,4 +1796,12 @@ En savoir plus. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + Polices manquantes : + This is a label that is followed by a list of missing fonts. + + + Polices non monospaciales : + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw index 3d0fb72f844..5bb075b01f9 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw @@ -309,6 +309,10 @@ L'applicazione terminale che viene avviata quando viene eseguita un'applicazione della riga di comando senza una sessione esistente, ad esempio dalla finestra di dialogo menu Start o Esegui. A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + API grafica + This text is shown next to a list of choices. + Direct3D 11 offre un'esperienza più performante e con funzionalità più elevate, mentre Direct2D è più stabile. L'opzione predefinita "Automatico" sceglierà l'API più adatta all'hardware grafico. Se si verificano problemi significativi, provare a usare Direct2D. @@ -316,10 +320,24 @@ Automatico The default choice between multiple graphics APIs. + + Direct2D + + + Direct3D 11 + + + Disabilitare invalidazione catena di scambio parziale + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + Per impostazione predefinita, il renderer di testo usa una catena di scambio FLIP_SEQUENTIAL e dichiara rettangoli modificati ma non modificati tramite l'API Present1. Quando questa impostazione è abilitata, verrà utilizzata una catena di scambio FLIP_DISCARD e non verranno dichiarati rettangoli modificati ma non modificati. Il miglioramento dell'uno o dell'altro dipende dall'hardware e da vari altri fattori. {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + Usare il rendering software (WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + Se questa opzione è abilitata, il terminale userà un rasterizzatore software (WARP). Questa impostazione deve essere lasciata disabilitata in quasi tutte le circostanze. {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". @@ -971,10 +989,6 @@ Esegui questo profilo come amministratore Header for a control to toggle whether the profile should always open elevated (in an admin window) - - Se questa opzione è abilitata, il profilo verrà aperto automaticamente in una finestra del terminale di amministrazione. Se la finestra corrente è già in esecuzione come amministratore, verrà aperta in questa finestra. - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - Dimensioni cronologia Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1207,10 +1221,6 @@ Se abilitato, il Terminale genera un nuovo blocco ambiente quando crea nuove schede o riquadri con questo profilo. Se disattivato, la scheda/riquadro erediterà le variabili con cui è stato avviato il Terminale. A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Abilitare il pass-through sperimentale del terminale virtuale - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Visualizzare un menu al clic con il pulsante destro del mouse This controls how a right-click behaves in the terminal @@ -1786,4 +1796,12 @@ Scopri di più. A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + Tipi di carattere mancanti: + This is a label that is followed by a list of missing fonts. + + + Caratteri senza spaziatura fissa: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw index 6cd0a869dd7..e9f4b3eb2f2 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw @@ -989,10 +989,6 @@ このプロファイルを管理者として実行する Header for a control to toggle whether the profile should always open elevated (in an admin window) - - 有効にすると、プロファイルは管理者ターミナル ウィンドウで自動的に開きます。現在のウィンドウが既に管理者として実行されている場合は、このウィンドウで開きます。 - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - 履歴のサイズ Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1225,10 +1221,6 @@ 有効にすると、ターミナルは、このプロファイルで新しいタブまたはウィンドウを作成するときに新しい環境ブロックを生成します。無効にすると、代わりにタブ/ペインはターミナルが開始された変数を継承します。 A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - 試験的な仮想ターミナル パススルーを有効にする - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - 右クリックでメニューを表示する This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw index 40e83f7dfc4..7e4a769c59b 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw @@ -989,10 +989,6 @@ 이 프로필을 관리자 권한으로 실행 Header for a control to toggle whether the profile should always open elevated (in an admin window) - - 사용하도록 설정하면 프로필이 관리 터미널 창에서 자동으로 열립니다. 현재 창이 관리자 권한으로 이미 실행되고 있는 경우 이 창에서 열립니다. - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - 기록 크기 Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1225,10 +1221,6 @@ 사용하도록 설정하면 이 프로필을 사용하여 새 탭이나 창을 만들 때 터미널이 새 환경 블록을 생성합니다. 사용하지 않도록 설정하면 탭이나 창이 터미널이 시작된 변수를 상속합니다. A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - 실험적 가상 터미널 통과 사용 - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - 마우스 오른쪽 단추를 클릭할 때 메뉴 표시 This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw index 1121be023e6..8352f42f0da 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw @@ -989,10 +989,6 @@ Executar esse perfil como Administrador Header for a control to toggle whether the profile should always open elevated (in an admin window) - - Se habilitado, o perfil será aberto automaticamente em uma janela do terminal admin. Se a janela atual já estiver em execução como administrador, ela será aberta nesta janela. - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - Tamanho de histórico Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1225,10 +1221,6 @@ Quando habilitado, o Terminal gerará um novo bloco de ambiente ao criar novas guias ou painéis com esse perfil. Quando desabilitado, a guia/painel herdará as variáveis com as quais o Terminal foi iniciado. A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Habilitar passagem de terminal virtual experimental - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Exibir um menu ao clicar com o botão direito do mouse This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw index 98bd519ebb1..4d9d01dacaf 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploc/Resources.resw @@ -990,7 +990,7 @@ Header for a control to toggle whether the profile should always open elevated (in an admin window) - ̃ éņãвļзδ, ŧĥĕ рŗоƒīľё ẅιľł óрėŋ ΐή åň Ąďmįŋ теѓmίидŀ шïпδσώ аůţòмăтìсаļļγ. Ĭƒ ŧĥе čцѓґ℮ⁿť ẁįлđόŵ їŝ áŀřėãďу ŕύŋņïπġ āš αðмīʼn, ϊţ'ŀℓ σрèń ĩй тħїŝ ẅīйδõẁ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + ̃ éņãвļзδ, ŧĥĕ рŗоƒīľё ẅιľł óрėŋ ΐή åň Ąďmįŋ теѓmίидŀ шïпδσώ аůţòмăтìсаļļγ. Ĭƒ ŧĥе čцѓґ℮ⁿť ẁįлđόŵ їŝ áŀřėãďу ŕύŋņïπġ āš αðмīʼn, ϊţ ẁїłℓ òρĕй іп тħΐş ωϊⁿđоẁ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description for what the "elevate" setting does. Presented near "Profile_Elevate". @@ -1225,10 +1225,6 @@ Ẁћέл εņаьŀèď, τħё Ŧëгmĩňªľ ẅīŀℓ ğεлěяαте å ʼnэщ еńνîřόńмęñт ьŀøĉĸ ŵħ℮л čґēãťîņğ ʼnεώ τâвѕ όя рªлёѕ щĭτћ тĥĭѕ ρŗòƒΐℓė. Ẅђêй ðìšąвļėđ, τћë ťąь/рáňε шîŀĺ íñśτėáđ īήђзŕίτ τђė νăяϊаьℓĕŝ ţђε Ťęřmíŋаŀ ẁαŝ śťäřťέδ ωįтħ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Зńăьℓē эхφзґímėпτªŀ νіѓтűǻļ τ℮ґмϊñāļ φаśşтнґöúģн !!! !!! !!! !!! !! - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Ðįşφłąÿ ǻ мèηΰ όή řïĝĥť-ćľїçķ !!! !!! !!! This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw index 98bd519ebb1..4d9d01dacaf 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-ploca/Resources.resw @@ -990,7 +990,7 @@ Header for a control to toggle whether the profile should always open elevated (in an admin window) - ̃ éņãвļзδ, ŧĥĕ рŗоƒīľё ẅιľł óрėŋ ΐή åň Ąďmįŋ теѓmίидŀ шïпδσώ аůţòмăтìсаļļγ. Ĭƒ ŧĥе čцѓґ℮ⁿť ẁįлđόŵ їŝ áŀřėãďу ŕύŋņïπġ āš αðмīʼn, ϊţ'ŀℓ σрèń ĩй тħїŝ ẅīйδõẁ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + ̃ éņãвļзδ, ŧĥĕ рŗоƒīľё ẅιľł óрėŋ ΐή åň Ąďmįŋ теѓmίидŀ шïпδσώ аůţòмăтìсаļļγ. Ĭƒ ŧĥе čцѓґ℮ⁿť ẁįлđόŵ їŝ áŀřėãďу ŕύŋņïπġ āš αðмīʼn, ϊţ ẁїłℓ òρĕй іп тħΐş ωϊⁿđоẁ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description for what the "elevate" setting does. Presented near "Profile_Elevate". @@ -1225,10 +1225,6 @@ Ẁћέл εņаьŀèď, τħё Ŧëгmĩňªľ ẅīŀℓ ğεлěяαте å ʼnэщ еńνîřόńмęñт ьŀøĉĸ ŵħ℮л čґēãťîņğ ʼnεώ τâвѕ όя рªлёѕ щĭτћ тĥĭѕ ρŗòƒΐℓė. Ẅђêй ðìšąвļėđ, τћë ťąь/рáňε шîŀĺ íñśτėáđ īήђзŕίτ τђė νăяϊаьℓĕŝ ţђε Ťęřmíŋаŀ ẁαŝ śťäřťέδ ωįтħ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Зńăьℓē эхφзґímėпτªŀ νіѓтűǻļ τ℮ґмϊñāļ φаśşтнґöúģн !!! !!! !!! !!! !! - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Ðįşφłąÿ ǻ мèηΰ όή řïĝĥť-ćľїçķ !!! !!! !!! This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw index 98bd519ebb1..4d9d01dacaf 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/qps-plocm/Resources.resw @@ -990,7 +990,7 @@ Header for a control to toggle whether the profile should always open elevated (in an admin window) - ̃ éņãвļзδ, ŧĥĕ рŗоƒīľё ẅιľł óрėŋ ΐή åň Ąďmįŋ теѓmίидŀ шïпδσώ аůţòмăтìсаļļγ. Ĭƒ ŧĥе čцѓґ℮ⁿť ẁįлđόŵ їŝ áŀřėãďу ŕύŋņïπġ āš αðмīʼn, ϊţ'ŀℓ σрèń ĩй тħїŝ ẅīйδõẁ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! + ̃ éņãвļзδ, ŧĥĕ рŗоƒīľё ẅιľł óрėŋ ΐή åň Ąďmįŋ теѓmίидŀ шïпδσώ аůţòмăтìсаļļγ. Ĭƒ ŧĥе čцѓґ℮ⁿť ẁįлđόŵ їŝ áŀřėãďу ŕύŋņïπġ āš αðмīʼn, ϊţ ẁїłℓ òρĕй іп тħΐş ωϊⁿđоẁ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! ! A description for what the "elevate" setting does. Presented near "Profile_Elevate". @@ -1225,10 +1225,6 @@ Ẁћέл εņаьŀèď, τħё Ŧëгmĩňªľ ẅīŀℓ ğεлěяαте å ʼnэщ еńνîřόńмęñт ьŀøĉĸ ŵħ℮л čґēãťîņğ ʼnεώ τâвѕ όя рªлёѕ щĭτћ тĥĭѕ ρŗòƒΐℓė. Ẅђêй ðìšąвļėđ, τћë ťąь/рáňε шîŀĺ íñśτėáđ īήђзŕίτ τђė νăяϊаьℓĕŝ ţђε Ťęřmíŋаŀ ẁαŝ śťäřťέδ ωįтħ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Зńăьℓē эхφзґímėпτªŀ νіѓтűǻļ τ℮ґмϊñāļ φаśşтнґöúģн !!! !!! !!! !!! !! - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Ðįşφłąÿ ǻ мèηΰ όή řïĝĥť-ćľїçķ !!! !!! !!! This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw index 913ae9ee97f..5d8bb846c6e 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ru-RU/Resources.resw @@ -989,10 +989,6 @@ Запустить этот профиль от имени администратора Header for a control to toggle whether the profile should always open elevated (in an admin window) - - Если этот параметр включен, профиль будет автоматически открываться в окне терминала администратора. Если текущее окно уже запущено от имени администратора, он откроется в этом окне. - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - Размер журнала Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1225,10 +1221,6 @@ Если этот параметр включен, Терминал будет создавать новый блок среды при создании новых вкладок или панелей с этим профилем. Если этот параметр отключен, вкладка или панель будет наследовать переменные, с которыми запущен Терминал. A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - Включить экспериментальную сквозную проверку на виртуальном терминале - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - Отображать меню при щелчке правой кнопкой мыши This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw index 91c54379777..7dcaa741b32 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-CN/Resources.resw @@ -309,6 +309,10 @@ 当命令行应用程序在没有现有会话(例如从“开始菜单”或“运行”对话框)运行时启动的终端应用程序。 A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + + 图形 API + This text is shown next to a list of choices. + Direct3D 11 提供性能更佳且功能更丰富的体验,而 Direct2D 则更稳定。默认选项“自动”将选择最适合你的图形硬件的 API。如果遇到严重问题,请考虑使用 Direct2D。 @@ -316,10 +320,24 @@ 自动 The default choice between multiple graphics APIs. + + Direct2D + + + Direct3D 11 + + + 禁用部分交换链失效 + "Swap Chain" is an official technical term by Microsoft. This text is shown next to a toggle. + 默认情况下,文本呈现器使用 FLIP_SEQUENTIAL 交换链并通过 Present1 API 声明脏矩形。启用此设置时,将改用 FLIP_DISCARD 交换链,并且不会声明脏矩形。一个或另一个是否更依赖于你的硬件和各种其他因素。 {Locked="Present1","FLIP_DISCARD","FLIP_SEQUENTIAL"} + + 使用软件渲染(WARP) + {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". This text is shown next to a toggle. + 启用后,终端将使用软件光栅 (WARP)。几乎在所有情况下都应禁用此设置。 {Locked="WARP"} WARP is the "Windows Advanced Rasterization Platform". @@ -971,10 +989,6 @@ 以管理员身份运行此配置文件 Header for a control to toggle whether the profile should always open elevated (in an admin window) - - 如果启用,配置文件将在管理终端窗口中自动打开。如果当前窗口已以管理员身份运行,它将在此窗口中打开。 - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - 历史记录大小 Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1207,10 +1221,6 @@ 启用后,使用此配置文件创建新选项卡或窗格时,终端将生成新的环境块。禁用后,选项卡/窗格将改为继承终端启动时所用的变量。 A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - 启用实验性虚拟终端传递 - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - 右键单击时显示菜单 This controls how a right-click behaves in the terminal @@ -1786,4 +1796,12 @@ 了解详细信息。 A hyperlink displayed near Settings_PortableModeNote.Text that the user can follow for more information. + + 缺少字体: + This is a label that is followed by a list of missing fonts. + + + 非等宽字体: + This is a label that is followed by a list of proportional fonts. + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw index 0e1d7c5e3ea..2f1cf24cb98 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/zh-TW/Resources.resw @@ -989,10 +989,6 @@ 以系統管理員身分執行此設定檔 Header for a control to toggle whether the profile should always open elevated (in an admin window) - - 如果啟用,設定檔將會自動在管理終端機視窗中開啟。如果目前的視窗已以系統管理員身分執行,則會在此視窗中開啟。 - A description for what the "elevate" setting does. Presented near "Profile_Elevate". - 歷史大小 Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session. @@ -1225,10 +1221,6 @@ 啟用時,終端機將在使用此設定檔建立新索引標籤或窗格時產生新的環境區塊。停用時,索引標籤/窗格將改為繼承終端機啟動時的變數。 A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". - - 啟用實驗性虛擬終端機通道 - An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY - 在以滑鼠右鍵按一下時顯示選單 This controls how a right-click behaves in the terminal diff --git a/src/cascadia/TerminalSettingsModel/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/es-ES/Resources.resw index 880bdde2e28..9d9ef4b93f1 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/es-ES/Resources.resw @@ -700,6 +700,9 @@ Reiniciar conexión + + Abrir el bloc de notas + Seleccionar salida del comando siguiente diff --git a/src/cascadia/TerminalSettingsModel/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/fr-FR/Resources.resw index 154e29f719d..ce62381140b 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/fr-FR/Resources.resw @@ -700,6 +700,9 @@ Redémarrer la connexion + + Ouvrir le bloc-notes + Sélectionner la sortie de commande suivante diff --git a/src/cascadia/TerminalSettingsModel/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/it-IT/Resources.resw index f0e738bb827..48ba557745d 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/it-IT/Resources.resw @@ -700,6 +700,9 @@ Riavvia connessione + + Aprire scratchpad + Seleziona l'output del comando successivo diff --git a/src/cascadia/TerminalSettingsModel/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/zh-CN/Resources.resw index b80c73e66ab..24746d831a9 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/zh-CN/Resources.resw @@ -700,6 +700,9 @@ 重新启动连接 + + 打开便笺本 + 选择下一个命令输出