Skip to content

Commit

Permalink
Introduce PseudoConsoleWindow a11y provider (#14541)
Browse files Browse the repository at this point in the history
In order to modify the accessibility information for the PseudoConsoleWindow, it needs to have a UIA provider registered. This PR introduces `PseudoConsoleWindowAccessibilityProvider` and registers it as a UIA provider appropriately. The registration process is based on that of the `WindowUiaProvider` for ConHost.

Closes #14385

## Validation Steps Performed
Run Accessibility Insights FastPass on the window. The PseudoConsoleWindow no longer is tagged as missing a name.
  • Loading branch information
carlos-zamora authored Jan 12, 2023
1 parent f1090a0 commit 09273be
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 4 deletions.
14 changes: 13 additions & 1 deletion src/interactivity/base/InteractivityFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ using namespace Microsoft::Console::Interactivity;
const auto gle = GetLastError();
status = NTSTATUS_FROM_WIN32(gle);
}

_pseudoConsoleWindowHwnd = hwnd;
break;
}
#ifdef BUILD_ONECORE_INTERACTIVITY
Expand Down Expand Up @@ -464,6 +464,18 @@ using namespace Microsoft::Console::Interactivity;
_WritePseudoWindowCallback((bool)wParam);
}
}
case WM_GETOBJECT:
{
if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId))
{
if (nullptr == _pPseudoConsoleUiaProvider)
{
LOG_IF_FAILED(WRL::MakeAndInitialize<PseudoConsoleWindowAccessibilityProvider>(&_pPseudoConsoleUiaProvider, _pseudoConsoleWindowHwnd));
}
return UiaReturnRawElementProvider(hWnd, wParam, lParam, _pPseudoConsoleUiaProvider.Get());
}
return 0;
}
}
// If we get this far, call the default window proc
return DefWindowProcW(hWnd, Message, wParam, lParam);
Expand Down
4 changes: 4 additions & 0 deletions src/interactivity/base/InteractivityFactory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ApiDetector.hpp"

#include "../inc/IInteractivityFactory.hpp"
#include "PseudoConsoleWindowAccessibilityProvider.hpp"

#include <map>

Expand Down Expand Up @@ -40,5 +41,8 @@ namespace Microsoft::Console::Interactivity

private:
void _WritePseudoWindowCallback(bool showOrHide);

HWND _pseudoConsoleWindowHwnd{ nullptr };
WRL::ComPtr<PseudoConsoleWindowAccessibilityProvider> _pPseudoConsoleUiaProvider{ nullptr };
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#include "precomp.h"

#include "PseudoConsoleWindowAccessibilityProvider.hpp"

using namespace Microsoft::Console::Interactivity;

HRESULT PseudoConsoleWindowAccessibilityProvider::RuntimeClassInitialize(HWND pseudoConsoleHwnd) noexcept
{
RETURN_HR_IF_NULL(E_INVALIDARG, pseudoConsoleHwnd);
_pseudoConsoleHwnd = pseudoConsoleHwnd;
return S_OK;
}

IFACEMETHODIMP PseudoConsoleWindowAccessibilityProvider::get_ProviderOptions(_Out_ ProviderOptions* pOptions)
{
RETURN_HR_IF_NULL(E_INVALIDARG, pOptions);
*pOptions = ProviderOptions_ServerSideProvider;
return S_OK;
}

IFACEMETHODIMP PseudoConsoleWindowAccessibilityProvider::GetPatternProvider(_In_ PATTERNID /*iid*/,
_COM_Outptr_result_maybenull_ IUnknown** ppInterface)
{
RETURN_HR_IF_NULL(E_INVALIDARG, ppInterface);
*ppInterface = nullptr;
return S_OK;
}

IFACEMETHODIMP PseudoConsoleWindowAccessibilityProvider::GetPropertyValue(_In_ PROPERTYID propertyId,
_Out_ VARIANT* pVariant)
{
RETURN_HR_IF_NULL(E_INVALIDARG, pVariant);

pVariant->vt = VT_EMPTY;

// Returning the default will leave the property as the default
// so we only really need to touch it for the properties we want to implement
switch (propertyId)
{
case UIA_ControlTypePropertyId:
{
pVariant->vt = VT_I4;
pVariant->lVal = UIA_WindowControlTypeId;
break;
}
case UIA_NamePropertyId:
{
static constexpr auto AutomationPropertyName = L"Internal Console Management Window";
pVariant->bstrVal = SysAllocString(AutomationPropertyName);
if (pVariant->bstrVal != nullptr)
{
pVariant->vt = VT_BSTR;
}
break;
}
case UIA_IsControlElementPropertyId:
case UIA_IsContentElementPropertyId:
case UIA_IsKeyboardFocusablePropertyId:
case UIA_HasKeyboardFocusPropertyId:
{
pVariant->vt = VT_BOOL;
pVariant->boolVal = VARIANT_FALSE;
break;
}
default:
break;
}
return S_OK;
}

