Skip to content

Commit

Permalink
Prepare til wrappers for migrating off of SMALL_RECT (#11902)
Browse files Browse the repository at this point in the history
This commit makes the following changes to `til::point/size/rectangle`
for the following reasons:
* Rename `rectangle` into `rect`
  This will make the naming consistent with a later `small_rect` struct
  as well as the existing Win32 POINT/SIZE/RECT structs.
* Standardizes til wrappers on `int32_t` instead of `ptrdiff_t`
  Provides a consistent behavior between x86 and x64, preventing accidental
  errors on x86, as it's less rigorously tested than x64. Additionally it
  improves interop with MIDL3 which only supports fixed width integer types.
* Standardizes til wrappers on throwing `gsl::narrow_error`
  Makes the behavior of our code more consistent.
* Makes all eligible functions `constexpr`
  Because why not.
* Removes implicit constructors and conversion operators
  This is a complex and controversial topic. My reasons are: You can't Ctrl+F
  for an implicit conversion. This breaks most non-IDE engines, like the one on
  GitHub or those we have internally at MS. This is important for me as these
  implicit conversion operators aren't cost free. Narrowing integers itself,
  as well as the boundary checks that need to be done have a certain,
  fixed overhead each time. Additionally the lack of noexcept prevents
  many advanced compiler optimizations. Removing their use entirely
  drops conhost's code segment size by around ~6.5%.

## References

Preliminary work for #4015.

## PR Checklist
* [x] I work here
* [x] Tests added/passed

## Validation Steps Performed
I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
  • Loading branch information
lhecker authored Jan 13, 2022
1 parent 1a62f47 commit b3fab51
Show file tree
Hide file tree
Showing 81 changed files with 2,695 additions and 3,642 deletions.
58 changes: 29 additions & 29 deletions src/buffer/out/textBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,7 +1076,7 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
#pragma warning(suppress : 26496)
auto copy{ target };
const auto bufferSize{ GetSize() };
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
if (target == bufferSize.Origin())
{
// can't expand left
Expand All @@ -1088,10 +1088,10 @@ const COORD TextBuffer::GetWordStart(const COORD target, const std::wstring_view
// that it actually points to a space in the buffer
copy = { bufferSize.RightInclusive(), bufferSize.BottomInclusive() };
}
else if (bufferSize.CompareInBounds(target, limit, true) >= 0)
else if (bufferSize.CompareInBounds(target, limit.to_win32_coord(), true) >= 0)
{
// if at/past the limit --> clamp to limit
copy = *limitOptional;
copy = limitOptional->to_win32_coord();
}

if (accessibilityMode)
Expand Down Expand Up @@ -1203,15 +1203,15 @@ const COORD TextBuffer::GetWordEnd(const COORD target, const std::wstring_view w

// Already at/past the limit. Can't move forward.
const auto bufferSize{ GetSize() };
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
if (bufferSize.CompareInBounds(target, limit.to_win32_coord(), true) >= 0)
{
return target;
}

if (accessibilityMode)
{
return _GetWordEndForAccessibility(target, wordDelimiters, limit);
return _GetWordEndForAccessibility(target, wordDelimiters, limit.to_win32_coord());
}
else
{
Expand Down Expand Up @@ -1366,10 +1366,10 @@ bool TextBuffer::MoveToNextWord(COORD& pos, const std::wstring_view wordDelimite
// NOTE: _GetWordEnd...() returns the exclusive position of the "end of the word"
// This is also the inclusive start of the next word.
const auto bufferSize{ GetSize() };
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
const auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, limit) };
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };
const auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, limit.to_win32_coord()) };

if (bufferSize.CompareInBounds(copy, limit, true) >= 0)
if (bufferSize.CompareInBounds(copy, limit.to_win32_coord(), true) >= 0)
{
return false;
}
Expand Down Expand Up @@ -1411,23 +1411,23 @@ bool TextBuffer::MoveToPreviousWord(COORD& pos, std::wstring_view wordDelimiters
// - pos - The COORD for the first cell of the current glyph (inclusive)
const til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional<til::point> limitOptional) const
{
COORD resultPos = pos;
COORD resultPos = pos.to_win32_coord();
const auto bufferSize = GetSize();
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };

