mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 00:48:23 -06:00
Custom WinRT implementation
This commit is contained in:
parent
62312a8943
commit
f02bfe06dc
@ -49,7 +49,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void InteractivityAutomationPeer::ParentProvider(AutomationPeer parentProvider)
|
||||
{
|
||||
_parentProvider = parentProvider;
|
||||
// LOAD-BEARING: use _parentProvider->ProviderFromPeer(_parentProvider) instead of this->ProviderFromPeer(*this).
|
||||
// Since we split the automation peer into TermControlAutomationPeer and InteractivityAutomationPeer,
|
||||
// using "this" returns null. This can cause issues with some UIA Client scenarios like any navigation in Narrator.
|
||||
_parentProvider = parentProvider ? parentProvider.as<IAutomationPeerProtected>().ProviderFromPeer(parentProvider) : nullptr;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@ -181,15 +184,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::_CreateXamlUiaTextRange(UIA::ITextRangeProvider* returnVal) const
|
||||
{
|
||||
// LOAD-BEARING: use _parentProvider->ProviderFromPeer(_parentProvider) instead of this->ProviderFromPeer(*this).
|
||||
// Since we split the automation peer into TermControlAutomationPeer and InteractivityAutomationPeer,
|
||||
// using "this" returns null. This can cause issues with some UIA Client scenarios like any navigation in Narrator.
|
||||
const auto parent{ _parentProvider.get() };
|
||||
if (!parent)
|
||||
if (!_parentProvider)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return winrt::make<XamlUiaTextRange>(returnVal, parent.as<IAutomationPeerProtected>().ProviderFromPeer(parent));
|
||||
return XamlUiaTextRange::Create(returnVal, _parentProvider);
|
||||
};
|
||||
|
||||
// Method Description:
|
||||
@ -200,21 +199,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - com_array of Xaml Wrapped UiaTextRange (ITextRangeProviders)
|
||||
com_array<XamlAutomation::ITextRangeProvider> InteractivityAutomationPeer::WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges)
|
||||
{
|
||||
// transfer ownership of UiaTextRanges to this new vector
|
||||
auto providers = SafeArrayToOwningVector<::Microsoft::Terminal::TermControlUiaTextRange>(textRanges);
|
||||
auto count = gsl::narrow<int>(providers.size());
|
||||
|
||||
std::vector<XamlAutomation::ITextRangeProvider> vec;
|
||||
vec.reserve(count);
|
||||
for (auto i = 0; i < count; i++)
|
||||
if (!_parentProvider)
|
||||
{
|
||||
if (auto xutr = _CreateXamlUiaTextRange(providers[i].detach()))
|
||||
{
|
||||
vec.emplace_back(std::move(xutr));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
|
||||
// transfer ownership of UiaTextRanges to this new vector
|
||||
auto providers = SafeArrayToOwningVector<::Microsoft::Terminal::TermControlUiaTextRange>(textRanges);
|
||||
const auto len = gsl::narrow<uint32_t>(providers.size());
|
||||
com_array<XamlAutomation::ITextRangeProvider> result{ len };
|
||||
|
||||
for (uint32_t i = 0; i < len; ++i)
|
||||
{
|
||||
result[i] = XamlUiaTextRange::Create(providers[i].detach(), _parentProvider);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
|
||||
winrt::Microsoft::Terminal::Control::implementation::ControlInteractivity* _interactivity;
|
||||
weak_ref<Windows::UI::Xaml::Automation::Peers::AutomationPeer> _parentProvider;
|
||||
winrt::Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple _parentProvider{ nullptr };
|
||||
|
||||
til::rect _controlBounds{};
|
||||
til::rect _controlPadding{};
|
||||
|
||||
@ -121,6 +121,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// GH#13978: If the TermControl has already been removed from the UI tree, XAML might run into weird bugs.
|
||||
// This will prevent the `dispatcher.RunAsync` calls below from raising UIA events on the main thread.
|
||||
_termControl = {};
|
||||
|
||||
// Solve the circular reference between us and the content automation peer.
|
||||
_contentAutomationPeer.ParentProvider(nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@ -338,27 +341,43 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
#pragma region ITextProvider
|
||||
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::GetSelection()
|
||||
{
|
||||
return _contentAutomationPeer.GetSelection();
|
||||
auto ret = _contentAutomationPeer.GetSelection();
|
||||
for (const auto& r : ret)
|
||||
{
|
||||
assert(((XamlUiaTextRange*)winrt::get_abi(r))->_refCount.load(std::memory_order_relaxed) == 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::GetVisibleRanges()
|
||||
{
|
||||
return _contentAutomationPeer.GetVisibleRanges();
|
||||
auto ret = _contentAutomationPeer.GetVisibleRanges();
|
||||
for (const auto& r : ret)
|
||||
{
|
||||
assert(((XamlUiaTextRange*)winrt::get_abi(r))->_refCount.load(std::memory_order_relaxed) == 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::RangeFromChild(XamlAutomation::IRawElementProviderSimple childElement)
|
||||
{
|
||||
return _contentAutomationPeer.RangeFromChild(childElement);
|
||||
auto r = _contentAutomationPeer.RangeFromChild(childElement);
|
||||
assert(((XamlUiaTextRange*)winrt::get_abi(r))->_refCount.load(std::memory_order_relaxed) == 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::RangeFromPoint(Windows::Foundation::Point screenLocation)
|
||||
{
|
||||
return _contentAutomationPeer.RangeFromPoint(screenLocation);
|
||||
auto r = _contentAutomationPeer.RangeFromPoint(screenLocation);
|
||||
assert(((XamlUiaTextRange*)winrt::get_abi(r))->_refCount.load(std::memory_order_relaxed) == 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::DocumentRange()
|
||||
{
|
||||
return _contentAutomationPeer.DocumentRange();
|
||||
auto r = _contentAutomationPeer.DocumentRange();
|
||||
assert(((XamlUiaTextRange*)winrt::get_abi(r))->_refCount.load(std::memory_order_relaxed) == 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
XamlAutomation::SupportedTextSelection TermControlAutomationPeer::SupportedTextSelection()
|
||||
|
||||
@ -33,6 +33,14 @@ static std::atomic<int64_t> refCount_XamlUiaTextRange;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
XamlAutomation::ITextRangeProvider XamlUiaTextRange::Create(::ITextRangeProvider* uiaProvider, Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple parentProvider)
|
||||
{
|
||||
const auto self = new XamlUiaTextRange(uiaProvider, parentProvider);
|
||||
XamlAutomation::ITextRangeProvider provider{ nullptr };
|
||||
winrt::attach_abi(provider, (ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider*)self);
|
||||
return provider;
|
||||
}
|
||||
|
||||
XamlUiaTextRange::XamlUiaTextRange(::ITextRangeProvider* uiaProvider, Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple parentProvider) :
|
||||
_parentProvider{ std::move(parentProvider) }
|
||||
{
|
||||
@ -46,225 +54,398 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
refCount_XamlUiaTextRange.fetch_sub(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider XamlUiaTextRange::Clone() const
|
||||
IFACEMETHODIMP_(ULONG) XamlUiaTextRange::AddRef() noexcept
|
||||
{
|
||||
UIA::ITextRangeProvider* pReturn;
|
||||
THROW_IF_FAILED(_uiaProvider->Clone(&pReturn));
|
||||
return winrt::make<XamlUiaTextRange>(pReturn, _parentProvider);
|
||||
return _refCount.fetch_add(1, std::memory_order_relaxed) + 1;
|
||||
}
|
||||
|
||||
bool XamlUiaTextRange::Compare(XamlAutomation::ITextRangeProvider pRange) const
|
||||
IFACEMETHODIMP_(ULONG) XamlUiaTextRange::Release() noexcept
|
||||
{
|
||||
auto self = winrt::get_self<XamlUiaTextRange>(pRange);
|
||||
const auto count = _refCount.fetch_sub(1, std::memory_order_release) - 1;
|
||||
if (count == 0)
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
delete this;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::QueryInterface(REFIID riid, void** ppvObject) noexcept
|
||||
{
|
||||
if (!ppvObject)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObject = nullptr;
|
||||
|
||||
if (riid == __uuidof(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider) ||
|
||||
riid == __uuidof(IInspectable) ||
|
||||
riid == __uuidof(IUnknown))
|
||||
{
|
||||
*ppvObject = static_cast<ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::GetIids(ULONG* iidCount, IID** iids) noexcept
|
||||
{
|
||||
if (!iidCount || !iids)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*iidCount = 1;
|
||||
*iids = static_cast<IID*>(CoTaskMemAlloc(sizeof(IID)));
|
||||
if (!*iids)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*iids)[0] = __uuidof(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::GetRuntimeClassName(HSTRING* className) noexcept
|
||||
{
|
||||
if (!className)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return WindowsCreateString(L"Microsoft.Terminal.Control.XamlUiaTextRange", 47, className);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::GetTrustLevel(TrustLevel* trustLevel) noexcept
|
||||
{
|
||||
if (!trustLevel)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*trustLevel = TrustLevel::BaseTrust;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::Clone(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider** result) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = nullptr;
|
||||
|
||||
UIA::ITextRangeProvider* pReturn;
|
||||
RETURN_IF_FAILED(_uiaProvider->Clone(&pReturn));
|
||||
|
||||
auto xamlRange = new (std::nothrow) XamlUiaTextRange(pReturn, _parentProvider);
|
||||
RETURN_IF_NULL_ALLOC(xamlRange);
|
||||
|
||||
*result = xamlRange;
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::Compare(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider* textRangeProvider, boolean* result) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = false;
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textRangeProvider);
|
||||
|
||||
auto self = static_cast<XamlUiaTextRange*>(textRangeProvider);
|
||||
|
||||
BOOL returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->Compare(self->_uiaProvider.get(), &returnVal));
|
||||
return returnVal;
|
||||
RETURN_IF_FAILED(_uiaProvider->Compare(self->_uiaProvider.get(), &returnVal));
|
||||
*result = !!returnVal;
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
int32_t XamlUiaTextRange::CompareEndpoints(XamlAutomation::TextPatternRangeEndpoint endpoint,
|
||||
XamlAutomation::ITextRangeProvider pTargetRange,
|
||||
XamlAutomation::TextPatternRangeEndpoint targetEndpoint)
|
||||
IFACEMETHODIMP XamlUiaTextRange::CompareEndpoints(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider* textRangeProvider,
|
||||
ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint,
|
||||
INT32* result) noexcept
|
||||
try
|
||||
{
|
||||
auto self = winrt::get_self<XamlUiaTextRange>(pTargetRange);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = 0;
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textRangeProvider);
|
||||
|
||||
auto self = static_cast<XamlUiaTextRange*>(textRangeProvider);
|
||||
|
||||
int32_t returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->CompareEndpoints(static_cast<UIA::TextPatternRangeEndpoint>(endpoint),
|
||||
self->_uiaProvider.get(),
|
||||
static_cast<UIA::TextPatternRangeEndpoint>(targetEndpoint),
|
||||
&returnVal));
|
||||
return returnVal;
|
||||
RETURN_IF_FAILED(_uiaProvider->CompareEndpoints(static_cast<UIA::TextPatternRangeEndpoint>(endpoint),
|
||||
self->_uiaProvider.get(),
|
||||
static_cast<UIA::TextPatternRangeEndpoint>(targetEndpoint),
|
||||
&returnVal));
|
||||
*result = returnVal;
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
void XamlUiaTextRange::ExpandToEnclosingUnit(XamlAutomation::TextUnit unit) const
|
||||
IFACEMETHODIMP XamlUiaTextRange::ExpandToEnclosingUnit(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit) noexcept
|
||||
try
|
||||
{
|
||||
THROW_IF_FAILED(_uiaProvider->ExpandToEnclosingUnit(static_cast<UIA::TextUnit>(unit)));
|
||||
RETURN_IF_FAILED(_uiaProvider->ExpandToEnclosingUnit(static_cast<UIA::TextUnit>(unit)));
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
XamlAutomation::ITextRangeProvider XamlUiaTextRange::FindAttribute(int32_t /*textAttributeId*/,
|
||||
winrt::Windows::Foundation::IInspectable /*val*/,
|
||||
bool /*searchBackward*/)
|
||||
IFACEMETHODIMP XamlUiaTextRange::FindAttribute(INT32 /*attributeId*/,
|
||||
IInspectable* /*value*/,
|
||||
boolean /*backward*/,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider** result) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = nullptr;
|
||||
// TODO GitHub #2161: potential accessibility improvement
|
||||
// we don't support this currently
|
||||
throw winrt::hresult_not_implemented();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider XamlUiaTextRange::FindText(winrt::hstring text,
|
||||
bool searchBackward,
|
||||
bool ignoreCase)
|
||||
IFACEMETHODIMP XamlUiaTextRange::FindText(HSTRING text,
|
||||
boolean searchBackward,
|
||||
boolean ignoreCase,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider** result) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = nullptr;
|
||||
|
||||
UIA::ITextRangeProvider* pReturn;
|
||||
const auto queryText = wil::make_bstr(text.c_str());
|
||||
uint32_t length;
|
||||
const auto textPtr = WindowsGetStringRawBuffer(text, &length);
|
||||
const auto queryText = wil::unique_bstr{ SysAllocStringLen(textPtr, length) };
|
||||
|
||||
THROW_IF_FAILED(_uiaProvider->FindText(queryText.get(), searchBackward, ignoreCase, &pReturn));
|
||||
RETURN_IF_FAILED(_uiaProvider->FindText(queryText.get(), searchBackward, ignoreCase, &pReturn));
|
||||
|
||||
return winrt::make<XamlUiaTextRange>(pReturn, _parentProvider);
|
||||
if (pReturn)
|
||||
{
|
||||
auto xamlRange = new (std::nothrow) XamlUiaTextRange(pReturn, _parentProvider);
|
||||
RETURN_IF_NULL_ALLOC(xamlRange);
|
||||
*result = xamlRange;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
winrt::Windows::Foundation::IInspectable XamlUiaTextRange::GetAttributeValue(int32_t textAttributeId) const
|
||||
IFACEMETHODIMP XamlUiaTextRange::GetAttributeValue(INT32 attributeId, IInspectable** result) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = nullptr;
|
||||
|
||||
// Call the function off of the underlying UiaTextRange.
|
||||
wil::unique_variant result;
|
||||
THROW_IF_FAILED(_uiaProvider->GetAttributeValue(textAttributeId, result.addressof()));
|
||||
wil::unique_variant varResult;
|
||||
RETURN_IF_FAILED(_uiaProvider->GetAttributeValue(attributeId, varResult.addressof()));
|
||||
|
||||
// Convert the resulting VARIANT into a format that is consumable by XAML.
|
||||
switch (result.vt)
|
||||
switch (varResult.vt)
|
||||
{
|
||||
case VT_BSTR:
|
||||
{
|
||||
return box_value(result.bstrVal);
|
||||
auto value = winrt::box_value(varResult.bstrVal);
|
||||
*result = static_cast<IInspectable*>(winrt::detach_abi(value));
|
||||
return S_OK;
|
||||
}
|
||||
case VT_I4:
|
||||
{
|
||||
// Surprisingly, `long` is _not_ a WinRT type.
|
||||
// So we have to use `int32_t` to make sure this is output properly.
|
||||
// Otherwise, you'll get "Attribute does not exist" out the other end.
|
||||
return box_value<int32_t>(result.lVal);
|
||||
auto value = winrt::box_value<int32_t>(varResult.lVal);
|
||||
*result = static_cast<IInspectable*>(winrt::detach_abi(value));
|
||||
return S_OK;
|
||||
}
|
||||
case VT_R8:
|
||||
{
|
||||
return box_value(result.dblVal);
|
||||
auto value = winrt::box_value(varResult.dblVal);
|
||||
*result = static_cast<IInspectable*>(winrt::detach_abi(value));
|
||||
return S_OK;
|
||||
}
|
||||
case VT_BOOL:
|
||||
{
|
||||
return box_value<bool>(result.boolVal);
|
||||
auto value = winrt::box_value<bool>(varResult.boolVal);
|
||||
*result = static_cast<IInspectable*>(winrt::detach_abi(value));
|
||||
return S_OK;
|
||||
}
|
||||
case VT_UNKNOWN:
|
||||
{
|
||||
// This one is particularly special.
|
||||
// We might return a special value like UiaGetReservedMixedAttributeValue
|
||||
// or UiaGetReservedNotSupportedValue.
|
||||
// Some text attributes may return a real value, however, none of those
|
||||
// are supported at this time.
|
||||
// So we need to figure out what was actually intended to be returned.
|
||||
|
||||
com_ptr<IUnknown> mixedAttributeVal;
|
||||
UiaGetReservedMixedAttributeValue(mixedAttributeVal.put());
|
||||
|
||||
if (result.punkVal == mixedAttributeVal.get())
|
||||
if (varResult.punkVal == mixedAttributeVal.get())
|
||||
{
|
||||
return Windows::UI::Xaml::DependencyProperty::UnsetValue();
|
||||
auto value = Windows::UI::Xaml::DependencyProperty::UnsetValue();
|
||||
*result = static_cast<IInspectable*>(winrt::detach_abi(value));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
[[fallthrough]];
|
||||
}
|
||||
default:
|
||||
{
|
||||
// We _need_ to return XAML_E_NOT_SUPPORTED here.
|
||||
// Returning nullptr is an improper implementation of it being unsupported.
|
||||
// UIA Clients rely on this HRESULT to signify that the requested attribute is undefined.
|
||||
// Anything else will result in the UIA Client refusing to read when navigating by word
|
||||
// Magically, this doesn't affect other forms of navigation...
|
||||
winrt::throw_hresult(XAML_E_NOT_SUPPORTED);
|
||||
}
|
||||
return XAML_E_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
void XamlUiaTextRange::GetBoundingRectangles(com_array<double>& returnValue) const
|
||||
IFACEMETHODIMP XamlUiaTextRange::GetBoundingRectangles(UINT32* returnValueLength, DOUBLE** returnValue) noexcept
|
||||
try
|
||||
{
|
||||
returnValue = {};
|
||||
try
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, returnValueLength);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, returnValue);
|
||||
*returnValueLength = 0;
|
||||
*returnValue = nullptr;
|
||||
|
||||
SAFEARRAY* pReturnVal;
|
||||
RETURN_IF_FAILED(_uiaProvider->GetBoundingRectangles(&pReturnVal));
|
||||
|
||||
double* pVals;
|
||||
RETURN_IF_FAILED(SafeArrayAccessData(pReturnVal, (void**)&pVals));
|
||||
|
||||
long lBound, uBound;
|
||||
RETURN_IF_FAILED(SafeArrayGetLBound(pReturnVal, 1, &lBound));
|
||||
RETURN_IF_FAILED(SafeArrayGetUBound(pReturnVal, 1, &uBound));
|
||||
|
||||
auto count = uBound - lBound + 1;
|
||||
|
||||
auto result = static_cast<DOUBLE*>(CoTaskMemAlloc(sizeof(DOUBLE) * count));
|
||||
if (!result)
|
||||
{
|
||||
SAFEARRAY* pReturnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->GetBoundingRectangles(&pReturnVal));
|
||||
|
||||
double* pVals;
|
||||
THROW_IF_FAILED(SafeArrayAccessData(pReturnVal, (void**)&pVals));
|
||||
|
||||
long lBound, uBound;
|
||||
THROW_IF_FAILED(SafeArrayGetLBound(pReturnVal, 1, &lBound));
|
||||
THROW_IF_FAILED(SafeArrayGetUBound(pReturnVal, 1, &uBound));
|
||||
|
||||
auto count = uBound - lBound + 1;
|
||||
|
||||
std::vector<double> vec;
|
||||
vec.reserve(count);
|
||||
for (auto i = 0; i < count; i++)
|
||||
{
|
||||
auto element = pVals[i];
|
||||
vec.push_back(element);
|
||||
}
|
||||
|
||||
winrt::com_array<double> result{ vec };
|
||||
returnValue = std::move(result);
|
||||
|
||||
THROW_IF_FAILED(SafeArrayUnaccessData(pReturnVal));
|
||||
THROW_IF_FAILED(SafeArrayDestroy(pReturnVal));
|
||||
SafeArrayUnaccessData(pReturnVal);
|
||||
SafeArrayDestroy(pReturnVal);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
XamlAutomation::IRawElementProviderSimple XamlUiaTextRange::GetEnclosingElement()
|
||||
for (auto i = 0; i < count; i++)
|
||||
{
|
||||
result[i] = pVals[i];
|
||||
}
|
||||
|
||||
*returnValueLength = count;
|
||||
*returnValue = result;
|
||||
|
||||
RETURN_IF_FAILED(SafeArrayUnaccessData(pReturnVal));
|
||||
RETURN_IF_FAILED(SafeArrayDestroy(pReturnVal));
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::GetEnclosingElement(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple** result) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = nullptr;
|
||||
|
||||
::Microsoft::Console::Types::UiaTracing::TextRange::GetEnclosingElement(*static_cast<::Microsoft::Console::Types::UiaTextRangeBase*>(_uiaProvider.get()));
|
||||
return _parentProvider;
|
||||
winrt::copy_to_abi(_parentProvider, (void*&)*result);
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
winrt::hstring XamlUiaTextRange::GetText(int32_t maxLength) const
|
||||
IFACEMETHODIMP XamlUiaTextRange::GetText(INT32 maxLength, HSTRING* result) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = nullptr;
|
||||
|
||||
wil::unique_bstr returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->GetText(maxLength, returnVal.put()));
|
||||
return winrt::hstring{ returnVal.get(), SysStringLen(returnVal.get()) };
|
||||
}
|
||||
RETURN_IF_FAILED(_uiaProvider->GetText(maxLength, returnVal.put()));
|
||||
|
||||
int32_t XamlUiaTextRange::Move(XamlAutomation::TextUnit unit,
|
||||
int32_t count)
|
||||
RETURN_IF_FAILED(WindowsCreateString(returnVal.get(), SysStringLen(returnVal.get()), result));
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::Move(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit,
|
||||
INT32 count,
|
||||
INT32* result) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = 0;
|
||||
|
||||
int returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->Move(static_cast<UIA::TextUnit>(unit),
|
||||
count,
|
||||
&returnVal));
|
||||
return returnVal;
|
||||
RETURN_IF_FAILED(_uiaProvider->Move(static_cast<UIA::TextUnit>(unit),
|
||||
count,
|
||||
&returnVal));
|
||||
*result = returnVal;
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
int32_t XamlUiaTextRange::MoveEndpointByUnit(XamlAutomation::TextPatternRangeEndpoint endpoint,
|
||||
XamlAutomation::TextUnit unit,
|
||||
int32_t count) const
|
||||
IFACEMETHODIMP XamlUiaTextRange::MoveEndpointByUnit(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit,
|
||||
INT32 count,
|
||||
INT32* result) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
*result = 0;
|
||||
|
||||
int returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->MoveEndpointByUnit(static_cast<UIA::TextPatternRangeEndpoint>(endpoint),
|
||||
static_cast<UIA::TextUnit>(unit),
|
||||
count,
|
||||
&returnVal));
|
||||
return returnVal;
|
||||
RETURN_IF_FAILED(_uiaProvider->MoveEndpointByUnit(static_cast<UIA::TextPatternRangeEndpoint>(endpoint),
|
||||
static_cast<UIA::TextUnit>(unit),
|
||||
count,
|
||||
&returnVal));
|
||||
*result = returnVal;
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
void XamlUiaTextRange::MoveEndpointByRange(XamlAutomation::TextPatternRangeEndpoint endpoint,
|
||||
XamlAutomation::ITextRangeProvider pTargetRange,
|
||||
XamlAutomation::TextPatternRangeEndpoint targetEndpoint) const
|
||||
IFACEMETHODIMP XamlUiaTextRange::MoveEndpointByRange(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider* textRangeProvider,
|
||||
ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint) noexcept
|
||||
try
|
||||
{
|
||||
auto self = winrt::get_self<XamlUiaTextRange>(pTargetRange);
|
||||
THROW_IF_FAILED(_uiaProvider->MoveEndpointByRange(static_cast<UIA::TextPatternRangeEndpoint>(endpoint),
|
||||
/*pTargetRange*/ self->_uiaProvider.get(),
|
||||
static_cast<UIA::TextPatternRangeEndpoint>(targetEndpoint)));
|
||||
}
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, textRangeProvider);
|
||||
|
||||
void XamlUiaTextRange::Select() const
|
||||
auto self = static_cast<XamlUiaTextRange*>(textRangeProvider);
|
||||
RETURN_IF_FAILED(_uiaProvider->MoveEndpointByRange(static_cast<UIA::TextPatternRangeEndpoint>(endpoint),
|
||||
self->_uiaProvider.get(),
|
||||
static_cast<UIA::TextPatternRangeEndpoint>(targetEndpoint)));
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
IFACEMETHODIMP XamlUiaTextRange::Select() noexcept
|
||||
try
|
||||
{
|
||||
THROW_IF_FAILED(_uiaProvider->Select());
|
||||
RETURN_IF_FAILED(_uiaProvider->Select());
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
void XamlUiaTextRange::AddToSelection() const
|
||||
IFACEMETHODIMP XamlUiaTextRange::AddToSelection() noexcept
|
||||
{
|
||||
// we don't support this
|
||||
throw winrt::hresult_not_implemented();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
void XamlUiaTextRange::RemoveFromSelection() const
|
||||
IFACEMETHODIMP XamlUiaTextRange::RemoveFromSelection() noexcept
|
||||
{
|
||||
// we don't support this
|
||||
throw winrt::hresult_not_implemented();
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
void XamlUiaTextRange::ScrollIntoView(bool alignToTop) const
|
||||
IFACEMETHODIMP XamlUiaTextRange::ScrollIntoView(boolean alignToTop) noexcept
|
||||
try
|
||||
{
|
||||
THROW_IF_FAILED(_uiaProvider->ScrollIntoView(alignToTop));
|
||||
RETURN_IF_FAILED(_uiaProvider->ScrollIntoView(alignToTop));
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
winrt::com_array<XamlAutomation::IRawElementProviderSimple> XamlUiaTextRange::GetChildren() const
|
||||
IFACEMETHODIMP XamlUiaTextRange::GetChildren(UINT32* resultLength,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple*** result) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, resultLength);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, result);
|
||||
|
||||
// we don't have any children
|
||||
return {};
|
||||
*resultLength = 0;
|
||||
*result = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,50 +23,68 @@ Author(s):
|
||||
#include "TermControlAutomationPeer.h"
|
||||
#include <UIAutomationCore.h>
|
||||
#include "../types/TermControlUiaTextRange.hpp"
|
||||
#include <windows.ui.xaml.automation.provider.h>
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
class XamlUiaTextRange :
|
||||
public winrt::implements<XamlUiaTextRange, Windows::UI::Xaml::Automation::Provider::ITextRangeProvider>
|
||||
class XamlUiaTextRange : public ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider
|
||||
{
|
||||
public:
|
||||
static winrt::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider Create(::ITextRangeProvider* uiaProvider, Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple parentProvider);
|
||||
|
||||
XamlUiaTextRange(::ITextRangeProvider* uiaProvider, Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple parentProvider);
|
||||
~XamlUiaTextRange();
|
||||
|
||||
// IUnknown
|
||||
IFACEMETHODIMP_(ULONG) AddRef() noexcept override;
|
||||
IFACEMETHODIMP_(ULONG) Release() noexcept override;
|
||||
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppvObject) noexcept override;
|
||||
|
||||
// IInspectable
|
||||
IFACEMETHODIMP GetIids(ULONG* iidCount, IID** iids) noexcept override;
|
||||
IFACEMETHODIMP GetRuntimeClassName(HSTRING* className) noexcept override;
|
||||
IFACEMETHODIMP GetTrustLevel(TrustLevel* trustLevel) noexcept override;
|
||||
|
||||
#pragma region ITextRangeProvider
|
||||
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider Clone() const;
|
||||
bool Compare(Windows::UI::Xaml::Automation::Provider::ITextRangeProvider pRange) const;
|
||||
int32_t CompareEndpoints(Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider pTargetRange,
|
||||
Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint);
|
||||
void ExpandToEnclosingUnit(Windows::UI::Xaml::Automation::Text::TextUnit unit) const;
|
||||
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider FindAttribute(int32_t textAttributeId,
|
||||
winrt::Windows::Foundation::IInspectable val,
|
||||
bool searchBackward);
|
||||
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider FindText(winrt::hstring text,
|
||||
bool searchBackward,
|
||||
bool ignoreCase);
|
||||
winrt::Windows::Foundation::IInspectable GetAttributeValue(int32_t textAttributeId) const;
|
||||
void GetBoundingRectangles(winrt::com_array<double>& returnValue) const;
|
||||
Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple GetEnclosingElement();
|
||||
winrt::hstring GetText(int32_t maxLength) const;
|
||||
int32_t Move(Windows::UI::Xaml::Automation::Text::TextUnit unit,
|
||||
int32_t count);
|
||||
int32_t MoveEndpointByUnit(Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
Windows::UI::Xaml::Automation::Text::TextUnit unit,
|
||||
int32_t count) const;
|
||||
void MoveEndpointByRange(Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider pTargetRange,
|
||||
Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint) const;
|
||||
void Select() const;
|
||||
void AddToSelection() const;
|
||||
void RemoveFromSelection() const;
|
||||
void ScrollIntoView(bool alignToTop) const;
|
||||
winrt::com_array<Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple> GetChildren() const;
|
||||
IFACEMETHODIMP Clone(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider** result) noexcept override;
|
||||
IFACEMETHODIMP Compare(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider* textRangeProvider, boolean* result) noexcept override;
|
||||
IFACEMETHODIMP CompareEndpoints(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider* textRangeProvider,
|
||||
ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint,
|
||||
INT32* result) noexcept override;
|
||||
IFACEMETHODIMP ExpandToEnclosingUnit(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit) noexcept override;
|
||||
IFACEMETHODIMP FindAttribute(INT32 attributeId,
|
||||
IInspectable* value,
|
||||
boolean backward,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider** result) noexcept override;
|
||||
IFACEMETHODIMP FindText(HSTRING text,
|
||||
boolean backward,
|
||||
boolean ignoreCase,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider** result) noexcept override;
|
||||
IFACEMETHODIMP GetAttributeValue(INT32 attributeId, IInspectable** result) noexcept override;
|
||||
IFACEMETHODIMP GetBoundingRectangles(UINT32* returnValueLength, DOUBLE** returnValue) noexcept override;
|
||||
IFACEMETHODIMP GetEnclosingElement(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple** result) noexcept override;
|
||||
IFACEMETHODIMP GetText(INT32 maxLength, HSTRING* result) noexcept override;
|
||||
IFACEMETHODIMP Move(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit,
|
||||
INT32 count,
|
||||
INT32* result) noexcept override;
|
||||
IFACEMETHODIMP MoveEndpointByUnit(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit,
|
||||
INT32 count,
|
||||
INT32* result) noexcept override;
|
||||
IFACEMETHODIMP MoveEndpointByRange(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider* textRangeProvider,
|
||||
ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint) noexcept override;
|
||||
IFACEMETHODIMP Select() noexcept override;
|
||||
IFACEMETHODIMP AddToSelection() noexcept override;
|
||||
IFACEMETHODIMP RemoveFromSelection() noexcept override;
|
||||
IFACEMETHODIMP ScrollIntoView(boolean alignToTop) noexcept override;
|
||||
IFACEMETHODIMP GetChildren(UINT32* resultLength,
|
||||
ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple*** result) noexcept override;
|
||||
#pragma endregion ITextRangeProvider
|
||||
|
||||
private:
|
||||
wil::com_ptr<::ITextRangeProvider> _uiaProvider;
|
||||
Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple _parentProvider;
|
||||
std::atomic<ULONG> _refCount{ 1 };
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user