terminal/src/host/tracing.hpp
Carlos Zamora 96496d8154
Accessibility: Set-up UIA Tree (#1691)
**The Basics of Accessibility**
- [What is a User Interaction Automation (UIA) Tree?](https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-tree-overview)
- Other projects (i.e.: Narrator) can take advantage of this UIA tree and are used to present information within it.
- Some things like XAML already have a UIA Tree. So some UIA tree navigation and features are already there. It's just a matter of getting them hooked up and looking right.

**Accessibility in our Project**
There's a few important classes...
regarding Accessibility...
- **WindowUiaProvider**: This sets up the UIA tree for a window. So this is the top-level for the UIA tree.
- **ScreenInfoUiaProvider**: This sets up the UIA tree for a terminal buffer.
- **UiaTextRange**: This is essential to interacting with the UIA tree for the terminal buffer. Actually gets portions of the buffer and presents them.

regarding the Windows Terminal window...
- **BaseWindow**: The foundation to a window. Deals with HWNDs and that kind of stuff.
- **IslandWindow**: This extends `BaseWindow` and is actually what holds our Windows Terminal
- **NonClientIslandWindow**: An extension of the `IslandWindow`

regarding ConHost...
- **IConsoleWindow**: This is an interface for the console window.
- **Window**: This is the actual window for ConHost. Extends `IConsoleWindow`

- `IConsoleWindow` changes:
  - move into `Microsoft::Console::Types` (a shared space)
  - Have `IslandWindow` extend it
- `WindowUiaProvider` changes:
  - move into `Microsoft::Console::Types` (a shared space)
- Hook up `WindowUiaProvider` to IslandWindow (yay! we now have a tree)

### Changes to the WindowUiaProvider
As mentioned earlier, the WindowUiaProvider is the top-level UIA provider for our projects. To reuse as much code as possible, I created `Microsoft::Console::Types::WindowUiaProviderBase`. Any existing functions that reference a `ScreenInfoUiaProvider` were virtual-ized.

In each project, a `WindowUiaProvider : WindowUiaProviderBase` was created to define those virtual functions. Note that that will be the main difference between ConHost and Windows Terminal moving forward: how many TextBuffers are on the screen.

So, ConHost should be the same as before, with only one `ScreenInfoUiaProvider`, whereas Windows Terminal needs to (1) update which one is on the screen and (2) may have multiple on the screen.

🚨 Windows Terminal doesn't have the `ScreenInfoUiaProvider` hooked up yet. We'll have all the XAML elements in the UIA tree. But, since `TermControl` is a custom XAML Control, I need to hook up the `ScreenInfoUiaProvider` to it. This work will be done in a new PR and resolve GitHub Issue #1352.


### Moved to `Microsoft::Console::Types`
These files got moved to a shared area so that they can be used by both ConHost and Windows Terminal.
This means that any references to the `ServiceLocator` had to be removed.

- `IConsoleWindow`
  - Windows Terminal: `IslandWindow : IConsoleWindow`
- `ScreenInfoUiaProvider`
  - all references to `ServiceLocator` and `SCREEN_INFORMATION` were removed. `IRenderData` was used to accomplish this. Refer to next section for more details.
- `UiaTextRange`
  - all references to `ServiceLocator` and `SCREEN_INFORMATION` were removed. `IRenderData` was used to accomplish this. Refer to next section for more details.
  - since most of the functions were `static`, that means that an `IRenderData` had to be added into most of them.


### Changes to IRenderData
Since `IRenderData` is now being used to abstract out `ServiceLocator` and `SCREEN_INFORMATION`, I had to add a few functions here:
- `bool IsAreaSelected()`
- `void ClearSelection()`
- `void SelectNewRegion(...)`
- `HRESULT SearchForText(...)`

`SearchForText()` is a problem here. The overall new design is great! But Windows Terminal doesn't have a way to search for text in the buffer yet, whereas ConHost does. So I'm punting on this issue for now. It looks nasty, but just look at all the other pretty things here. :)
2019-07-29 15:21:15 -07:00

