-
Notifications
You must be signed in to change notification settings - Fork 8.5k
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
Split TermControl
into a Core, Interactivity, and Control layer
#9820
Conversation
This is the code as of 4703dfe I'm moving it to TermControl in a new branch, to actually try checking it out now that I think it's mostly done. There are still 14 !TODO!s but this should at least let me start testing
Wadda ya know, we _can_ have TerminalCore expose types. Maybe we just got that in a recent VS / cppwinrt update, but it works finally
…rminalcontrol-into-lib # Conflicts: # src/cascadia/TerminalApp/TerminalSettings.h # src/cascadia/TerminalSettingsModel/TerminalSettings.cpp
…le. Convert some older macro uses to TYPED_EVENT
…l' into dev/migrie/oop-terminal.control-split-control
…al.control-split-control # Conflicts: # src/cascadia/TerminalApp/TerminalPage.cpp # src/cascadia/TerminalApp/TerminalPage.h # src/cascadia/TerminalControl/TermControl.cpp # src/cascadia/TerminalControl/TermControl.h # src/cascadia/TerminalControl/TermControl.idl # src/cascadia/TerminalControl/TerminalControl.def # src/cascadia/TerminalControl/TerminalControlLib.vcxproj # src/cascadia/TerminalControl/dll/Microsoft.Terminal.Control.def # src/cascadia/TerminalControl/dll/TerminalControl.def # src/cascadia/TerminalControl/dll/TerminalControl.vcxproj
…nteractivity-control UpdateHoveredCell was a MESS
…nteractivity-control
This also moved _HyperlinkHandler, and _TrySendMouseEvent Started with 29 errors, down to 24
Now we're down to 12 errors. This is starting to feel like it's coming together. Mouse scrolling is scary though.
And a bit of cleanup of things left behind by the previous commits. Down to 5 errors!
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 sold. You addressed my 150 comments. Thank you for doing that, and I am excited to re-platform the WPF control on top of this.
Unresolved comments:
- Adding counters to the opacity callback tests to make certain the callback is run.
- Verifying floats using delta algorithm instead of ARE_EQUAL -
VERIFY_IS_LESS_THAN(std::abs(1.0 - expectedOpacity), 0.001))
- Was the ordering on UpdateSettings before/after UI settings (TermControl) important
- Split
TermControl
into a Core, Interactivity, and Control layer #9820 (comment) Is this invariant something that should be promoted to a doc comment? - gonna have to do a manual test pass to ensure that modifiers and OS-level keys do not jump the terminal down or dismiss selection.
- @miniksa commented on "this should be on the UI thread", "Is there any way to assert/throw if it's not on the XAML thread?"
- Should the mocks WEX::Log
- Maybe make Interactivity figure out
focused
on its own - @carlos-zamora comments on dropping an else branch in opacity adjustment (ControlCore) - Split
TermControl
into a Core, Interactivity, and Control layer #9820 (comment) - Same place, but question if we need SetBackgroundOpacity - Split
TermControl
into a Core, Interactivity, and Control layer #9820 (comment)
You could also write the following:
hostingTab.TaskbarProgressChanged({ get_weak(), &TerminalPage::_SetTaskbarProgressHandler });
Unfortunately there's no explanation in this file why
get_weak()
is being used in certain places instead of a simplethis
. If you know why a comment would probably be useful and prevent someone from breaking it in the future.@lhecker https://github.com/microsoft/terminal/pull/9820/files#r616981656
If you make this method resistant against being called from a background thread you don't need to switch into the foreground thread in neither
_RendererWarning
nor_RaiseReadOnlyWarning
.
@carlos-zamora you are a waiter on this PR. @miniksa You and I discussed this, so I may dismiss your review. |
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.
Alright, let's do this.
Dustin said it was cool if I dismiss you, so 👋
Hello @zadjii-msft! 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 (
|
## Summary of the Pull Request This PR encompasses the first three bugs we found post-#9820. ### A: Mousedown, select, SCROLL does a weird thing with endpoints that doesn't happen in stable We were using the terminal position to set the selection anchor, when we should have used the pixel position. This is fixed in 4f4df01. ### B: Trackpad scrolling down with small increments seems buggy This one's the most complicated. The touchpad sends very many small scroll deltas, less than one row at a time. The control scrollbar can store a `double`, so small deltas can accumulate. Originally, these would accumulate in the scrollbar, and we'd only read that out as an `int` in the scrollbar updater, which is throttled. In the interactivity split, there's no place for us to store that double. We immediately narrow to an `int` for `ControlInteractivity::_updateScrollbar`. So this introduces a double inside `ControlInteractivity` as a fake scrollbar, with which to accumulate to. This is fixed in 33d29fa...0fefc5b ### C: Looks like there's a selection issue when you click and drag too quickly. The diff for this one is: <table> <tr><td>1.8</td><td>main</td></tr> <tr> <td> ```c++ if (_singleClickTouchdownPos) { // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point auto& touchdownPoint{ *_singleClickTouchdownPos }; auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) }; const til::size fontSize{ _actualFont.GetSize() }; const auto fontSizeInDips = fontSize.scale(til::math::rounding, 1.0f / _renderEngine->GetScaling()); if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) { _terminal->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); // stop tracking the touchdown point _singleClickTouchdownPos = std::nullopt; } } ``` </td> <td> ```c++ if (_singleClickTouchdownPos) { // Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point auto& touchdownPoint{ *_singleClickTouchdownPos }; float dx = ::base::saturated_cast<float>(pixelPosition.x() - touchdownPoint.x()); float dy = ::base::saturated_cast<float>(pixelPosition.y() - touchdownPoint.y()); auto distance{ std::sqrtf(std::powf(dx, 2) + std::powf(dy, 2)) }; const auto fontSizeInDips{ _core->FontSizeInDips() }; if (distance >= (std::min(fontSizeInDips.width(), fontSizeInDips.height()) / 4.f)) { _core->SetSelectionAnchor(terminalPosition); // stop tracking the touchdown point _singleClickTouchdownPos = std::nullopt; } } ``` </td> </tr> </table> ```c++ _terminal->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint)); ``` vs ```c++ _core->SetSelectionAnchor(terminalPosition); ``` We're now using the location of the drag event as the selection anchor, instead of the location that the user initially clicked. Oops. ## PR Checklist * [x] Checks three boxes, though I'll be shocked if they're the last. * [x] I work here * [x] Tests added/passed 🎉🎉🎉 * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments All three have tests, 🙌🙌🙌🙌 ## Validation Steps Performed Manual, and automated via tests
🎉 Handy links: |
## Summary of the Pull Request This was missed in #10051. We need to make sure that the UIA provider can immediately know about the padding in the control, not just after the settings reload. ## PR Checklist * [x] Closes #9955.e * [x] Additionally, this just closes #9955. The only remaining box in there never repro'd, so probably wasn't even root caused by #9820. I think we can close that issue for now, and reactivate if something else was broken. * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Validation Steps Performed Checked before/after in Accessibility Insights. Before the row rectangles were the full width of the control initially. Now they're properly padded.
This is on me. When I got rid of the `_updatePatternLocations` `ThrottledFunc` in the `TermControl`, I didn't add a matching call to `_updatePatternLocations->Run()` in this method. In #9820, in `TermControl::_ScrollPositionChanged`, there was still a call to `_updatePatternLocations->Run();`. (TermControl.cpp:1655 on the right) https://github.com/microsoft/terminal/pull/9820/files#diff-c10bb023995e88dac6c1d786129284c454c2df739ea547ce462129dc86dc2697R1654 #10051 didn't change this In #10187 I moved the `_updatePatternLocations` throttled func from termcontrol to controlcore. Places it existed before: * [x] `TermControl::_coreReceivedOutput`: already matched by ControlCore::_connectionOutputHandler * [x] `TermControl::_ScrollbarChangeHandler` -> added in c20eb9d * [x] `TermControl::_ScrollPositionChanged` -> `ControlCore::_terminalScrollPositionChanged` ## Validation Steps Performed Print a URL, scroll the wheel: it still works. Closes #11055
This is on me. When I got rid of the `_updatePatternLocations` `ThrottledFunc` in the `TermControl`, I didn't add a matching call to `_updatePatternLocations->Run()` in this method. In #9820, in `TermControl::_ScrollPositionChanged`, there was still a call to `_updatePatternLocations->Run();`. (TermControl.cpp:1655 on the right) https://github.com/microsoft/terminal/pull/9820/files#diff-c10bb023995e88dac6c1d786129284c454c2df739ea547ce462129dc86dc2697R1654 #10051 didn't change this In #10187 I moved the `_updatePatternLocations` throttled func from termcontrol to controlcore. Places it existed before: * [x] `TermControl::_coreReceivedOutput`: already matched by ControlCore::_connectionOutputHandler * [x] `TermControl::_ScrollbarChangeHandler` -> added in c20eb9d * [x] `TermControl::_ScrollPositionChanged` -> `ControlCore::_terminalScrollPositionChanged` ## Validation Steps Performed Print a URL, scroll the wheel: it still works. Closes #11055 (cherry picked from commit 7423734)
Summary of the Pull Request
Brace yourselves, it's finally here. This PR does the dirty work of splitting the monolithic
TermControl
into three components. These components are:ControlCore
: This encapsulates theTerminal
instance, theDxEngine
andRenderer
, and theConnection
. This is intended to everything that someone might need to stand up a terminal instance in a control, but without any regard for how the UX works.ControlInteractivity
: This is a wrapper for theControlCore
, which holds the logic for things like double-click, right click copy/paste, selection, etc. This is intended to be a UI framework-independent abstraction. The methods this layer exposes can be called the same from both the WinUI TermControl and the WPF control.TermControl
: This is the UWP control. It's got a Core and Interactivity inside it, which it uses for the actual logic of the terminal itself. TermControl's main responsibility is nowBy splitting into smaller pieces, it will enable us to
Core
andInteractivity
bits, which we desparately needControlCore
andControlInteractivity
in an out-of-proc core process in the future, to enable tab tearout.However, we're not doing that work quite yet. There's still lots of work to be done to enable that, thought this is likely the biggest portion.
Ideally, this would just be methods moved wholesale from one file to another. Unfortunately, there are a bunch of cases where that didn't work as well as expected. Especially when trying to better enforce the boundary between the classes.
We've got a couple tests here that I've added. These are partially examples, and partially things I ran into while implementing this. A bunch of things from #7001 can go in now that we have this.
This PR is gonna be a huge pain to review - 38 files with 3,730 additions and 1,661 deletions is nothing to scoff at. It will also conflict 100% with anything that's targeting
TermControl
. I'm hoping we can review this over the course of the next week and just be done with it, and leave plenty of runway for 1.9 bugs in post.References
PR Checklist
Detailed Description of the Pull Request / Additional comments
ControlCore
andControlInteractivity
. Open to other names.ICoreState
interface for "properties that come from theControlCore
, but consumers of theTermControl
need to know". In the future, these will all need to be handled specially, because they might involve an RPC call to retrieve the info from the core (or cache it) in the window process.EventArgs
to make more events properTypedEvent
s.Something that snuck into this branch in the very long history is the switch toDCompositionCreateSurfaceHandle
for theDxEngine
. @miniksa wrote this originally in 30b8335, I'm just finally committing it here. We'll need that in the future for the out-of-proc stuff.ThrottledFunc
things are left inTermControl
. Some might be able to move down into core/interactivity, but once we figure out how to use a different kind of Dispatcher (because a UI thread won't necessarily exist for those components).Validation Steps Performed
I've got a rolling list in #6842 (comment) that I'm updating as I go.