// Clamp pos to limit
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
if (bufferSize.CompareInBounds(resultPos, limit.to_win32_coord(), true) > 0)
{
resultPos = limit;
resultPos = limit.to_win32_coord();
}

// limit is exclusive, so we need to move back to be within valid bounds
if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
if (resultPos != limit.to_win32_coord() && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
{
bufferSize.DecrementInBounds(resultPos, true);
}

return resultPos;
return til::point{ resultPos };
}

// Method Description:
Expand All @@ -1439,17 +1439,17 @@ const til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional<t
// - pos - The COORD for the last cell of the current glyph (exclusive)
const til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode, std::optional<til::point> limitOptional) const
{
COORD resultPos = pos;
COORD resultPos = pos.to_win32_coord();
const auto bufferSize = GetSize();
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };

// Clamp pos to limit
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
if (bufferSize.CompareInBounds(resultPos, limit.to_win32_coord(), true) > 0)
{
resultPos = limit;
resultPos = limit.to_win32_coord();
}

if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
if (resultPos != limit.to_win32_coord() && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
{
bufferSize.IncrementInBounds(resultPos, true);
}
Expand All @@ -1459,7 +1459,7 @@ const til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilit
{
bufferSize.IncrementInBounds(resultPos, true);
}
return resultPos;
return til::point{ resultPos };
}

// Method Description:
Expand All @@ -1474,9 +1474,9 @@ const til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilit
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::optional<til::point> limitOptional) const
{
const auto bufferSize = GetSize();
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };

const auto distanceToLimit{ bufferSize.CompareInBounds(pos, limit, true) };
const auto distanceToLimit{ bufferSize.CompareInBounds(pos.to_win32_coord(), limit.to_win32_coord(), true) };
if (distanceToLimit >= 0)
{
// Corner Case: we're on/past the limit
Expand All @@ -1493,7 +1493,7 @@ bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::o
}

// Try to move forward, but if we hit the buffer boundary, we fail to move.
auto iter{ GetCellDataAt(pos, bufferSize) };
auto iter{ GetCellDataAt(pos.to_win32_coord(), bufferSize) };
const bool success{ ++iter };

// Move again if we're on a wide glyph
Expand All @@ -1502,7 +1502,7 @@ bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::o
++iter;
}

pos = iter.Pos();
pos = til::point{ iter.Pos() };
return success;
}

Expand All @@ -1515,11 +1515,11 @@ bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::o
// - pos - The COORD for the first cell of the previous glyph (inclusive)
bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional) const
{
COORD resultPos = pos;
COORD resultPos = pos.to_win32_coord();
const auto bufferSize = GetSize();
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
const auto limit{ limitOptional.value_or(til::point{ bufferSize.EndExclusive() }) };

if (bufferSize.CompareInBounds(pos, limit, true) > 0)
if (bufferSize.CompareInBounds(pos.to_win32_coord(), limit.to_win32_coord(), true) > 0)
{
// we're past the end
// clamp us to the limit
Expand All @@ -1534,7 +1534,7 @@ bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point>
bufferSize.DecrementInBounds(resultPos, true);
}

pos = resultPos;
pos = til::point{ resultPos };
return success;
}

Expand Down
28 changes: 17 additions & 11 deletions src/cascadia/PublicTerminalCore/HwndTerminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,11 +549,11 @@ try

