This commit is contained in:
Leonard Hecker 2025-09-02 19:47:21 +02:00
parent 8d41ace320
commit 5ddf429688
31 changed files with 322 additions and 225 deletions

View File

@ -3012,6 +3012,12 @@
"description": "If set to true, the profile will not appear in the list of profiles. This can be used to hide default profiles and dynamically generated profiles, while leaving them in your settings file.",
"type": "boolean"
},
"minimumBufferWidth": {
"default": 0,
"description": "The width of the backing text buffer. If it's wider than the viewport, a horizontal scrollbar is shown.",
"minimum": 0,
"type": "integer"
},
"historySize": {
"default": 9001,
"description": "The number of lines above the ones displayed in the window you can scroll back to.",

View File

@ -516,7 +516,7 @@ namespace winrt::TerminalApp::implementation
ASSERT_UI_THREAD();
auto control = GetActiveTerminalControl();
const auto currentOffset = control.ScrollOffset();
const auto currentOffset = control.ScrollOffset().Y;
control.ScrollViewport(::base::ClampAdd(currentOffset, delta));
}

View File

@ -2342,7 +2342,7 @@ namespace winrt::TerminalApp::implementation
{
// The magic value of WHEEL_PAGESCROLL indicates that we need to scroll the entire page
realRowsToScroll = _systemRowsToScroll == WHEEL_PAGESCROLL ?
tabImpl->GetActiveTerminalControl().ViewHeight() :
tabImpl->GetActiveTerminalControl().ViewSize().Y :
_systemRowsToScroll;
}
else
@ -2783,7 +2783,7 @@ namespace winrt::TerminalApp::implementation
{
if (const auto& control{ _GetActiveControl() })
{
const auto termHeight = control.ViewHeight();
const auto termHeight = control.ViewSize().Y;
auto scrollDelta = _ComputeScrollDelta(scrollDirection, termHeight);
tabImpl->Scroll(scrollDelta);
}

View File

@ -708,7 +708,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return false;
}
void ControlCore::UserScrollViewport(const int viewTop)
void ControlCore::UserScrollViewport(const til::point viewTop)
{
{
// This is a scroll event that wasn't initiated by the terminal
@ -1483,10 +1483,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _terminal->GetTaskbarProgress();
}
int ControlCore::ScrollOffset()
Core::Point ControlCore::ScrollOffset() const
{
const auto lock = _terminal->LockForReading();
return _terminal->GetScrollOffset();
return _terminal->GetScrollOffset().to_core_point();
}
// Function Description:
@ -1494,10 +1494,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// height of the viewport.
// Return Value:
// - The height of the terminal in lines of text
int ControlCore::ViewHeight() const
Core::Point ControlCore::ViewSize() const
{
const auto lock = _terminal->LockForReading();
return _terminal->GetViewport().Height();
return _terminal->GetViewport().Dimensions().to_core_point();
}
// Function Description:
@ -1505,10 +1505,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// history AND the viewport.
// Return Value:
// - The height of the terminal in lines of text
int ControlCore::BufferHeight() const
Core::Point ControlCore::BufferSize() const
{
const auto lock = _terminal->LockForReading();
return _terminal->GetBufferHeight();
return _terminal->GetBufferSize().to_core_point();
}
void ControlCore::_terminalWarningBell()
@ -2596,7 +2596,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlCore::ScrollToMark(const Control::ScrollToMarkDirection& direction)
{
const auto lock = _terminal->LockForWriting();
const auto currentOffset = ScrollOffset();
const auto currentOffset = ScrollOffset().Y;
const auto& marks{ _terminal->GetMarkExtents() };
std::optional<::MarkExtents> tgt;
@ -2605,7 +2605,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
case ScrollToMarkDirection::Last:
{
int highest = currentOffset;
auto highest = currentOffset;
for (const auto& mark : marks)
{
const auto newY = mark.start.y;
@ -2619,7 +2619,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
case ScrollToMarkDirection::First:
{
int lowest = currentOffset;
auto lowest = currentOffset;
for (const auto& mark : marks)
{
const auto newY = mark.start.y;
@ -2633,7 +2633,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
case ScrollToMarkDirection::Next:
{
int minDistance = INT_MAX;
auto minDistance = til::CoordTypeMax;
for (const auto& mark : marks)
{
const auto delta = mark.start.y - currentOffset;
@ -2648,7 +2648,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
case ScrollToMarkDirection::Previous:
default:
{
int minDistance = INT_MAX;
auto minDistance = til::CoordTypeMax;
for (const auto& mark : marks)
{
const auto delta = currentOffset - mark.start.y;
@ -2662,29 +2662,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
const auto viewHeight = ViewHeight();
const auto bufferSize = BufferHeight();
const auto scrollOffsetX = ScrollOffset().X;
const auto viewHeight = ViewSize().Y;
const auto bufferSize = BufferSize().Y;
// UserScrollViewport, to update the Terminal about where the viewport should be
// then raise a _terminalScrollPositionChanged to inform the control to update the scrollbar.
if (tgt.has_value())
til::CoordType y = 0;
if (tgt)
{
UserScrollViewport(tgt->start.y);
_terminalScrollPositionChanged(tgt->start.y, viewHeight, bufferSize);
y = tgt->start.y;
}
else
else if (direction == ScrollToMarkDirection::Last || direction == ScrollToMarkDirection::Next)
{
if (direction == ScrollToMarkDirection::Last || direction == ScrollToMarkDirection::Next)
{
UserScrollViewport(BufferHeight());
_terminalScrollPositionChanged(BufferHeight(), viewHeight, bufferSize);
}
else if (direction == ScrollToMarkDirection::First || direction == ScrollToMarkDirection::Previous)
{
UserScrollViewport(0);
_terminalScrollPositionChanged(0, viewHeight, bufferSize);
}
y = bufferSize;
}
UserScrollViewport({ scrollOffsetX, y });
_terminalScrollPositionChanged(y, viewHeight, bufferSize);
}
void ControlCore::_terminalCompletionsChanged(std::wstring_view menuJson, unsigned int replaceLength)

View File

@ -170,9 +170,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TerminalConnection::ConnectionState ConnectionState() const;
int ScrollOffset();
int ViewHeight() const;
int BufferHeight() const;
Core::Point ScrollOffset() const;
Core::Point ViewSize() const;
Core::Point BufferSize() const;
bool HasSelection() const;
bool HasMultiLineSelection() const;
@ -208,7 +208,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const ::Microsoft::Terminal::Core::ControlKeyStates states,
const short wheelDelta,
const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state);
void UserScrollViewport(const int viewTop);
void UserScrollViewport(const til::point viewTop);
void ClearBuffer(Control::ClearBufferType clearType);

View File

@ -403,8 +403,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlInteractivity::TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint,
const bool focused)
{
if (focused &&
_touchAnchor)
if (focused && _touchAnchor)
{
const auto anchor = _touchAnchor.value();
@ -413,23 +412,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto fontSizeInDips{ _core->FontSizeInDips() };
// Get the difference between the point we've dragged to and the start of the touch.
const auto dy = static_cast<float>(newTouchPoint.Y - anchor.Y);
const auto dx = newTouchPoint.X - anchor.X;
const auto dy = newTouchPoint.Y - anchor.Y;
// Start viewport scroll after we've moved more than a half row of text
if (std::abs(dy) > (fontSizeInDips.Height / 2.0f))
// Start viewport scroll after we've moved more than a half row/col of text
if (std::abs(dx) > (fontSizeInDips.Width * 0.5f) || std::abs(dy) > (fontSizeInDips.Height * 0.5f))
{
const auto currentOffset = _core->ScrollOffset();
// Multiply by -1, because moving the touch point down will
// create a positive delta, but we want the viewport to move up,
// so we'll need a negative scroll amount (and the inverse for
// panning down)
const auto numRows = dy / -fontSizeInDips.Height;
const auto currentOffset = _core->ScrollOffset();
const auto newValue = numRows + currentOffset;
const auto x = (dx / -fontSizeInDips.Width) + currentOffset.X;
const auto y = (dy / -fontSizeInDips.Height) + currentOffset.Y;
// Update the Core's viewport position, and raise a
// ScrollPositionChanged event to update the scrollbar
UpdateScrollbar(newValue);
UpdateScrollbar({ x, y });
// Use this point as our new scroll anchor.
_touchAnchor = newTouchPoint;
@ -574,11 +574,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// underneath us. We wouldn't know - we don't want the overhead of
// another ScrollPositionChanged handler. If the scrollbar should be
// somewhere other than where it is currently, then start from that row.
const auto currentInternalRow = std::lround(_internalScrollbarPosition);
const auto currentInternalRow = std::lround(_internalScrollbarPosition.Y);
const auto currentCoreRow = _core->ScrollOffset();
const auto currentOffset = currentInternalRow == currentCoreRow ?
_internalScrollbarPosition :
currentCoreRow;
const auto currentOffset = currentInternalRow == currentCoreRow.Y ? _internalScrollbarPosition.Y : currentCoreRow.Y;
// negative = down, positive = up
// However, for us, the signs are flipped.
@ -589,12 +587,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// WHEEL_PAGESCROLL is a Win32 constant that represents the "scroll one page
// at a time" setting. If we ignore it, we will scroll a truly absurd number
// of rows.
const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? _core->ViewHeight() : _rowsToScroll };
const auto rowsToScroll{ _rowsToScroll == WHEEL_PAGESCROLL ? _core->ViewSize().Y : _rowsToScroll };
const auto newValue = rowsToScroll * rowDelta + currentOffset;
// Update the Core's viewport position, and raise a
// ScrollPositionChanged event to update the scrollbar
UpdateScrollbar(newValue);
UpdateScrollbar({ static_cast<float>(currentCoreRow.X), newValue });
if (isLeftButtonPressed)
{
@ -620,26 +618,38 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - newValue: The new top of the viewport
// Return Value:
// - <none>
void ControlInteractivity::UpdateScrollbar(const float newValue)
void ControlInteractivity::UpdateScrollbar(winrt::Windows::Foundation::Point newValue)
{
const auto bufferSize = _core->BufferSize();
const auto scrollOffsetBefore = til::point{ _core->ScrollOffset() };
// Set this as the new value of our internal scrollbar representation.
// We're doing this so we can accumulate fractional amounts of a row to
// scroll each time the mouse scrolls.
_internalScrollbarPosition = std::clamp(newValue, 0.0f, static_cast<float>(_core->BufferHeight()));
_internalScrollbarPosition.X = std::clamp(newValue.X, 0.0f, static_cast<float>(bufferSize.X));
_internalScrollbarPosition.Y = std::clamp(newValue.Y, 0.0f, static_cast<float>(bufferSize.Y));
// If the new scrollbar position, rounded to an int, is at a different
// row, then actually update the scroll position in the core, and raise
// a ScrollPositionChanged to inform the control.
const auto viewTop = std::lround(_internalScrollbarPosition);
if (viewTop != _core->ScrollOffset())
{
_core->UserScrollViewport(viewTop);
const til::point scrollOffset{
std::lround(_internalScrollbarPosition.X),
std::lround(_internalScrollbarPosition.Y),
};
// _core->ScrollOffset() is now set to newValue
ScrollPositionChanged.raise(*this,
winrt::make<ScrollPositionChangedArgs>(_core->ScrollOffset(),
_core->ViewHeight(),
_core->BufferHeight()));
if (scrollOffset != scrollOffsetBefore)
{
_core->UserScrollViewport(scrollOffset);
if (scrollOffset.y != scrollOffsetBefore.y)
{
ScrollPositionChanged.raise(
*this,
winrt::make<ScrollPositionChangedArgs>(
scrollOffset.y,
_core->ViewSize().Y,
bufferSize.Y));
}
}
}
@ -706,16 +716,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return pixelPosition / fontSize;
}
bool ControlInteractivity::_sendMouseEventHelper(const til::point terminalPosition,
bool ControlInteractivity::_sendMouseEventHelper(til::point terminalPosition,
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const SHORT wheelDelta,
Control::MouseButtonState buttonState)
{
const auto adjustment = _core->BufferHeight() - _core->ScrollOffset() - _core->ViewHeight();
// If the click happened outside the active region, core should get a chance to filter it out or clamp it.
const auto adjustedY = terminalPosition.y - adjustment;
return _core->SendMouseEvent({ terminalPosition.x, adjustedY }, pointerUpdateKind, modifiers, wheelDelta, toInternalMouseState(buttonState));
terminalPosition -= til::point{ _core->BufferSize() };
terminalPosition += til::point{ _core->ScrollOffset() };
terminalPosition += til::point{ _core->ViewSize() };
return _core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, wheelDelta, toInternalMouseState(buttonState));
}
// Method Description:

View File

@ -78,7 +78,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const Core::Point pixelPosition,
const Control::MouseButtonState state);
void UpdateScrollbar(const float newValue);
void UpdateScrollbar(winrt::Windows::Foundation::Point newValue);
#pragma endregion
@ -111,7 +111,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::com_ptr<ControlCore> _core{ nullptr };
UINT _rowsToScroll = 3;
float _internalScrollbarPosition = 0;
winrt::Windows::Foundation::Point _internalScrollbarPosition{};
// If this is set, then we assume we are in the middle of panning the
// viewport via touch input.

View File

@ -64,7 +64,7 @@ namespace Microsoft.Terminal.Control
Microsoft.Terminal.Core.Point pixelPosition,
MouseButtonState state);
void UpdateScrollbar(Single newValue);
void UpdateScrollbar(Windows.Foundation.Point newValue);
event Windows.Foundation.TypedEventHandler<Object, OpenHyperlinkEventArgs> OpenHyperlink;
event Windows.Foundation.TypedEventHandler<Object, ScrollPositionChangedArgs> ScrollPositionChanged;

View File

@ -301,7 +301,7 @@ HRESULT HwndTerminal::Initialize()
_renderEngine = std::move(engine);
_terminal->Create({ 80, 25 }, 9001, *_renderer);
_terminal->Create({ 80, 25 }, 0, 9001, *_renderer);
_terminal->SetWriteInputCallback([=](std::wstring_view input) noexcept { _WriteTextToConnection(input); });
_terminal->SetCopyToClipboardCallback([=](wil::zwstring_view text) noexcept { _CopyTextToSystemClipboard(text, {}, {}); });
_renderer->EnablePainting();
@ -592,7 +592,8 @@ try
if (const auto publicTerminal = static_cast<const HwndTerminal*>(terminal); publicTerminal && publicTerminal->_terminal)
{
const auto lock = publicTerminal->_terminal->LockForWriting();
publicTerminal->_terminal->UserScrollViewport(viewTop);
const auto current = publicTerminal->_terminal->GetScrollOffset();
publicTerminal->_terminal->UserScrollViewport({ current.x, viewTop });
}
}
CATCH_LOG()
@ -962,7 +963,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
for (size_t tableIndex = 0; tableIndex < 16; tableIndex++)
{
// It's using gsl::at to check the index is in bounds, but the analyzer still calls this array-to-pointer-decay
GSL_SUPPRESS(bounds .3)
GSL_SUPPRESS(bounds.3)
renderSettings.SetColorTableEntry(tableIndex, gsl::at(theme.ColorTable, tableIndex));
}
@ -1185,7 +1186,7 @@ void HwndTerminal::ChangeViewport(const til::inclusive_rect& NewWindow)
return;
}
const auto lock = _terminal->LockForWriting();
_terminal->UserScrollViewport(NewWindow.top);
_terminal->UserScrollViewport({ NewWindow.left, NewWindow.top });
}
HRESULT HwndTerminal::GetHostUiaProvider(IRawElementProviderSimple** provider) noexcept

View File

@ -38,9 +38,9 @@ namespace Microsoft.Terminal.Control
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
Int32 ScrollOffset { get; };
Int32 ViewHeight { get; };
Int32 BufferHeight { get; };
Microsoft.Terminal.Core.Point ScrollOffset { get; };
Microsoft.Terminal.Core.Point ViewSize { get; };
Microsoft.Terminal.Core.Point BufferSize { get; };
Boolean HasSelection { get; };
Boolean HasMultiLineSelection { get; };

View File

@ -176,7 +176,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void InteractivityAutomationPeer::ChangeViewport(const til::inclusive_rect& NewWindow)
{
_interactivity->UpdateScrollbar(static_cast<float>(NewWindow.top));
_interactivity->UpdateScrollbar({ static_cast<float>(NewWindow.left), static_cast<float>(NewWindow.top) });
}
#pragma endregion

View File

@ -549,7 +549,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_isInternalScrollBarUpdate = true;
auto scrollBar = ScrollBar();
auto scrollBar = VerticalScrollBar();
if (update.newValue)
{
scrollBar.Value(*update.newValue);
@ -612,7 +612,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto pipHeight = lround(1 * scaleFactor);
const auto maxOffsetY = drawableRange - pipHeight;
const auto offsetScale = maxOffsetY / gsl::narrow_cast<float>(update.newMaximum + update.newViewportSize);
const auto offsetScale = maxOffsetY / static_cast<float>(update.newMaximum + update.newViewportSize);
// A helper to turn a TextBuffer row offset into a bitmap offset.
const auto dataAt = [&](til::CoordType row) [[msvc::forceinline]] {
const auto y = std::clamp<long>(lrintf(row * offsetScale), 0, maxOffsetY);
@ -798,7 +798,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Clear search highlights scroll marks (by triggering an update after closing the search box)
if (_showMarksInScrollbar)
{
const auto scrollBar = ScrollBar();
const auto scrollBar = VerticalScrollBar();
ScrollBarUpdate update{
.newValue = scrollBar.Value(),
.newMaximum = scrollBar.Maximum(),
@ -940,19 +940,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
SwapChainPanel().Margin(newMargin);
// Apply settings for scrollbar
auto indicatorMode = Controls::Primitives::ScrollingIndicatorMode::MouseIndicator;
auto visibility = Visibility::Visible;
if (settings.ScrollState() == ScrollbarState::Hidden)
{
// In the scenario where the user has turned off the OS setting to automatically hide scrollbars, the
// Terminal scrollbar would still be visible; so, we need to set the control's visibility accordingly to
// achieve the intended effect.
ScrollBar().IndicatorMode(Controls::Primitives::ScrollingIndicatorMode::None);
ScrollBar().Visibility(Visibility::Collapsed);
indicatorMode = Controls::Primitives::ScrollingIndicatorMode::None;
visibility = Visibility::Collapsed;
}
else // (default or Visible)
for (auto&& scrollbar : { HorizontalScrollBar(), VerticalScrollBar() })
{
// Default behavior
ScrollBar().IndicatorMode(Controls::Primitives::ScrollingIndicatorMode::MouseIndicator);
ScrollBar().Visibility(Visibility::Visible);
scrollbar.IndicatorMode(indicatorMode);
scrollbar.Visibility(visibility);
}
_interactivity.UpdateSettings();
@ -1396,13 +1397,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_core.EnablePainting();
auto bufferHeight = _core.BufferHeight();
{
const auto bufferSize = _core.ViewSize();
ScrollBar().Maximum(0);
ScrollBar().Minimum(0);
ScrollBar().Value(0);
ScrollBar().ViewportSize(bufferHeight);
ScrollBar().LargeChange(bufferHeight); // scroll one "screenful" at a time when the scroll bar is clicked
const auto hori = HorizontalScrollBar();
hori.Maximum(400);
hori.Minimum(0);
hori.Value(0);
hori.ViewportSize(bufferSize.X);
hori.LargeChange(bufferSize.X);
const auto vert = VerticalScrollBar();
vert.Maximum(0);
vert.Minimum(0);
vert.Value(0);
vert.ViewportSize(bufferSize.Y);
vert.LargeChange(bufferSize.Y); // scroll one "screenful" at a time when the scroll bar is clicked
}
// Set up blinking cursor
int blinkTime = GetCaretBlinkTime();
@ -2243,8 +2254,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_core.AdjustFontSize(fontSizeDelta);
}
void TermControl::_ScrollbarChangeHandler(const Windows::Foundation::IInspectable& /*sender*/,
const Controls::Primitives::RangeBaseValueChangedEventArgs& args)
void TermControl::_HorizontalScrollBarChangeHandler(const Windows::Foundation::IInspectable& /*sender*/,
const Controls::Primitives::RangeBaseValueChangedEventArgs& args)
{
if (_isInternalScrollBarUpdate || _IsClosing())
{
@ -2255,7 +2266,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
const auto newValue = args.NewValue();
_interactivity.UpdateScrollbar(static_cast<float>(newValue));
const auto scrollOffset = _core.ScrollOffset();
_interactivity.UpdateScrollbar({ static_cast<float>(newValue), static_cast<float>(scrollOffset.Y) });
}
void TermControl::_VerticalScrollBarChangeHandler(const Windows::Foundation::IInspectable& /*sender*/,
const Controls::Primitives::RangeBaseValueChangedEventArgs& args)
{
if (_isInternalScrollBarUpdate || _IsClosing())
{
// The update comes from ourselves, more specifically from the
// terminal. So we don't have to update the terminal because it
// already knows.
return;
}
const auto newValue = args.NewValue();
const auto scrollOffset = _core.ScrollOffset();
_interactivity.UpdateScrollbar({ static_cast<float>(scrollOffset.X), static_cast<float>(newValue) });
// User input takes priority over terminal events so cancel
// any pending scroll bar update if the user scrolls.
@ -2366,9 +2394,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_lastAutoScrollUpdateTime)
{
static constexpr auto microSecPerSec = 1000000.0;
const auto deltaTime = std::chrono::duration_cast<std::chrono::microseconds>(timeNow - *_lastAutoScrollUpdateTime).count() / microSecPerSec;
ScrollBar().Value(ScrollBar().Value() + _autoScrollVelocity * deltaTime);
const auto deltaTime = std::chrono::duration<double>(timeNow - *_lastAutoScrollUpdateTime).count();
VerticalScrollBar().Value(VerticalScrollBar().Value() + _autoScrollVelocity * deltaTime);
if (_autoScrollingPointerPoint)
{
@ -2764,10 +2791,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - viewTop: the viewTop to scroll to
void TermControl::ScrollViewport(int viewTop)
{
ScrollBar().Value(viewTop);
VerticalScrollBar().Value(viewTop);
}
int TermControl::ScrollOffset() const
Core::Point TermControl::ScrollOffset() const
{
return _core.ScrollOffset();
}
@ -2776,14 +2803,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Gets the height of the terminal in lines of text
// Return Value:
// - The height of the terminal in lines of text
int TermControl::ViewHeight() const
Core::Point TermControl::ViewSize() const
{
return _core.ViewHeight();
return _core.ViewSize();
}
int TermControl::BufferHeight() const
Core::Point TermControl::BufferSize() const
{
return _core.BufferHeight();
return _core.BufferSize();
}
// Function Description:
@ -2964,10 +2991,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto fontSize = _core.FontSizeInDips();
auto width = fontSize.Width;
auto height = fontSize.Height;
// Reserve additional space if scrollbar is intended to be visible
if (_core.Settings().ScrollState() != ScrollbarState::Hidden)
{
width += static_cast<float>(ScrollBar().ActualWidth());
width += static_cast<float>(VerticalScrollBar().ActualWidth());
height += static_cast<float>(HorizontalScrollBar().ActualHeight());
}
// Account for the size of any padding
@ -2999,13 +3028,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto fontDimension = widthOrHeight ? fontSize.Width : fontSize.Height;
const auto padding = GetPadding();
auto nonTerminalArea = gsl::narrow_cast<float>(widthOrHeight ?
padding.Left + padding.Right :
padding.Top + padding.Bottom);
auto nonTerminalArea = static_cast<float>(widthOrHeight ?
padding.Left + padding.Right :
padding.Top + padding.Bottom);
if (widthOrHeight && _core.Settings().ScrollState() != ScrollbarState::Hidden)
if (_core.Settings().ScrollState() != ScrollbarState::Hidden)
{
nonTerminalArea += gsl::narrow_cast<float>(ScrollBar().ActualWidth());
const auto scrollbar = widthOrHeight ? VerticalScrollBar() : HorizontalScrollBar();
nonTerminalArea += static_cast<float>(scrollbar.ActualWidth());
}
const auto gridSize = dimension - nonTerminalArea;
@ -3643,7 +3673,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto selectionAnchor{ movingEnd ? markerData.EndPos : markerData.StartPos };
const auto& marker{ movingEnd ? SelectionEndMarker() : SelectionStartMarker() };
const auto& otherMarker{ movingEnd ? SelectionStartMarker() : SelectionEndMarker() };
if (selectionAnchor.Y < 0 || selectionAnchor.Y >= _core.ViewHeight())
if (selectionAnchor.Y < 0 || selectionAnchor.Y >= _core.ViewSize().Y)
{
// if the endpoint is outside of the viewport,
// just hide the markers
@ -3869,7 +3899,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
if (_showMarksInScrollbar)
{
const auto scrollBar = ScrollBar();
const auto scrollBar = VerticalScrollBar();
ScrollBarUpdate update{
.newValue = scrollBar.Value(),
.newMaximum = scrollBar.Maximum(),

View File

@ -94,9 +94,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TerminalConnection::ConnectionState ConnectionState() const;
int ScrollOffset() const;
int ViewHeight() const;
int BufferHeight() const;
Core::Point ScrollOffset() const;
Core::Point ViewSize() const;
Core::Point BufferSize() const;
bool HasSelection() const;
bool HasMultiLineSelection() const;
@ -371,7 +371,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _PointerReleasedHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);
void _PointerExitedHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);
void _MouseWheelHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);
void _ScrollbarChangeHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs& e);
void _HorizontalScrollBarChangeHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs& e);
void _VerticalScrollBarChangeHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs& e);
void _QuickFixButton_PointerEntered(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);
void _QuickFixButton_PointerExited(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e);

View File

@ -94,17 +94,17 @@
12dips. This is harder for folks to hit with the mouse, and isn't
consistent with the rest of the scrollbars on the platform (as much
as they can be).
To work around this, we have to entirely copy the template for the
ScrollBar into our XAML file. We're then also re-defining
ScrollBarSize here to 16, so that the new template will pick up on
the new value.
This is kinda a pain, and we have to be careful to be sure to ingest
an updated version of the template any time we update MUX. The
latest ControlsV2 version of the template can be found at:
https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/CommonStyles/ScrollBar_themeresources.xaml#L218
Additionally we have:
* removed the corner radius, because that should be flush
with the top of the window above the TermControl.
@ -113,7 +113,7 @@
the Win11-style WinUI ScrollView. If you also have the "Always show scrollbars" setting enabled in
the settings app (do it if you haven't already), it avoids any and all animations during startup which
makes the app start feel noticeably better and also shaves off another ~167ms of our "busy time".
We're also planning on making this adjustable in the future
(GH#9218), where we might need this anyways.
-->
@ -1338,7 +1338,19 @@
SearchChanged="_SearchChanged" />
</Grid>
<ScrollBar x:Name="ScrollBar"
<ScrollBar x:Name="HorizontalScrollBar"
VerticalAlignment="Bottom"
IndicatorMode="MouseIndicator"
IsTabStop="False"
LargeChange="4"
Maximum="1"
Orientation="Horizontal"
SmallChange="1"
Style="{StaticResource ForkedScrollbarTemplate}"
ValueChanged="_HorizontalScrollBarChangeHandler"
ViewportSize="10" />
<ScrollBar x:Name="VerticalScrollBar"
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
@ -1347,11 +1359,9 @@
LargeChange="4"
Maximum="1"
Orientation="Vertical"
PointerPressed="_CapturePointer"
PointerReleased="_ReleasePointerCapture"
SmallChange="1"
Style="{StaticResource ForkedScrollbarTemplate}"
ValueChanged="_ScrollbarChangeHandler"
ValueChanged="_VerticalScrollBarChangeHandler"
ViewportSize="10" />
<Image x:Name="ScrollBarCanvas"

View File

@ -7,6 +7,7 @@ namespace Microsoft.Terminal.Core
{
interface ICoreSettings requires ICoreAppearance
{
Int32 MinimumBufferWidth;
// TODO:MSFT:20642297 - define a sentinel for Infinite Scrollback
Int32 HistorySize;
Int32 InitialRows;

View File

@ -1,33 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "ControlKeyStates.hpp"
namespace Microsoft::Terminal::Core
{
class ITerminalInput
{
public:
virtual ~ITerminalInput() {}
ITerminalInput(const ITerminalInput&) = default;
ITerminalInput(ITerminalInput&&) = default;
ITerminalInput& operator=(const ITerminalInput&) = default;
ITerminalInput& operator=(ITerminalInput&&) = default;
[[nodiscard]] virtual ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states, const bool keyDown) = 0;
[[nodiscard]] virtual ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) = 0;
[[nodiscard]] virtual ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) = 0;
[[nodiscard]] virtual ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType FocusChanged(const bool focused) = 0;
[[nodiscard]] virtual HRESULT UserResize(const til::size size) noexcept = 0;
virtual void UserScrollViewport(const int viewTop) = 0;
virtual int GetScrollOffset() = 0;
virtual void TrySnapOnInput() = 0;
protected:
ITerminalInput() = default;
};
}

View File

@ -40,12 +40,23 @@ Terminal::Terminal(TestDummyMarker) :
#endif
}
void Terminal::Create(til::size viewportSize, til::CoordType scrollbackLines, Renderer& renderer)
void Terminal::Create(
til::size viewportSize,
til::CoordType minimumBufferWidth,
til::CoordType scrollbackLines,
Renderer& renderer)
{
viewportSize.width = Utils::ClampToShortMax(viewportSize.width, 1);
viewportSize.height = Utils::ClampToShortMax(viewportSize.height, 1);
_minimumBufferWidth = Utils::ClampToShortMax(minimumBufferWidth, 0);
_scrollbackLines = Utils::ClampToShortMax(scrollbackLines, 1);
_mutableViewport = Viewport::FromDimensions({ 0, 0 }, viewportSize);
_scrollbackLines = scrollbackLines;
const til::size bufferSize{ viewportSize.width,
Utils::ClampToShortMax(viewportSize.height + scrollbackLines, 1) };
const til::size bufferSize{
std::max(viewportSize.width, _minimumBufferWidth),
Utils::ClampToShortMax(viewportSize.height + _scrollbackLines, 1),
};
const TextAttribute attr{};
const UINT cursorSize = 12;
_mainBuffer = std::make_unique<TextBuffer>(bufferSize, attr, cursorSize, true, &renderer);
@ -63,11 +74,11 @@ void Terminal::Create(til::size viewportSize, til::CoordType scrollbackLines, Re
void Terminal::CreateFromSettings(ICoreSettings settings,
Renderer& renderer)
{
const til::size viewportSize{ Utils::ClampToShortMax(settings.InitialCols(), 1),
Utils::ClampToShortMax(settings.InitialRows(), 1) };
// TODO:MSFT:20642297 - Support infinite scrollback here, if HistorySize is -1
Create(viewportSize, Utils::ClampToShortMax(settings.HistorySize(), 0), renderer);
const til::size viewportSize{
settings.InitialCols(),
settings.InitialRows(),
};
Create(viewportSize, settings.MinimumBufferWidth(), settings.HistorySize(), renderer);
UpdateSettings(settings);
}
@ -285,12 +296,14 @@ try
return S_OK;
}
const auto newBufferHeight = std::clamp(viewportSize.height + _scrollbackLines, 1, SHRT_MAX);
const til::size bufferSize{ viewportSize.width, newBufferHeight };
const til::size bufferSize{
std::max(viewportSize.width, _minimumBufferWidth),
Utils::ClampToShortMax(viewportSize.height + _scrollbackLines, 1),
};
// If the original buffer had _no_ scroll offset, then we should be at the
// bottom in the new buffer as well. Track that case now.
const auto originalOffsetWasZero = _scrollOffset == 0;
const auto originalOffsetWasZero = _scrollOffset.y == 0;
// GH#3848 - We'll initialize the new buffer with the default attributes,
// but after the resize, we'll want to make sure that the new buffer's
@ -434,7 +447,7 @@ try
// If the old scrolloffset was 0, then we weren't scrolled back at all
// before, and shouldn't be now either.
_scrollOffset = originalOffsetWasZero ? 0 : static_cast<int>(::base::ClampSub(_mutableViewport.Top(), newVisibleTop));
_scrollOffset.y = originalOffsetWasZero ? 0 : static_cast<int>(::base::ClampSub(_mutableViewport.Top(), newVisibleTop));
_mainBuffer->TriggerRedrawAll();
_NotifyScrollEvent();
@ -457,9 +470,9 @@ void Terminal::Write(std::wstring_view stringView)
// - <none>
void Terminal::TrySnapOnInput()
{
if (_snapOnInput && _scrollOffset != 0)
if (_snapOnInput && _scrollOffset.y != 0)
{
_scrollOffset = 0;
_scrollOffset.y = 0;
_NotifyScrollEvent();
}
}
@ -993,18 +1006,18 @@ Viewport Terminal::_GetMutableViewport() const noexcept
_mutableViewport;
}
til::CoordType Terminal::GetBufferHeight() const noexcept
til::size Terminal::GetBufferSize() const noexcept
{
return _GetMutableViewport().BottomExclusive();
return _GetMutableViewport().BottomRightExclusive().to_size();
}
// ViewStartIndex is also the length of the scrollback
int Terminal::ViewStartIndex() const noexcept
til::CoordType Terminal::ViewStartIndex() const noexcept
{
return _inAltBuffer() ? 0 : _mutableViewport.Top();
}
int Terminal::ViewEndIndex() const noexcept
til::CoordType Terminal::ViewEndIndex() const noexcept
{
return _inAltBuffer() ? _altBufferSize.height - 1 : _mutableViewport.BottomInclusive();
}
@ -1034,14 +1047,14 @@ const TerminalInput& Terminal::_getTerminalInput() const noexcept
}
// _VisibleStartIndex is the first visible line of the buffer
int Terminal::_VisibleStartIndex() const noexcept
til::CoordType Terminal::_VisibleStartIndex() const noexcept
{
return _inAltBuffer() ? 0 : std::max(0, _mutableViewport.Top() - _scrollOffset);
return _inAltBuffer() ? 0 : std::max(0, _mutableViewport.Top() - _scrollOffset.y);
}
int Terminal::_VisibleEndIndex() const noexcept
til::CoordType Terminal::_VisibleEndIndex() const noexcept
{
return _inAltBuffer() ? _altBufferSize.height - 1 : std::max(0, _mutableViewport.BottomInclusive() - _scrollOffset);
return _inAltBuffer() ? _altBufferSize.height - 1 : std::max(0, _mutableViewport.BottomInclusive() - _scrollOffset.y);
}
Viewport Terminal::_GetVisibleViewport() const noexcept
@ -1049,27 +1062,25 @@ Viewport Terminal::_GetVisibleViewport() const noexcept
// GH#3493: if we're in the alt buffer, then it's possible that the mutable
// viewport's size hasn't been updated yet. In that case, use the
// temporarily stashed _altBufferSize instead.
const til::point origin{ 0, _VisibleStartIndex() };
const auto size{ _inAltBuffer() ? _altBufferSize :
_mutableViewport.Dimensions() };
return Viewport::FromDimensions(origin,
size);
const til::point origin{ _scrollOffset.x, _VisibleStartIndex() };
const auto size{ _inAltBuffer() ? _altBufferSize : _mutableViewport.Dimensions() };
return Viewport::FromDimensions(origin, size);
}
void Terminal::_PreserveUserScrollOffset(const int viewportDelta) noexcept
void Terminal::_PreserveUserScrollOffset(const til::CoordType viewportDelta) noexcept
{
// When the mutable viewport is moved down, and there's an active selection,
// or the visible viewport isn't already at the bottom, then we want to keep
// the visible viewport where it is. To do this, we adjust the scroll offset
// by the same amount that we've just moved down.
if (viewportDelta > 0 && (IsSelectionActive() || _scrollOffset != 0))
if (viewportDelta > 0 && (IsSelectionActive() || _scrollOffset.y != 0))
{
const auto maxScrollOffset = _activeBuffer().GetSize().Height() - _mutableViewport.Height();
_scrollOffset = std::min(_scrollOffset + viewportDelta, maxScrollOffset);
_scrollOffset.y = std::min(_scrollOffset.y + viewportDelta, maxScrollOffset);
}
}
void Terminal::UserScrollViewport(const int viewTop)
void Terminal::UserScrollViewport(const til::point viewTop)
{
// Clear the regex pattern tree so the renderer does not try to render them while scrolling
_clearPatternTree();
@ -1079,12 +1090,10 @@ void Terminal::UserScrollViewport(const int viewTop)
return;
}
const auto clampedNewTop = std::max(0, viewTop);
const auto realTop = ViewStartIndex();
const auto newDelta = realTop - clampedNewTop;
// if viewTop > realTop, we want the offset to be 0.
_scrollOffset = std::max(0, newDelta);
const auto origin = _inAltBuffer() ? til::point{} : _mutableViewport.Origin();
_scrollOffset.x = std::max(0, origin.x - std::max(0, viewTop.x));
_scrollOffset.y = std::max(0, origin.y - std::max(0, viewTop.y));
// We can use the void variant of TriggerScroll here because
// we adjusted the viewport so it can detect the difference
@ -1092,9 +1101,16 @@ void Terminal::UserScrollViewport(const int viewTop)
_activeBuffer().TriggerScroll();
}
int Terminal::GetScrollOffset() noexcept
til::point Terminal::GetScrollOffset() noexcept
{
return _VisibleStartIndex();
if (_inAltBuffer())
{
return til::point{};
}
const auto x = std::max(0, _mutableViewport.Left() - _scrollOffset.x);
const auto y = std::max(0, _mutableViewport.Top() - _scrollOffset.y);
return { x, y };
}
void Terminal::_NotifyScrollEvent()
@ -1107,7 +1123,7 @@ void Terminal::_NotifyScrollEvent()
const auto visible = _GetVisibleViewport();
const auto top = visible.Top();
const auto height = visible.Height();
const auto bottom = this->GetBufferHeight();
const auto bottom = GetBufferSize().height;
_pfnScrollPositionChanged(top, height, bottom);
}
}
@ -1634,7 +1650,7 @@ til::point Terminal::GetViewportRelativeCursorPosition() const noexcept
const auto absoluteCursorPosition{ GetCursorPosition() };
const auto mutableViewport{ _GetMutableViewport() };
const auto relativeCursorPos = absoluteCursorPosition - mutableViewport.Origin();
return { relativeCursorPos.x, relativeCursorPos.y + _scrollOffset };
return { relativeCursorPos.x + _scrollOffset.x, relativeCursorPos.y + _scrollOffset.y };
}
void Terminal::PreviewText(std::wstring_view input)

View File

@ -5,15 +5,14 @@
#include <conattrs.hpp>
#include "../../inc/DefaultSettings.h"
#include "../../buffer/out/textBuffer.hpp"
#include "../../cascadia/terminalcore/ControlKeyStates.hpp"
#include "../../inc/DefaultSettings.h"
#include "../../renderer/inc/IRenderData.hpp"
#include "../../terminal/adapter/ITerminalApi.hpp"
#include "../../terminal/parser/StateMachine.hpp"
#include "../../terminal/input/terminalInput.hpp"
#include "../../terminal/parser/StateMachine.hpp"
#include "../../types/inc/Viewport.hpp"
#include "../../types/inc/GlyphWidth.hpp"
#include "../../cascadia/terminalcore/ITerminalInput.hpp"
#include <til/generational.h>
#include <til/ticket_lock.h>
@ -54,7 +53,6 @@ namespace TerminalCoreUnitTests
class Microsoft::Terminal::Core::Terminal final :
public Microsoft::Console::VirtualTerminal::ITerminalApi,
public Microsoft::Terminal::Core::ITerminalInput,
public Microsoft::Console::Render::IRenderData
{
using RenderSettings = Microsoft::Console::Render::RenderSettings;
@ -83,9 +81,11 @@ public:
Terminal();
Terminal(TestDummyMarker);
void Create(til::size viewportSize,
til::CoordType scrollbackLines,
Microsoft::Console::Render::Renderer& renderer);
void Create(
til::size viewportSize,
til::CoordType minimumBufferWidth,
til::CoordType scrollbackLines,
Microsoft::Console::Render::Renderer& renderer);
void CreateFromSettings(winrt::Microsoft::Terminal::Core::ICoreSettings settings,
Microsoft::Console::Render::Renderer& renderer);
@ -110,10 +110,10 @@ public:
[[nodiscard]] std::unique_lock<til::recursive_ticket_lock> LockForWriting() noexcept;
til::recursive_ticket_lock_suspension SuspendLock() noexcept;
til::CoordType GetBufferHeight() const noexcept;
til::size GetBufferSize() const noexcept;
int ViewStartIndex() const noexcept;
int ViewEndIndex() const noexcept;
til::CoordType ViewStartIndex() const noexcept;
til::CoordType ViewEndIndex() const noexcept;
RenderSettings& GetRenderSettings() noexcept;
const RenderSettings& GetRenderSettings() const noexcept;
@ -170,16 +170,16 @@ public:
#pragma region ITerminalInput
// These methods are defined in Terminal.cpp
[[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states, const bool keyDown) override;
[[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) override;
[[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) override;
[[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType FocusChanged(const bool focused) override;
[[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states, const bool keyDown);
[[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendMouseEvent(const til::point viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state);
[[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states);
[[nodiscard]] ::Microsoft::Console::VirtualTerminal::TerminalInput::OutputType FocusChanged(const bool focused);
[[nodiscard]] HRESULT UserResize(const til::size viewportSize) noexcept override;
void UserScrollViewport(const int viewTop) override;
int GetScrollOffset() noexcept override;
[[nodiscard]] HRESULT UserResize(const til::size viewportSize) noexcept;
void UserScrollViewport(const til::point viewTop);
til::point GetScrollOffset() noexcept;
void TrySnapOnInput() override;
void TrySnapOnInput();
bool IsTrackingMouseInput() const noexcept;
bool ShouldSendAlternateScroll(const unsigned int uiButton, const int32_t delta) const noexcept;
@ -414,6 +414,7 @@ private:
std::unique_ptr<TextBuffer> _mainBuffer;
std::unique_ptr<TextBuffer> _altBuffer;
Microsoft::Console::Types::Viewport _mutableViewport;
til::CoordType _minimumBufferWidth = 0;
til::CoordType _scrollbackLines = 0;
bool _detectURLs = false;
bool _clipboardOperationsAllowed = true;
@ -423,7 +424,7 @@ private:
// _scrollOffset is the number of lines above the viewport that are currently visible
// If _scrollOffset is 0, then the visible region of the buffer is the viewport.
til::CoordType _scrollOffset = 0;
til::point _scrollOffset;
// TODO this might not be the value we want to store.
// We might want to store the height in the scrollback that's currently visible.
// Think on this some more.
@ -461,13 +462,13 @@ private:
Console::VirtualTerminal::TerminalInput& _getTerminalInput() noexcept;
const Console::VirtualTerminal::TerminalInput& _getTerminalInput() const noexcept;
int _VisibleStartIndex() const noexcept;
int _VisibleEndIndex() const noexcept;
til::CoordType _VisibleStartIndex() const noexcept;
til::CoordType _VisibleEndIndex() const noexcept;
Microsoft::Console::Types::Viewport _GetMutableViewport() const noexcept;
Microsoft::Console::Types::Viewport _GetVisibleViewport() const noexcept;
void _PreserveUserScrollOffset(const int viewportDelta) noexcept;
void _PreserveUserScrollOffset(const til::CoordType viewportDelta) noexcept;
til::CoordType _ScrollToPoints(const til::point coordStart, const til::point coordEnd);
void _NotifyScrollEvent();

View File

@ -1019,13 +1019,13 @@ void Terminal::_ScrollToPoint(const til::point pos)
if (const auto amtAboveView = visibleViewport.Top() - pos.y; amtAboveView > 0)
{
// anchor is above visible viewport, scroll by that amount
_scrollOffset += amtAboveView;
_scrollOffset.y += amtAboveView;
}
else
{
// anchor is below visible viewport, scroll by that amount
const auto amtBelowView = pos.y - visibleViewport.BottomInclusive();
_scrollOffset -= amtBelowView;
_scrollOffset.y -= amtBelowView;
}
_NotifyScrollEvent();
_activeBuffer().TriggerScroll();

View File

@ -179,7 +179,7 @@ til::CoordType Terminal::_ScrollToPoints(const til::point coordStart, const til:
if (coordStart.y < _VisibleStartIndex())
{
// recalculate the scrollOffset
_scrollOffset = ViewStartIndex() - coordStart.y;
_scrollOffset.y = ViewStartIndex() - coordStart.y;
notifyScrollChange = true;
}
else if (coordEnd.y > _VisibleEndIndex())
@ -188,7 +188,7 @@ til::CoordType Terminal::_ScrollToPoints(const til::point coordStart, const til:
// beneath the current visible viewport, it may be within the
// current mutableViewport and the scrollOffset will be smaller
// than 0
_scrollOffset = std::max(0, ViewStartIndex() - coordStart.y);
_scrollOffset.y = std::max(0, ViewStartIndex() - coordStart.y);
notifyScrollChange = true;
}

View File

@ -152,6 +152,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_profile, AntialiasingMode);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Opacity);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), UseAcrylic);
OBSERVABLE_PROJECTED_SETTING(_profile, MinimumBufferWidth);
OBSERVABLE_PROJECTED_SETTING(_profile, HistorySize);
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);

View File

@ -145,6 +145,7 @@ namespace Microsoft.Terminal.Settings.Editor
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, StartingDirectory);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, MinimumBufferWidth);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, HistorySize);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing);

View File

@ -66,6 +66,19 @@
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Minimum Buffer Width -->
<local:SettingContainer x:Uid="Profile_MinimumBufferWidth"
ClearSettingValue="{x:Bind Profile.ClearMinimumBufferWidth}"
HasSettingValue="{x:Bind Profile.HasMinimumBufferWidth, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.MinimumBufferWidthOverrideSource, Mode=OneWay}">
<muxc:NumberBox x:Uid="Profile_MinimumBufferWidthBox"
LargeChange="100"
Minimum="0"
SmallChange="10"
Style="{StaticResource NumberBoxSettingStyle}"
Value="{x:Bind Profile.MinimumBufferWidth, Mode=TwoWay}" />
</local:SettingContainer>
<!-- History Size -->
<local:SettingContainer x:Uid="Profile_HistorySize"
ClearSettingValue="{x:Bind Profile.ClearHistorySize}"

View File

@ -1105,6 +1105,17 @@
<value>If enabled, the profile will open in an Admin terminal window automatically. If the current window is already running as admin, it will open in this window.</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_MinimumBufferWidth.Header" xml:space="preserve">
<value>Minimum Buffer Width</value>
<comment>"Buffer Width" refers to the width of a terminal buffer (as opposed to the viewport width)</comment>
</data>
<data name="Profile_MinimumBufferWidthBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Minimum Buffer Width</value>
<comment>"Buffer Width" refers to the width of a terminal buffer (as opposed to the viewport width)</comment>
</data>
<data name="Profile_MinimumBufferWidth.HelpText" xml:space="preserve">
<value>The width of the backing text buffer. If it's wider than the viewport, a horizontal scrollbar is shown.</value>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>History size</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@ -79,6 +79,7 @@ Author(s):
// * IControlSettings.idl or ICoreSettings.idl
// * ControlProperties.h
#define MTSM_PROFILE_SETTINGS(X) \
X(int32_t, MinimumBufferWidth, "minimumBufferWidth", 0) \
X(int32_t, HistorySize, "historySize", DEFAULT_HISTORY_SIZE) \
X(bool, SnapOnInput, "snapOnInput", true) \
X(bool, AltGrAliasing, "altGrAliasing", true) \

View File

@ -68,6 +68,7 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.TextAntialiasingMode, AntialiasingMode);
INHERITABLE_PROFILE_SETTING(Int32, MinimumBufferWidth);
INHERITABLE_PROFILE_SETTING(Int32, HistorySize);
INHERITABLE_PROFILE_SETTING(Boolean, SnapOnInput);
INHERITABLE_PROFILE_SETTING(Boolean, AltGrAliasing);

View File

@ -292,6 +292,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void TerminalSettings::_ApplyProfileSettings(const Profile& profile)
{
// Fill in the Terminal Setting's CoreSettings from the profile
_MinimumBufferWidth = profile.MinimumBufferWidth();
_HistorySize = profile.HistorySize();
_SnapOnInput = profile.SnapOnInput();
_AltGrAliasing = profile.AltGrAliasing();

View File

@ -80,6 +80,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, til::color, DefaultForeground, DEFAULT_FOREGROUND);
INHERITABLE_SETTING(Model::TerminalSettings, til::color, DefaultBackground, DEFAULT_BACKGROUND);
INHERITABLE_SETTING(Model::TerminalSettings, til::color, SelectionBackground, DEFAULT_FOREGROUND);
INHERITABLE_SETTING(Model::TerminalSettings, int32_t, MinimumBufferWidth, 0);
INHERITABLE_SETTING(Model::TerminalSettings, int32_t, HistorySize, DEFAULT_HISTORY_SIZE);
INHERITABLE_SETTING(Model::TerminalSettings, int32_t, InitialRows, 30);
INHERITABLE_SETTING(Model::TerminalSettings, int32_t, InitialCols, 80);

View File

@ -33,6 +33,7 @@
// --------------------------- Core Settings ---------------------------
// All of these settings are defined in ICoreSettings.
#define CORE_SETTINGS(X) \
X(int32_t, MinimumBufferWidth, 0) \
X(int32_t, HistorySize, DEFAULT_HISTORY_SIZE) \
X(int32_t, InitialRows, 30) \
X(int32_t, InitialCols, 80) \

View File

@ -23,6 +23,8 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
}
}
struct size;
struct point
{
CoordType x = 0;
@ -165,6 +167,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return gsl::narrow<T>(y);
}
// Defined in size.h
constexpr size to_size() const noexcept;
#ifdef _WINDEF_
explicit constexpr point(const POINT other) noexcept :
x{ other.x }, y{ other.y }

View File

@ -117,6 +117,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return gsl::narrow<T>(static_cast<int64_t>(width) * static_cast<int64_t>(height));
}
constexpr point to_point() const noexcept
{
return { width, height };
}
#ifdef _WINDEF_
explicit constexpr size(const SIZE other) noexcept :
width{ other.cx }, height{ other.cy }
@ -170,6 +175,18 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
}
#endif
#ifdef WINRT_Microsoft_Terminal_Core_H
explicit constexpr size(const winrt::Microsoft::Terminal::Core::Point other) :
width{ other.X }, height{ other.Y }
{
}
winrt::Microsoft::Terminal::Core::Point to_core_point() const noexcept
{
return { width, height };
}
#endif
std::wstring to_string() const
{
return wil::str_printf<std::wstring>(L"[W:%d, H:%d]", width, height);
@ -179,6 +196,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
CoordType height = 0;
};
constexpr size point::to_size() const noexcept
{
return size{ x, y };
}
constexpr size wrap_coord_size(const COORD sz) noexcept
{
return { sz.X, sz.Y };