2019-05-03 00:29:04 +02:00
|
|
|
/*++
|
|
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
Licensed under the MIT license.
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
- IRenderData.hpp
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
- This serves as the interface defining all information needed to render to the screen.
|
|
|
|
|
|
|
|
Author(s):
|
|
|
|
- Michael Niksa (MiNiksa) 17-Nov-2015
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../../host/conimeinfo.h"
|
|
|
|
#include "../../buffer/out/TextAttribute.hpp"
|
2019-08-19 20:03:45 +02:00
|
|
|
#include "../../types/IBaseData.h"
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
class Cursor;
|
|
|
|
|
|
|
|
namespace Microsoft::Console::Render
|
|
|
|
{
|
|
|
|
struct RenderOverlay final
|
|
|
|
{
|
|
|
|
// This is where the data is stored
|
|
|
|
const TextBuffer& buffer;
|
|
|
|
|
|
|
|
// This is where the top left of the stored buffer should be overlayed on the screen
|
|
|
|
// (relative to the current visible viewport)
|
|
|
|
const COORD origin;
|
|
|
|
|
|
|
|
// This is the area of the buffer that is actually used for overlay.
|
|
|
|
// Anything outside of this is considered empty by the overlay and shouldn't be used
|
|
|
|
// for painting purposes.
|
|
|
|
const Microsoft::Console::Types::Viewport region;
|
|
|
|
};
|
|
|
|
|
2019-08-19 20:03:45 +02:00
|
|
|
class IRenderData : public Microsoft::Console::Types::IBaseData
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
public:
|
2019-10-11 23:02:09 +02:00
|
|
|
~IRenderData() = 0;
|
|
|
|
IRenderData(const IRenderData&) = default;
|
|
|
|
IRenderData(IRenderData&&) = default;
|
|
|
|
IRenderData& operator=(const IRenderData&) = default;
|
|
|
|
IRenderData& operator=(IRenderData&&) = default;
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
virtual const TextAttribute GetDefaultBrushColors() noexcept = 0;
|
|
|
|
|
Refactor the renderer color calculations (#6853)
This is a refactoring of the renderer color calculations to simplify the
implementation, and to make it easier to support additional
color-altering rendition attributes in the future (e.g. _faint_ and
_conceal_).
## References
* This is a followup to PRs #3817 and #6809, which introduced additional
complexity in the color calculations, and which suggested the need for
refactoring.
## Detailed Description of the Pull Request / Additional comments
When we added support for `DECSCNM`, that required the foreground and
background color lookup methods to be able to return the opposite of
what was requested when the reversed mode was set. That made those
methods unnecessarily complicated, and I thought we could simplify them
considerably just by combining the calculations into a single method
that derived both colors at the same time.
And since both conhost and Windows Terminal needed to perform the same
calculations, it also made sense to move that functionality into the
`TextAttribute` class, where it could easily be shared.
In general this way of doing things is a bit more efficient. However, it
does result in some unnecessary work when only one of the colors is
required, as is the case for the gridline painter. So to make that less
of an issue, I've reordered the gridline code a bit so it at least
avoids looking up the colors when no gridlines are needed.
## Validation Steps Performed
Because of the API changes, quite a lot of the unit tests had to be
updated. For example instead of verifying colors with two separate calls
to `LookupForegroundColor` and `LookupBackgroundColor`, that's now
achieved with a single `LookupAttributeColors` call, comparing against a
pair of values. The specifics of the tests haven't changed though, and
they're all still working as expected.
I've also manually confirmed that the various color sequences and
rendition attributes are rendering correctly with the new refactoring.
2020-07-11 00:26:34 +02:00
|
|
|
virtual std::pair<COLORREF, COLORREF> GetAttributeColors(const TextAttribute& attr) const noexcept = 0;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
virtual COORD GetCursorPosition() const noexcept = 0;
|
|
|
|
virtual bool IsCursorVisible() const noexcept = 0;
|
|
|
|
virtual bool IsCursorOn() const noexcept = 0;
|
|
|
|
virtual ULONG GetCursorHeight() const noexcept = 0;
|
|
|
|
virtual CursorType GetCursorStyle() const noexcept = 0;
|
|
|
|
virtual ULONG GetCursorPixelWidth() const noexcept = 0;
|
|
|
|
virtual COLORREF GetCursorColor() const noexcept = 0;
|
Show a double width cursor for double width characters (#5319)
# Summary of the Pull Request
This PR will allow the cursor to be double width when on top of a double width character. This required changing `IsCursorDoubleWidth` to check whether the glyph the cursor's on top of is double width. This code is exactly the same as the original PR that addressed this issue in #2932. That one got reverted at some point due to the crashes related to it, but due to a combination of Terminal having come further since that PR and other changes to address use-after-frees, some of the crashes may/may not be relevant now. The ones that seemed to be relevant/repro-able, I attempt to address in this PR.
The `IsCursorDoubleWidth` check would fail during the `TextBuffer::Reflow` call inside of `Terminal::UserResize` occasionally, particularly when `newCursor.EndDeferDrawing()` is called. This is because when we tell the newCursor to `EndDefer`, the renderer will attempt to redraw the cursor. As part of this redraw, it'll ask if `IsCursorDoubleWidth`, and if the renderer managed to ask this before `UserResize` swapped out the old buffer with the new one from `Reflow`, the renderer will be asking the old buffer if its out-of-bounds cursor is double width. This was pretty easily repro'd using `cmatrix -u0` and resizing the window like a madman.
As a solution, I've moved the Start/End DeferDrawing calls out of `Reflow` and into `UserResize`. This way, I can "clamp" the portion of the code where the newBuffer is getting created and reflowed and swapped into the Terminal buffer, and only allow the renderer to draw once the swap is done. This also means that ConHost's `ResizeWithReflow` needed to change slightly.
In addition, I've added a WriteLock to `SetCursorOn`. It was mentioned as a fix for a crash in #2965 (although I can't repro), and I also figured it would be good to try to emulate where ConHost locks with regards to Cursor operations, and this seemed to be one that we were missing.
## PR Checklist
* [x] Closes #2713
* [x] CLA signed
* [x] Tests added/passed
## Validation Steps Performed
Manual validation that the cursor is indeed chonky, added a test case to check that we are correctly saying that the cursor is double width (not too sure if I put it in the right place). Also open to other test case ideas and thoughts on what else I should be careful for since I am quite nervous about what other crashes might occur.
2020-04-15 21:23:06 +02:00
|
|
|
virtual bool IsCursorDoubleWidth() const = 0;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-03-13 01:54:43 +01:00
|
|
|
virtual bool IsScreenReversed() const noexcept = 0;
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
virtual const std::vector<RenderOverlay> GetOverlays() const noexcept = 0;
|
|
|
|
|
|
|
|
virtual const bool IsGridLineDrawingAllowed() noexcept = 0;
|
|
|
|
virtual const std::wstring GetConsoleTitle() const noexcept = 0;
|
2019-10-11 23:02:09 +02:00
|
|
|
|
2020-09-03 19:52:39 +02:00
|
|
|
virtual const std::wstring GetHyperlinkUri(uint16_t id) const noexcept = 0;
|
|
|
|
virtual const std::wstring GetHyperlinkCustomId(uint16_t id) const noexcept = 0;
|
|
|
|
|
2020-10-28 21:24:43 +01:00
|
|
|
virtual const std::vector<size_t> GetPatternId(const COORD location) const noexcept = 0;
|
|
|
|
|
2019-10-11 23:02:09 +02:00
|
|
|
protected:
|
|
|
|
IRenderData() = default;
|
2019-05-03 00:29:04 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// See docs/virtual-dtors.md for an explanation of why this is weird.
|
|
|
|
inline IRenderData::~IRenderData() {}
|
|
|
|
}
|