2019-05-03 00:29:04 +02:00
|
|
|
/*++
|
|
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
Licensed under the MIT license.
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
- Renderer.hpp
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
- This is the definition of our renderer.
|
|
|
|
- It provides interfaces for the console application to notify when various portions of the console state have changed and need to be redrawn.
|
|
|
|
- It requires a data interface to fetch relevant console structures required for drawing and a drawing engine target for output.
|
|
|
|
|
|
|
|
Author(s):
|
|
|
|
- Michael Niksa (MiNiksa) 17-Nov-2015
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../inc/IRenderer.hpp"
|
|
|
|
#include "../inc/IRenderEngine.hpp"
|
|
|
|
#include "../inc/IRenderData.hpp"
|
|
|
|
|
|
|
|
#include "thread.hpp"
|
|
|
|
|
|
|
|
#include "../../buffer/out/textBuffer.hpp"
|
|
|
|
#include "../../buffer/out/CharRow.hpp"
|
|
|
|
|
|
|
|
namespace Microsoft::Console::Render
|
|
|
|
{
|
|
|
|
class Renderer sealed : public IRenderer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Renderer(IRenderData* pData,
|
|
|
|
_In_reads_(cEngines) IRenderEngine** const pEngine,
|
|
|
|
const size_t cEngines,
|
|
|
|
std::unique_ptr<IRenderThread> thread);
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] static HRESULT s_CreateInstance(IRenderData* pData,
|
|
|
|
_In_reads_(cEngines) IRenderEngine** const rgpEngines,
|
|
|
|
const size_t cEngines,
|
|
|
|
_Outptr_result_nullonfailure_ Renderer** const ppRenderer);
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] static HRESULT s_CreateInstance(IRenderData* pData,
|
|
|
|
_Outptr_result_nullonfailure_ Renderer** const ppRenderer);
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
virtual ~Renderer() override;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT PaintFrame();
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
void TriggerSystemRedraw(const RECT* const prcDirtyClient) override;
|
|
|
|
void TriggerRedraw(const Microsoft::Console::Types::Viewport& region) override;
|
|
|
|
void TriggerRedraw(const COORD* const pcoord) override;
|
|
|
|
void TriggerRedrawCursor(const COORD* const pcoord) override;
|
|
|
|
void TriggerRedrawAll() override;
|
|
|
|
void TriggerTeardown() override;
|
|
|
|
|
|
|
|
void TriggerSelection() override;
|
|
|
|
void TriggerScroll() override;
|
|
|
|
void TriggerScroll(const COORD* const pcoordDelta) override;
|
|
|
|
|
|
|
|
void TriggerCircling() override;
|
|
|
|
void TriggerTitleChange() override;
|
|
|
|
|
|
|
|
void TriggerFontChange(const int iDpi,
|
|
|
|
const FontInfoDesired& FontInfoDesired,
|
|
|
|
_Out_ FontInfo& FontInfo) override;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT GetProposedFont(const int iDpi,
|
|
|
|
const FontInfoDesired& FontInfoDesired,
|
|
|
|
_Out_ FontInfo& FontInfo) override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
bool IsGlyphWideByFont(const std::wstring_view glyph) override;
|
|
|
|
|
|
|
|
void EnablePainting() override;
|
|
|
|
void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) override;
|
2020-06-11 00:35:14 +02:00
|
|
|
void WaitUntilCanRender() override;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
void AddRenderEngine(_In_ IRenderEngine* const pEngine) override;
|
|
|
|
|
2020-04-14 22:11:47 +02:00
|
|
|
void SetRendererEnteredErrorStateCallback(std::function<void()> pfn);
|
|
|
|
void ResetErrorStateAndResume();
|
|
|
|
|
2020-10-28 21:24:43 +01:00
|
|
|
void UpdateLastHoveredInterval(const std::optional<interval_tree::IntervalTree<til::point, size_t>::interval>& newInterval);
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
private:
|
|
|
|
std::deque<IRenderEngine*> _rgpEngines;
|
|
|
|
|
|
|
|
IRenderData* _pData; // Non-ownership pointer
|
|
|
|
|
|
|
|
std::unique_ptr<IRenderThread> _pThread;
|
|
|
|
bool _destructing = false;
|
|
|
|
|
2020-10-28 21:24:43 +01:00
|
|
|
std::optional<interval_tree::IntervalTree<til::point, size_t>::interval> _hoveredInterval;
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
void _NotifyPaintFrame();
|
|
|
|
|
2020-02-03 20:03:08 +01:00
|
|
|
[[nodiscard]] HRESULT _PaintFrameForEngine(_In_ IRenderEngine* const pEngine) noexcept;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
bool _CheckViewportAndScroll();
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _PaintBackground(_In_ IRenderEngine* const pEngine);
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
void _PaintBufferOutput(_In_ IRenderEngine* const pEngine);
|
|
|
|
|
|
|
|
void _PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
|
|
|
|
TextBufferCellIterator it,
|
Make Conpty emit wrapped lines as actually wrapped lines (#4415)
## Summary of the Pull Request
Changes how conpty emits text to preserve line-wrap state, and additionally adds rudimentary support to the Windows Terminal for wrapped lines.
## References
* Does _not_ fix (!) #3088, but that might be lower down in conhost. This makes wt behave like conhost, so at least there's that
* Still needs a proper deferred EOL wrap implementation in #780, which is left as a todo
* #4200 is the mega bucket with all this work
* MSFT:16485846 was the first attempt at this task, which caused the regression MSFT:18123777 so we backed it out.
* #4403 - I made sure this worked with that PR before I even sent #4403
## PR Checklist
* [x] Closes #405
* [x] Closes #3367
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I started with the following implementation:
When conpty is about to write the last column, note that we wrapped this line here. If the next character the vt renderer is told to paint get is supposed to be at the start of the following line, then we know that the previous line had wrapped, so we _won't_ emit the usual `\r\n` here, and we'll just continue emitting text.
However, this isn't _exactly_ right - if someone fills the row _exactly_ with text, the information that's available to the vt renderer isn't enough to know for sure if this line broke or not. It is possible for the client to write a full line of text, with a `\n` at the end, to manually break the line. So, I had to also add the `lineWrapped` param to the `IRenderEngine` interface, which is about half the files in this changelist.
## Validation Steps Performed
* Ran tests
* Checked how the Windows Terminal behaves with these changes
* Made sure that conhost/inception and gnome-terminal both act as you'd expect with wrapped lines from conpty
2020-02-27 17:40:11 +01:00
|
|
|
const COORD target,
|
|
|
|
const bool lineWrapped);
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
static IRenderEngine::GridLines s_GetGridlines(const TextAttribute& textAttribute) noexcept;
|
|
|
|
|
|
|
|
void _PaintBufferOutputGridLineHelper(_In_ IRenderEngine* const pEngine,
|
|
|
|
const TextAttribute textAttribute,
|
|
|
|
const size_t cchLine,
|
|
|
|
const COORD coordTarget);
|
|
|
|
|
|
|
|
void _PaintSelection(_In_ IRenderEngine* const pEngine);
|
|
|
|
void _PaintCursor(_In_ IRenderEngine* const pEngine);
|
|
|
|
|
|
|
|
void _PaintOverlays(_In_ IRenderEngine* const pEngine);
|
|
|
|
void _PaintOverlay(IRenderEngine& engine, const RenderOverlay& overlay);
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _UpdateDrawingBrushes(_In_ IRenderEngine* const pEngine, const TextAttribute attr, const bool isSettingDefaultBrushes);
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _PerformScrolling(_In_ IRenderEngine* const pEngine);
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-07-16 23:46:10 +02:00
|
|
|
Microsoft::Console::Types::Viewport _viewport;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-06-11 00:02:05 +02:00
|
|
|
static constexpr float _shrinkThreshold = 0.8f;
|
|
|
|
std::vector<Cluster> _clusterBuffer;
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
std::vector<SMALL_RECT> _GetSelectionRects() const;
|
2020-04-13 22:09:02 +02:00
|
|
|
void _ScrollPreviousSelection(const til::point delta);
|
2019-05-03 00:29:04 +02:00
|
|
|
std::vector<SMALL_RECT> _previousSelection;
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] HRESULT _PaintTitle(IRenderEngine* const pEngine);
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-06-04 14:58:22 +02:00
|
|
|
[[nodiscard]] std::optional<CursorOptions> _GetCursorInfo();
|
|
|
|
[[nodiscard]] HRESULT _PrepareRenderInfo(_In_ IRenderEngine* const pEngine);
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
// Helper functions to diagnose issues with painting and layout.
|
|
|
|
// These are only actually effective/on in Debug builds when the flag is set using an attached debugger.
|
|
|
|
bool _fDebug = false;
|
Create tests that roundtrip output through a conpty to a Terminal (#4213)
## Summary of the Pull Request
This PR adds two tests:
* First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests.
* Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests.
## References
Done in pursuit of #4200, but I felt this warranted it's own atomic PR
## PR Checklist
* [x] Doesn't close anything on it's own.
* [x] I work here
* [x] you better believe this adds tests
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
From the comment in `ConptyRoundtripTests`:
> This test class creates an in-proc conpty host as well as a Terminal, to
> validate that strings written to the conpty create the same resopnse on the
> terminal end. Tests can be written that validate both the contents of the
> host buffer as well as the terminal buffer. Everytime that
> `renderer.PaintFrame()` is called, the tests will validate the expected
> output, and then flush the output of the VtEngine straight to th
Also, some other bits had to be updated:
* The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint`
* Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT`
* `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
|
|
|
|
2020-04-14 22:11:47 +02:00
|
|
|
std::function<void()> _pfnRendererEnteredErrorState;
|
|
|
|
|
Create tests that roundtrip output through a conpty to a Terminal (#4213)
## Summary of the Pull Request
This PR adds two tests:
* First, I started by writing a test where I could write output to the console host and inspect what output came out of conpty. This is the `ConptyOutputTests` in the host unit tests.
* Then I got crazy and thought _"what if I could take that output and dump it straight into the `Terminal`"_? Hence, the `ConptyRoundtripTests` were born, into the TerminalCore unit tests.
## References
Done in pursuit of #4200, but I felt this warranted it's own atomic PR
## PR Checklist
* [x] Doesn't close anything on it's own.
* [x] I work here
* [x] you better believe this adds tests
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
From the comment in `ConptyRoundtripTests`:
> This test class creates an in-proc conpty host as well as a Terminal, to
> validate that strings written to the conpty create the same resopnse on the
> terminal end. Tests can be written that validate both the contents of the
> host buffer as well as the terminal buffer. Everytime that
> `renderer.PaintFrame()` is called, the tests will validate the expected
> output, and then flush the output of the VtEngine straight to th
Also, some other bits had to be updated:
* The renderer needed to be able to survive without a thread, so I hadded a simple check that it actually had a thread before calling `pThread->NotifyPaint`
* Bits in `CommonState` used `NTSTATUS_FROM_HRESULT` which did _not_ work outside the host project. Since the `NTSTATUS` didn't seem that important, I replaced that with a `HRESULT`
* `CommonState` likes to initialize the console to some _weird_ defaults. I added an optional param to let us just use the defaults.
2020-01-17 17:40:12 +01:00
|
|
|
#ifdef UNIT_TESTING
|
|
|
|
friend class ConptyOutputTests;
|
|
|
|
#endif
|
2019-05-03 00:29:04 +02:00
|
|
|
};
|
|
|
|
}
|