I want to get the padding out of interactivity, but the control bounds are still wrong

This commit is contained in:
Mike Griese 2021-05-07 10:51:55 -05:00
parent 5e7d270fa2
commit 6e031e5257
13 changed files with 129 additions and 197 deletions

View file

@ -44,15 +44,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_selectionNeedsToBeCopied{ false }
{
_core = winrt::make_self<ControlCore>(settings, connection);
// _core->ScrollPositionChanged({ this, &ControlInteractivity::_coreScrollPositionChanged });
}
void ControlInteractivity::UpdateSettings(const til::rectangle padding)
// Method Description:
// - Updates our internal settings. These settings should be
// interactivity-specific. Right now, we primarily update _rowsToScroll
// with the current value of SPI_GETWHEELSCROLLLINES.
// Arguments:
// - <none>
// Return Value:
// - <none>
void ControlInteractivity::UpdateSettings()
{
_updateSystemParameterSettings();
_lastPadding = padding;
}
void ControlInteractivity::Initialize()
@ -587,7 +592,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// Method Description:
// - Creates an automation peer for the Terminal Control, enabling accessibility on our control.
// - Creates an automation peer for the Terminal Control, enabling
// accessibility on our control.
// - Our implementation implements the ITextProvider pattern, and the
// IControlAccessibilityInfo, to connect to the UiaEngine, which must be
// attached to the core's renderer.
// - The TermControlAutomationPeer will connect this to the UI tree.
// Arguments:
// - None
// Return Value:
@ -595,17 +605,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Control::InteractivityAutomationPeer ControlInteractivity::OnCreateAutomationPeer()
try
{
// if (_initializedTerminal && !_closing) // only set up the automation peer if we're ready to go live
// {
// create a custom automation peer with this code pattern:
// (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers)
auto autoPeer = winrt::make_self<implementation::InteractivityAutomationPeer>(this);
_uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(autoPeer.get());
_core->AttachUiaEngine(_uiaEngine.get());
return *autoPeer;
// }
// return nullptr;
}
catch (...)
{
@ -622,9 +626,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// {
// return _settings.ProfileName();
// }
til::rectangle ControlInteractivity::GetPadding() const
{
return _lastPadding;
}
// til::rectangle ControlInteractivity::GetPadding() const
// {
// return _lastPadding;
// }
}

View file