if (multiClickMapper == 3)
{
_terminal->MultiClickSelection(cursorPosition / fontSize, ::Terminal::SelectionExpansion::Line);
_terminal->MultiClickSelection((cursorPosition / fontSize).to_win32_coord(), ::Terminal::SelectionExpansion::Line);
}
else if (multiClickMapper == 2)
{
_terminal->MultiClickSelection(cursorPosition / fontSize, ::Terminal::SelectionExpansion::Word);
_terminal->MultiClickSelection((cursorPosition / fontSize).to_win32_coord(), ::Terminal::SelectionExpansion::Word);
}
else
{
Expand Down Expand Up @@ -582,19 +582,25 @@ try

RETURN_HR_IF(E_NOT_VALID_STATE, fontSize.area() == 0); // either dimension = 0, area == 0

if (this->_singleClickTouchdownPos)
// This is a copy of ControlInteractivity::PointerMoved
if (_singleClickTouchdownPos)
{
const auto& touchdownPoint{ *this->_singleClickTouchdownPos };
const auto distance{ std::sqrtf(std::powf(cursorPosition.x<float>() - touchdownPoint.x<float>(), 2) + std::powf(cursorPosition.y<float>() - touchdownPoint.y<float>(), 2)) };
if (distance >= (std::min(fontSize.width(), fontSize.height()) / 4.f))
const auto touchdownPoint = *_singleClickTouchdownPos;
const auto dx = cursorPosition.x - touchdownPoint.x;
const auto dy = cursorPosition.y - touchdownPoint.y;
const auto w = fontSize.width;
const auto distanceSquared = dx * dx + dy * dy;
const auto maxDistanceSquared = w * w / 16; // (w / 4)^2

if (distanceSquared >= maxDistanceSquared)
{
_terminal->SetSelectionAnchor(touchdownPoint / fontSize);
_terminal->SetSelectionAnchor((touchdownPoint / fontSize).to_win32_coord());
// stop tracking the touchdown point
_singleClickTouchdownPos = std::nullopt;
}
}

this->_terminal->SetSelectionEnd(cursorPosition / fontSize);
this->_terminal->SetSelectionEnd((cursorPosition / fontSize).to_win32_coord());
this->_renderer->TriggerSelection();

return S_OK;
Expand Down Expand Up @@ -696,9 +702,9 @@ try
wheelDelta = HIWORD(wParam);

// If it's a *WHEEL event, it's in screen coordinates, not window (?!)
POINT coordsToTransform = cursorPosition;
POINT coordsToTransform = cursorPosition.to_win32_point();
ScreenToClient(_hwnd.get(), &coordsToTransform);
cursorPosition = coordsToTransform;
cursorPosition = til::point{ coordsToTransform };
}

const TerminalInput::MouseButtonState state{
Expand All @@ -707,7 +713,7 @@ try
WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed)
};

return _terminal->SendMouseEvent(cursorPosition / fontSize, uMsg, getControlKeyState(), wheelDelta, state);
return _terminal->SendMouseEvent((cursorPosition / fontSize).to_win32_coord(), uMsg, getControlKeyState(), wheelDelta, state);
}
catch (...)
{
Expand Down
35 changes: 16 additions & 19 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const short wheelDelta,
const TerminalInput::MouseButtonState state)
{
return _terminal->SendMouseEvent(viewportPos, uiButton, states, wheelDelta, state);
return _terminal->SendMouseEvent(viewportPos.to_win32_coord(), uiButton, states, wheelDelta, state);
}

void ControlCore::UserScrollViewport(const int viewTop)
Expand Down Expand Up @@ -546,12 +546,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_lastHoveredCell = terminalPosition;
uint16_t newId{ 0u };
// we can't use auto here because we're pre-declaring newInterval.
decltype(_terminal->GetHyperlinkIntervalFromPosition(til::point{})) newInterval{ std::nullopt };
decltype(_terminal->GetHyperlinkIntervalFromPosition(COORD{})) newInterval{ std::nullopt };
if (terminalPosition.has_value())
{
auto lock = _terminal->LockForReading(); // Lock for the duration of our reads.
newId = _terminal->GetHyperlinkIdAtPosition(*terminalPosition);
newInterval = _terminal->GetHyperlinkIntervalFromPosition(*terminalPosition);
newId = _terminal->GetHyperlinkIdAtPosition(terminalPosition->to_win32_coord());
newInterval = _terminal->GetHyperlinkIntervalFromPosition(terminalPosition->to_win32_coord());
}

// If the hyperlink ID changed or the interval changed, trigger a redraw all
Expand All @@ -577,26 +577,26 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}

winrt::hstring ControlCore::GetHyperlink(const til::point pos) const
winrt::hstring ControlCore::GetHyperlink(const Core::Point pos) const
{
// Lock for the duration of our reads.
auto lock = _terminal->LockForReading();
return winrt::hstring{ _terminal->GetHyperlinkAtPosition(pos) };
return winrt::hstring{ _terminal->GetHyperlinkAtPosition(til::point{ pos }.to_win32_coord()) };
}