113 lines
4.2 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- tracing.hpp
Abstract:
- This module is used for recording tracing/debugging information to the telemetry ETW channel
- The data is not automatically broadcast to telemetry backends as it does not set the TELEMETRY keyword.
- NOTE: Many functions in this file appear to be copy/pastes. This is because the TraceLog documentation warns
to not be "cute" in trying to reduce its macro usages with variables as it can cause unexpected behavior.
Author(s):
- Michael Niksa (miniksa) 25-Nov-2014
--*/
#pragma once
#include <functional>
#include "../types/inc/Viewport.hpp"
namespace Microsoft::Console::Interactivity::Win32
{
class UiaTextRange;
namespace UiaTextRangeTracing
{
enum class ApiCall;
struct IApiMsg;
}
class ScreenInfoUiaProvider;
namespace ScreenInfoUiaProviderTracing
{
enum class ApiCall;
struct IApiMsg;
}
}
#if DBG
#define DBGCHARS(_params_) \
{ \
Tracing::s_TraceChars _params_; \
}
#define DBGOUTPUT(_params_) \
{ \
Tracing::s_TraceOutput _params_; \
}
#else
#define DBGCHARS(_params_)
#define DBGOUTPUT(_params_)
#endif
class Tracing
{
public:
~Tracing();
static Tracing s_TraceApiCall(const NTSTATUS& result, PCSTR traceName);
static void s_TraceApi(const NTSTATUS status, const CONSOLE_GETLARGESTWINDOWSIZE_MSG* const a);
static void s_TraceApi(const NTSTATUS status, const CONSOLE_SCREENBUFFERINFO_MSG* const a, const bool fSet);
static void s_TraceApi(const NTSTATUS status, const CONSOLE_SETSCREENBUFFERSIZE_MSG* const a);
static void s_TraceApi(const NTSTATUS status, const CONSOLE_SETWINDOWINFO_MSG* const a);
static void s_TraceApi(_In_ const void* const buffer, const CONSOLE_WRITECONSOLE_MSG* const a);
static void s_TraceApi(const CONSOLE_SCREENBUFFERINFO_MSG* const a);
static void s_TraceApi(const CONSOLE_MODE_MSG* const a, const std::wstring& handleType);
static void s_TraceApi(const CONSOLE_SETTEXTATTRIBUTE_MSG* const a);
static void s_TraceApi(const CONSOLE_WRITECONSOLEOUTPUTSTRING_MSG* const a);
static void s_TraceWindowViewport(const Microsoft::Console::Types::Viewport& viewport);
static void s_TraceChars(_In_z_ const char* pszMessage, ...);
static void s_TraceOutput(_In_z_ const char* pszMessage, ...);
static void s_TraceWindowMessage(const MSG& msg);
static void s_TraceInputRecord(const INPUT_RECORD& inputRecord);
static void __stdcall TraceFailure(const wil::FailureInfo& failure) noexcept;
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
#if 0
static void s_TraceUia(const Microsoft::Console::Interactivity::Win32::UiaTextRange* const range,
const Microsoft::Console::Interactivity::Win32::UiaTextRangeTracing::ApiCall apiCall,
const Microsoft::Console::Interactivity::Win32::UiaTextRangeTracing::IApiMsg* const apiMsg);
static void s_TraceUia(const Microsoft::Console::Interactivity::Win32::ScreenInfoUiaProvider* const pProvider,
const Microsoft::Console::Interactivity::Win32::ScreenInfoUiaProviderTracing::ApiCall apiCall,
const Microsoft::Console::Interactivity::Win32::ScreenInfoUiaProviderTracing::IApiMsg* const apiMsg);
static void s_TraceUia(const Microsoft::Console::Types::WindowUiaProvider* const pProvider,
const Microsoft::Console::Types::WindowUiaProviderTracing::ApiCall apiCall,
const Microsoft::Console::Types::WindowUiaProviderTracing::IApiMsg* const apiMsg);
#endif
private:
static ULONG s_ulDebugFlag;
Tracing(std::function<void()> onExit);
std::function<void()> _onExit;
static const wchar_t* const _textPatternRangeEndpointToString(int endpoint);
static const wchar_t* const _textUnitToString(int unit);
static const wchar_t* const _eventIdToString(long eventId);
static const wchar_t* const _directionToString(int direction);
};