Skip to content

Commit

Permalink
Accessibility: Finalized Shared UIA Tree Model (#1915)
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-zamora committed Jul 23, 2019
1 parent 6a501c1 commit c10a895
Show file tree
Hide file tree
Showing 32 changed files with 2,362 additions and 2,568 deletions.
18 changes: 17 additions & 1 deletion src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ class Microsoft::Terminal::Core::Terminal final :
const std::vector<Microsoft::Console::Render::RenderOverlay> GetOverlays() const noexcept override;
const bool IsGridLineDrawingAllowed() noexcept override;
std::vector<Microsoft::Console::Types::Viewport> GetSelectionRects() noexcept override;
bool IsAreaSelected() const override;
void ClearSelection() override;
void SelectNewRegion(const COORD coordStart, const COORD coordEnd) override;

// TODO GitHub #605: Search functionality
// For now, just adding it here to make UiaTextRange easier to create (Accessibility)
// We should actually abstract this out better once Windows Terminal has Search
HRESULT SearchForText(_In_ BSTR text,
_In_ BOOL searchBackward,
_In_ BOOL ignoreCase,
_Outptr_result_maybenull_ ITextRangeProvider** ppRetVal,
unsigned int _start,
unsigned int _end,
std::function<unsigned int(IRenderData*, const COORD)> _coordToEndpoint,
std::function<COORD(IRenderData*, const unsigned int)> _endpointToCoord,
std::function<IFACEMETHODIMP(ITextRangeProvider**)> Clone) override;

const std::wstring GetConsoleTitle() const noexcept override;
void LockConsole() noexcept override;
void UnlockConsole() noexcept override;
Expand All @@ -122,7 +139,6 @@ class Microsoft::Terminal::Core::Terminal final :
void SetSelectionAnchor(const COORD position);
void SetEndSelectionPosition(const COORD position);
void SetBoxSelection(const bool isEnabled) noexcept;
void ClearSelection() noexcept;

const std::wstring RetrieveSelectedTextFromBuffer(bool trimTrailingWhitespace) const;
#pragma endregion
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalCore/TerminalSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ void Terminal::SetBoxSelection(const bool isEnabled) noexcept

// Method Description:
// - clear selection data and disable rendering it
void Terminal::ClearSelection() noexcept
void Terminal::ClearSelection()
{
_selectionActive = false;
_selectionAnchor = { 0, 0 };
Expand Down
27 changes: 27 additions & 0 deletions src/cascadia/TerminalCore/terminalrenderdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,33 @@ std::vector<Microsoft::Console::Types::Viewport> Terminal::GetSelectionRects() n
return result;
}

bool Terminal::IsAreaSelected() const
{
return _selectionActive;
}

void Terminal::SelectNewRegion(const COORD coordStart, const COORD coordEnd)
{
SetSelectionAnchor(coordStart);
SetEndSelectionPosition(coordEnd);
}

// TODO GitHub #605: Search functionality
// For now, just adding it here to make UiaTextRange easier to create (Accessibility)
// We should actually abstract this out better once Windows Terminal has Search
HRESULT Terminal::SearchForText(_In_ BSTR /*text*/,
_In_ BOOL /*searchBackward*/,
_In_ BOOL /*ignoreCase*/,
_Outptr_result_maybenull_ ITextRangeProvider** /*ppRetVal*/,
unsigned int /*_start*/,
unsigned int /*_end*/,
std::function<unsigned int(IRenderData*, const COORD)> /*_coordToEndpoint*/,
std::function<COORD(IRenderData*, const unsigned int)> /*_endpointToCoord*/,
std::function<IFACEMETHODIMP(ITextRangeProvider**)> /*Clone*/)
{
return E_NOTIMPL;
}

const std::wstring Terminal::GetConsoleTitle() const noexcept
{
return _title;
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/WindowsTerminal/BaseWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#pragma once

#include "..\types\IConsoleWindow.hpp"
#include "..\types\WindowUiaProvider.h"
#include "..\types\WindowUiaProviderBase.hpp"

// Custom window messages
#define CM_UPDATE_TITLE (WM_USER)
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/WindowsTerminal/IslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "pch.h"
#include "BaseWindow.h"
#include "../types/IConsoleWindow.hpp"
#include "../types/WindowUiaProvider.h"
#include "WindowUiaProvider.hpp"
#include <winrt/Microsoft.Terminal.TerminalControl.h>
#include <winrt/TerminalApp.h>

Expand Down
167 changes: 167 additions & 0 deletions src/cascadia/WindowsTerminal/WindowUiaProvider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

#include "WindowUiaProvider.hpp"
#include "../types/ScreenInfoUiaProvider.h"

#include "../host/renderData.hpp"

WindowUiaProvider::WindowUiaProvider(Microsoft::Console::Types::IConsoleWindow* baseWindow) :
//_pScreenInfoProvider{ nullptr },
WindowUiaProviderBase(baseWindow)
{
}

WindowUiaProvider::~WindowUiaProvider()
{
/*if (_pScreenInfoProvider)
{
_pScreenInfoProvider->Release();
}*/
}

WindowUiaProvider* WindowUiaProvider::Create(Microsoft::Console::Types::IConsoleWindow* baseWindow)
{
WindowUiaProvider* pWindowProvider = nullptr;
Microsoft::Console::Types::ScreenInfoUiaProvider* pScreenInfoProvider = nullptr;
try
{
pWindowProvider = new WindowUiaProvider(baseWindow);

// TODO GitHub #1352: Hook up ScreenInfoUiaProvider to WindowUiaProvider
/*Globals& g = ServiceLocator::LocateGlobals();
CONSOLE_INFORMATION& gci = g.getConsoleInformation();
Microsoft::Console::Render::IRenderData* renderData = &gci.renderData;
pScreenInfoProvider = new Microsoft::Console::Types::ScreenInfoUiaProvider(renderData, pWindowProvider);
pWindowProvider->_pScreenInfoProvider = pScreenInfoProvider;
*/

// TODO GitHub #1914: Re-attach Tracing to UIA Tree
//Tracing::s_TraceUia(pWindowProvider, ApiCall::Create, nullptr);

return pWindowProvider;
}
catch (...)
{
if (nullptr != pWindowProvider)
{
pWindowProvider->Release();
}

if (nullptr != pScreenInfoProvider)
{
pScreenInfoProvider->Release();
}

LOG_CAUGHT_EXCEPTION();

return nullptr;
}
}

[[nodiscard]] HRESULT WindowUiaProvider::SetTextAreaFocus()
{
try
{
// TODO GitHub #1352: Hook up ScreenInfoUiaProvider to WindowUiaProvider
//return _pScreenInfoProvider->Signal(UIA_AutomationFocusChangedEventId);
}
CATCH_RETURN();
}

[[nodiscard]] HRESULT WindowUiaProvider::Signal(_In_ EVENTID id)
{
HRESULT hr = S_OK;

// ScreenInfoUiaProvider is responsible for signaling selection
// changed events and text changed events
if (id == UIA_Text_TextSelectionChangedEventId ||
id == UIA_Text_TextChangedEventId)
{
// TODO GitHub #1352: Hook up ScreenInfoUiaProvider to WindowUiaProvider
/*if (_pScreenInfoProvider)
{
hr = _pScreenInfoProvider->Signal(id);
}
else
{
hr = E_POINTER;
}*/
hr = E_POINTER;
return hr;
}

if (_signalEventFiring.find(id) != _signalEventFiring.end() &&
_signalEventFiring[id] == true)
{
return hr;
}

try
{
_signalEventFiring[id] = true;
}
CATCH_RETURN();

IRawElementProviderSimple* pProvider = static_cast<IRawElementProviderSimple*>(this);
hr = UiaRaiseAutomationEvent(pProvider, id);
_signalEventFiring[id] = false;

return hr;
}

#pragma region IRawElementProviderFragment

IFACEMETHODIMP WindowUiaProvider::Navigate(_In_ NavigateDirection direction, _COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider)
{
RETURN_IF_FAILED(_EnsureValidHwnd());
*ppProvider = nullptr;
HRESULT hr = S_OK;

// TODO GitHub #1352: Hook up ScreenInfoUiaProvider to WindowUiaProvider
/*if (direction == NavigateDirection_FirstChild || direction == NavigateDirection_LastChild)
{
*ppProvider = _pScreenInfoProvider;
(*ppProvider)->AddRef();
// signal that the focus changed
LOG_IF_FAILED(_pScreenInfoProvider->Signal(UIA_AutomationFocusChangedEventId));
}*/

// For the other directions (parent, next, previous) the default of nullptr is correct
return hr;
}

IFACEMETHODIMP WindowUiaProvider::SetFocus()
{
RETURN_IF_FAILED(_EnsureValidHwnd());
return Signal(UIA_AutomationFocusChangedEventId);
}
#pragma endregion

#pragma region IRawElementProviderFragmentRoot

IFACEMETHODIMP WindowUiaProvider::ElementProviderFromPoint(_In_ double /*x*/,
_In_ double /*y*/,
_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider)
{
RETURN_IF_FAILED(_EnsureValidHwnd());

// TODO GitHub #1352: Hook up ScreenInfoUiaProvider to WindowUiaProvider
/**ppProvider = _pScreenInfoProvider;
(*ppProvider)->AddRef();*/

return S_OK;
}

IFACEMETHODIMP WindowUiaProvider::GetFocus(_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider)
{
RETURN_IF_FAILED(_EnsureValidHwnd());
// TODO GitHub #1352: Hook up ScreenInfoUiaProvider to WindowUiaProvider
//return _pScreenInfoProvider->QueryInterface(IID_PPV_ARGS(ppProvider));
return S_OK;
}

#pragma endregion
48 changes: 48 additions & 0 deletions src/cascadia/WindowsTerminal/WindowUiaProvider.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- windowUiaProvider.hpp
Abstract:
- This module provides UI Automation access to the console window to
support both automation tests and accessibility (screen reading)
applications.
- 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 "../types/WindowUiaProviderBase.hpp"

class WindowUiaProvider final :
public Microsoft::Console::Types::WindowUiaProviderBase
{
public:
static WindowUiaProvider* Create(Microsoft::Console::Types::IConsoleWindow* baseWindow);

[[nodiscard]] HRESULT Signal(_In_ EVENTID id) override;
[[nodiscard]] HRESULT SetTextAreaFocus() override;

// IRawElementProviderFragment methods
IFACEMETHODIMP Navigate(_In_ NavigateDirection direction,
_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider) override;
IFACEMETHODIMP SetFocus() override;

// IRawElementProviderFragmentRoot methods
IFACEMETHODIMP ElementProviderFromPoint(_In_ double x,
_In_ double y,
_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider) override;
IFACEMETHODIMP GetFocus(_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider) override;

private:
WindowUiaProvider(Microsoft::Console::Types::IConsoleWindow* baseWindow);
~WindowUiaProvider();
};
2 changes: 2 additions & 0 deletions src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<ClInclude Include="BaseWindow.h" />
<ClInclude Include="IslandWindow.h" />
<ClInclude Include="NonClientIslandWindow.h" />
<ClInclude Include="WindowUiaProvider.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
Expand All @@ -62,6 +63,7 @@
<ClCompile Include="AppHost.cpp" />
<ClCompile Include="IslandWindow.cpp" />
<ClCompile Include="NonClientIslandWindow.cpp" />
<ClCompile Include="WindowUiaProvider.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WindowsTerminal.rc" />
Expand Down
Loading

0 comments on commit c10a895

Please sign in to comment.