terminal/src/types/ScreenInfoUiaProviderBase.h
Michael Niksa 9e44df0c9f
Cache the size viewport structure inside TextBuffer (#6841)
Looking up the size of the viewport from the underlying dimensions of
the structures seemed like a good idea at the time (so it would only be
in one place), but it turns out to be more of a perf cost than we
expected. Not necessarily on any one hot path, but if we sort by
functions in WPR, it was the top consumer on the Terminal side. This
instead saves the size as a member of the `TextBuffer` and serves that
out. It only changes when it is constructed or resized traditionally, so
it's easy to update/keep track of. It impacted conhost/conpty to a
lesser degree but was still noticeable.

## Validation Steps Performed
- Run `time cat big.txt` under WPR. Checked before and after perf
  metrics.

## PR Checklist
* [x] Closes perf itch
* [x] I work here
* [x] Manual test
* [x] Documentation irrelevant.
* [x] Schema irrelevant.
* [x] Am core contributor.
2020-07-09 11:18:25 +00:00

133 lines
6.5 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- ScreenInfoUiaProviderBase.hpp
Abstract:
- This module provides UI Automation access to the screen buffer to
support both automation tests and accessibility (screen reading)
applications.
- ConHost and Windows Terminal must use IRenderData to have access to the proper information
- Based on examples, sample code, and guidance from
https://msdn.microsoft.com/en-us/library/windows/desktop/ee671596(v=vs.85).aspx
Author(s):
- Michael Niksa (MiNiksa) 2017
- Austin Diviness (AustDi) 2017
- Carlos Zamora (CaZamor) 2019
--*/
#pragma once
#include "../buffer/out/textBuffer.hpp"
#include "UiaTextRangeBase.hpp"
#include "IUiaData.h"
#include "IUiaTraceable.h"
#include <UIAutomationCore.h>
#include <wrl/implements.h>
namespace Microsoft::Console::Types
{
class Viewport;
class ScreenInfoUiaProviderBase :
public WRL::RuntimeClass<WRL::RuntimeClassFlags<WRL::ClassicCom | WRL::InhibitFtmBase>, IRawElementProviderSimple, IRawElementProviderFragment, ITextProvider>,
public IUiaTraceable
{
public:
virtual HRESULT RuntimeClassInitialize(_In_ IUiaData* pData, _In_ std::wstring_view wordDelimiters = UiaTextRangeBase::DefaultWordDelimiter) noexcept;
ScreenInfoUiaProviderBase(const ScreenInfoUiaProviderBase&) = delete;
ScreenInfoUiaProviderBase(ScreenInfoUiaProviderBase&&) = delete;
ScreenInfoUiaProviderBase& operator=(const ScreenInfoUiaProviderBase&) = delete;
ScreenInfoUiaProviderBase& operator=(ScreenInfoUiaProviderBase&&) = delete;
~ScreenInfoUiaProviderBase() = default;
[[nodiscard]] HRESULT Signal(_In_ EVENTID id);
virtual void ChangeViewport(const SMALL_RECT NewWindow) = 0;
// IRawElementProviderSimple methods
IFACEMETHODIMP get_ProviderOptions(_Out_ ProviderOptions* pOptions) noexcept override;
IFACEMETHODIMP GetPatternProvider(_In_ PATTERNID iid,
_COM_Outptr_result_maybenull_ IUnknown** ppInterface) override;
IFACEMETHODIMP GetPropertyValue(_In_ PROPERTYID idProp,
_Out_ VARIANT* pVariant) noexcept override;
IFACEMETHODIMP get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider) noexcept override;
// IRawElementProviderFragment methods
virtual IFACEMETHODIMP Navigate(_In_ NavigateDirection direction,
_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider) = 0;
IFACEMETHODIMP GetRuntimeId(_Outptr_result_maybenull_ SAFEARRAY** ppRuntimeId) override;
virtual IFACEMETHODIMP get_BoundingRectangle(_Out_ UiaRect* pRect) = 0;
IFACEMETHODIMP GetEmbeddedFragmentRoots(_Outptr_result_maybenull_ SAFEARRAY** ppRoots) noexcept override;
IFACEMETHODIMP SetFocus() override;
virtual IFACEMETHODIMP get_FragmentRoot(_COM_Outptr_result_maybenull_ IRawElementProviderFragmentRoot** ppProvider) = 0;
// ITextProvider
IFACEMETHODIMP GetSelection(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) override;
IFACEMETHODIMP GetVisibleRanges(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) override;
IFACEMETHODIMP RangeFromChild(_In_ IRawElementProviderSimple* childElement,
_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;
IFACEMETHODIMP RangeFromPoint(_In_ UiaPoint point,
_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;
IFACEMETHODIMP get_DocumentRange(_COM_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;
IFACEMETHODIMP get_SupportedTextSelection(_Out_ SupportedTextSelection* pRetVal) noexcept override;
protected:
ScreenInfoUiaProviderBase() = default;
virtual HRESULT GetSelectionRange(_In_ IRawElementProviderSimple* pProvider, const std::wstring_view wordDelimiters, _COM_Outptr_result_maybenull_ UiaTextRangeBase** ppUtr) = 0;
// degenerate range
virtual HRESULT CreateTextRange(_In_ IRawElementProviderSimple* const pProvider, const std::wstring_view wordDelimiters, _COM_Outptr_result_maybenull_ UiaTextRangeBase** ppUtr) = 0;
// degenerate range at cursor position
virtual HRESULT CreateTextRange(_In_ IRawElementProviderSimple* const pProvider,
const Cursor& cursor,
const std::wstring_view wordDelimiters,
_COM_Outptr_result_maybenull_ UiaTextRangeBase** ppUtr) = 0;
// specific endpoint range
virtual HRESULT CreateTextRange(_In_ IRawElementProviderSimple* const pProvider,
const COORD start,
const COORD end,
const std::wstring_view wordDelimiters,
_COM_Outptr_result_maybenull_ UiaTextRangeBase** ppUtr) = 0;
// range from a UiaPoint
virtual HRESULT CreateTextRange(_In_ IRawElementProviderSimple* const pProvider,
const UiaPoint point,
const std::wstring_view wordDelimiters,
_COM_Outptr_result_maybenull_ UiaTextRangeBase** ppUtr) = 0;
// weak reference to IUiaData
IUiaData* _pData{ nullptr };
std::wstring _wordDelimiters{};
private:
// this is used to prevent the object from
// signaling an event while it is already in the
// process of signalling another event.
// This fixes a problem with JAWS where it would
// call a public method that calls
// UiaRaiseAutomationEvent to signal something
// happened, which JAWS then detects the signal
// and calls the same method in response,
// eventually overflowing the stack.
// We aren't using this as a cheap locking
// mechanism for multi-threaded code.
std::unordered_map<EVENTID, bool> _signalFiringMapping{};
const COORD _getScreenBufferCoords() const noexcept;
const TextBuffer& _getTextBuffer() const noexcept;
const Viewport _getViewport() const noexcept;
void _LockConsole() noexcept;
void _UnlockConsole() noexcept;
};
}