@ -39,14 +39,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void GainFocus();
void LostFocus();
void UpdateSettings(const til::rectangle padding);
void UpdateSettings(/*const til::rectangle padding*/);
void Initialize();
Control::ControlCore GetCore();
// hstring GetProfileName() const;
Control::InteractivityAutomationPeer OnCreateAutomationPeer();
::Microsoft::Console::Types::IUiaData* GetUiaData() const;
til::rectangle GetPadding() const;
// til::rectangle GetPadding() const;
#pragma region Input Methods
void PointerPressed(Control::MouseButtonState buttonState,
@ -93,7 +93,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
unsigned int _rowsToScroll;
double _internalScrollbarPosition{ 0.0 };
til::rectangle _lastPadding;
std::unique_ptr<::Microsoft::Console::Render::UiaEngine> _uiaEngine;
// If this is set, then we assume we are in the middle of panning the

View file

@ -17,7 +17,7 @@ namespace Microsoft.Terminal.Control
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
ControlCore GetCore();
void UpdateSettings(Microsoft.Terminal.Core.Padding padding);
void UpdateSettings();
void Initialize();
void GainFocus();
void LostFocus();

View file

@ -35,6 +35,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
THROW_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, _interactivity->GetUiaData(), this));
};
void InteractivityAutomationPeer::SetControlBounds(const Windows::Foundation::Rect bounds)
{
_controlBounds = til::rectangle{ til::math::rounding, bounds };
}
void InteractivityAutomationPeer::SetControlPadding(const Core::Padding padding)
{
_controlPadding = padding;
}
// Method Description:
// - Signals the ui automation client that the terminal's selection has changed and should be updated
// Arguments:
@ -97,59 +106,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
});
}
// hstring InteractivityAutomationPeer::GetClassNameCore() const
// {
// return L"TermControl";
// }
// AutomationControlType InteractivityAutomationPeer::GetAutomationControlTypeCore() const
// {
// return AutomationControlType::Text;
// }
// hstring InteractivityAutomationPeer::GetLocalizedControlTypeCore() const
// {
// return RS_(L"TerminalControl_ControlType");
// }
// Windows::Foundation::IInspectable InteractivityAutomationPeer::GetPatternCore(PatternInterface patternInterface) const
// {
// switch (patternInterface)
// {
// case PatternInterface::Text:
// return *this;
// break;
// default:
// return nullptr;
// }
// }
// AutomationOrientation InteractivityAutomationPeer::GetOrientationCore() const
// {
// return AutomationOrientation::Vertical;
// }
// hstring InteractivityAutomationPeer::GetNameCore() const
// {
// // fallback to title if profile name is empty
// auto profileName = _interactivity->GetProfileName();
// if (profileName.empty())
// {
// return _interactivity->GetCore().Title();
// }
// return profileName;
// }
// hstring InteractivityAutomationPeer::GetHelpTextCore() const
// {
// return _interactivity->GetCore().Title();
// }
// AutomationLiveSetting InteractivityAutomationPeer::GetLiveSettingCore() const
// {
// return AutomationLiveSetting::Polite;
// }
#pragma region ITextProvider
com_array<XamlAutomation::ITextRangeProvider> InteractivityAutomationPeer::GetSelection()
{
@ -214,11 +170,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
RECT InteractivityAutomationPeer::GetBounds() const
{
const auto padding = _interactivity->GetPadding();
// TODO! Get this from the core
const til::size dimensions{ 100, 100 };
const til::rectangle realBounds{ padding.origin(), dimensions };
return realBounds;
// const auto padding = _interactivity->GetPadding();
// // TODO! Get this from the core
// const til::size dimensions{ 100, 100 };
// const til::rectangle realBounds{ padding.origin(), dimensions };
// return realBounds;
// auto rect = GetBoundingRectangle();
// return {
// gsl::narrow_cast<LONG>(rect.X),
@ -226,6 +182,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// gsl::narrow_cast<LONG>(rect.X + rect.Width),
// gsl::narrow_cast<LONG>(rect.Y + rect.Height)
// };
return _controlBounds;
}
HRESULT InteractivityAutomationPeer::GetHostUiaProvider(IRawElementProviderSimple** provider)
@ -238,7 +195,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
RECT InteractivityAutomationPeer::GetPadding() const
{
return _interactivity->GetPadding();
return _controlPadding;
// return _interactivity->GetPadding();
// return {
// gsl::narrow_cast<LONG>(padding.Left),
// gsl::narrow_cast<LONG>(padding.Top),

View file

@ -2,8 +2,24 @@
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- InteractivityAutomationPeer.h
TODO!
Abstract:
- This module provides UI Automation access to the ControlInteractivity,
to support both automation tests and accessibility (screen
reading) applications.
- See TermControlAutomationPeer for more details on how UIA is implemented.
- This is the primary implementation of the ITextProvider interface, for the
TermControlAutomationPeer. The TermControlAutomationPeer will be attached to
the actual UI tree, via FrameworkElementAutomationPeer. However, the
ControlInteractivity is totally oblivious to the UI tree that might be hosting
it. So this class implements the actual text pattern for the buffer, because
it has access to the buffer. TermControlAutomationPeer can then call the
methods on this class to expose the implemeentation in the actual UI tree.
Author(s):
- Mike Griese (migrie), May 2021
--*/
@ -25,16 +41,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
public:
InteractivityAutomationPeer(Microsoft::Terminal::Control::implementation::ControlInteractivity* owner);
// #pragma region FrameworkElementAutomationPeer
// hstring GetClassNameCore() const;
// Windows::UI::Xaml::Automation::Peers::AutomationControlType GetAutomationControlTypeCore() const;
// hstring GetLocalizedControlTypeCore() const;
// Windows::Foundation::IInspectable GetPatternCore(Windows::UI::Xaml::Automation::Peers::PatternInterface patternInterface) const;
// Windows::UI::Xaml::Automation::Peers::AutomationOrientation GetOrientationCore() const;
// hstring GetNameCore() const;
// hstring GetHelpTextCore() const;
// Windows::UI::Xaml::Automation::Peers::AutomationLiveSetting GetLiveSettingCore() const;
// #pragma endregion
void SetControlBounds(const Windows::Foundation::Rect bounds);
void SetControlPadding(const Core::Padding padding);
#pragma region IUiaEventDispatcher
void SignalSelectionChanged() override;
@ -61,11 +69,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override;
#pragma endregion
// RECT GetBoundingRectWrapped();
private:
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
winrt::Microsoft::Terminal::Control::implementation::ControlInteractivity* _interactivity;
til::rectangle _controlBounds;
til::rectangle _controlPadding;
winrt::com_array<Windows::UI::Xaml::Automation::Provider::ITextRangeProvider> WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges);
};
}

