diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index e68810d192f..df1e15164aa 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1120,7 +1120,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation co_return; } - const auto hr = args.Result(); + // HRESULT is a signed 32-bit integer which would result in a hex output like "-0x7766FFF4", + // but canonically HRESULTs are displayed unsigned as "0x8899000C". See GH#11556. + const auto hr = std::bit_cast(args.Result()); const auto parameter = args.Parameter(); winrt::hstring message; diff --git a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw index 06ef4c0b3c2..61ef4151625 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/es-ES/Resources.resw @@ -733,10 +733,16 @@ Examinar... Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window. + + Agregar nuevo eje de fuente + Agregar nuevo Button label that adds a new font axis for the current font. + + Agregar nueva característica de fuente + Agregar nuevo Button label that adds a new font feature for the current font. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw index 6cbfe190b22..1b2550d1d61 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/it-IT/Resources.resw @@ -733,10 +733,16 @@ Sfoglia... Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window. + + Aggiungi nuovo asse dei tipi di carattere + Aggiungi nuovo Button label that adds a new font axis for the current font. + + Aggiungi nuova funzionalità dei tipi di carattere + Aggiungi nuovo Button label that adds a new font feature for the current font. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw index 70e4da642b0..3ba41206daa 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ja-JP/Resources.resw @@ -733,10 +733,16 @@ 参照... Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window. + + 新しいフォント軸の追加 + 新規追加 Button label that adds a new font axis for the current font. + + 新しいフォント機能の追加 + 新規追加 Button label that adds a new font feature for the current font. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw index 04bf3054043..4e022bd43b8 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/ko-KR/Resources.resw @@ -733,10 +733,16 @@ 찾아보기... Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window. + + 새 글꼴 추가 축 + 새로 추가 Button label that adds a new font axis for the current font. + + 새 글꼴 추가 기능 + 새로 추가 Button label that adds a new font feature for the current font. diff --git a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw index 09611a80f06..8ac46dede93 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/pt-BR/Resources.resw @@ -733,10 +733,16 @@ Procurar... Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window. + + Adicionar novo eixo de fonte + Adicionar novo Button label that adds a new font axis for the current font. + + Adicionar novo recurso de fonte + Adicionar novo Button label that adds a new font feature for the current font. diff --git a/src/renderer/atlas/AtlasEngine.r.cpp b/src/renderer/atlas/AtlasEngine.r.cpp index f0a448d491b..a0dbdcc5470 100644 --- a/src/renderer/atlas/AtlasEngine.r.cpp +++ b/src/renderer/atlas/AtlasEngine.r.cpp @@ -55,7 +55,7 @@ catch (const wil::ResultException& exception) { const auto hr = exception.GetErrorCode(); - if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET || hr == D2DERR_RECREATE_TARGET) { _p.dxgi = {}; return E_PENDING; diff --git a/src/renderer/atlas/BackendD2D.cpp b/src/renderer/atlas/BackendD2D.cpp index 4310bed3f89..d0909de361f 100644 --- a/src/renderer/atlas/BackendD2D.cpp +++ b/src/renderer/atlas/BackendD2D.cpp @@ -148,11 +148,11 @@ void BackendD2D::_handleSettingsUpdate(const RenderingPayload& p) _viewportCellCount = p.s->viewportCellCount; } -void BackendD2D::_drawBackground(const RenderingPayload& p) noexcept +void BackendD2D::_drawBackground(const RenderingPayload& p) { if (_backgroundBitmapGeneration != p.colorBitmapGenerations[0]) { - _backgroundBitmap->CopyFromMemory(nullptr, p.backgroundBitmap.data(), gsl::narrow_cast(p.colorBitmapRowStride * sizeof(u32))); + THROW_IF_FAILED(_backgroundBitmap->CopyFromMemory(nullptr, p.backgroundBitmap.data(), gsl::narrow_cast(p.colorBitmapRowStride * sizeof(u32)))); _backgroundBitmapGeneration = p.colorBitmapGenerations[0]; } @@ -356,7 +356,7 @@ f32r BackendD2D::_getGlyphRunDesignBounds(const DWRITE_GLYPH_RUN& glyphRun, f32 _glyphMetrics = Buffer{ size }; } - glyphRun.fontFace->GetDesignGlyphMetrics(glyphRun.glyphIndices, glyphRun.glyphCount, _glyphMetrics.data(), false); + THROW_IF_FAILED(glyphRun.fontFace->GetDesignGlyphMetrics(glyphRun.glyphIndices, glyphRun.glyphCount, _glyphMetrics.data(), false)); const f32 fontScale = glyphRun.fontEmSize / fontMetrics.designUnitsPerEm; f32r accumulatedBounds{ @@ -541,7 +541,8 @@ void BackendD2D::_resizeCursorBitmap(const RenderingPayload& p, const til::size const D2D1_SIZE_F sizeF{ static_cast(newSizeInPx.width), static_cast(newSizeInPx.height) }; const D2D1_SIZE_U sizeU{ gsl::narrow_cast(newSizeInPx.width), gsl::narrow_cast(newSizeInPx.height) }; wil::com_ptr cursorRenderTarget; - _renderTarget->CreateCompatibleRenderTarget(&sizeF, &sizeU, nullptr, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, cursorRenderTarget.addressof()); + THROW_IF_FAILED(_renderTarget->CreateCompatibleRenderTarget(&sizeF, &sizeU, nullptr, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, cursorRenderTarget.addressof())); + cursorRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); cursorRenderTarget->BeginDraw(); @@ -553,7 +554,7 @@ void BackendD2D::_resizeCursorBitmap(const RenderingPayload& p, const til::size } THROW_IF_FAILED(cursorRenderTarget->EndDraw()); - cursorRenderTarget->GetBitmap(_cursorBitmap.put()); + THROW_IF_FAILED(cursorRenderTarget->GetBitmap(_cursorBitmap.put())); _cursorBitmapSize = newSize; } diff --git a/src/renderer/atlas/BackendD2D.h b/src/renderer/atlas/BackendD2D.h index 3bc40bb22cd..e6993d60603 100644 --- a/src/renderer/atlas/BackendD2D.h +++ b/src/renderer/atlas/BackendD2D.h @@ -17,7 +17,7 @@ namespace Microsoft::Console::Render::Atlas private: ATLAS_ATTR_COLD void _handleSettingsUpdate(const RenderingPayload& p); - void _drawBackground(const RenderingPayload& p) noexcept; + void _drawBackground(const RenderingPayload& p); void _drawText(RenderingPayload& p); ATLAS_ATTR_COLD f32 _drawTextPrepareLineRendition(const RenderingPayload& p, const ShapedRow* row, f32 baselineY) const noexcept; ATLAS_ATTR_COLD void _drawTextResetLineRendition(const ShapedRow* row) const noexcept; diff --git a/src/renderer/vt/XtermEngine.cpp b/src/renderer/vt/XtermEngine.cpp index 75fc3510fa6..9c489aa29cc 100644 --- a/src/renderer/vt/XtermEngine.cpp +++ b/src/renderer/vt/XtermEngine.cpp @@ -37,7 +37,16 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe, // the pipe. [[nodiscard]] HRESULT XtermEngine::StartPaint() noexcept { - RETURN_IF_FAILED(VtEngine::StartPaint()); + const auto hr = VtEngine::StartPaint(); + if (hr != S_OK) + { + // If _noFlushOnEnd was set, and we didn't return early, it would usually + // have been reset in the EndPaint call. But since that's not going to + // happen now, we need to reset it here, otherwise we may mistakenly skip + // the flush on the next frame. + _noFlushOnEnd = false; + return hr; + } _trace.TraceLastText(_lastText); @@ -83,15 +92,6 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe, } } - if (!_quickReturn) - { - if (_WillWriteSingleChar()) - { - // Don't re-enable the cursor. - _quickReturn = true; - } - } - return S_OK; } @@ -520,9 +520,10 @@ CATCH_RETURN(); // proper utf-8 string, depending on our mode. // Arguments: // - wstr - wstring of text to be written +// - flush - set to true if the string should be flushed immediately // Return Value: // - S_OK or suitable HRESULT error from either conversion or writing pipe. -[[nodiscard]] HRESULT XtermEngine::WriteTerminalW(const std::wstring_view wstr) noexcept +[[nodiscard]] HRESULT XtermEngine::WriteTerminalW(const std::wstring_view wstr, const bool flush) noexcept { RETURN_IF_FAILED(_fUseAsciiOnly ? VtEngine::_WriteTerminalAscii(wstr) : @@ -535,8 +536,11 @@ CATCH_RETURN(); // cause flickering (where we've buffered some state but not the whole // "frame" as specified by the app). We'll just immediately buffer this // sequence, and flush it when the render thread comes around to paint the - // frame normally. - + // frame normally, unless a flush has been explicitly requested. + if (flush) + { + _flushImpl(); + } return S_OK; } diff --git a/src/renderer/vt/XtermEngine.hpp b/src/renderer/vt/XtermEngine.hpp index 6f1b480b61e..7449fb3e38b 100644 --- a/src/renderer/vt/XtermEngine.hpp +++ b/src/renderer/vt/XtermEngine.hpp @@ -51,7 +51,7 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT InvalidateScroll(const til::point* const pcoordDelta) noexcept override; - [[nodiscard]] HRESULT WriteTerminalW(const std::wstring_view str) noexcept override; + [[nodiscard]] HRESULT WriteTerminalW(const std::wstring_view str, const bool flush) noexcept override; [[nodiscard]] HRESULT SetWindowVisibility(const bool showOrHide) noexcept override; diff --git a/src/renderer/vt/invalidate.cpp b/src/renderer/vt/invalidate.cpp index 489a6b50bc1..942ba58df26 100644 --- a/src/renderer/vt/invalidate.cpp +++ b/src/renderer/vt/invalidate.cpp @@ -75,7 +75,7 @@ CATCH_RETURN(); } _skipCursor = false; - _cursorMoved = true; + _cursorMoved = psrRegion->origin() != _lastText; return S_OK; } diff --git a/src/renderer/vt/math.cpp b/src/renderer/vt/math.cpp index d86e4644ca5..354ca0e9925 100644 --- a/src/renderer/vt/math.cpp +++ b/src/renderer/vt/math.cpp @@ -52,38 +52,3 @@ void VtEngine::_OrRect(_Inout_ til::inclusive_rect* const pRectExisting, const t pRectExisting->right = std::max(pRectExisting->right, pRectToOr->right); pRectExisting->bottom = std::max(pRectExisting->bottom, pRectToOr->bottom); } - -// Method Description: -// - Returns true if the invalidated region indicates that we only need to -// simply print text from the current cursor position. This will prevent us -// from sending extra VT set-up/tear down sequences (?12h/l) when all we -// need to do is print more text at the current cursor position. -// Arguments: -// - -// Return Value: -// - true iff only the next character is invalid -bool VtEngine::_WillWriteSingleChar() const -{ - // If there is no scroll delta, return false. - if (til::point{ 0, 0 } != _scrollDelta) - { - return false; - } - - // If there is more than one invalid char, return false. - if (!_invalidMap.one()) - { - return false; - } - - // Get the single point at which things are invalid. - const auto invalidPoint = _invalidMap.runs().front().origin(); - - // Either the next character to the right or the immediately previous - // character should follow this code path - // (The immediate previous character would suggest a backspace) - auto invalidIsNext = invalidPoint == _lastText; - auto invalidIsLast = invalidPoint == til::point{ _lastText.x - 1, _lastText.y }; - - return invalidIsNext || invalidIsLast; -} diff --git a/src/renderer/vt/paint.cpp b/src/renderer/vt/paint.cpp index af08cdd5b58..1fcb5335887 100644 --- a/src/renderer/vt/paint.cpp +++ b/src/renderer/vt/paint.cpp @@ -20,30 +20,30 @@ using namespace Microsoft::Console::Types; // HRESULT error code if painting didn't start successfully. [[nodiscard]] HRESULT VtEngine::StartPaint() noexcept { + // When unit testing, there may be no pipe, but we still need to paint. if (!_hFile) { - return S_FALSE; + return S_OK; } // If we're using line renditions, and this is a full screen paint, we can // potentially stop using them at the end of this frame. _stopUsingLineRenditions = _usingLineRenditions && _AllIsInvalid(); - // If there's nothing to do, quick return + // If there's nothing to do, we won't need to paint. auto somethingToDo = _invalidMap.any() || _scrollDelta != til::point{ 0, 0 } || _cursorMoved || _titleChanged; - _quickReturn = !somethingToDo; - _trace.TraceStartPaint(_quickReturn, + _trace.TraceStartPaint(!somethingToDo, _invalidMap, _lastViewport.ToExclusive(), _scrollDelta, _cursorMoved, _wrappedRow); - return _quickReturn ? S_FALSE : S_OK; + return somethingToDo ? S_OK : S_FALSE; } // Routine Description: @@ -142,9 +142,9 @@ using namespace Microsoft::Console::Types; _usingLineRenditions = true; } // One simple optimization is that we can skip sending the line attributes - // when _quickReturn is true. That indicates that we're writing out a single - // character, which should preclude there being a rendition switch. - if (_usingLineRenditions && !_quickReturn) + // when we're writing out a single character, which should preclude there + // being a rendition switch. + if (_usingLineRenditions && !_invalidMap.one()) { RETURN_IF_FAILED(_MoveCursor({ _lastText.x, targetRow })); switch (lineRendition) diff --git a/src/renderer/vt/state.cpp b/src/renderer/vt/state.cpp index 881fb0c2cce..f192536e3e6 100644 --- a/src/renderer/vt/state.cpp +++ b/src/renderer/vt/state.cpp @@ -37,7 +37,6 @@ VtEngine::VtEngine(_In_ wil::unique_hfile pipe, _pool(til::pmr::get_default_resource()), _invalidMap(initialViewport.Dimensions(), false, &_pool), _scrollDelta(0, 0), - _quickReturn(false), _clearedAllThisFrame(false), _cursorMoved(false), _resized(false), diff --git a/src/renderer/vt/vtrenderer.hpp b/src/renderer/vt/vtrenderer.hpp index 0125fe17369..26fc67cb138 100644 --- a/src/renderer/vt/vtrenderer.hpp +++ b/src/renderer/vt/vtrenderer.hpp @@ -78,7 +78,7 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT RequestCursor() noexcept; [[nodiscard]] HRESULT InheritCursor(const til::point coordCursor) noexcept; [[nodiscard]] HRESULT WriteTerminalUtf8(const std::string_view str) noexcept; - [[nodiscard]] virtual HRESULT WriteTerminalW(const std::wstring_view str) noexcept = 0; + [[nodiscard]] virtual HRESULT WriteTerminalW(const std::wstring_view str, const bool flush = false) noexcept = 0; void SetTerminalOwner(Microsoft::Console::VirtualTerminal::VtIo* const terminalOwner); void SetResizeQuirk(const bool resizeQuirk); void SetLookingForDSRCallback(std::function pfnLooking) noexcept; @@ -113,7 +113,6 @@ namespace Microsoft::Console::Render til::point _lastText; til::point _scrollDelta; - bool _quickReturn; bool _clearedAllThisFrame; bool _cursorMoved; bool _resized; @@ -214,8 +213,6 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT _RgbUpdateDrawingBrushes(const TextAttribute& textAttributes) noexcept; [[nodiscard]] HRESULT _16ColorUpdateDrawingBrushes(const TextAttribute& textAttributes) noexcept; - bool _WillWriteSingleChar() const; - // buffer space for these two functions to build their lines // so they don't have to alloc/free in a tight loop std::wstring _bufferLine; diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index bf038dd75ee..02c22db8eec 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -4882,7 +4882,7 @@ ITermDispatch::StringHandler AdaptDispatch::_CreatePassthroughHandler() { buffer += L'\\'; } - engine.ActionPassThroughString(buffer); + engine.ActionPassThroughString(buffer, true); buffer.clear(); } return !endOfString; diff --git a/src/terminal/parser/IStateMachineEngine.hpp b/src/terminal/parser/IStateMachineEngine.hpp index 1eefc5be2a5..d1d838ccc5e 100644 --- a/src/terminal/parser/IStateMachineEngine.hpp +++ b/src/terminal/parser/IStateMachineEngine.hpp @@ -35,7 +35,7 @@ namespace Microsoft::Console::VirtualTerminal virtual bool ActionPrint(const wchar_t wch) = 0; virtual bool ActionPrintString(const std::wstring_view string) = 0; - virtual bool ActionPassThroughString(const std::wstring_view string) = 0; + virtual bool ActionPassThroughString(const std::wstring_view string, const bool flush = false) = 0; virtual bool ActionEscDispatch(const VTID id) = 0; virtual bool ActionVt52EscDispatch(const VTID id, const VTParameters parameters) = 0; diff --git a/src/terminal/parser/InputStateMachineEngine.cpp b/src/terminal/parser/InputStateMachineEngine.cpp index df7a8c2cfb7..4a25d056f49 100644 --- a/src/terminal/parser/InputStateMachineEngine.cpp +++ b/src/terminal/parser/InputStateMachineEngine.cpp @@ -276,9 +276,10 @@ bool InputStateMachineEngine::ActionPrintString(const std::wstring_view string) // string of characters given. // Arguments: // - string - string to dispatch. +// - flush - not applicable to the input state machine. // Return Value: // - true iff we successfully dispatched the sequence. -bool InputStateMachineEngine::ActionPassThroughString(const std::wstring_view string) +bool InputStateMachineEngine::ActionPassThroughString(const std::wstring_view string, const bool /*flush*/) { if (_pDispatch->IsVtInputEnabled()) { diff --git a/src/terminal/parser/InputStateMachineEngine.hpp b/src/terminal/parser/InputStateMachineEngine.hpp index 6b90c729492..4b17669aedc 100644 --- a/src/terminal/parser/InputStateMachineEngine.hpp +++ b/src/terminal/parser/InputStateMachineEngine.hpp @@ -142,7 +142,7 @@ namespace Microsoft::Console::VirtualTerminal bool ActionPrintString(const std::wstring_view string) override; - bool ActionPassThroughString(const std::wstring_view string) override; + bool ActionPassThroughString(const std::wstring_view string, const bool flush) override; bool ActionEscDispatch(const VTID id) override; diff --git a/src/terminal/parser/OutputStateMachineEngine.cpp b/src/terminal/parser/OutputStateMachineEngine.cpp index 34d40fc850d..f4b3fcbf677 100644 --- a/src/terminal/parser/OutputStateMachineEngine.cpp +++ b/src/terminal/parser/OutputStateMachineEngine.cpp @@ -180,14 +180,15 @@ bool OutputStateMachineEngine::ActionPrintString(const std::wstring_view string) // we don't know what to do with it) // Arguments: // - string - string to dispatch. +// - flush - set to true if the string should be flushed immediately. // Return Value: // - true iff we successfully dispatched the sequence. -bool OutputStateMachineEngine::ActionPassThroughString(const std::wstring_view string) +bool OutputStateMachineEngine::ActionPassThroughString(const std::wstring_view string, const bool flush) { auto success = true; if (_pTtyConnection != nullptr) { - const auto hr = _pTtyConnection->WriteTerminalW(string); + const auto hr = _pTtyConnection->WriteTerminalW(string, flush); LOG_IF_FAILED(hr); success = SUCCEEDED(hr); } diff --git a/src/terminal/parser/OutputStateMachineEngine.hpp b/src/terminal/parser/OutputStateMachineEngine.hpp index 1ff22ab5a99..64fbf81503e 100644 --- a/src/terminal/parser/OutputStateMachineEngine.hpp +++ b/src/terminal/parser/OutputStateMachineEngine.hpp @@ -38,7 +38,7 @@ namespace Microsoft::Console::VirtualTerminal bool ActionPrintString(const std::wstring_view string) override; - bool ActionPassThroughString(const std::wstring_view string) override; + bool ActionPassThroughString(const std::wstring_view string, const bool flush) override; bool ActionEscDispatch(const VTID id) override; diff --git a/src/terminal/parser/ut_parser/StateMachineTest.cpp b/src/terminal/parser/ut_parser/StateMachineTest.cpp index 0bf36050e95..f910a72c1a4 100644 --- a/src/terminal/parser/ut_parser/StateMachineTest.cpp +++ b/src/terminal/parser/ut_parser/StateMachineTest.cpp @@ -59,7 +59,7 @@ class Microsoft::Console::VirtualTerminal::TestStateMachineEngine : public IStat return true; }; - bool ActionPassThroughString(const std::wstring_view string) override + bool ActionPassThroughString(const std::wstring_view string, const bool /*flush*/) override { passedThrough += string; return true;