IFACEMETHODIMP PseudoConsoleWindowAccessibilityProvider::get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider)
{
RETURN_HR_IF_NULL(E_INVALIDARG, ppProvider);
RETURN_HR_IF_NULL(gsl::narrow_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE), _pseudoConsoleHwnd);
return UiaHostProviderFromHwnd(_pseudoConsoleHwnd, ppProvider);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#pragma once

#include "precomp.h"

namespace Microsoft::Console::Interactivity
{
class PseudoConsoleWindowAccessibilityProvider final :
public WRL::RuntimeClass<WRL::RuntimeClassFlags<WRL::ClassicCom | WRL::InhibitFtmBase>, IRawElementProviderSimple>
{
public:
PseudoConsoleWindowAccessibilityProvider() = default;
~PseudoConsoleWindowAccessibilityProvider() = default;
HRESULT RuntimeClassInitialize(HWND pseudoConsoleHwnd) noexcept;

PseudoConsoleWindowAccessibilityProvider(const PseudoConsoleWindowAccessibilityProvider&) = delete;
PseudoConsoleWindowAccessibilityProvider(PseudoConsoleWindowAccessibilityProvider&&) = delete;
PseudoConsoleWindowAccessibilityProvider& operator=(const PseudoConsoleWindowAccessibilityProvider&) = delete;
PseudoConsoleWindowAccessibilityProvider& operator=(PseudoConsoleWindowAccessibilityProvider&&) = delete;

// IRawElementProviderSimple methods
IFACEMETHODIMP get_ProviderOptions(_Out_ ProviderOptions* pOptions) override;
IFACEMETHODIMP GetPatternProvider(_In_ PATTERNID iid,
_COM_Outptr_result_maybenull_ IUnknown** ppInterface) override;
IFACEMETHODIMP GetPropertyValue(_In_ PROPERTYID idProp,
_Out_ VARIANT* pVariant) override;
IFACEMETHODIMP get_HostRawElementProvider(_COM_Outptr_result_maybenull_ IRawElementProviderSimple** ppProvider) override;

private:
HWND _pseudoConsoleHwnd;
};
}
4 changes: 3 additions & 1 deletion src/interactivity/base/lib/InteractivityBase.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<ClCompile Include="..\precomp.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\PseudoConsoleWindowAccessibilityProvider.cpp" />
<ClCompile Include="..\RemoteConsoleControl.cpp" />
<ClCompile Include="..\ServiceLocator.cpp" />
<ClCompile Include="..\VtApiRedirection.cpp" />
Expand All @@ -49,9 +50,10 @@
<ClInclude Include="..\InteractivityFactory.hpp" />
<ClInclude Include="..\precomp.h" />
<ClInclude Include="..\..\inc\ServiceLocator.hpp" />
<ClInclude Include="..\PseudoConsoleWindowAccessibilityProvider.hpp" />
<ClInclude Include="..\RemoteConsoleControl.hpp" />
</ItemGroup>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
</Project>
</Project>
9 changes: 9 additions & 0 deletions src/interactivity/base/lib/InteractivityBase.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
<ClCompile Include="..\HostSignalInputThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\VtApiRedirection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\PseudoConsoleWindowAccessibilityProvider.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\InteractivityFactory.hpp">
Expand Down Expand Up @@ -89,6 +95,9 @@
<ClInclude Include="..\HostSignalInputThread.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\PseudoConsoleWindowAccessibilityProvider.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
Expand Down
5 changes: 3 additions & 2 deletions src/interactivity/base/sources.inc
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ SOURCES = \
..\VtApiRedirection.cpp \
..\EventSynthesis.cpp \
..\RemoteConsoleControl.cpp \
..\HostSignalInputThread.cpp \
..\HostSignalInputThread.cpp \
..\PseudoConsoleWindowAccessibilityProvider.cpp \

INCLUDES = \
$(INCLUDES); \
..; \
..\..\..\..\..\ConIoSrv; \


0 comments on commit 09273be

Please sign in to comment.