Use floating DIPs throughout the stack (#18027)

I sure hope I didn't break anything!
While `til::math` was a good idea its convenience led us to use it
in the only place where it absolutely must not be used: The UI code.
So, this PR replaces all those `til::point`s, etc., with floats.
Now we use DIPs consistently throughout all layers of the UI code,
except for the UIA area (that would've required too many changes).

## Validation Steps Performed
Launch, looks good, no obvious defects, UIA positioning seems ok. 
This commit is contained in:
Leonard Hecker 2024-11-15 04:26:10 -08:00 committed by GitHub
parent 91c96a60a7
commit cd1742454c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 176 additions and 253 deletions

View File

@ -2243,7 +2243,7 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_MoveContent(std::vector<Settings::Model::ActionAndArgs>&& actions, void TerminalPage::_MoveContent(std::vector<Settings::Model::ActionAndArgs>&& actions,
const winrt::hstring& windowName, const winrt::hstring& windowName,
const uint32_t tabIndex, const uint32_t tabIndex,
const std::optional<til::point>& dragPoint) const std::optional<winrt::Windows::Foundation::Point>& dragPoint)
{ {
const auto winRtActions{ winrt::single_threaded_vector<ActionAndArgs>(std::move(actions)) }; const auto winRtActions{ winrt::single_threaded_vector<ActionAndArgs>(std::move(actions)) };
const auto str{ ActionAndArgs::Serialize(winRtActions) }; const auto str{ ActionAndArgs::Serialize(winRtActions) };
@ -2252,7 +2252,7 @@ namespace winrt::TerminalApp::implementation
tabIndex); tabIndex);
if (dragPoint.has_value()) if (dragPoint.has_value())
{ {
request->WindowPosition(dragPoint->to_winrt_point()); request->WindowPosition(*dragPoint);
} }
RequestMoveContent.raise(*this, *request); RequestMoveContent.raise(*this, *request);
} }
@ -5202,16 +5202,17 @@ namespace winrt::TerminalApp::implementation
// position the dropped window. // position the dropped window.
// First, the position of the pointer, from the CoreWindow // First, the position of the pointer, from the CoreWindow
const til::point pointerPosition{ til::math::rounding, CoreWindow::GetForCurrentThread().PointerPosition() }; const auto pointerPosition = CoreWindow::GetForCurrentThread().PointerPosition();
// Next, the position of the tab itself: // Next, the position of the tab itself:
const til::point tabPosition{ til::math::rounding, eventTab.TransformToVisual(nullptr).TransformPoint({ 0, 0 }) }; const auto tabPosition = eventTab.TransformToVisual(nullptr).TransformPoint({ 0, 0 });
// Now, we need to add the origin of our CoreWindow to the tab // Now, we need to add the origin of our CoreWindow to the tab
// position. // position.
const auto& coreWindowBounds{ CoreWindow::GetForCurrentThread().Bounds() }; const auto windowOrigin = CoreWindow::GetForCurrentThread().Bounds();
const til::point windowOrigin{ til::math::rounding, coreWindowBounds.X, coreWindowBounds.Y };
const auto realTabPosition = windowOrigin + tabPosition;
// Subtract the two to get the offset. // Subtract the two to get the offset.
_stashed.dragOffset = til::point{ pointerPosition - realTabPosition }; _stashed.dragOffset = {
pointerPosition.X - windowOrigin.X - tabPosition.X,
pointerPosition.Y - windowOrigin.Y - tabPosition.Y,
};
// Into the DataPackage, let's stash our own window ID. // Into the DataPackage, let's stash our own window ID.
const auto id{ _WindowProperties.WindowId() }; const auto id{ _WindowProperties.WindowId() };
@ -5385,14 +5386,17 @@ namespace winrt::TerminalApp::implementation
// -1 is the magic number for "new window" // -1 is the magic number for "new window"
// 0 as the tab index, because we don't care. It's making a new window. It'll be the only tab. // 0 as the tab index, because we don't care. It's making a new window. It'll be the only tab.
const til::point adjusted = til::point{ til::math::rounding, pointerPoint } - _stashed.dragOffset; const winrt::Windows::Foundation::Point adjusted = {
pointerPoint.X - _stashed.dragOffset.X,
pointerPoint.Y - _stashed.dragOffset.Y,
};
_sendDraggedTabToWindow(winrt::hstring{ L"-1" }, 0, adjusted); _sendDraggedTabToWindow(winrt::hstring{ L"-1" }, 0, adjusted);
} }
} }
void TerminalPage::_sendDraggedTabToWindow(const winrt::hstring& windowId, void TerminalPage::_sendDraggedTabToWindow(const winrt::hstring& windowId,
const uint32_t tabIndex, const uint32_t tabIndex,
std::optional<til::point> dragPoint) std::optional<winrt::Windows::Foundation::Point> dragPoint)
{ {
auto startupActions = _stashed.draggedTab->BuildStartupActions(BuildStartupKind::Content); auto startupActions = _stashed.draggedTab->BuildStartupActions(BuildStartupKind::Content);
_DetachTabFromWindow(_stashed.draggedTab); _DetachTabFromWindow(_stashed.draggedTab);

View File

@ -292,7 +292,7 @@ namespace winrt::TerminalApp::implementation
struct StashedDragData struct StashedDragData
{ {
winrt::com_ptr<winrt::TerminalApp::implementation::TabBase> draggedTab{ nullptr }; winrt::com_ptr<winrt::TerminalApp::implementation::TabBase> draggedTab{ nullptr };
til::point dragOffset{ 0, 0 }; winrt::Windows::Foundation::Point dragOffset{ 0, 0 };
} _stashed; } _stashed;
winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::NewConnection_revoker _newConnectionRevoker; winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::NewConnection_revoker _newConnectionRevoker;
@ -561,8 +561,8 @@ namespace winrt::TerminalApp::implementation
void _MoveContent(std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs>&& actions, void _MoveContent(std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs>&& actions,
const winrt::hstring& windowName, const winrt::hstring& windowName,
const uint32_t tabIndex, const uint32_t tabIndex,
const std::optional<til::point>& dragPoint = std::nullopt); const std::optional<winrt::Windows::Foundation::Point>& dragPoint = std::nullopt);
void _sendDraggedTabToWindow(const winrt::hstring& windowId, const uint32_t tabIndex, std::optional<til::point> dragPoint); void _sendDraggedTabToWindow(const winrt::hstring& windowId, const uint32_t tabIndex, std::optional<winrt::Windows::Foundation::Point> dragPoint);
void _PopulateContextMenu(const Microsoft::Terminal::Control::TermControl& control, const Microsoft::UI::Xaml::Controls::CommandBarFlyout& sender, const bool withSelection); void _PopulateContextMenu(const Microsoft::Terminal::Control::TermControl& control, const Microsoft::UI::Xaml::Controls::CommandBarFlyout& sender, const bool withSelection);
void _PopulateQuickFixMenu(const Microsoft::Terminal::Control::TermControl& control, const Windows::UI::Xaml::Controls::MenuFlyout& sender); void _PopulateQuickFixMenu(const Microsoft::Terminal::Control::TermControl& control, const Windows::UI::Xaml::Controls::MenuFlyout& sender);

View File

@ -718,8 +718,8 @@ namespace winrt::TerminalApp::implementation
// //
// contentBounds is in screen pixels, but that's okay! we want to // contentBounds is in screen pixels, but that's okay! we want to
// return screen pixels out of here. Nailed it. // return screen pixels out of here. Nailed it.
const til::rect bounds = { til::math::rounding, _contentBounds.Value() }; const auto bounds = _contentBounds.Value();
initialPosition = { bounds.left, bounds.top }; initialPosition = { lroundf(bounds.X), lroundf(bounds.Y) };
} }
return { return {
initialPosition.X ? initialPosition.X.Value() : defaultInitialX, initialPosition.X ? initialPosition.X.Value() : defaultInitialX,

View File

@ -106,6 +106,7 @@ namespace Microsoft.Terminal.Control
UInt64 SwapChainHandle { get; }; UInt64 SwapChainHandle { get; };
Windows.Foundation.Size FontSize { get; }; Windows.Foundation.Size FontSize { get; };
Windows.Foundation.Size FontSizeInDips { get; };
UInt16 FontWeight { get; }; UInt16 FontWeight { get; };
Single Opacity { get; }; Single Opacity { get; };
Boolean UseAcrylic { get; }; Boolean UseAcrylic { get; };

View File

@ -324,7 +324,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
} }
} }
void ControlInteractivity::TouchPressed(const Core::Point contactPoint) void ControlInteractivity::TouchPressed(const winrt::Windows::Foundation::Point contactPoint)
{ {
_touchAnchor = contactPoint; _touchAnchor = contactPoint;
} }
@ -384,7 +384,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return handledCompletely; return handledCompletely;
} }
void ControlInteractivity::TouchMoved(const Core::Point newTouchPoint, void ControlInteractivity::TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint,
const bool focused) const bool focused)
{ {
if (focused && if (focused &&

View File

@ -56,7 +56,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const uint64_t timestamp, const uint64_t timestamp,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const Core::Point pixelPosition); const Core::Point pixelPosition);
void TouchPressed(const Core::Point contactPoint); void TouchPressed(const winrt::Windows::Foundation::Point contactPoint);
bool PointerMoved(Control::MouseButtonState buttonState, bool PointerMoved(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind, const unsigned int pointerUpdateKind,
@ -64,7 +64,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const bool focused, const bool focused,
const Core::Point pixelPosition, const Core::Point pixelPosition,
const bool pointerPressedInBounds); const bool pointerPressedInBounds);
void TouchMoved(const Core::Point newTouchPoint, void TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint,
const bool focused); const bool focused);
void PointerReleased(Control::MouseButtonState buttonState, void PointerReleased(Control::MouseButtonState buttonState,
@ -115,7 +115,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// If this is set, then we assume we are in the middle of panning the // If this is set, then we assume we are in the middle of panning the
// viewport via touch input. // viewport via touch input.
std::optional<Core::Point> _touchAnchor; std::optional<winrt::Windows::Foundation::Point> _touchAnchor;
using Timestamp = uint64_t; using Timestamp = uint64_t;

View File

@ -41,7 +41,7 @@ namespace Microsoft.Terminal.Control
UInt64 timestamp, UInt64 timestamp,
Microsoft.Terminal.Core.ControlKeyStates modifiers, Microsoft.Terminal.Core.ControlKeyStates modifiers,
Microsoft.Terminal.Core.Point pixelPosition); Microsoft.Terminal.Core.Point pixelPosition);
void TouchPressed(Microsoft.Terminal.Core.Point contactPoint); void TouchPressed(Windows.Foundation.Point contactPoint);
Boolean PointerMoved(MouseButtonState buttonState, Boolean PointerMoved(MouseButtonState buttonState,
UInt32 pointerUpdateKind, UInt32 pointerUpdateKind,
@ -50,7 +50,7 @@ namespace Microsoft.Terminal.Control
Microsoft.Terminal.Core.Point pixelPosition, Microsoft.Terminal.Core.Point pixelPosition,
Boolean pointerPressedInBounds); Boolean pointerPressedInBounds);
void TouchMoved(Microsoft.Terminal.Core.Point newTouchPoint, void TouchMoved(Windows.Foundation.Point newTouchPoint,
Boolean focused); Boolean focused);
void PointerReleased(MouseButtonState buttonState, void PointerReleased(MouseButtonState buttonState,

View File

@ -1092,11 +1092,6 @@ til::rect HwndTerminal::GetPadding() const noexcept
return {}; return {};
} }
float HwndTerminal::GetScaleFactor() const noexcept
{
return static_cast<float>(_currentDpi) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
}
void HwndTerminal::ChangeViewport(const til::inclusive_rect& NewWindow) void HwndTerminal::ChangeViewport(const til::inclusive_rect& NewWindow)
{ {
if (!_terminal) if (!_terminal)

View File

@ -145,7 +145,6 @@ private:
// Inherited via IControlAccessibilityInfo // Inherited via IControlAccessibilityInfo
til::size GetFontSize() const noexcept override; til::size GetFontSize() const noexcept override;
til::rect GetBounds() const noexcept override; til::rect GetBounds() const noexcept override;
float GetScaleFactor() const noexcept override;
void ChangeViewport(const til::inclusive_rect& NewWindow) override; void ChangeViewport(const til::inclusive_rect& NewWindow) override;
HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) noexcept override; HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) noexcept override;
til::rect GetPadding() const noexcept override; til::rect GetPadding() const noexcept override;

View File

@ -35,14 +35,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation
THROW_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, _interactivity->GetRenderData(), this)); THROW_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, _interactivity->GetRenderData(), this));
}; };
// Bounds is expected to be in pixels.
void InteractivityAutomationPeer::SetControlBounds(const Windows::Foundation::Rect bounds) void InteractivityAutomationPeer::SetControlBounds(const Windows::Foundation::Rect bounds)
{ {
_controlBounds = til::rect{ til::math::rounding, bounds }; _controlBounds = { til::math::rounding, bounds };
} }
// Padding is expected to be in DIPs.
void InteractivityAutomationPeer::SetControlPadding(const Core::Padding padding) void InteractivityAutomationPeer::SetControlPadding(const Core::Padding padding)
{ {
_controlPadding = til::rect{ til::math::rounding, padding }; const auto scale = static_cast<float>(DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel());
_controlPadding = { til::math::rounding, padding.Left * scale, padding.Top * scale, padding.Right * scale, padding.Bottom * scale };
} }
void InteractivityAutomationPeer::ParentProvider(AutomationPeer parentProvider) void InteractivityAutomationPeer::ParentProvider(AutomationPeer parentProvider)
{ {
_parentProvider = parentProvider; _parentProvider = parentProvider;
@ -169,11 +174,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _controlPadding; return _controlPadding;
} }
float InteractivityAutomationPeer::GetScaleFactor() const noexcept
{
return static_cast<float>(DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel());
}
void InteractivityAutomationPeer::ChangeViewport(const til::inclusive_rect& NewWindow) void InteractivityAutomationPeer::ChangeViewport(const til::inclusive_rect& NewWindow)
{ {
_interactivity->UpdateScrollbar(static_cast<float>(NewWindow.top)); _interactivity->UpdateScrollbar(static_cast<float>(NewWindow.top));

View File

@ -66,7 +66,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
virtual til::size GetFontSize() const noexcept override; virtual til::size GetFontSize() const noexcept override;
virtual til::rect GetBounds() const noexcept override; virtual til::rect GetBounds() const noexcept override;
virtual til::rect GetPadding() const noexcept override; virtual til::rect GetPadding() const noexcept override;
virtual float GetScaleFactor() const noexcept override;
virtual void ChangeViewport(const til::inclusive_rect& NewWindow) override; virtual void ChangeViewport(const til::inclusive_rect& NewWindow) override;
virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override; virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override;
#pragma endregion #pragma endregion

View File

@ -1163,9 +1163,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// This is needed for TermControlAutomationPeer. We probably could find a // This is needed for TermControlAutomationPeer. We probably could find a
// clever way around asking the core for this. // clever way around asking the core for this.
til::point TermControl::GetFontSize() const winrt::Windows::Foundation::Size TermControl::GetFontSize() const
{ {
return { til::math::rounding, _core.FontSize().Width, _core.FontSize().Height }; return _core.FontSize();
} }
const Windows::UI::Xaml::Thickness TermControl::GetPadding() const Windows::UI::Xaml::Thickness TermControl::GetPadding()
@ -1912,9 +1912,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (type == Windows::Devices::Input::PointerDeviceType::Touch) if (type == Windows::Devices::Input::PointerDeviceType::Touch)
{ {
// NB: I don't think this is correct because the touch should be in the center of the rect.
// I suspect the point.Position() would be correct.
const auto contactRect = point.Properties().ContactRect(); const auto contactRect = point.Properties().ContactRect();
auto anchor = til::point{ til::math::rounding, contactRect.X, contactRect.Y }; _interactivity.TouchPressed({ contactRect.X, contactRect.Y });
_interactivity.TouchPressed(anchor.to_core_point());
} }
else else
{ {
@ -1923,7 +1924,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TermControl::GetPointerUpdateKind(point), TermControl::GetPointerUpdateKind(point),
point.Timestamp(), point.Timestamp(),
ControlKeyStates{ args.KeyModifiers() }, ControlKeyStates{ args.KeyModifiers() },
_toTerminalOrigin(cursorPosition).to_core_point()); _toTerminalOrigin(cursorPosition));
} }
args.Handled(true); args.Handled(true);
@ -1962,7 +1963,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TermControl::GetPointerUpdateKind(point), TermControl::GetPointerUpdateKind(point),
ControlKeyStates(args.KeyModifiers()), ControlKeyStates(args.KeyModifiers()),
_focused, _focused,
pixelPosition.to_core_point(), pixelPosition,
_pointerPressedInBounds); _pointerPressedInBounds);
// GH#9109 - Only start an auto-scroll when the drag actually // GH#9109 - Only start an auto-scroll when the drag actually
@ -2002,9 +2003,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
else if (type == Windows::Devices::Input::PointerDeviceType::Touch) else if (type == Windows::Devices::Input::PointerDeviceType::Touch)
{ {
const auto contactRect = point.Properties().ContactRect(); const auto contactRect = point.Properties().ContactRect();
til::point newTouchPoint{ til::math::rounding, contactRect.X, contactRect.Y }; _interactivity.TouchMoved({ contactRect.X, contactRect.Y }, _focused);
_interactivity.TouchMoved(newTouchPoint.to_core_point(), _focused);
} }
args.Handled(true); args.Handled(true);
@ -2040,7 +2039,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_interactivity.PointerReleased(TermControl::GetPressedMouseButtons(point), _interactivity.PointerReleased(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point), TermControl::GetPointerUpdateKind(point),
ControlKeyStates(args.KeyModifiers()), ControlKeyStates(args.KeyModifiers()),
pixelPosition.to_core_point()); pixelPosition);
} }
else if (type == Windows::Devices::Input::PointerDeviceType::Touch) else if (type == Windows::Devices::Input::PointerDeviceType::Touch)
{ {
@ -2080,7 +2079,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto result = _interactivity.MouseWheel(ControlKeyStates{ args.KeyModifiers() }, auto result = _interactivity.MouseWheel(ControlKeyStates{ args.KeyModifiers() },
point.Properties().MouseWheelDelta(), point.Properties().MouseWheelDelta(),
_toTerminalOrigin(point.Position()).to_core_point(), _toTerminalOrigin(point.Position()),
TermControl::GetPressedMouseButtons(point)); TermControl::GetPressedMouseButtons(point));
if (result) if (result)
{ {
@ -2111,7 +2110,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
WI_SetFlagIf(state, Control::MouseButtonState::IsMiddleButtonDown, midButtonDown); WI_SetFlagIf(state, Control::MouseButtonState::IsMiddleButtonDown, midButtonDown);
WI_SetFlagIf(state, Control::MouseButtonState::IsRightButtonDown, rightButtonDown); WI_SetFlagIf(state, Control::MouseButtonState::IsRightButtonDown, rightButtonDown);
return _interactivity.MouseWheel(modifiers, delta, _toTerminalOrigin(location).to_core_point(), state); return _interactivity.MouseWheel(modifiers, delta, _toTerminalOrigin(location), state);
} }
// Method Description: // Method Description:
@ -2481,7 +2480,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - cursorPosition: in pixels, relative to the origin of the control // - cursorPosition: in pixels, relative to the origin of the control
void TermControl::_SetEndSelectionPointAtCursor(const Windows::Foundation::Point& cursorPosition) void TermControl::_SetEndSelectionPointAtCursor(const Windows::Foundation::Point& cursorPosition)
{ {
_interactivity.SetEndSelectionPoint(_toTerminalOrigin(cursorPosition).to_core_point()); _interactivity.SetEndSelectionPoint(_toTerminalOrigin(cursorPosition));
} }
// Method Description: // Method Description:
@ -2847,7 +2846,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - The dimensions of a single character of this control, in DIPs // - The dimensions of a single character of this control, in DIPs
winrt::Windows::Foundation::Size TermControl::CharacterDimensions() const winrt::Windows::Foundation::Size TermControl::CharacterDimensions() const
{ {
return _core.FontSize(); return _core.FontSizeInDips();
} }
// Method Description: // Method Description:
@ -2863,7 +2862,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{ {
if (_initializedTerminal) if (_initializedTerminal)
{ {
const auto fontSize = _core.FontSize(); const auto fontSize = _core.FontSizeInDips();
auto width = fontSize.Width; auto width = fontSize.Width;
auto height = fontSize.Height; auto height = fontSize.Height;
// Reserve additional space if scrollbar is intended to be visible // Reserve additional space if scrollbar is intended to be visible
@ -2881,14 +2880,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
} }
else else
{ {
// If the terminal hasn't been initialized yet, then the font size will // Do we ever get here (= uninitialized terminal)? If so: How?
// have dimensions {1, fontSize.height}, which can mess with consumers of assert(false);
// this method. In that case, we'll need to pre-calculate the font return { 10, 10 };
// width, before we actually have a renderer or swapchain.
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
const auto scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
return GetProposedDimensions(_core.Settings(), dpi, minSize);
} }
} }
@ -2902,7 +2896,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - A dimension that would be aligned to the character grid. // - A dimension that would be aligned to the character grid.
float TermControl::SnapDimensionToGrid(const bool widthOrHeight, const float dimension) float TermControl::SnapDimensionToGrid(const bool widthOrHeight, const float dimension)
{ {
const auto fontSize = _core.FontSize(); const auto fontSize = _core.FontSizeInDips();
const auto fontDimension = widthOrHeight ? fontSize.Width : fontSize.Height; const auto fontDimension = widthOrHeight ? fontSize.Width : fontSize.Height;
const auto padding = GetPadding(); const auto padding = GetPadding();
@ -3056,26 +3050,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return flags; return flags;
} }
til::point TermControl::_toControlOrigin(const til::point terminalPos) winrt::Windows::Foundation::Point TermControl::_toControlOrigin(const til::point terminalPos)
{ {
const auto fontSize{ CharacterDimensions() }; const auto fontSize{ CharacterDimensions() };
// Convert text buffer cursor position to client coordinate position
// within the window. This point is in _pixels_
const auto clientCursorPosX = terminalPos.x * fontSize.Width;
const auto clientCursorPosY = terminalPos.y * fontSize.Height;
// Get scale factor for view
const auto scaleFactor = SwapChainPanel().CompositionScaleX();
const auto clientCursorInDipsX = clientCursorPosX / scaleFactor;
const auto clientCursorInDipsY = clientCursorPosY / scaleFactor;
auto padding{ GetPadding() }; auto padding{ GetPadding() };
til::point relativeToOrigin{ til::math::rounding,
clientCursorInDipsX + padding.Left, // Convert text buffer cursor position to client coordinate position within the window.
clientCursorInDipsY + padding.Top }; return {
return relativeToOrigin; terminalPos.x * fontSize.Width + static_cast<float>(padding.Left),
terminalPos.y * fontSize.Height + static_cast<float>(padding.Top),
};
} }
// Method Description: // Method Description:
@ -3086,24 +3070,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// NOTE: origin (0,0) is top-left. // NOTE: origin (0,0) is top-left.
// Return Value: // Return Value:
// - the corresponding viewport terminal position (in pixels) for the given Point parameter // - the corresponding viewport terminal position (in pixels) for the given Point parameter
const til::point TermControl::_toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition) Core::Point TermControl::_toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition)
{ {
// cursorPosition is DIPs, relative to SwapChainPanel origin // cursorPosition is DIPs, relative to SwapChainPanel origin
const til::point cursorPosInDIPs{ til::math::rounding, cursorPosition }; const auto padding = GetPadding();
const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top };
// This point is the location of the cursor within the actual grid of characters, in DIPs // This point is the location of the cursor within the actual grid of characters, in DIPs
const auto relativeToMarginInDIPs = cursorPosInDIPs - marginsInDips; const auto relativeToMarginInDIPsX = cursorPosition.X - static_cast<float>(padding.Left);
const auto relativeToMarginInDIPsY = cursorPosition.Y - static_cast<float>(padding.Top);
// Convert it to pixels // Convert it to pixels
const auto scale = SwapChainPanel().CompositionScaleX(); const auto scale = SwapChainPanel().CompositionScaleX();
const til::point relativeToMarginInPixels{
til::math::flooring,
relativeToMarginInDIPs.x * scale,
relativeToMarginInDIPs.y * scale,
};
return relativeToMarginInPixels; return {
lroundf(relativeToMarginInDIPsX * scale),
lroundf(relativeToMarginInDIPsY * scale),
};
} }
// Method Description: // Method Description:
@ -3587,25 +3569,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation
} }
const auto panel = SwapChainPanel(); const auto panel = SwapChainPanel();
const auto scale = panel.CompositionScaleX();
const auto offset = panel.ActualOffset(); const auto offset = panel.ActualOffset();
// Update the tooltip with the URI // Update the tooltip with the URI
HoveredUri().Text(uriText); HoveredUri().Text(uriText);
// Set the border thickness so it covers the entire cell // Set the border thickness so it covers the entire cell
const auto charSizeInPixels = CharacterDimensions(); const auto fontSize = CharacterDimensions();
const auto htInDips = charSizeInPixels.Height / scale; const Thickness newThickness{ fontSize.Height, fontSize.Width, 0, 0 };
const auto wtInDips = charSizeInPixels.Width / scale;
const Thickness newThickness{ wtInDips, htInDips, 0, 0 };
HyperlinkTooltipBorder().BorderThickness(newThickness); HyperlinkTooltipBorder().BorderThickness(newThickness);
// Compute the location of the top left corner of the cell in DIPS // Compute the location of the top left corner of the cell in DIPS
const til::point locationInDIPs{ _toPosInDips(lastHoveredCell.Value()) }; const auto locationInDIPs{ _toPosInDips(lastHoveredCell.Value()) };
// Move the border to the top left corner of the cell // Move the border to the top left corner of the cell
OverlayCanvas().SetLeft(HyperlinkTooltipBorder(), locationInDIPs.x - offset.x); OverlayCanvas().SetLeft(HyperlinkTooltipBorder(), locationInDIPs.X - offset.x);
OverlayCanvas().SetTop(HyperlinkTooltipBorder(), locationInDIPs.y - offset.y); OverlayCanvas().SetTop(HyperlinkTooltipBorder(), locationInDIPs.Y - offset.y);
} }
safe_void_coroutine TermControl::_updateSelectionMarkers(IInspectable /*sender*/, Control::UpdateSelectionMarkersEventArgs args) safe_void_coroutine TermControl::_updateSelectionMarkers(IInspectable /*sender*/, Control::UpdateSelectionMarkersEventArgs args)
@ -3647,13 +3626,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Add one to the viewport pos' x-coord to fix that. // Add one to the viewport pos' x-coord to fix that.
terminalPos.X += 1; terminalPos.X += 1;
} }
const til::point locationInDIPs{ _toPosInDips(terminalPos) }; const auto locationInDIPs{ _toPosInDips(terminalPos) };
// Move the marker to the top left corner of the cell // Move the marker to the top left corner of the cell
SelectionCanvas().SetLeft(marker, SelectionCanvas().SetLeft(marker,
(locationInDIPs.x - SwapChainPanel().ActualOffset().x)); (locationInDIPs.X - SwapChainPanel().ActualOffset().x));
SelectionCanvas().SetTop(marker, SelectionCanvas().SetTop(marker,
(locationInDIPs.y - SwapChainPanel().ActualOffset().y)); (locationInDIPs.Y - SwapChainPanel().ActualOffset().y));
marker.Visibility(Visibility::Visible); marker.Visibility(Visibility::Visible);
}; };
@ -3694,15 +3673,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
} }
} }
til::point TermControl::_toPosInDips(const Core::Point terminalCellPos) winrt::Windows::Foundation::Point TermControl::_toPosInDips(const Core::Point terminalCellPos)
{ {
const til::point terminalPos{ terminalCellPos }; const auto marginsInDips{ GetPadding() };
const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top }; const auto fontSize{ _core.FontSizeInDips() };
const til::size fontSize{ til::math::rounding, _core.FontSize() }; return {
const til::point posInPixels{ terminalPos * fontSize }; terminalCellPos.X * fontSize.Width + static_cast<float>(marginsInDips.Left),
const auto scale{ SwapChainPanel().CompositionScaleX() }; terminalCellPos.Y * fontSize.Height + static_cast<float>(marginsInDips.Top),
const til::point posInDIPs{ til::math::flooring, posInPixels.x / scale, posInPixels.y / scale }; };
return posInDIPs + marginsInDips;
} }
void TermControl::_coreFontSizeChanged(const IInspectable& /*sender*/, void TermControl::_coreFontSizeChanged(const IInspectable& /*sender*/,
@ -3974,53 +3952,42 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Returns the text cursor's position relative to our origin, in DIPs. // Returns the text cursor's position relative to our origin, in DIPs.
Windows::Foundation::Point TermControl::CursorPositionInDips() Windows::Foundation::Point TermControl::CursorPositionInDips()
{ {
const til::point cursorPos{ _core.CursorPosition() }; const auto cursorPos{ _core.CursorPosition() };
// CharacterDimensions returns a font size in pixels. // CharacterDimensions returns a font size in pixels.
const auto fontSize{ CharacterDimensions() }; const auto fontSize{ CharacterDimensions() };
// Convert text buffer cursor position to client coordinate position
// within the window. This point is in _pixels_
const Windows::Foundation::Point clientCursorPos{ cursorPos.x * fontSize.Width,
cursorPos.y * fontSize.Height };
// Get scale factor for view
const auto scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
// Adjust to DIPs
const til::point clientCursorInDips{ til::math::rounding, clientCursorPos.X / scaleFactor, clientCursorPos.Y / scaleFactor };
// Account for the margins, which are in DIPs // Account for the margins, which are in DIPs
auto padding{ GetPadding() }; auto padding{ GetPadding() };
til::point relativeToOrigin{ til::math::flooring,
clientCursorInDips.x + padding.Left,
clientCursorInDips.y + padding.Top };
return relativeToOrigin.to_winrt_point(); // Convert text buffer cursor position to client coordinate position
// within the window. This point is in _pixels_
return {
cursorPos.X * fontSize.Width + static_cast<float>(padding.Left),
cursorPos.Y * fontSize.Height + static_cast<float>(padding.Top),
};
} }
void TermControl::_contextMenuHandler(IInspectable /*sender*/, void TermControl::_contextMenuHandler(IInspectable /*sender*/,
Control::ContextMenuRequestedEventArgs args) Control::ContextMenuRequestedEventArgs args)
{ {
// Position the menu where the pointer is. This was the best way I found how. // Position the menu where the pointer is. This was the best way I found how.
const til::point absolutePointerPos{ til::math::rounding, CoreWindow::GetForCurrentThread().PointerPosition() }; const auto absolutePointerPos = CoreWindow::GetForCurrentThread().PointerPosition();
const til::point absoluteWindowOrigin{ til::math::rounding, const auto absoluteWindowOrigin = CoreWindow::GetForCurrentThread().Bounds();
CoreWindow::GetForCurrentThread().Bounds().X,
CoreWindow::GetForCurrentThread().Bounds().Y };
// Get the offset (margin + tabs, etc..) of the control within the window // Get the offset (margin + tabs, etc..) of the control within the window
const til::point controlOrigin{ til::math::flooring, const auto controlOrigin = TransformToVisual(nullptr).TransformPoint({});
this->TransformToVisual(nullptr).TransformPoint(Windows::Foundation::Point(0, 0)) }; _showContextMenuAt({
absolutePointerPos.X - absoluteWindowOrigin.X - controlOrigin.X,
const auto pos = (absolutePointerPos - absoluteWindowOrigin - controlOrigin); absolutePointerPos.Y - absoluteWindowOrigin.Y - controlOrigin.Y,
_showContextMenuAt(pos); });
} }
void TermControl::_showContextMenuAt(const til::point& controlRelativePos) void TermControl::_showContextMenuAt(const winrt::Windows::Foundation::Point& controlRelativePos)
{ {
Controls::Primitives::FlyoutShowOptions myOption{}; Controls::Primitives::FlyoutShowOptions myOption{};
myOption.ShowMode(Controls::Primitives::FlyoutShowMode::Standard); myOption.ShowMode(Controls::Primitives::FlyoutShowMode::Standard);
myOption.Placement(Controls::Primitives::FlyoutPlacementMode::TopEdgeAlignedLeft); myOption.Placement(Controls::Primitives::FlyoutPlacementMode::TopEdgeAlignedLeft);
myOption.Position(controlRelativePos.to_winrt_point()); myOption.Position(controlRelativePos);
// The "Select command" and "Select output" buttons should only be // The "Select command" and "Select output" buttons should only be
// visible if shell integration is actually turned on. // visible if shell integration is actually turned on.
@ -4127,7 +4094,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// draw the button in the gutter // draw the button in the gutter
const auto& quickFixBtnPosInDips = _toPosInDips({ 0, _quickFixBufferPos }); const auto& quickFixBtnPosInDips = _toPosInDips({ 0, _quickFixBufferPos });
Controls::Canvas::SetLeft(quickFixBtn, -termPadding.Left); Controls::Canvas::SetLeft(quickFixBtn, -termPadding.Left);
Controls::Canvas::SetTop(quickFixBtn, quickFixBtnPosInDips.y - termPadding.Top); Controls::Canvas::SetTop(quickFixBtn, quickFixBtnPosInDips.Y - termPadding.Top);
quickFixBtn.Visibility(Visibility::Visible); quickFixBtn.Visibility(Visibility::Visible);
if (auto automationPeer{ FrameworkElementAutomationPeer::FromElement(*this) }) if (auto automationPeer{ FrameworkElementAutomationPeer::FromElement(*this) })

View File

@ -123,7 +123,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void AdjustFontSize(float fontSizeDelta); void AdjustFontSize(float fontSizeDelta);
void ResetFontSize(); void ResetFontSize();
til::point GetFontSize() const; winrt::Windows::Foundation::Size GetFontSize() const;
void SendInput(const winrt::hstring& input); void SendInput(const winrt::hstring& input);
void ClearBuffer(Control::ClearBufferType clearType); void ClearBuffer(Control::ClearBufferType clearType);
@ -411,8 +411,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept; static void _ClearKeyboardState(const WORD vkey, const WORD scanCode) noexcept;
bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown); bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
til::point _toControlOrigin(const til::point terminalPosition); winrt::Windows::Foundation::Point _toControlOrigin(const til::point terminalPosition);
const til::point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition); Core::Point _toTerminalOrigin(winrt::Windows::Foundation::Point cursorPosition);
double _GetAutoScrollSpeed(double cursorDistanceFromBorder) const; double _GetAutoScrollSpeed(double cursorDistanceFromBorder) const;
@ -431,13 +431,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _coreWarningBell(const IInspectable& sender, const IInspectable& args); void _coreWarningBell(const IInspectable& sender, const IInspectable& args);
void _coreOutputIdle(const IInspectable& sender, const IInspectable& args); void _coreOutputIdle(const IInspectable& sender, const IInspectable& args);
til::point _toPosInDips(const Core::Point terminalCellPos); winrt::Windows::Foundation::Point _toPosInDips(const Core::Point terminalCellPos);
void _throttledUpdateScrollbar(const ScrollBarUpdate& update); void _throttledUpdateScrollbar(const ScrollBarUpdate& update);
void _pasteTextWithBroadcast(const winrt::hstring& text); void _pasteTextWithBroadcast(const winrt::hstring& text);
void _contextMenuHandler(IInspectable sender, Control::ContextMenuRequestedEventArgs args); void _contextMenuHandler(IInspectable sender, Control::ContextMenuRequestedEventArgs args);
void _showContextMenuAt(const til::point& controlRelativePos); void _showContextMenuAt(const winrt::Windows::Foundation::Point& controlRelativePos);
void _bubbleSearchMissingCommand(const IInspectable& sender, const Control::SearchMissingCommandEventArgs& args); void _bubbleSearchMissingCommand(const IInspectable& sender, const Control::SearchMissingCommandEventArgs& args);
winrt::fire_and_forget _bubbleWindowSizeChanged(const IInspectable& sender, Control::WindowSizeChangedEventArgs args); winrt::fire_and_forget _bubbleWindowSizeChanged(const IInspectable& sender, Control::WindowSizeChangedEventArgs args);

View File

@ -58,7 +58,14 @@ namespace winrt::Microsoft::Terminal::UI::implementation
// Misc // Misc
winrt::Windows::UI::Text::FontWeight Converters::DoubleToFontWeight(double value) winrt::Windows::UI::Text::FontWeight Converters::DoubleToFontWeight(double value)
{ {
return winrt::Windows::UI::Text::FontWeight{ base::ClampedNumeric<uint16_t>(value) }; uint16_t val = 400;
if (value >= 1.0 && value <= 1000.0)
{
val = gsl::narrow_cast<uint16_t>(lrint(value));
}
return winrt::Windows::UI::Text::FontWeight{ val };
} }
winrt::Windows::UI::Xaml::Media::SolidColorBrush Converters::ColorToBrush(const winrt::Windows::UI::Color color) winrt::Windows::UI::Xaml::Media::SolidColorBrush Converters::ColorToBrush(const winrt::Windows::UI::Color color)

View File

@ -872,12 +872,12 @@ void AppHost::_RaiseVisualBell(const winrt::Windows::Foundation::IInspectable&,
// - delta: the wheel delta that triggered this event. // - delta: the wheel delta that triggered this event.
// Return Value: // Return Value:
// - <none> // - <none>
void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta) void AppHost::_WindowMouseWheeled(const winrt::Windows::Foundation::Point coord, const int32_t delta)
{ {
if (_windowLogic) if (_windowLogic)
{ {
// Find all the elements that are underneath the mouse // Find all the elements that are underneath the mouse
auto elems = Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord.to_winrt_point(), _windowLogic.GetRoot()); auto elems = Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord, _windowLogic.GetRoot());
for (const auto& e : elems) for (const auto& e : elems)
{ {
// If that element has implemented IMouseWheelListener, call OnMouseWheel on that element. // If that element has implemented IMouseWheelListener, call OnMouseWheel on that element.
@ -888,15 +888,18 @@ void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta)
// Translate the event to the coordinate space of the control // Translate the event to the coordinate space of the control
// we're attempting to dispatch it to // we're attempting to dispatch it to
const auto transform = e.TransformToVisual(nullptr); const auto transform = e.TransformToVisual(nullptr);
const til::point controlOrigin{ til::math::flooring, transform.TransformPoint({}) }; const auto controlOrigin = transform.TransformPoint({});
const auto offsetPoint = coord - controlOrigin; const winrt::Windows::Foundation::Point offsetPoint{
coord.X - controlOrigin.X,
coord.Y - controlOrigin.Y,
};
const auto lButtonDown = WI_IsFlagSet(GetKeyState(VK_LBUTTON), KeyPressed); const auto lButtonDown = WI_IsFlagSet(GetKeyState(VK_LBUTTON), KeyPressed);
const auto mButtonDown = WI_IsFlagSet(GetKeyState(VK_MBUTTON), KeyPressed); const auto mButtonDown = WI_IsFlagSet(GetKeyState(VK_MBUTTON), KeyPressed);
const auto rButtonDown = WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed); const auto rButtonDown = WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed);
if (control.OnMouseWheel(offsetPoint.to_winrt_point(), delta, lButtonDown, mButtonDown, rButtonDown)) if (control.OnMouseWheel(offsetPoint, delta, lButtonDown, mButtonDown, rButtonDown))
{ {
// If the element handled the mouse wheel event, don't // If the element handled the mouse wheel event, don't
// continue to iterate over the remaining controls. // continue to iterate over the remaining controls.
@ -1493,14 +1496,12 @@ void AppHost::_handleMoveContent(const winrt::Windows::Foundation::IInspectable&
if (args.WindowPosition() && _window) if (args.WindowPosition() && _window)
{ {
// The WindowPosition is in DIPs. We need to convert it to pixels. // The WindowPosition is in DIPs. We need to convert it to pixels.
const til::point dragPositionInDips{ til::math::rounding, args.WindowPosition().Value() }; const auto dragPositionInDips = args.WindowPosition().Value();
const auto scale = _window->GetCurrentDpiScale(); const auto scale = _window->GetCurrentDpiScale();
til::point dragPositionInPixels{ auto dragPositionInPixels = dragPositionInDips;
til::math::rounding, dragPositionInPixels.X *= scale;
dragPositionInDips.x * scale, dragPositionInPixels.Y *= scale;
dragPositionInDips.y * scale,
};
// Fortunately, the window position is already in pixels. // Fortunately, the window position is already in pixels.
til::rect windowBoundsInPixels{ _window->GetWindowRect() }; til::rect windowBoundsInPixels{ _window->GetWindowRect() };
@ -1532,17 +1533,20 @@ void AppHost::_handleMoveContent(const winrt::Windows::Foundation::IInspectable&
} }
// Adjust for the non-client bounds // Adjust for the non-client bounds
dragPositionInPixels.x -= nonClientFrame.left; dragPositionInPixels.X -= nonClientFrame.left;
dragPositionInPixels.y -= nonClientFrame.top; dragPositionInPixels.Y -= nonClientFrame.top;
windowSize = windowSize - nonClientFrame.size(); windowSize = windowSize - nonClientFrame.size();
// Convert to DIPs for the size, so that dragging across a DPI boundary // Convert to DIPs for the size, so that dragging across a DPI boundary
// retains the correct dimensions. // retains the correct dimensions.
const auto sizeInDips = windowSize.scale(til::math::rounding, 1.0f / scale);
til::rect inDips{ dragPositionInPixels, sizeInDips };
// Use the drag event as the new position, and the size of the actual window. // Use the drag event as the new position, and the size of the actual window.
windowBoundsReference = inDips.to_winrt_rect(); const auto inverseScale = 1.0f / scale;
windowBoundsReference = winrt::Windows::Foundation::Rect{
dragPositionInPixels.X * inverseScale,
dragPositionInPixels.Y * inverseScale,
windowSize.width * inverseScale,
windowSize.height * inverseScale,
};
} }
_windowManager.RequestMoveContent(args.Window(), args.Content(), args.TabIndex(), windowBoundsReference); _windowManager.RequestMoveContent(args.Window(), args.Content(), args.TabIndex(), windowBoundsReference);

View File

@ -90,7 +90,7 @@ private:
void _RaiseVisualBell(const winrt::Windows::Foundation::IInspectable& sender, void _RaiseVisualBell(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& arg); const winrt::Windows::Foundation::IInspectable& arg);
void _WindowMouseWheeled(const til::point coord, const int32_t delta); void _WindowMouseWheeled(const winrt::Windows::Foundation::Point coord, const int32_t delta);
void _WindowActivated(bool activated); void _WindowActivated(bool activated);
safe_void_coroutine _peasantNotifyActivateWindow(); safe_void_coroutine _peasantNotifyActivateWindow();
void _WindowMoved(); void _WindowMoved();

View File

@ -228,6 +228,16 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam)
auto winRect = reinterpret_cast<LPRECT>(lParam); auto winRect = reinterpret_cast<LPRECT>(lParam);
// If we're the quake window, prevent resizing on all sides except the
// bottom. This also applies to resizing with the Alt+Space menu
if (IsQuakeWindow() && wParam != WMSZ_BOTTOM)
{
// Stuff our current window size into the lParam, and return true. This
// will tell User32 to use our current dimensions to resize to.
::GetWindowRect(_window.get(), winRect);
return true;
}
// Find nearest monitor. // Find nearest monitor.
auto hmon = MonitorFromRect(winRect, MONITOR_DEFAULTTONEAREST); auto hmon = MonitorFromRect(winRect, MONITOR_DEFAULTTONEAREST);
@ -239,36 +249,30 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam)
// bad parameters, which we won't have, so no big deal. // bad parameters, which we won't have, so no big deal.
LOG_IF_FAILED(GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy)); LOG_IF_FAILED(GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy));
const long minWidthScaled = minimumWidth * dpix / USER_DEFAULT_SCREEN_DPI;
const auto nonClientSize = GetTotalNonClientExclusiveSize(dpix); const auto nonClientSize = GetTotalNonClientExclusiveSize(dpix);
const auto dipPerPx = static_cast<float>(USER_DEFAULT_SCREEN_DPI) / static_cast<float>(dpix);
const auto pxPerDip = static_cast<float>(dpix) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
auto clientWidth = winRect->right - winRect->left - nonClientSize.width; auto clientWidth = winRect->right - winRect->left - nonClientSize.width;
clientWidth = std::max(minWidthScaled, clientWidth);
auto clientHeight = winRect->bottom - winRect->top - nonClientSize.height; auto clientHeight = winRect->bottom - winRect->top - nonClientSize.height;
// If we're the quake window, prevent resizing on all sides except the
// bottom. This also applies to resizing with the Alt+Space menu
if (IsQuakeWindow() && wParam != WMSZ_BOTTOM)
{
// Stuff our current window size into the lParam, and return true. This
// will tell User32 to use our current dimensions to resize to.
::GetWindowRect(_window.get(), winRect);
return true;
}
if (wParam != WMSZ_TOP && wParam != WMSZ_BOTTOM) if (wParam != WMSZ_TOP && wParam != WMSZ_BOTTOM)
{ {
// If user has dragged anything but the top or bottom border (so e.g. left border, // If user has dragged anything but the top or bottom border (so e.g. left border,
// top-right corner etc.), then this means that the width has changed. We thus ask to // top-right corner etc.), then this means that the width has changed. We thus ask to
// adjust this new width so that terminal(s) is/are aligned to their character grid(s). // adjust this new width so that terminal(s) is/are aligned to their character grid(s).
clientWidth = gsl::narrow_cast<decltype(clientWidth)>(_pfnSnapDimensionCallback(true, gsl::narrow_cast<float>(clientWidth))); auto width = clientWidth * dipPerPx;
width = std::max(width, minimumWidth);
width = _pfnSnapDimensionCallback(true, width);
clientWidth = lroundf(width * pxPerDip);
} }
if (wParam != WMSZ_LEFT && wParam != WMSZ_RIGHT) if (wParam != WMSZ_LEFT && wParam != WMSZ_RIGHT)
{ {
// Analogous to above, but for height. // Analogous to above, but for height.
clientHeight = gsl::narrow_cast<decltype(clientHeight)>(_pfnSnapDimensionCallback(false, gsl::narrow_cast<float>(clientHeight))); auto height = clientHeight * dipPerPx;
height = std::max(height, minimumHeight);
height = _pfnSnapDimensionCallback(false, height);
clientHeight = lroundf(height * pxPerDip);
} }
// Now make the window rectangle match the calculated client width and height, // Now make the window rectangle match the calculated client width and height,
@ -470,30 +474,16 @@ void IslandWindow::_OnGetMinMaxInfo(const WPARAM /*wParam*/, const LPARAM lParam
// From now we use dpix for all computations (same as in _OnSizing). // From now we use dpix for all computations (same as in _OnSizing).
const auto nonClientSizeScaled = GetTotalNonClientExclusiveSize(dpix); const auto nonClientSizeScaled = GetTotalNonClientExclusiveSize(dpix);
const auto pxPerDip = static_cast<float>(dpix) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
auto lpMinMaxInfo = reinterpret_cast<LPMINMAXINFO>(lParam);
lpMinMaxInfo->ptMinTrackSize.x = _calculateTotalSize(true, minimumWidth * dpix / USER_DEFAULT_SCREEN_DPI, nonClientSizeScaled.width);
lpMinMaxInfo->ptMinTrackSize.y = _calculateTotalSize(false, minimumHeight * dpiy / USER_DEFAULT_SCREEN_DPI, nonClientSizeScaled.height);
}
// Method Description:
// - Helper function that calculates a single dimension value, given initialWindow and nonClientSizes
// Arguments:
// - isWidth: parameter to pass to SnapDimensionCallback.
// True if the method is invoked for width computation, false if for height.
// - clientSize: the size of the client area (already)
// - nonClientSizeScaled: the exclusive non-client size (already scaled)
// Return Value:
// - The total dimension
long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize)
{
if (_pfnSnapDimensionCallback)
{
return gsl::narrow_cast<int>(_pfnSnapDimensionCallback(isWidth, gsl::narrow_cast<float>(clientSize)) + nonClientSize);
}
// We might have been called in WM_CREATE, before we've initialized XAML or // We might have been called in WM_CREATE, before we've initialized XAML or
// our page. That's okay. // our page. That's okay.
return clientSize + nonClientSize; const auto width = _pfnSnapDimensionCallback(true, minimumWidth);
const auto height = _pfnSnapDimensionCallback(false, minimumHeight);
auto lpMinMaxInfo = reinterpret_cast<LPMINMAXINFO>(lParam);
lpMinMaxInfo->ptMinTrackSize.x = lroundf(width * pxPerDip) + nonClientSizeScaled.width;
lpMinMaxInfo->ptMinTrackSize.y = lroundf(height * pxPerDip) + nonClientSizeScaled.height;
} }
[[nodiscard]] LRESULT IslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept [[nodiscard]] LRESULT IslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
@ -655,7 +645,7 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
const auto relative = eventPoint - origin; const auto relative = eventPoint - origin;
// Convert to logical scaling before raising the event. // Convert to logical scaling before raising the event.
const auto scale = GetCurrentDpiScale(); const auto scale = GetCurrentDpiScale();
const til::point real{ til::math::flooring, relative.x / scale, relative.y / scale }; const winrt::Windows::Foundation::Point real{ relative.x / scale, relative.y / scale };
const auto wheelDelta = static_cast<short>(HIWORD(wparam)); const auto wheelDelta = static_cast<short>(HIWORD(wparam));