winrt::hstring ControlCore::HoveredUriText() const
{
auto lock = _terminal->LockForReading(); // Lock for the duration of our reads.
if (_lastHoveredCell.has_value())
{
return winrt::hstring{ _terminal->GetHyperlinkAtPosition(*_lastHoveredCell) };
return winrt::hstring{ _terminal->GetHyperlinkAtPosition(_lastHoveredCell->to_win32_coord()) };
}
return {};
}

Windows::Foundation::IReference<Core::Point> ControlCore::HoveredCell() const
{
return _lastHoveredCell.has_value() ? Windows::Foundation::IReference<Core::Point>{ _lastHoveredCell.value() } : nullptr;
return _lastHoveredCell.has_value() ? Windows::Foundation::IReference<Core::Point>{ _lastHoveredCell.value().to_core_point() } : nullptr;
}

// Method Description:
Expand Down Expand Up @@ -938,7 +938,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlCore::SetSelectionAnchor(til::point const& position)
{
auto lock = _terminal->LockForWriting();
_terminal->SetSelectionAnchor(position);
_terminal->SetSelectionAnchor(position.to_win32_coord());
}

// Method Description:
Expand All @@ -956,16 +956,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// you move its endpoints while it is generating a frame.
auto lock = _terminal->LockForWriting();

const short lastVisibleRow = std::max<short>(_terminal->GetViewport().Height() - 1, 0);
const short lastVisibleCol = std::max<short>(_terminal->GetViewport().Width() - 1, 0);

til::point terminalPosition{
std::clamp<short>(position.x<short>(), 0, lastVisibleCol),
std::clamp<short>(position.y<short>(), 0, lastVisibleRow)
std::clamp(position.x, 0, _terminal->GetViewport().Width() - 1),
std::clamp(position.y, 0, _terminal->GetViewport().Height() - 1)
};

// save location (for rendering) + render
_terminal->SetSelectionEnd(terminalPosition);
_terminal->SetSelectionEnd(terminalPosition.to_win32_coord());
_renderer->TriggerSelection();
}

Expand Down Expand Up @@ -1433,7 +1430,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _terminal != nullptr && _terminal->IsTrackingMouseInput();
}

til::point ControlCore::CursorPosition() const
Core::Point ControlCore::CursorPosition() const
{
// If we haven't been initialized yet, then fake it.
if (!_initializedTerminal)
Expand All @@ -1442,7 +1439,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}

auto lock = _terminal->LockForReading();
return _terminal->GetCursorPosition();
return til::point{ _terminal->GetCursorPosition() }.to_core_point();
}

// This one's really pushing the boundary of what counts as "encapsulation".
Expand Down Expand Up @@ -1494,15 +1491,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// If shift is pressed and there is a selection we extend it using
// the selection mode (expand the "end" selection point)
_terminal->SetSelectionEnd(terminalPosition, mode);
_terminal->SetSelectionEnd(terminalPosition.to_win32_coord(), mode);
selectionNeedsToBeCopied = true;
}
else if (mode != ::Terminal::SelectionExpansion::Char || shiftEnabled)
{
// If we are handling a double / triple-click or shift+single click
// we establish selection using the selected mode
// (expand both "start" and "end" selection points)
_terminal->MultiClickSelection(terminalPosition, mode);
_terminal->MultiClickSelection(terminalPosition.to_win32_coord(), mode);
selectionNeedsToBeCopied = true;
}

Expand Down
4 changes: 2 additions & 2 deletions src/cascadia/TerminalControl/ControlCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void UpdatePatternLocations();
void SetHoveredCell(Core::Point terminalPosition);
void ClearHoveredCell();
winrt::hstring GetHyperlink(const til::point position) const;
winrt::hstring GetHyperlink(const Core::Point position) const;
winrt::hstring HoveredUriText() const;
Windows::Foundation::IReference<Core::Point> HoveredCell() const;

Expand Down Expand Up @@ -138,7 +138,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void CursorOn(const bool isCursorOn);

bool IsVtMouseModeEnabled() const;
til::point CursorPosition() const;
Core::Point CursorPosition() const;

bool HasSelection() const;
bool CopyOnSelect() const;
Expand Down
Loading

0 comments on commit b3fab51

Please sign in to comment.