View file

@ -7,5 +7,8 @@ namespace Microsoft.Terminal.Control
Windows.UI.Xaml.Automation.Peers.AutomationPeer,
Windows.UI.Xaml.Automation.Provider.ITextProvider
{
void SetControlBounds(Windows.Foundation.Rect bounds);
void SetControlPadding(Microsoft.Terminal.Core.Padding padding);
}
}

View file

@ -419,10 +419,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
ScrollBar().Visibility(Visibility::Visible);
}
_interactivity.UpdateSettings(winrt::Microsoft::Terminal::Core::Padding{ newMargin.Left,
newMargin.Top,
newMargin.Right,
newMargin.Bottom });
_interactivity.UpdateSettings();
if (auto ap{ _automationPeer.get() })
{
ap.SetControlPadding(Core::Padding{ newMargin.Left,
newMargin.Top,
newMargin.Right,
newMargin.Bottom });
}
}
// Method Description:
@ -532,6 +536,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
const auto& interactivityAutoPeer = _interactivity.OnCreateAutomationPeer();
auto autoPeer = winrt::make_self<implementation::TermControlAutomationPeer>(this, interactivityAutoPeer);
_automationPeer = winrt::weak_ref<Control::TermControlAutomationPeer>(*autoPeer);
return *autoPeer;
}
return nullptr;
@ -1529,6 +1534,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto newSize = e.NewSize();
_core.SizeChanged(newSize.Width, newSize.Height);
if (auto ap{ _automationPeer.get() })
{
auto controlOrigin{ ActualOffset() };
ap.SetControlBounds(Windows::Foundation::Rect{ controlOrigin.x, controlOrigin.y, newSize.Width, newSize.Height });
}
}
// Method Description:

View file

@ -171,6 +171,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
winrt::weak_ref<Control::TermControlAutomationPeer> _automationPeer{ nullptr };
void _UpdateSettingsFromUIThread(IControlSettings newSettings);
void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance);
void _ApplyUISettings(const IControlSettings&);

View file