View File

@ -74,11 +74,10 @@ public:
til::event<winrt::delegate<>> DragRegionClicked; til::event<winrt::delegate<>> DragRegionClicked;
til::event<winrt::delegate<>> WindowCloseButtonClicked; til::event<winrt::delegate<>> WindowCloseButtonClicked;
til::event<winrt::delegate<void(til::point, int32_t)>> MouseScrolled; til::event<winrt::delegate<void(winrt::Windows::Foundation::Point, int32_t)>> MouseScrolled;
til::event<winrt::delegate<void(bool)>> WindowActivated; til::event<winrt::delegate<void(bool)>> WindowActivated;
til::event<winrt::delegate<void()>> NotifyNotificationIconPressed; til::event<winrt::delegate<void()>> NotifyNotificationIconPressed;
til::event<winrt::delegate<void()>> NotifyWindowHidden; til::event<winrt::delegate<void()>> NotifyWindowHidden;
til::event<winrt::delegate<void(til::point)>> NotifyShowNotificationIconContextMenu;
til::event<winrt::delegate<void(HMENU, UINT)>> NotifyNotificationIconMenuItemSelected; til::event<winrt::delegate<void(HMENU, UINT)>> NotifyNotificationIconMenuItemSelected;
til::event<winrt::delegate<void()>> NotifyReAddNotificationIcon; til::event<winrt::delegate<void()>> NotifyReAddNotificationIcon;
til::event<winrt::delegate<void()>> ShouldExitFullscreen; til::event<winrt::delegate<void()>> ShouldExitFullscreen;
@ -130,7 +129,6 @@ protected:
LONG _getDesiredWindowStyle() const; LONG _getDesiredWindowStyle() const;
void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam); void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam);
long _calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize);
void _globalActivateWindow(const uint32_t dropdownDuration, void _globalActivateWindow(const uint32_t dropdownDuration,
const winrt::Microsoft::Terminal::Remoting::MonitorBehavior toMonitor); const winrt::Microsoft::Terminal::Remoting::MonitorBehavior toMonitor);
@ -163,10 +161,10 @@ protected:
private: private:
// This minimum width allows for width the tabs fit // This minimum width allows for width the tabs fit
static constexpr long minimumWidth = 460L; static constexpr float minimumWidth = 460;
// We run with no height requirement for client area, // We run with no height requirement for client area,
// though the total height will take into account the non-client area // though the total height will take into account the non-client area
// and the requirements of components hosted in the client area // and the requirements of components hosted in the client area
static constexpr long minimumHeight = 0L; static constexpr float minimumHeight = 0;
}; };

