diff --git a/OpenConsole.sln b/OpenConsole.sln index 4b9181d31a..08d5778de3 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -254,6 +254,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_TerminalApp", "s EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winconpty", "src\winconpty\winconpty.vcxproj", "{58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererUia", "src\renderer\uia\lib\uia.vcxproj", "{48D21369-3D7B-4431-9967-24E81292CF63}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AuditMode|Any CPU = AuditMode|Any CPU @@ -1257,6 +1259,24 @@ Global {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Release|x64.Build.0 = Release|x64 {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Release|x86.ActiveCfg = Release|Win32 {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Release|x86.Build.0 = Release|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 + {48D21369-3D7B-4431-9967-24E81292CF63}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 + {48D21369-3D7B-4431-9967-24E81292CF63}.AuditMode|x64.ActiveCfg = AuditMode|x64 + {48D21369-3D7B-4431-9967-24E81292CF63}.AuditMode|x64.Build.0 = AuditMode|x64 + {48D21369-3D7B-4431-9967-24E81292CF63}.AuditMode|x86.ActiveCfg = AuditMode|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.AuditMode|x86.Build.0 = AuditMode|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|ARM64.Build.0 = Debug|ARM64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x64.ActiveCfg = Debug|x64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x64.Build.0 = Debug|x64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x86.ActiveCfg = Debug|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x86.Build.0 = Debug|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM64.ActiveCfg = Release|ARM64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM64.Build.0 = Release|ARM64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Release|x64.ActiveCfg = Release|x64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Release|x64.Build.0 = Release|x64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Release|x86.ActiveCfg = Release|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1321,6 +1341,7 @@ Global {CA5CAD1A-9A12-429C-B551-8562EC954746} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506} = {59840756-302F-44DF-AA47-441A9D673202} {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} + {48D21369-3D7B-4431-9967-24E81292CF63} = {05500DEF-2294-41E3-AF9A-24E580B82836} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271} diff --git a/src/renderer/uia/UiaRenderer.cpp b/src/renderer/uia/UiaRenderer.cpp new file mode 100644 index 0000000000..cba61ff18a --- /dev/null +++ b/src/renderer/uia/UiaRenderer.cpp @@ -0,0 +1,404 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "precomp.h" + +#include "UiaRenderer.hpp" + +#pragma hdrstop + +using namespace Microsoft::Console::Render; +using namespace Microsoft::Console::Types; + +// Routine Description: +// - Constructs a UIA engine for console text +// which primarily notifies automation clients of any activity +UiaEngine::UiaEngine() noexcept : + _isPainting{ false }, + _isEnabled{ false }, + RenderEngineBase() +{ +} + +// Routine Description: +// - Sets this engine to enabled allowing presentation to occur +// Arguments: +// - +// Return Value: +// - S_OK +[[nodiscard]] HRESULT UiaEngine::Enable() noexcept +{ + _isEnabled = true; + return S_OK; +} + +// Routine Description: +// - Sets this engine to disabled to prevent presentation from occuring +// Arguments: +// - +// Return Value: +// - S_OK +[[nodiscard]] HRESULT UiaEngine::Disable() noexcept +{ + _isEnabled = false; + return S_OK; +} + +// Routine Description: +// - Notifies us that the console has changed the character region specified. +// - NOTE: This typically triggers on cursor or text buffer changes +// Arguments: +// - psrRegion - Character region (SMALL_RECT) that has been changed +// Return Value: +// - S_OK, else an appropriate HRESULT for failing to allocate or write. +[[nodiscard]] HRESULT UiaEngine::Invalidate(const SMALL_RECT* const /*psrRegion*/) noexcept +{ + return E_NOTIMPL; +} + +// Routine Description: +// - Notifies us that the console has changed the position of the cursor. +// For UIA, this doesn't mean anything. So do nothing. +// Arguments: +// - pcoordCursor - the new position of the cursor +// Return Value: +// - S_FALSE +[[nodiscard]] HRESULT UiaEngine::InvalidateCursor(const COORD* const /*pcoordCursor*/) noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Invalidates a rectangle describing a pixel area on the display +// For UIA, this doesn't mean anything. So do nothing. +// Arguments: +// - prcDirtyClient - pixel rectangle +// Return Value: +// - S_FALSE +[[nodiscard]] HRESULT UiaEngine::InvalidateSystem(const RECT* const /*prcDirtyClient*/) noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Notifies us that the console has changed the selection region and would +// like it updated +// Arguments: +// - rectangles - One or more rectangles describing character positions on the grid +// Return Value: +// - S_OK +[[nodiscard]] HRESULT UiaEngine::InvalidateSelection(const std::vector& /*rectangles*/) noexcept +{ + return E_NOTIMPL; +} + +// Routine Description: +// - Scrolls the existing dirty region (if it exists) and +// invalidates the area that is uncovered in the window. +// Arguments: +// - pcoordDelta - The number of characters to move and uncover. +// - -Y is up, Y is down, -X is left, X is right. +// Return Value: +// - S_OK +[[nodiscard]] HRESULT UiaEngine::InvalidateScroll(const COORD* const /*pcoordDelta*/) noexcept +{ + return E_NOTIMPL; +} + +// Routine Description: +// - Notifies to repaint everything. +// - NOTE: Use sparingly. Only use when something that could affect the entire +// frame simultaneously occurs. +// Arguments: +// - +// Return Value: +// - S_OK, else an appropriate HRESULT for failing to allocate or write. +[[nodiscard]] HRESULT UiaEngine::InvalidateAll() noexcept +{ + return E_NOTIMPL; +} + +// Routine Description: +// - This currently has no effect in this renderer. +// Arguments: +// - pForcePaint - Always filled with false +// Return Value: +// - S_FALSE because we don't use this. +[[nodiscard]] HRESULT UiaEngine::InvalidateCircling(_Out_ bool* const pForcePaint) noexcept +{ + RETURN_HR_IF_NULL(E_INVALIDARG, pForcePaint); + + *pForcePaint = false; + return S_FALSE; +} + +// Routine Description: +// - This is unused by this renderer. +// Arguments: +// - pForcePaint - always filled with false. +// Return Value: +// - S_FALSE because this is unused. +[[nodiscard]] HRESULT UiaEngine::PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept +{ + RETURN_HR_IF_NULL(E_INVALIDARG, pForcePaint); + + *pForcePaint = false; + return S_FALSE; +} + +// Routine Description: +// - Prepares internal structures for a painting operation. +// Arguments: +// - +// Return Value: +// - S_OK if we started to paint. S_FALSE if we didn't need to paint. +[[nodiscard]] HRESULT UiaEngine::StartPaint() noexcept +{ + RETURN_HR_IF(S_FALSE, !_isEnabled); + + // If there's nothing to do, quick return + bool somethingToDo = false; + + if (_isEnabled) + { + somethingToDo = false; + + if (somethingToDo) + { + _isPainting = true; + } + } + + return S_OK; +} + +// Routine Description: +// - Ends batch drawing and notifies automation clients of updated regions +// Arguments: +// - +// Return Value: +// - S_OK, else an appropriate HRESULT for failing to allocate or write. +[[nodiscard]] HRESULT UiaEngine::EndPaint() noexcept +{ + RETURN_HR_IF(E_INVALIDARG, !_isPainting); // invalid to end paint when we're not painting + + if (_isEnabled) + { + _isPainting = false; + + // fire UIA events here + } + + return S_OK; +} + +// Routine Description: +// - Used to perform longer running presentation steps outside the lock so the +// other threads can continue. +// - Not currently used by UiaEngine. +// Arguments: +// - +// Return Value: +// - S_FALSE since we do nothing. +[[nodiscard]] HRESULT UiaEngine::Present() noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - This is currently unused. +// Arguments: +// - +// Return Value: +// - S_FALSE +[[nodiscard]] HRESULT UiaEngine::ScrollFrame() noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Paints the background of the invalid area of the frame. +// For UIA, this doesn't mean anything. So do nothing. +// Arguments: +// - +// Return Value: +// - S_FALSE since we do nothing +[[nodiscard]] HRESULT UiaEngine::PaintBackground() noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Places one line of text onto the screen at the given position +// Arguments: +// - clusters - Iterable collection of cluster information (text and columns it should consume) +// - coord - Character coordinate position in the cell grid +// - fTrimLeft - Whether or not to trim off the left half of a double wide character +// Return Value: +// - E_NOTIMPL +[[nodiscard]] HRESULT UiaEngine::PaintBufferLine(std::basic_string_view const /*clusters*/, + COORD const /*coord*/, + const bool /*trimLeft*/) noexcept +{ + return E_NOTIMPL; +} + +// Routine Description: +// - Paints lines around cells (draws in pieces of the grid) +// For UIA, this doesn't mean anything. So do nothing. +// Arguments: +// - lines - +// - color - +// - cchLine - +// - coordTarget - +// Return Value: +// - S_FALSE +[[nodiscard]] HRESULT UiaEngine::PaintBufferGridLines(GridLines const /*lines*/, + COLORREF const /*color*/, + size_t const /*cchLine*/, + COORD const /*coordTarget*/) noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Reads the selected area, selection mode, and active screen buffer +// from the global properties and dispatches a GDI invert on the selected text area. +// Because the selection is the responsibility of the terminal, and not the +// host, render nothing. +// Arguments: +// - rect - Rectangle to invert or highlight to make the selection area +// Return Value: +// - S_FALSE +[[nodiscard]] HRESULT UiaEngine::PaintSelection(const SMALL_RECT /*rect*/) noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Draws the cursor on the screen +// Arguments: +// - options - Packed options relevant to how to draw the cursor +// Return Value: +// - S_FALSE +[[nodiscard]] HRESULT UiaEngine::PaintCursor(const IRenderEngine::CursorOptions& /*options*/) noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Updates the default brush colors used for drawing +// - Not currently used by UiaEngine. +// Arguments: +// - colorForeground - +// - colorBackground - +// - legacyColorAttribute - +// - isBold - +// - isSettingDefaultBrushes - +// Return Value: +// - S_FALSE since we do nothing +[[nodiscard]] HRESULT UiaEngine::UpdateDrawingBrushes(const COLORREF /*colorForeground*/, + const COLORREF /*colorBackground*/, + const WORD /*legacyColorAttribute*/, + const ExtendedAttributes /*extendedAttrs*/, + const bool /*isSettingDefaultBrushes*/) noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Updates the font used for drawing +// Arguments: +// - pfiFontInfoDesired - +// - fiFontInfo - +// Return Value: +// - S_FALSE since we do nothing +[[nodiscard]] HRESULT UiaEngine::UpdateFont(const FontInfoDesired& /*pfiFontInfoDesired*/, FontInfo& /*fiFontInfo*/) noexcept +{ + return E_NOTIMPL; +} + +// Routine Description: +// - Sets the DPI in this renderer +// - Not currently used by UiaEngine. +// Arguments: +// - iDpi - DPI +// Return Value: +// - S_OK +[[nodiscard]] HRESULT UiaEngine::UpdateDpi(int const /*iDpi*/) noexcept +{ + return E_NOTIMPL; +} + +// Method Description: +// - This method will update our internal reference for how big the viewport is. +// Arguments: +// - srNewViewport - The bounds of the new viewport. +// Return Value: +// - HRESULT S_OK +[[nodiscard]] HRESULT UiaEngine::UpdateViewport(const SMALL_RECT /*srNewViewport*/) noexcept +{ + return E_NOTIMPL; +} + +// Routine Description: +// - Currently unused by this renderer +// Arguments: +// - pfiFontInfoDesired - +// - pfiFontInfo - +// - iDpi - +// Return Value: +// - S_FALSE +[[nodiscard]] HRESULT UiaEngine::GetProposedFont(const FontInfoDesired& /*pfiFontInfoDesired*/, + FontInfo& /*pfiFontInfo*/, + int const /*iDpi*/) noexcept +{ + return S_FALSE; +} + +// Routine Description: +// - Gets the area that we currently believe is dirty within the character cell grid +// - Not currently used by UiaEngine. +// Arguments: +// - +// Return Value: +// - Rectangle describing dirty area in characters. +[[nodiscard]] SMALL_RECT UiaEngine::GetDirtyRectInChars() noexcept +{ + return Viewport::Empty().ToInclusive(); +} + +// Routine Description: +// - Gets the current font size +// Arguments: +// - pFontSize - Filled with the font size. +// Return Value: +// - S_OK +[[nodiscard]] HRESULT UiaEngine::GetFontSize(_Out_ COORD* const /*pFontSize*/) noexcept +{ + return E_NOTIMPL; +} + +// Routine Description: +// - Currently unused by this renderer. +// Arguments: +// - glyph - The glyph run to process for column width. +// - pResult - True if it should take two columns. False if it should take one. +// Return Value: +// - E_NOTIMPL +[[nodiscard]] HRESULT UiaEngine::IsGlyphWideByFont(const std::wstring_view /*glyph*/, _Out_ bool* const /*pResult*/) noexcept +{ + return E_NOTIMPL; +} + +// Method Description: +// - Updates the window's title string. +// - Currently unused by this renderer. +// Arguments: +// - newTitle: the new string to use for the title of the window +// Return Value: +// - S_FALSE +[[nodiscard]] HRESULT UiaEngine::_DoUpdateTitle(_In_ const std::wstring& /*newTitle*/) noexcept +{ + return S_FALSE; +} diff --git a/src/renderer/uia/UiaRenderer.hpp b/src/renderer/uia/UiaRenderer.hpp new file mode 100644 index 0000000000..1e93e8ba8e --- /dev/null +++ b/src/renderer/uia/UiaRenderer.hpp @@ -0,0 +1,83 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- UiaRenderer.hpp + +Abstract: +- This is the definition of the UIA specific implementation of the renderer +- It keeps track of what regions of the display have changed and notifies automation clients. + +Author(s): +- Carlos Zamora (CaZamor) Sep-2019 +--*/ + +#pragma once + +#include "../../renderer/inc/RenderEngineBase.hpp" + +#include "../../types/inc/Viewport.hpp" + +namespace Microsoft::Console::Render +{ + class UiaEngine final : public RenderEngineBase + { + public: + UiaEngine() noexcept; + + // 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; + [[nodiscard]] HRESULT Disable() noexcept; + + // IRenderEngine Members + [[nodiscard]] HRESULT StartPaint() noexcept override; + [[nodiscard]] HRESULT EndPaint() noexcept override; + [[nodiscard]] HRESULT Present() noexcept override; + + [[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override; + + [[nodiscard]] HRESULT ScrollFrame() noexcept override; + + [[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override; + [[nodiscard]] HRESULT InvalidateCursor(const COORD* const pcoordCursor) noexcept override; + [[nodiscard]] HRESULT InvalidateSystem(const RECT* const prcDirtyClient) noexcept override; + [[nodiscard]] HRESULT InvalidateSelection(const std::vector& rectangles) noexcept override; + [[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override; + [[nodiscard]] HRESULT InvalidateAll() noexcept override; + [[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override; + + [[nodiscard]] HRESULT PaintBackground() noexcept override; + [[nodiscard]] HRESULT PaintBufferLine(std::basic_string_view const clusters, + COORD const coord, + bool const fTrimLeft) noexcept override; + [[nodiscard]] HRESULT PaintBufferGridLines(GridLines const lines, COLORREF const color, size_t const cchLine, COORD const coordTarget) noexcept override; + [[nodiscard]] HRESULT PaintSelection(const SMALL_RECT rect) noexcept override; + + [[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override; + + [[nodiscard]] HRESULT UpdateDrawingBrushes(const COLORREF colorForeground, + const COLORREF colorBackground, + const WORD legacyColorAttribute, + const ExtendedAttributes extendedAttrs, + const bool isSettingDefaultBrushes) noexcept override; + [[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo) noexcept override; + [[nodiscard]] HRESULT UpdateDpi(int const iDpi) noexcept override; + [[nodiscard]] HRESULT UpdateViewport(const SMALL_RECT srNewViewport) noexcept override; + + [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; + + [[nodiscard]] SMALL_RECT GetDirtyRectInChars() noexcept override; + [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; + [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; + + protected: + [[nodiscard]] HRESULT _DoUpdateTitle(const std::wstring& newTitle) noexcept override; + + private: + bool _isEnabled; + bool _isPainting; + }; +} diff --git a/src/renderer/uia/lib/uia.vcxproj b/src/renderer/uia/lib/uia.vcxproj new file mode 100644 index 0000000000..1bb36777bc --- /dev/null +++ b/src/renderer/uia/lib/uia.vcxproj @@ -0,0 +1,24 @@ + + + + + + Create + + + + + + + + + {48D21369-3D7B-4431-9967-24E81292CF63} + Win32Proj + uia + RendererUia + ConRenderUia + + + + + diff --git a/src/renderer/uia/precomp.cpp b/src/renderer/uia/precomp.cpp new file mode 100644 index 0000000000..c51e9b31b2 --- /dev/null +++ b/src/renderer/uia/precomp.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "precomp.h" diff --git a/src/renderer/uia/precomp.h b/src/renderer/uia/precomp.h new file mode 100644 index 0000000000..ce87349d9d --- /dev/null +++ b/src/renderer/uia/precomp.h @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +// This includes support libraries from the CRT, STL, WIL, and GSL +#include "LibraryIncludes.h" + +#include + +#pragma hdrstop