Skip to content

Commit

Permalink
Introduce UiaTextRangeBase::FindText() for Accessibility (#4373)
Browse files Browse the repository at this point in the history
Moved `FindText` to `UiaTextRangeBase`. Now that Search is a shared component (thanks #3279), I can just reuse it basically as-is.

#3279 - Make Search a shared component
#4018 - UiaTextRange Refactor

I removed it from the two different kinds of UiaTextRange and put it in the base class.

I needed a very minor change to ensure we convert from an inclusive end (from Search) to an exclusive end (in UTR).

Worked with `FindText` was globally messed with in windows.h. So we had to do a few weird things there (thanks Michael).

No need for additional tests because it _literally_ just sets up a Searcher and calls it.
  • Loading branch information
carlos-zamora committed Jan 31, 2020
1 parent 29df540 commit 55b6388
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 87 deletions.
9 changes: 0 additions & 9 deletions src/cascadia/TerminalControl/UiaTextRange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,6 @@ IFACEMETHODIMP UiaTextRange::Clone(_Outptr_result_maybenull_ ITextRangeProvider*
return S_OK;
}

IFACEMETHODIMP UiaTextRange::FindText(_In_ BSTR /*text*/,
_In_ BOOL /*searchBackward*/,
_In_ BOOL /*ignoreCase*/,
_Outptr_result_maybenull_ ITextRangeProvider** /*ppRetVal*/)
{
// TODO GitHub #605: Search functionality
return E_NOTIMPL;
}

void UiaTextRange::_ChangeViewport(const SMALL_RECT /*NewWindow*/)
{
// TODO GitHub #2361: Update viewport when calling UiaTextRangeBase::ScrollIntoView()
Expand Down
4 changes: 0 additions & 4 deletions src/cascadia/TerminalControl/UiaTextRange.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ namespace Microsoft::Terminal
HRESULT RuntimeClassInitialize(const UiaTextRange& a);

IFACEMETHODIMP Clone(_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;
IFACEMETHODIMP FindText(_In_ BSTR text,
_In_ BOOL searchBackward,
_In_ BOOL ignoreCase,
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;

protected:
void _ChangeViewport(const SMALL_RECT NewWindow) override;
Expand Down
18 changes: 11 additions & 7 deletions src/cascadia/TerminalControl/XamlUiaTextRange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "pch.h"
#include "XamlUiaTextRange.h"
#include "UiaTextRange.hpp"
#include <UIAutomationClient.h>

// the same as COR_E_NOTSUPPORTED
// we don't want to import the CLR headers to get it
Expand Down Expand Up @@ -73,14 +74,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
throw winrt::hresult_not_implemented();
}

XamlAutomation::ITextRangeProvider XamlUiaTextRange::FindText(winrt::hstring /*text*/,
bool /*searchBackward*/,
bool /*ignoreCase*/)
XamlAutomation::ITextRangeProvider XamlUiaTextRange::FindText(winrt::hstring text,
bool searchBackward,
bool ignoreCase)
{
// TODO GitHub #605: Search functionality
// we need to wrap this around the UiaTextRange FindText() function
// but right now it returns E_NOTIMPL, so let's just return nullptr for now.
return nullptr;
UIA::ITextRangeProvider* pReturn;
const auto queryText = wil::make_bstr(text.c_str());

THROW_IF_FAILED(_uiaProvider->FindText(queryText.get(), searchBackward, ignoreCase, &pReturn));

auto xutr = winrt::make_self<XamlUiaTextRange>(pReturn, _parentProvider);
return *xutr;
}

winrt::Windows::Foundation::IInspectable XamlUiaTextRange::GetAttributeValue(int32_t textAttributeId) const
Expand Down
4 changes: 4 additions & 0 deletions src/inc/HostAndPropsheetIncludes.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

// clang-format off

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN // If this is not defined, windows.h includes commdlg.h which defines FindText globally and conflicts with UIAutomation ITextRangeProvider.
#endif

// Define and then undefine WIN32_NO_STATUS because windows.h has no guard to prevent it from double defing certain statuses
// when included with ntstatus.h
#define WIN32_NO_STATUS
Expand Down
3 changes: 2 additions & 1 deletion src/interactivity/win32/screenInfoUiaProvider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ Author(s):

#pragma once

#include "precomp.h"
#include <UIAutomationCore.h>

#include "..\types\ScreenInfoUiaProviderBase.h"
#include "..\types\UiaTextRangeBase.hpp"
#include "uiaTextRange.hpp"
Expand Down
53 changes: 0 additions & 53 deletions src/interactivity/win32/uiaTextRange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

#include "uiaTextRange.hpp"
#include "screenInfoUiaProvider.hpp"
#include "..\buffer\out\search.h"
#include "..\interactivity\inc\ServiceLocator.hpp"

using namespace Microsoft::Console::Types;
Expand Down Expand Up @@ -105,58 +104,6 @@ IFACEMETHODIMP UiaTextRange::Clone(_Outptr_result_maybenull_ ITextRangeProvider*
return S_OK;
}

IFACEMETHODIMP UiaTextRange::FindText(_In_ BSTR text,
_In_ BOOL searchBackward,
_In_ BOOL ignoreCase,
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal)
{
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
//Tracing::s_TraceUia(this, ApiCall::FindText, nullptr);
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
*ppRetVal = nullptr;
try
{
const std::wstring wstr{ text, SysStringLen(text) };
const auto sensitivity = ignoreCase ? Search::Sensitivity::CaseInsensitive : Search::Sensitivity::CaseSensitive;

auto searchDirection = Search::Direction::Forward;
auto searchAnchor = _start;
if (searchBackward)
{
searchDirection = Search::Direction::Backward;
searchAnchor = _end;
}

CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
THROW_HR_IF(E_POINTER, !gci.HasActiveOutputBuffer());
Search searcher{ gci.renderData, wstr, searchDirection, sensitivity, searchAnchor };

HRESULT hr = S_OK;
if (searcher.FindNext())
{
const auto foundLocation = searcher.GetFoundLocation();
const auto start = foundLocation.first;
const auto end = foundLocation.second;
const auto bufferSize = _pData->GetTextBuffer().GetSize();

// make sure what was found is within the bounds of the current range
if ((searchDirection == Search::Direction::Forward && bufferSize.CompareInBounds(end, _end) < 0) ||
(searchDirection == Search::Direction::Backward && bufferSize.CompareInBounds(start, _start) > 0))
{
hr = Clone(ppRetVal);
if (SUCCEEDED(hr))
{
UiaTextRange& range = static_cast<UiaTextRange&>(**ppRetVal);
range._start = start;
range._end = end;
}
}
}
return hr;
}
CATCH_RETURN();
}

void UiaTextRange::_ChangeViewport(const SMALL_RECT NewWindow)
{
auto provider = static_cast<ScreenInfoUiaProvider*>(_pProvider);
Expand Down
4 changes: 0 additions & 4 deletions src/interactivity/win32/uiaTextRange.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ namespace Microsoft::Console::Interactivity::Win32
HRESULT RuntimeClassInitialize(const UiaTextRange& a);

IFACEMETHODIMP Clone(_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;
IFACEMETHODIMP FindText(_In_ BSTR text,
_In_ BOOL searchBackward,
_In_ BOOL ignoreCase,
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) override;

protected:
void _ChangeViewport(const SMALL_RECT NewWindow) override;
Expand Down
3 changes: 2 additions & 1 deletion src/types/ScreenInfoUiaProviderBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ Author(s):

#pragma once

#include "precomp.h"
#include "../buffer/out/textBuffer.hpp"
#include "UiaTextRangeBase.hpp"
#include "IUiaData.h"

#include <UIAutomationCore.h>

#include <wrl/implements.h>

namespace Microsoft::Console::Types
Expand Down
55 changes: 54 additions & 1 deletion src/types/UiaTextRangeBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "precomp.h"
#include "UiaTextRangeBase.hpp"
#include "ScreenInfoUiaProviderBase.h"
#include "..\buffer\out\search.h"

using namespace Microsoft::Console::Types;
using namespace Microsoft::Console::Types::UiaTextRangeBaseTracing;
Expand Down Expand Up @@ -346,6 +347,58 @@ IFACEMETHODIMP UiaTextRangeBase::FindAttribute(_In_ TEXTATTRIBUTEID /*textAttrib
return E_NOTIMPL;
}

IFACEMETHODIMP UiaTextRangeBase::FindText(_In_ BSTR text,
_In_ BOOL searchBackward,
_In_ BOOL ignoreCase,
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) noexcept
try
{
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
//Tracing::s_TraceUia(this, ApiCall::FindText, nullptr);
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
*ppRetVal = nullptr;

const std::wstring queryText{ text, SysStringLen(text) };
const auto bufferSize = _pData->GetTextBuffer().GetSize();
const auto sensitivity = ignoreCase ? Search::Sensitivity::CaseInsensitive : Search::Sensitivity::CaseSensitive;

auto searchDirection = Search::Direction::Forward;
auto searchAnchor = _start;
if (searchBackward)
{
searchDirection = Search::Direction::Backward;

// we need to convert the end to inclusive
// because Search operates with an inclusive COORD
searchAnchor = _end;
bufferSize.DecrementInBounds(searchAnchor, true);
}

Search searcher{ *_pData, queryText, searchDirection, sensitivity, searchAnchor };

if (searcher.FindNext())
{
const auto foundLocation = searcher.GetFoundLocation();
const auto start = foundLocation.first;

// we need to increment the position of end because it's exclusive
auto end = foundLocation.second;
bufferSize.IncrementInBounds(end, true);

// make sure what was found is within the bounds of the current range
if ((searchDirection == Search::Direction::Forward && bufferSize.CompareInBounds(end, _end, true) < 0) ||
(searchDirection == Search::Direction::Backward && bufferSize.CompareInBounds(start, _start) > 0))
{
RETURN_IF_FAILED(Clone(ppRetVal));
UiaTextRangeBase& range = static_cast<UiaTextRangeBase&>(**ppRetVal);
range._start = start;
range._end = end;
}
}
return S_OK;
}
CATCH_RETURN();

IFACEMETHODIMP UiaTextRangeBase::GetAttributeValue(_In_ TEXTATTRIBUTEID textAttributeId,
_Out_ VARIANT* pRetVal) noexcept
{
Expand Down Expand Up @@ -930,7 +983,7 @@ const unsigned int UiaTextRangeBase::_getViewportHeight(const SMALL_RECT viewpor
void UiaTextRangeBase::_getBoundingRect(_In_ const COORD startAnchor, _In_ const COORD endAnchor, _Inout_ std::vector<double>& coords) const
{
FAIL_FAST_IF(startAnchor.Y != endAnchor.Y);
FAIL_FAST_IF(startAnchor.X <= endAnchor.X);
FAIL_FAST_IF(startAnchor.X >= endAnchor.X);

const auto viewport = _pData->GetViewport();
const auto currentFontSize = _getScreenFontSize();
Expand Down
11 changes: 5 additions & 6 deletions src/types/UiaTextRangeBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ Author(s):

#pragma once

#include "precomp.h"

#include "inc/viewport.hpp"
#include "../buffer/out/textBuffer.hpp"
#include "IUiaData.h"
#include "unicode.hpp"

#include <UIAutomationCore.h>
#include <deque>
#include <tuple>
#include <wrl/implements.h>
Expand Down Expand Up @@ -103,10 +102,10 @@ namespace Microsoft::Console::Types
_In_ VARIANT val,
_In_ BOOL searchBackward,
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) noexcept override;
virtual IFACEMETHODIMP FindText(_In_ BSTR text,
_In_ BOOL searchBackward,
_In_ BOOL ignoreCase,
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) = 0;
IFACEMETHODIMP FindText(_In_ BSTR text,
_In_ BOOL searchBackward,
_In_ BOOL ignoreCase,
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal) noexcept override;
IFACEMETHODIMP GetAttributeValue(_In_ TEXTATTRIBUTEID textAttributeId,
_Out_ VARIANT* pRetVal) noexcept override;
IFACEMETHODIMP GetBoundingRectangles(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) noexcept override;
Expand Down
2 changes: 1 addition & 1 deletion src/types/WindowUiaProviderBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Author(s):

#pragma once

#include "precomp.h"
#include <UIAutomationCore.h>

#include <wrl/implements.h>

Expand Down

0 comments on commit 55b6388

Please sign in to comment.