View File

@ -27,7 +27,6 @@ namespace Microsoft::Console::Types
virtual til::size GetFontSize() const noexcept = 0; virtual til::size GetFontSize() const noexcept = 0;
virtual til::rect GetBounds() const noexcept = 0; virtual til::rect GetBounds() const noexcept = 0;
virtual til::rect GetPadding() const noexcept = 0; virtual til::rect GetPadding() const noexcept = 0;
virtual float GetScaleFactor() const noexcept = 0;
virtual void ChangeViewport(const til::inclusive_rect& NewWindow) = 0; virtual void ChangeViewport(const til::inclusive_rect& NewWindow) = 0;
virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) = 0; virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) = 0;

View File

@ -140,14 +140,11 @@ til::size TermControlUiaProvider::GetFontSize() const noexcept
return _controlInfo->GetFontSize(); return _controlInfo->GetFontSize();
} }
til::rect TermControlUiaProvider::GetPadding() const noexcept til::point TermControlUiaProvider::GetContentOrigin() const noexcept
{ {
return _controlInfo->GetPadding(); const auto bounds = _controlInfo->GetBounds();
} const auto padding = _controlInfo->GetPadding();
return { bounds.left + padding.left, bounds.top + padding.top };
float TermControlUiaProvider::GetScaleFactor() const noexcept
{
return _controlInfo->GetScaleFactor();
} }
void TermControlUiaProvider::ChangeViewport(const til::inclusive_rect& NewWindow) void TermControlUiaProvider::ChangeViewport(const til::inclusive_rect& NewWindow)