@ -34,9 +34,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Control::InteractivityAutomationPeer impl) :
TermControlAutomationPeerT<TermControlAutomationPeer>(*owner), // pass owner to FrameworkElementAutomationPeer
_termControl{ owner },
_implementation{ impl } {
// THROW_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, _interactivity->GetUiaData(), this));
};
_implementation{ impl }
{
auto controlOrigin{ owner->ActualOffset() };
auto controlSize{ owner->ActualSize() };
impl.SetControlBounds(Windows::Foundation::Rect{ controlOrigin.x, controlOrigin.y, controlSize.x, controlSize.y });
};
void TermControlAutomationPeer::SetControlBounds(const Windows::Foundation::Rect bounds)
{
_implementation.SetControlBounds(bounds);
}
void TermControlAutomationPeer::SetControlPadding(const Core::Padding padding)
{
_implementation.SetControlPadding(padding);
}
// Method Description:
// - Signals the ui automation client that the terminal's selection has changed and should be updated
@ -145,111 +157,35 @@ namespace winrt::Microsoft::Terminal::Control::implementation
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::GetSelection()
{
return _implementation.GetSelection();
// SAFEARRAY* pReturnVal;
// THROW_IF_FAILED(_uiaProvider->GetSelection(&pReturnVal));
// return WrapArrayOfTextRangeProviders(pReturnVal);
}
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::GetVisibleRanges()
{
return _implementation.GetVisibleRanges();
// SAFEARRAY* pReturnVal;
// THROW_IF_FAILED(_uiaProvider->GetVisibleRanges(&pReturnVal));
// return WrapArrayOfTextRangeProviders(pReturnVal);
}
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::RangeFromChild(XamlAutomation::IRawElementProviderSimple childElement)
{
return _implementation.RangeFromChild(childElement);
// UIA::ITextRangeProvider* returnVal;
// // ScreenInfoUiaProvider doesn't actually use parameter, so just pass in nullptr
// THROW_IF_FAILED(_uiaProvider->RangeFromChild( IRawElementProviderSimple nullptr,
// &returnVal));
// auto parentProvider = this->ProviderFromPeer(*this);
// auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
// return xutr.as<XamlAutomation::ITextRangeProvider>();
}
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::RangeFromPoint(Windows::Foundation::Point screenLocation)
{
return _implementation.RangeFromPoint(screenLocation);
// UIA::ITextRangeProvider* returnVal;
// THROW_IF_FAILED(_uiaProvider->RangeFromPoint({ screenLocation.X, screenLocation.Y }, &returnVal));
// auto parentProvider = this->ProviderFromPeer(*this);
// auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
// return xutr.as<XamlAutomation::ITextRangeProvider>();
}
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::DocumentRange()
{
return _implementation.DocumentRange();
// UIA::ITextRangeProvider* returnVal;
// THROW_IF_FAILED(_uiaProvider->get_DocumentRange(&returnVal));
// auto parentProvider = this->ProviderFromPeer(*this);
// auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
// return xutr.as<XamlAutomation::ITextRangeProvider>();
}
XamlAutomation::SupportedTextSelection TermControlAutomationPeer::SupportedTextSelection()
{
return _implementation.SupportedTextSelection();
// UIA::SupportedTextSelection returnVal;
// THROW_IF_FAILED(_uiaProvider->get_SupportedTextSelection(&returnVal));
// return static_cast<XamlAutomation::SupportedTextSelection>(returnVal);
}
#pragma endregion
#pragma region IControlAccessibilityInfo
// COORD TermControlAutomationPeer::GetFontSize() const
// {
// return til::size{ til::math::rounding, _interactivity->GetCore()->FontSize() };
// }
// RECT TermControlAutomationPeer::GetBounds() const
// {
// auto rect = GetBoundingRectangle();
// return {
// gsl::narrow_cast<LONG>(rect.X),
// gsl::narrow_cast<LONG>(rect.Y),
// gsl::narrow_cast<LONG>(rect.X + rect.Width),
// gsl::narrow_cast<LONG>(rect.Y + rect.Height)
// };
// }
// HRESULT TermControlAutomationPeer::GetHostUiaProvider(IRawElementProviderSimple** provider)
// {
// RETURN_HR_IF(E_INVALIDARG, provider == nullptr);
// *provider = nullptr;
// return S_OK;
// }
// RECT TermControlAutomationPeer::GetPadding() const
// {
// return RECT{ _interactivity->GetPadding() };
// // return {
// // gsl::narrow_cast<LONG>(padding.Left),
// // gsl::narrow_cast<LONG>(padding.Top),
// // gsl::narrow_cast<LONG>(padding.Right),
// // gsl::narrow_cast<LONG>(padding.Bottom)
// // };
// }
// double TermControlAutomationPeer::GetScaleFactor() const
// {
// return DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
// }
// void TermControlAutomationPeer::ChangeViewport(const SMALL_RECT NewWindow)
// {
// _interactivity->UpdateScrollbar(NewWindow.Top);
// }
#pragma endregion
// Method Description:
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
// Arguments:

View file

