Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessibility: Set-up UIA Tree #1691

Merged
merged 13 commits into from
Jul 29, 2019
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
28 changes: 27 additions & 1 deletion src/cascadia/WindowsTerminal/BaseWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@

#pragma once

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

// Custom window messages
#define CM_UPDATE_TITLE (WM_USER)

#include <wil/resource.h>

using namespace Microsoft::Console::Types;

template<typename T>
class BaseWindow
{
Expand Down Expand Up @@ -51,6 +56,11 @@ class BaseWindow
return HandleDpiChange(_window.get(), wparam, lparam);
}

case WM_GETOBJECT:
{
return HandleGetObject(_window.get(), wparam, lparam);
}

case WM_DESTROY:
{
PostQuitMessage(0);
Expand Down Expand Up @@ -121,6 +131,22 @@ class BaseWindow
return 0;
}

[[nodiscard]] LRESULT HandleGetObject(const HWND hWnd, const WPARAM wParam, const LPARAM lParam)
{
LRESULT retVal = 0;

// If we are receiving a request from Microsoft UI Automation framework, then return the basic UIA COM interface.
if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId))
{
retVal = UiaReturnRawElementProvider(hWnd, wParam, lParam, _GetUiaProvider());
}
// Otherwise, return 0. We don't implement MS Active Accessibility (the other framework that calls WM_GETOBJECT).

return retVal;
}

virtual IRawElementProviderSimple* _GetUiaProvider() = 0;

virtual void OnResize(const UINT width, const UINT height) = 0;
virtual void OnMinimize() = 0;
virtual void OnRestore() = 0;
Expand All @@ -130,7 +156,7 @@ class BaseWindow
RECT rc = { 0 };
::GetWindowRect(_window.get(), &rc);
return rc;
}
};
carlos-zamora marked this conversation as resolved.
Show resolved Hide resolved

HWND GetHandle() const noexcept
{
Expand Down
24 changes: 24 additions & 0 deletions src/cascadia/WindowsTerminal/IslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,30 @@ void IslandWindow::OnSize(const UINT width, const UINT height)
return base_type::MessageHandler(message, wparam, lparam);
}

// Routine Description:
// - Creates/retrieves a handle to the UI Automation provider COM interfaces
// Arguments:
// - <none>
// Return Value:
// - Pointer to UI Automation provider class/interfaces.
IRawElementProviderSimple* IslandWindow::_GetUiaProvider()
{
if (nullptr == _pUiaProvider)
{
try
{
_pUiaProvider = WindowUiaProvider::Create(this);
}
catch (...)
{
LOG_HR(wil::ResultFromCaughtException());
_pUiaProvider = nullptr;
}
}

return _pUiaProvider;
}

// Method Description:
// - Called when the window has been resized (or maximized)
// Arguments:
Expand Down
40 changes: 39 additions & 1 deletion src/cascadia/WindowsTerminal/IslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@

#include "pch.h"
#include "BaseWindow.h"
#include "../types/IUiaWindow.h"
#include "WindowUiaProvider.hpp"
#include <winrt/Microsoft.Terminal.TerminalControl.h>
#include <winrt/TerminalApp.h>

class IslandWindow : public BaseWindow<IslandWindow>
class IslandWindow :
public BaseWindow<IslandWindow>,
public IUiaWindow
{
public:
IslandWindow() noexcept;
Expand All @@ -17,6 +21,7 @@ class IslandWindow : public BaseWindow<IslandWindow>
virtual void OnSize(const UINT width, const UINT height);

[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
IRawElementProviderSimple* _GetUiaProvider();
void OnResize(const UINT width, const UINT height) override;
void OnMinimize() override;
void OnRestore() override;
Expand All @@ -29,6 +34,38 @@ class IslandWindow : public BaseWindow<IslandWindow>

void UpdateTheme(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);

#pragma region IUiaWindow
void ChangeViewport(const SMALL_RECT NewWindow)
{
// TODO GitHub #1352: Hook up ScreenInfoUiaProvider to WindowUiaProvider
// Relevant comment from zadjii-msft:
/*
In my head for designing this, I'd then have IslandWindow::ChangeViewport
call a callback that AppHost sets, where AppHost will then call into the
TerminalApp to have TerminalApp handle the ChangeViewport call.
(See IslandWindow::SetCreateCallback as an example of a similar
pattern we're using today.) That way, if someone else were trying
to resuse this, they could have their own AppHost (or TerminalApp
equivalent) handle the ChangeViewport call their own way.
*/
return;
};

HWND GetWindowHandle() const noexcept override
{
return BaseWindow::GetHandle();
};

[[nodiscard]] HRESULT SignalUia(_In_ EVENTID id) override { return E_NOTIMPL; };
[[nodiscard]] HRESULT UiaSetTextAreaFocus() override { return E_NOTIMPL; };

RECT GetWindowRect() const noexcept override
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why override to just call parent?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this because IUIAWindowNeedsIt?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. BaseWindow AND IUiaWindow both have GetWindowRect() and GetWindowHandle() (BaseWindow just calls it GetHandle()). When I remove these from here, I get "ambiguous access of 'GetWindowRect'" in NonClientIslandWindow (inherits from IslandWindow). Is there a C++-ism that you know about to get around this?

{
return BaseWindow::GetWindowRect();
};

#pragma endregion

protected:
void ForceResize()
{
Expand All @@ -38,6 +75,7 @@ class IslandWindow : public BaseWindow<IslandWindow>
}

HWND _interopWindowHandle;
WindowUiaProvider* _pUiaProvider;

winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _source;

Expand Down
Loading