View File

@ -44,8 +44,7 @@ namespace Microsoft::Terminal
IFACEMETHODIMP get_FragmentRoot(_COM_Outptr_result_maybenull_ IRawElementProviderFragmentRoot** ppProvider) noexcept override; IFACEMETHODIMP get_FragmentRoot(_COM_Outptr_result_maybenull_ IRawElementProviderFragmentRoot** ppProvider) noexcept override;
til::size GetFontSize() const noexcept; til::size GetFontSize() const noexcept;
til::rect GetPadding() const noexcept; til::point GetContentOrigin() const noexcept;
float GetScaleFactor() const noexcept;
void ChangeViewport(const til::inclusive_rect& NewWindow) override; void ChangeViewport(const til::inclusive_rect& NewWindow) override;
protected: protected:

View File

@ -76,28 +76,9 @@ IFACEMETHODIMP TermControlUiaTextRange::Clone(_Outptr_result_maybenull_ ITextRan
void TermControlUiaTextRange::_TranslatePointToScreen(til::point& clientPoint) const void TermControlUiaTextRange::_TranslatePointToScreen(til::point& clientPoint) const
{ {
const gsl::not_null<TermControlUiaProvider*> provider = static_cast<TermControlUiaProvider*>(_pProvider); const gsl::not_null<TermControlUiaProvider*> provider = static_cast<TermControlUiaProvider*>(_pProvider);
const auto point = provider->GetContentOrigin();
const auto includeOffsets = [](long clientPos, double termControlPos, double padding, double scaleFactor) { clientPoint.x += point.x;
auto result = base::ClampedNumeric<double>(padding); clientPoint.y += point.y;
// only the padding is in DIPs now
result *= scaleFactor;
result += clientPos;
result += termControlPos;
return result;
};
// update based on TermControl location (important for Panes)
UiaRect boundingRect;
THROW_IF_FAILED(provider->get_BoundingRectangle(&boundingRect));
// update based on TermControl padding
const auto padding = provider->GetPadding();
// Get scale factor for display
const auto scaleFactor = provider->GetScaleFactor();
clientPoint.x = includeOffsets(clientPoint.x, boundingRect.left, padding.left, scaleFactor);
clientPoint.y = includeOffsets(clientPoint.y, boundingRect.top, padding.top, scaleFactor);
} }
// Method Description: // Method Description:
@ -110,26 +91,9 @@ void TermControlUiaTextRange::_TranslatePointToScreen(til::point& clientPoint) c
void TermControlUiaTextRange::_TranslatePointFromScreen(til::point& screenPoint) const void TermControlUiaTextRange::_TranslatePointFromScreen(til::point& screenPoint) const
{ {
const gsl::not_null<TermControlUiaProvider*> provider = static_cast<TermControlUiaProvider*>(_pProvider); const gsl::not_null<TermControlUiaProvider*> provider = static_cast<TermControlUiaProvider*>(_pProvider);
const auto point = provider->GetContentOrigin();
const auto includeOffsets = [](long screenPos, double termControlPos, double padding, double scaleFactor) { screenPoint.x -= point.x;
auto result = base::ClampedNumeric<til::CoordType>(screenPos); screenPoint.y -= point.y;
result -= padding / scaleFactor;
result -= termControlPos;
return result;
};
// update based on TermControl location (important for Panes)
UiaRect boundingRect;
THROW_IF_FAILED(provider->get_BoundingRectangle(&boundingRect));
// update based on TermControl padding
const auto padding = provider->GetPadding();
// Get scale factor for display
const auto scaleFactor = provider->GetScaleFactor();
screenPoint.x = includeOffsets(screenPoint.x, boundingRect.left, padding.left, scaleFactor);
screenPoint.y = includeOffsets(screenPoint.y, boundingRect.top, padding.top, scaleFactor);
} }
til::size TermControlUiaTextRange::_getScreenFontSize() const noexcept til::size TermControlUiaTextRange::_getScreenFontSize() const noexcept