@ -20,6 +20,10 @@ Abstract:
Author(s):
- Carlos Zamora (CaZamor) 2019
Modifications:
- May 2021: Pulled the core logic of ITextProvider implementation into the
InteractivityAutomationPeer, to support tab tear out.
--*/
#pragma once
@ -35,13 +39,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
struct TermControlAutomationPeer :
public TermControlAutomationPeerT<TermControlAutomationPeer>,
::Microsoft::Console::Types::IUiaEventDispatcher /*,
::Microsoft::Console::Types::IControlAccessibilityInfo*/
::Microsoft::Console::Types::IUiaEventDispatcher
{
public:
TermControlAutomationPeer(Microsoft::Terminal::Control::implementation::TermControl* owner,
Control::InteractivityAutomationPeer implementation);
void SetControlBounds(const Windows::Foundation::Rect bounds);
void SetControlPadding(const Core::Padding padding);
#pragma region FrameworkElementAutomationPeer
hstring GetClassNameCore() const;
Windows::UI::Xaml::Automation::Peers::AutomationControlType GetAutomationControlTypeCore() const;
@ -68,22 +74,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider DocumentRange();
#pragma endregion
// #pragma region IControlAccessibilityInfo Pattern
// // Inherited via IControlAccessibilityInfo
// virtual COORD GetFontSize() const override;
// virtual RECT GetBounds() const override;
// virtual RECT GetPadding() const override;
// virtual double GetScaleFactor() const override;
// virtual void ChangeViewport(SMALL_RECT NewWindow) override;
// virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override;
// #pragma endregion
// RECT GetBoundingRectWrapped();
private:
// ::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
// winrt::Microsoft::Terminal::Control::implementation::ControlInteractivity* _interactivity;
winrt::Microsoft::Terminal::Control::implementation::TermControl* _termControl;
Control::InteractivityAutomationPeer _implementation;

View file

@ -9,5 +9,8 @@ namespace Microsoft.Terminal.Control
Windows.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer,
Windows.UI.Xaml.Automation.Provider.ITextProvider
{
void SetControlBounds(Windows.Foundation.Rect bounds);
void SetControlPadding(Microsoft.Terminal.Core.Padding padding);
}
}

View file

@ -24,18 +24,18 @@ namespace Microsoft.Terminal.Core
UInt8 A;
};
// TODO!
// TerminalCore declares its own Color struct to avoid depending on
// Windows.UI. Windows.Foundation.POint also exists, but it's composedof
// floating-point coordinates,whenwe almost always need integer coordinates.
// It is supported by til::point for conversions in and out of WinRT land.
struct Point
{
Int32 X;
Int32 Y;
};
// It is supported by Microsoft::Terminal::Core::ControlKeyStates for conversions in and out of WinRT land.
struct ControlKeyStates
{
Int32 Value;
};
// Same thing here, but with padding. Can't use Windows.UI.Thickness, so
// we'll declare our own.
struct Padding {
Double Left;
Double Top;
@ -43,6 +43,13 @@ namespace Microsoft.Terminal.Core
Double Bottom;
};
// This is a projection of Microsoft::Terminal::Core::ControlKeyStates,
// for conversions in and out of WinRT land.
struct ControlKeyStates
{
Int32 Value;
};
declare
{
// Forward declare this parameterized specialization so that it lives

View file

@ -183,6 +183,14 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
}
// This template will convert to rectangle from anything that has a X, Y, Width, and Height field that are floating-point;
// a math type is required.
template<typename TilMath, typename TOther>
constexpr rectangle(TilMath, const TOther& other, std::enable_if_t<std::is_floating_point_v<decltype(std::declval<TOther>().X)> && std::is_floating_point_v<decltype(std::declval<TOther>().Y)> && std::is_floating_point_v<decltype(std::declval<TOther>().Width)> && std::is_floating_point_v<decltype(std::declval<TOther>().Height)>, int> /*sentinel*/ = 0) :
rectangle(til::point{ TilMath::template cast<ptrdiff_t>(other.X), TilMath::template cast<ptrdiff_t>(other.Y) }, til::size{ TilMath::template cast<ptrdiff_t>(other.Width), TilMath::template cast<ptrdiff_t>(other.Height) })
{
}
// This template will convert to rectangle from anything that has a left, top, right, and bottom field that are floating-point;
// a math type is required.
template<typename TilMath, typename TOther>