-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Further refactor and simplify the ConGetSet API #12703
Conversation
ddd3a73
to
42d3d34
Compare
There's more I'd still like to do to simplify I know this is a big change, and there's a definite chance it might break something, but I do think it's worth the risk. Because once we've got a more complete VT implementation on the Terminal side, the pass-through mode starts to look like a realistic prospect. |
FYI This week we're all a bit preoccupied with projects outside of regular Terminal work (something called "Fix Hack Learn"). Personally, I'll be on vacation next week, so I'll unfortunately only get a chance to take a look at this in about two weeks (unless it's already merged by then). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, this is quite the read. I've got minor questions scattered about. I don't think I have any blocking concerns. Everything looks like it found a new home.
Really looking forward to having one less layer to deal with after all these years.
else if (cursorPosition.Y > viewport.top) | ||
{ | ||
// Otherwise we move the cursor up, but not past the top of the viewport. | ||
const COORD newCursorPosition{ cursorPosition.X, cursorPosition.Y - 1 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this actually clamp to the viewport? ClampPositionWithinLine
doesn't seem to clamp the y position, only the x
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the condition above (cursorPosition.Y > viewport.top
). If Y
is greater than the viewport top, then Y-1
will still be greater than or equal to the top, which is still in range.
if (oldCursorPosition.Y > viewport.Top) | ||
{ | ||
// Cursor is below the top line of the viewport | ||
THROW_IF_NTSTATUS_FAILED(AdjustCursorPosition(screenInfo, newCursorPosition, TRUE, nullptr)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose before AdjustCursorPosition
would make sure to move the viewport to make the cursor visible, but it was never moving outside of the viewport, so that's not an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE!: The call to InitializeCursorRowAttributes
though - does that still happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this particular situation it wouldn't apply, because ReverseLineFeed
shouldn't be panning the viewport when it moves the cursor. That said, When it reaches the top, it'll trigger a scroll of the buffer content, and that does do something similar to InitializeCursorRowAttributes
for the revealed line. See the calls to _FillRect
and ResetLineRenditionRange
in the _ScrollRectVertically
method.
cursor.SetPosition(textBuffer.ClampPositionWithinLine(newCursorPosition)); | ||
cursor.SetDelay(false); | ||
cursor.SetIsOn(true); | ||
cursor.SetHasMoved(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were these guys getting done before? (sometimes hard to parse all the side effects of AdjustCursorPosition)
cursor.SetXPosition(0); | ||
cursor.SetDelay(false); | ||
cursor.SetIsOn(true); | ||
cursor.SetHasMoved(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we need a helper for set cursor position and {delay, on, moved}={false, true, true}
, since this is the second time I'm seeing it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. I was considering that, but I thought maybe we could push that off for a follow up issue because I think this cursor handling needs further investigation.
If these calls are needed all the time, then why aren't they set automatically in the SetPosition
method? If they aren't needed all the time, then we may need to be more selective about where they are used, and dumping these calls in a helper is just hiding the problem.
And note that Windows Terminal doesn't use these flags at all as far as I can tell, so I'm hoping it might be possible to do away with them altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, I eventually decided you were right about this and added a helper for setting these flags. It does make things a bit tidier and gave me the opportunity to add a bit of documentation on what we are doing here (at least as I understand it). See commit 446002e.
const auto data = OutputCell(*textBuffer.GetCellDataAt(sourcePos)); | ||
textBuffer.Write(OutputCellIterator({ &data, 1 }), targetPos); | ||
source.WalkInBounds(sourcePos, walkDirection); | ||
} while (target.WalkInBounds(targetPos, walkDirection)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coreect me if I'm wrong here - if we had a buffer like:
1234567890
And the cursor was on the 1
, and we inserted 5 characters, we'd call this with (textBuffer, { 0, 0, 80, 1 }, 5)
Actually nevermind me. That works perfectly fine. I thought we'd start reading from the section we were writing from, so it'd look like
12341234
or something, but nah this works fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I just stole that code from the existing _CopyRectangle
function:
Lines 107 to 111 in ce6ce50
const auto data = OutputCell(*screenInfo.GetCellDataAt(sourcePos)); | |
screenInfo.Write(OutputCellIterator({ &data, 1 }), targetPos); | |
source.WalkInBounds(sourcePos, walkDirection); | |
} while (target.WalkInBounds(targetPos, walkDirection)); |
cursor.SetXPosition(column); | ||
cursor.SetDelay(false); | ||
cursor.SetIsOn(true); | ||
cursor.SetHasMoved(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay I found it. These come from: SCREEN_INFORMATION::SetCursorPosition
terminal/src/host/screenInfo.cpp
Lines 1728 to 1740 in 0651d92
if (gci.Flags & CONSOLE_HAS_FOCUS) | |
{ | |
if (TurnOn) | |
{ | |
cursor.SetDelay(false); | |
cursor.SetIsOn(true); | |
} | |
else | |
{ | |
cursor.SetDelay(true); | |
} | |
cursor.SetHasMoved(true); | |
} |
IsOn
is always passed as true in ApiRoutines::SetConsoleCursorPositionImpl
, so this right here is assuming that the console has focus.... that's probably okay. I don't entirely know the origin of that HAS_FOCUS check.
This may be served well by having a helper - I think I'm gonna have to introduce focus tracking even for conpty fairly soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My impression was the the HAS_FOCUS
check was just an optimization, and it shouldn't harm to set these flags anyway. The TimerRoutine
that processes this stuff has it's own HAS_FOCUS
check that prevents it triggering a notification if the window isn't focused.
terminal/src/host/CursorBlinker.cpp
Lines 86 to 89 in ce6ce50
if (!WI_IsFlagSet(gci.Flags, CONSOLE_HAS_FOCUS)) | |
{ | |
goto DoScroll; | |
} |
If anything, I think the existing HAS_FOCUS
check might cause it lose some move events, and could be a bug. But again I thought this stuff should probably be investigated further in a follow up issue. I didn't want to get too bogged down trying to resolve side issues like this if I could avoid it. As long as we aren't making thing worse in the meantime.
Another project maintenance note: We've been largely focused on fixes that we can service back to 1.12, for syncing fixes with the OS build of the Terminal. This seems like it would firmly fit outside the realm of servicable fixes, so things that build off this may have a much harder time getting serviced to 1.12. Looking through the 1.14 list, there's like, two categories where this might matter:
Okay, not that complicated. Definitely doable, annoying, but doable if we want the FG stuff in 1.12. @DHowett as fyi |
I don't mind if you want to do those first. I only looked at them briefly, but I didn't think they'd be a huge problem to merge. |
I'm cool merging this. I'm a big kid, I can deal with the conflicts in my own branches. Happy to get this one in and get you unblocked That being said, literally every time I've tried pushing a merge fix to a branch from a fork, I'm botched it horribly. |
Hello @DHowett! Because you've given me some instructions on how to help merge this pull request, I'll be modifying my merge approach. Here's how I understand your requirements for merging this pull request: If this doesn't seem right to you, you can tell me to cancel these instructions and use the auto-merge policy that has been configured for this repository. Try telling me "forget everything I just told you". |
@DHowett I'm still at work at the moment, but I should be able to look at it later tonight. I was hoping to try and address the issues that Leonard raised at the same time, although they probably aren't essential if you want to get this over and done with. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm at 26/28, and I want to go get lunch. I'll swing back by for the other 2. I'm not surprised that I only have one comment so far -- this is top-notch work, as always. :)
@@ -28,6 +28,9 @@ | |||
<ProjectReference Include="..\..\..\interactivity\base\lib\InteractivityBase.vcxproj"> | |||
<Project>{06ec74cb-9a12-429c-b551-8562ec964846}</Project> | |||
</ProjectReference> | |||
<ProjectReference Include="..\..\..\renderer\base\lib\base.vcxproj"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Taking a mental note to adjust the link line in the sources
file to include ConRenderBase (thanks for calling this one to my attention!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done the merge and the other updates. Would you like me to do this too or should I leave it for you to fix? I'm not exactly sure what is required, but I thought maybe I just had to add back this line:
$(WINCORE_OBJ_PATH)\console\open\src\renderer\base\lib\$(O)\ConRenderBase.lib \
Or is there more to it than that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a nonzero chance there's more to it than that (Base might depend on Interactivity, which would bring back in the whole kit&kaboodle). I'm happy to handle this one, but thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(The best way to know is to try and build it, and the best way to do that is probably having an actual Windows enlistment, and.. well, you know.)
I'm happy to wait for this! Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am so on board with this. I love the reduced indirection and the improved obviousness of what adaptDispatch is doing. Thanks so much, James.
I'm only marking a comment here so that we don't automerge, but... this is an approval through and through
if (savedCursorState.IsOriginModeRelative && _scrollMargins.Bottom != 0) | ||
// If the origin mode is relative, we need to make sure the restored | ||
// position is clamped within the margins. | ||
if (savedCursorState.IsOriginModeRelative) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why we don't need to check any longer that there are margins -- what overarching change made this safe to do both with and without margins?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we have the _GetVerticalMargins
helper function which always returns a valid set of margins - if margins haven't been set, it'll return the margins of the viewport itself. In this particular case it means we'd be clamping the row to the viewport, which is essentially a noop. But in general it makes things cleaner not having to care whether the margins are set or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right -- you called this out in the PR body. Thanks!
// This uses a private API instead of the public one, because the public API | ||
// will set the cursor shape back to legacy. | ||
_pConApi->SetCursorVisibility(fIsVisible); | ||
_pConApi->GetTextBuffer().GetCursor().SetIsVisible(fIsVisible); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be good to ruminate on what happens if we ever make the Cursor a "global good" (since we learned that an alt buffer and main buffer share cursor properties, for example -- does it make sense to have one per text buffer then?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that the cursor coordinates are absolute, so when the buffers aren't the same size, the coordinates won't be the same. And when it comes to the console buffers, I think their cursor positions might be completely independent - I can't remember now.
Cursor properties (like visibility, shape, blinking status) could possibly be made global though. I've made a few attempts at that in the past, but always got stuck on something. I haven't given up on the idea, but it wasn't as straightforward as I expected it to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That totally makes sense. I legitimately forgot that the cursor's position wasn't shared.
Hello @DHowett! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
@msftbot nevermind |
Hello @DHowett! Because you've told me to reset the custom auto-merge settings, I'll use the configured settings for this repository when I'm merging this pull request. |
## Summary of the Pull Request This PR replaces the `TerminalDispatch` class with the `AdaptDispatch` class from conhost, so we're no longer duplicating the VT functionality in two places. It also gives us a more complete VT implementation on the Terminal side, so it should work better in pass-through mode. ## References This is essentially part two of PR #12703. ## PR Checklist * [x] Closes #3849 * [x] CLA signed. * [ ] Tests added/passed * [ ] Documentation updated. * [ ] Schema updated. * [x] I've discussed this with core contributors already. Issue number where discussion took place: #12662 ## Detailed Description of the Pull Request / Additional comments The first thing was to give the `ConGetSet` interface a new name, since it's now no longer specific to conhost. I went with `ITerminalApi`, since that was the equivalent interface on the terminal side, and it still seemed like a generic enough name. I also changed the way the api is managed by the `AdaptDispatch` class, so it's now stored as a reference rather than a `unique_ptr`, which more closely matches the way the `TerminalDispatch` class worked. I then had to make sure that `AdaptDispatch` actually included all of the functionality currently in `TerminalDispatch`. That meant copying across the code for bracketed paste mode, the copy to clipboard operation, and the various ConEmu OSC operations. This also required a few new methods to the `ConGetSet`/`ITerminalApi` interface, but for now these are just stubs in conhost. Then there were a few thing in the api interface that needed cleaning up. The `ReparentWindow` method doesn't belong there, so I've moved that into `PtySignalInputThread` class. And the `WriteInput` method was too low-level for the Terminal requirements, so I've replaced that with a `ReturnResponse` method which takes a `wstring_view`. It was then a matter of getting the `Terminal` class to implement all the methods in the new `ITerminalApi` interface that it didn't already have. This was mostly mapping to existing functionality, but there are still a number of methods that I've had to leave as stubs for now. However, what we have is still good enough that I could then nuke the `TerminalDispatch` class from the Terminal code and replace it with `AdaptDispatch`. One oddity that came up in testing, though, was the `AdaptDispatch` implementation of `EraseAll` would push a blank line into the scrollback when called on an empty buffer, whereas the previous terminal implementation did not. That caused problems for the conpty connection, because one of the first things it does on startup is send an `ED 2` sequence. I've now updated the `AdaptDispatch` implementation to match the behavior of the terminal implementation in that regard. Another problem was that the terminal implementation of the color table commands had special handling for the background color to notify the application window that it needed to repaint the background. I didn't want to have to push the color table operations through the `ITerminalApi` interface, so I've instead moved the handling of the background update into the renderer, initiated by a flag on the `TriggerRefreshAll` method. ## Validation Steps Performed Surprisingly this PR didn't require a lot of changes to get the unit tests working again. There were just a few methods used from the original `ITerminalApi` that have now been removed, and which needed an equivalent replacement. Also the updated behavior of the `EraseAll` method in conhost resulted in a change to the expected cursor position in one of the screen buffer tests. In terms of manual testing, I've tried out all the different shells in Windows Terminal to make sure there wasn't anything obviously wrong. And I've run a bunch of the tests from _vttest_ to try and get a wider coverage of the VT functionality, and confirmed everything still works at least as well as it used to. I've also run some of my own tests to verify the operations that had to be copied from `TerminalDispatch` to `AdaptDispatch`.
## Summary of the Pull Request When the conpty passthrough mode is enabled, it often needs to send `DSR-CPR` queries (cursor position reports) to the client terminal to obtain the current cursor position. However, the code that originally handled the responses to these queries got broken by the refactoring of the `ConGetSet` API. This PR is an attempt to correct that regression. ## References The conpty passthrough mode was introduced in PR #11264. The refactoring that broke the cursor position handling was in PR #12703. ## PR Checklist * [x] Closes #13106 * [x] CLA signed. * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments Prior to the `ConGetSet` refactoring, the code that handled `DSR-CPR` responses (`InteractDispatch::MoveCursor`) would pass the cursor position to `ConGetSet::SetCursorPosition`, which in turn would forward it to the `SetConsoleCursorPositionImpl` API, and from there to the `VtIo` class. After the refactor, all of those intermediate steps were removed - the cursor was simply updated directly in `InteractDispatch::MoveCursor`, and the `VtIo` call was moved from `SetConsoleCursorPositionImpl` to `InteractDispatch` (since that was the only place it was actually required). However, when the conpty passthrough mode was introduced - which happened in parallel - it relied on the `SetConsoleCursorPositionImpl` API being called from `InteractDispatch` in order to handle its own `DSR-CPR` responses, and that's why things stopped working when the two PRs merged. So what I've done now is made `InteractDispatch::MoveCursor` method call `SetConsoleCursorPositionImpl` again (although without the intermediate `ConGetSet` overhead), and moved the `VtIo::SetCursorPosition` call back into `SetConsoleCursorPositionImpl`. This is not ideal, and there are still a bunch of problems with the `DSR-CPR` handling in passthrough mode, but it's at least as good as it was before. ## Validation Steps Performed I've just manually tested various shells with passthrough mode enabled, and confirmed that they're working better now. There are still issues, but nothing that wasn't already a problem in the initial implementation, at least as far as I can tell.
## Summary of the Pull Request When the conpty passthrough mode is enabled, it often needs to send `DSR-CPR` queries (cursor position reports) to the client terminal to obtain the current cursor position. However, the code that originally handled the responses to these queries got broken by the refactoring of the `ConGetSet` API. This PR is an attempt to correct that regression. ## References The conpty passthrough mode was introduced in PR #11264. The refactoring that broke the cursor position handling was in PR #12703. ## PR Checklist * [x] Closes #13106 * [x] CLA signed. * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments Prior to the `ConGetSet` refactoring, the code that handled `DSR-CPR` responses (`InteractDispatch::MoveCursor`) would pass the cursor position to `ConGetSet::SetCursorPosition`, which in turn would forward it to the `SetConsoleCursorPositionImpl` API, and from there to the `VtIo` class. After the refactor, all of those intermediate steps were removed - the cursor was simply updated directly in `InteractDispatch::MoveCursor`, and the `VtIo` call was moved from `SetConsoleCursorPositionImpl` to `InteractDispatch` (since that was the only place it was actually required). However, when the conpty passthrough mode was introduced - which happened in parallel - it relied on the `SetConsoleCursorPositionImpl` API being called from `InteractDispatch` in order to handle its own `DSR-CPR` responses, and that's why things stopped working when the two PRs merged. So what I've done now is made `InteractDispatch::MoveCursor` method call `SetConsoleCursorPositionImpl` again (although without the intermediate `ConGetSet` overhead), and moved the `VtIo::SetCursorPosition` call back into `SetConsoleCursorPositionImpl`. This is not ideal, and there are still a bunch of problems with the `DSR-CPR` handling in passthrough mode, but it's at least as good as it was before. ## Validation Steps Performed I've just manually tested various shells with passthrough mode enabled, and confirmed that they're working better now. There are still issues, but nothing that wasn't already a problem in the initial implementation, at least as far as I can tell. (cherry picked from commit e1086de) Service-Card-Id: 82005205 Service-Version: 1.14
🎉 Handy links: |
This is an attempt to simplify the
ConGetSet
interface down to thesmallest set of methods necessary to support the
AdaptDispatch
class.The idea is that it should then be easier to implement that interface in
Windows Terminal, so we can replace the
TerminalDispatch
class withAdaptDispatch
.This is a continuation of the refactoring started in #12247, and a
significant step towards #3849.
Detailed Description of the Pull Request / Additional comments
The general idea was to give the
AdaptDispatch
class direct access tothe high-level structures on which it needs to operate. Some of these
structures are now passed in when the class is constructed (the
Renderer
,RenderSettings
, andTerminalInput
), and some are exposedas new methods in
ConGetSet
(GetStateMachine
,GetTextBuffer
, andGetViewport
).Many of the existing
ConhostInternalGetSet
methods could easily thenbe reimplemented in
AdaptDispatch
, since they were often simplyforwarding to methods in one of the above structures. Some were a little
more complicated, though, and require further explanation.
GetConsoleScreenBufferInfoEx
: What we were typically using this forwas to obtain the viewport, although what we really wanted was the
virtual viewport, which is now accessible via the
GetViewport
method. This was also used to obtain the cursor position and buffer
width, which we can now get via the
GetTextBuffer
method.SetConsoleScreenBufferInfoEx
: This was only really used for theAdaptDispatch::SetColumns
implementation (forDECCOLM
mode), andthat could be replaced with
ResizeWindow
. This is a slight change inbehaviour (it sizes the window rather than the buffer), but neither is
technically correct for
DECCOLM
, so I think it's good enough fornow, and at least it's consistent with the other VT sizing operations.
SetCursorPosition
: This could mostly be replaced with directmanipulation of the
Cursor
object (accessible via the text buffer),although again this is a slight change in behavior. The original code
would also have made a call to
ConsoleImeResizeCompStrView
(which Idon't think is applicable to VT movement), and would potentially have
moved the viewport (not essential for now, but could later be
supported by
DECHCCM
). It also calledVtIo::SetCursorPosition
tohandle cursor inheritance, but that should only apply to
InteractDispatch
, so I've moved that to theInteractDispatch::MoveCursor
method.ScrollRegion
: This has been replaced by two simple helper methods inAdaptDispatch
which better meet the VT requirements -_ScrollRectVertically
and_ScrollRectHorizontally
. Unlike theoriginal
ScrollRegion
implementation, these don't generateEVENT_CONSOLE_UPDATE_SCROLL
events (see ScrollRegion function generates inappropriate EVENT_CONSOLE_UPDATE_SCROLL #12656 for more details).FillRegion
: This has been replaced by the_FillRect
helper methodin
AdaptDispatch
. It differs from the originalFillRegion
in thatit takes a rect rather than a start position and length, which gives
us more flexibility for future operations.
ReverseLineFeed
: This has been replaced with a somewhat refactoredreimplementation in
AdaptDispatch
, mostly using the_ScrollRectVertically
helper described above.EraseAll
: This was previously handled bySCREEN_INFORMATION::VtEraseAll
, but has now been entirelyreimplemented in the
AdaptDispatch::_EraseAll
method.DeleteLines
/InsertLines
/_modifyLines
: These have been replacedby the
_InsertDeleteLineHelper
method inAdaptDispatch
, whichmostly relies on the
_ScrollRectVertically
helper described above.Finally there were a few methods that weren't actually needed in the
ConGetSet
interface:MoveToBottom
: This was really just a hack to get the virtualviewport from
GetConsoleScreenBufferInfoEx
. We may still wantsomething like in the future (e.g. to support
DECVCCM
or Option to cause window to automatically scroll to bottom when new output is received #8879), butI don't think it's essential for now.
SuppressResizeRepaint
: This was only needed inInteractDispatch
and
PtySignalInputThread
, and they could easily access theVtIo
object to implement it themselves.
ClearBuffer
: This was only used inPtySignalInputThread
, and thatcould easily access the buffer directly via the global console
information.
WriteControlInput
: This was only used inInteractDispatch
, andthat could easily be replaced with a direct call to
HandleGenericKeyEvent
.As part of these changes, I've also refactored some of the existing
AdaptDispatch
code:_InsertDeleteHelper
(renamed_InsertDeleteCharacterHelper
) is nowjust a straightforward call to the new
_ScrollRectHorizontally
helper.
EraseInDisplay
andEraseInLine
have been implemented as a seriesof
_FillRect
calls, so_EraseSingleLineHelper
is no longerrequired.
_EraseScrollback
is a essentially a special form of scrollingoperation, which mostly depends on the
TextBuffer::ScrollRows
method, and with the filling now provided by the new
_FillRect
helper.
There are quite a few operations now in
AdaptDispatch
that areaffected by the scrolling margins, so I've pulled out the common
margin setup into a new
_GetVerticalMargins
helper method. This alsofixes some edge cases where margins could end up out of range.
Validation Steps Performed
There were a number of unit tests that needed to be updated to work
around functions that have now been removed, but these substitutions
were fairly straightforward for the most part.
The adapter tests were a different story, though. In that case we were
explicitly testing how operations were passed through to the
ConGetSet
interface, but with more than half those methods now gone, a significant
rewrite was required.
I've tried to retain the crux of the original tests, but we now have to
validate the state changes on the underlying data structures, where
before that state would have been tracked in the
TestGetSet
mock. Andin some cases we were testing what happened when a method failed, but
since that scenario is no longer possible, I've simply removed those
tests.
I've also tried to manually test all the affected operations to confirm
that they're still working as expected, both in vttest as well as my own
test scripts.
Closes #12662