Files
terminal/src/cascadia/TerminalControl/ControlInteractivity.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

755 lines
33 KiB
C++
Raw Normal View History

Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "ControlInteractivity.h"
#include <DefaultSettings.h>
#include <unicode.hpp>
#include <Utils.h>
#include <LibraryResources.h>
#include "../../types/inc/GlyphWidth.hpp"
#include "../../types/inc/Utils.hpp"
#include "../../buffer/out/search.h"
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
#include "InteractivityAutomationPeer.h"
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
#include "ControlInteractivity.g.cpp"
using namespace ::Microsoft::Console::Types;
using namespace ::Microsoft::Console::VirtualTerminal;
using namespace ::Microsoft::Terminal::Core;
using namespace winrt::Windows::Graphics::Display;
using namespace winrt::Windows::System;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
static constexpr unsigned int MAX_CLICK_COUNT = 3;
namespace winrt::Microsoft::Terminal::Control::implementation
{
Introduce a ContentManager helper (#14851) ## Summary _Thus we come to the introduction of a new servant, the `ContentManager`, a singular entity that serves at the behest of the `emperor`. It is its charge to keep track of all `TermControl` instances created by the windows, for each window must seek its blessing before calling forth such an instance._ _With the aid of the `ContentManager`, the `TermControl` shall now be traced by the hand of fate through the use of unique identifying marks, known as `GUID`s. Yet, its purpose remains yet unknown, for it is merely a waypoint upon the journey yet to come._ _This act of bridging also brings a change to the handling of events within the `TermControl`. This change shall see the addition of a revoker, similar to the manner in which the `AppHost` hath employed it, to the `TermControl`. Additionally, there is a new layer of indirection between the `ControlCore` and the `App` layer, making ready for the day when the `TermControl` may be repositioned and re-parented with ease._ _Consider this but a trivial act, a mere shadow of things yet to come, for its impact shall be felt but briefly, like the passing of a gentle breeze._ Related to #5000 Related to #1256 # Detailed description This PR is another small bridge PR between the big work in #14843, and the PR that will enable panes to move between windows. This introduces a new class, called `ContentManager`. This is a global singleton object, owned by the emperor. Whenever a window wants to instantiate a new `TermControl`, it must ask the ContentManager to give it one. This allows the ContentManager to track each "content" by GUID. That's it. We don't do anything with them in this PR by itself, we just track them. This also includes a small change to the way TermControl events are handled. It adds an `AppHost`-like revoker struct, and weak_ref's all the handlers. We also add a layer of indirection between the ControlCore's raising of events and the App layer's handling. This will make reparenting content easier in the future. This is a pretty trivial change which shouldn't have any major side effects. Consider it exposition of the things to come. It's intentionally small to try and keep the reviews more managable.
2023-03-22 12:11:44 -05:00
std::atomic<uint64_t> ControlInteractivity::_nextId{ 1 };
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
static constexpr TerminalInput::MouseButtonState toInternalMouseState(const Control::MouseButtonState& state)
{
return TerminalInput::MouseButtonState{
WI_IsFlagSet(state, MouseButtonState::IsLeftButtonDown),
WI_IsFlagSet(state, MouseButtonState::IsMiddleButtonDown),
WI_IsFlagSet(state, MouseButtonState::IsRightButtonDown)
};
}
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
ControlInteractivity::ControlInteractivity(IControlSettings settings,
Change the `ControlCore` layer to own a copy of its settings (#11619) ## Summary of the Pull Request Currently, the TermControl and ControlCore recieve a settings object that implements `IControlSettings`. They use for this for both reading the settings they should use, and also storing some runtime overrides to those settings (namely, `Opacity`). The object they recieve currently is a `T.S.M.TerminalSettings` object, as well as another `TerminalSettings` object if the user wants to have an `unfocusedAppearance`. All these are all hosted in the same process, so everything is fine and dandy. With the upcoming move to having the Terminal split into multiple processes, this will no longer work. If the `ControlCore` in the Content Process is given a pointer to a `TerminalSettings` in a certain Window Process, and that control is subsequently moved to another window, then there's no guarantee that the original `TerminalSettings` object continues to exist. In this scenario, when window 1 is closed, now the Core is unable to read any settings, because the process that owned that object no longer exists. The solution to this issue is to have the `ControlCore`'s own their own copy of the settings they were created with. that way, they can be confident those settings will always exist. Enter `ControlSettings`, a dumb struct for just storing all the contents of the Settings. I used x-macros for this, so that we don't need to copy-paste into this file every time we add a setting. Changing this has all sorts of other fallout effects: * Previewing a scheme/anything is a tad bit more annoying. Before, we could just sneak the previewed scheme into a `TerminalSettings` that lived between the settings we created the control with, and the settings they were actually using, and it would _just work_. Even explaining that here, it sounds like magic, because it was. However, now, the TermControl can't use a layered `TerminalSettings` for the settings anymore. Now we need to actually read out the current color table, and set the whole scheme when we change it. So now there's also a `Microsoft.Terminal.Core.Scheme` _struct_ for holding that data. - Why a `struct`? Because that will go across the process boundary as a blob, rather than as a pointer to an object in the other process. That way we can transit the whole struct from window to core safely. * A TermControl doesn't have a `IControlSettings` at all anymore - it initalizes itself via the settings in the `Core`. This will be useful for tear-out, when we need to have the `TermControl` initialize itself from just a `ControlCore`, without being able to rebuild the settings from scratch. * The `TabTests` that were written under the assumption that the Control had a layered `TerminalSettings` obviously broke, as they were designed to. They've been modified to reflect the new reality. * When we initialize the Control, we give it the settings and the `UnfocusedAppearance` all at once. If we don't give it an `unfocusedAppearance`, it will just use the focused appearance as the unfocused appearance. * The Control no longer can _write_ settings to the `ControlSettings`. We don't want to be storing things in there. Pretty much everything we set in the control, we store somewhere other than in the settings object itself. However, `opacity` and `useAcrylic`, we need to store in a handy new `RUNTIME_SETTING` property. We can write those runtime overrides to those properties. * We no longer store the color scheme for a pane in the persisted state. I'm tracking that in #9800. I don't think it's too hard to add back, but I wanted this in front of eyes sooner than later. ## References * #1256 * #5000 * #9794 has the scheme previewing in it. * #9818 is WAY more possible now. ## PR Checklist * [x] Surprisingly there wasn't ever a card or issue for this one. This was only ever a bullet point in #5000. * A bunch of these issues were fixed along the way, though I never intended to fix them: * [x] Closes #11571 * [x] Closes #11586 * [x] Closes #7219 * [x] Closes #11067 * [x] I think #11623 actually ended up resolving this one, but I'm double tapping on it here: Closes #5703 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Along the way I tried to clean up code where possible, but not too agressively. I didn't end up converting the various `MockTerminalSettings` classes used in tests to the x macros quite yet. I wanted to merge this with #11416 in `main` before I went too crazy. ## Validation Steps Performed * [x] Scheme previewing works * [x] Adjusting the font size works * [x] focused/unfocused appearances still work * [x] mouse-wheeling opacity still works * [x] acrylic & cleartype still does the right thing * [x] saving the settings still works * [x] going wild on sliding the opacity slider in the settings doesn't crash the terminal * [x] toggling retro effects with a keybinding still works * [x] toggling retro effects with the command palette works * [x] The matrix of (`useAcrylic(true,false)`)x(`opacity(50,100)`)x(`antialiasingMode(cleartype, grayscale)`) works as expected. Slightly changed, falls back to grayscale more often, but looks more right.
2021-12-01 13:33:51 -06:00
Control::IControlAppearance unfocusedAppearance,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
TerminalConnection::ITerminalConnection connection) :
_touchAnchor{ std::nullopt },
_lastMouseClickTimestamp{},
_lastMouseClickPos{},
_selectionNeedsToBeCopied{ false }
{
Introduce a ContentManager helper (#14851) ## Summary _Thus we come to the introduction of a new servant, the `ContentManager`, a singular entity that serves at the behest of the `emperor`. It is its charge to keep track of all `TermControl` instances created by the windows, for each window must seek its blessing before calling forth such an instance._ _With the aid of the `ContentManager`, the `TermControl` shall now be traced by the hand of fate through the use of unique identifying marks, known as `GUID`s. Yet, its purpose remains yet unknown, for it is merely a waypoint upon the journey yet to come._ _This act of bridging also brings a change to the handling of events within the `TermControl`. This change shall see the addition of a revoker, similar to the manner in which the `AppHost` hath employed it, to the `TermControl`. Additionally, there is a new layer of indirection between the `ControlCore` and the `App` layer, making ready for the day when the `TermControl` may be repositioned and re-parented with ease._ _Consider this but a trivial act, a mere shadow of things yet to come, for its impact shall be felt but briefly, like the passing of a gentle breeze._ Related to #5000 Related to #1256 # Detailed description This PR is another small bridge PR between the big work in #14843, and the PR that will enable panes to move between windows. This introduces a new class, called `ContentManager`. This is a global singleton object, owned by the emperor. Whenever a window wants to instantiate a new `TermControl`, it must ask the ContentManager to give it one. This allows the ContentManager to track each "content" by GUID. That's it. We don't do anything with them in this PR by itself, we just track them. This also includes a small change to the way TermControl events are handled. It adds an `AppHost`-like revoker struct, and weak_ref's all the handlers. We also add a layer of indirection between the ControlCore's raising of events and the App layer's handling. This will make reparenting content easier in the future. This is a pretty trivial change which shouldn't have any major side effects. Consider it exposition of the things to come. It's intentionally small to try and keep the reviews more managable.
2023-03-22 12:11:44 -05:00
_id = _nextId.fetch_add(1, std::memory_order_relaxed);
Change the `ControlCore` layer to own a copy of its settings (#11619) ## Summary of the Pull Request Currently, the TermControl and ControlCore recieve a settings object that implements `IControlSettings`. They use for this for both reading the settings they should use, and also storing some runtime overrides to those settings (namely, `Opacity`). The object they recieve currently is a `T.S.M.TerminalSettings` object, as well as another `TerminalSettings` object if the user wants to have an `unfocusedAppearance`. All these are all hosted in the same process, so everything is fine and dandy. With the upcoming move to having the Terminal split into multiple processes, this will no longer work. If the `ControlCore` in the Content Process is given a pointer to a `TerminalSettings` in a certain Window Process, and that control is subsequently moved to another window, then there's no guarantee that the original `TerminalSettings` object continues to exist. In this scenario, when window 1 is closed, now the Core is unable to read any settings, because the process that owned that object no longer exists. The solution to this issue is to have the `ControlCore`'s own their own copy of the settings they were created with. that way, they can be confident those settings will always exist. Enter `ControlSettings`, a dumb struct for just storing all the contents of the Settings. I used x-macros for this, so that we don't need to copy-paste into this file every time we add a setting. Changing this has all sorts of other fallout effects: * Previewing a scheme/anything is a tad bit more annoying. Before, we could just sneak the previewed scheme into a `TerminalSettings` that lived between the settings we created the control with, and the settings they were actually using, and it would _just work_. Even explaining that here, it sounds like magic, because it was. However, now, the TermControl can't use a layered `TerminalSettings` for the settings anymore. Now we need to actually read out the current color table, and set the whole scheme when we change it. So now there's also a `Microsoft.Terminal.Core.Scheme` _struct_ for holding that data. - Why a `struct`? Because that will go across the process boundary as a blob, rather than as a pointer to an object in the other process. That way we can transit the whole struct from window to core safely. * A TermControl doesn't have a `IControlSettings` at all anymore - it initalizes itself via the settings in the `Core`. This will be useful for tear-out, when we need to have the `TermControl` initialize itself from just a `ControlCore`, without being able to rebuild the settings from scratch. * The `TabTests` that were written under the assumption that the Control had a layered `TerminalSettings` obviously broke, as they were designed to. They've been modified to reflect the new reality. * When we initialize the Control, we give it the settings and the `UnfocusedAppearance` all at once. If we don't give it an `unfocusedAppearance`, it will just use the focused appearance as the unfocused appearance. * The Control no longer can _write_ settings to the `ControlSettings`. We don't want to be storing things in there. Pretty much everything we set in the control, we store somewhere other than in the settings object itself. However, `opacity` and `useAcrylic`, we need to store in a handy new `RUNTIME_SETTING` property. We can write those runtime overrides to those properties. * We no longer store the color scheme for a pane in the persisted state. I'm tracking that in #9800. I don't think it's too hard to add back, but I wanted this in front of eyes sooner than later. ## References * #1256 * #5000 * #9794 has the scheme previewing in it. * #9818 is WAY more possible now. ## PR Checklist * [x] Surprisingly there wasn't ever a card or issue for this one. This was only ever a bullet point in #5000. * A bunch of these issues were fixed along the way, though I never intended to fix them: * [x] Closes #11571 * [x] Closes #11586 * [x] Closes #7219 * [x] Closes #11067 * [x] I think #11623 actually ended up resolving this one, but I'm double tapping on it here: Closes #5703 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Along the way I tried to clean up code where possible, but not too agressively. I didn't end up converting the various `MockTerminalSettings` classes used in tests to the x macros quite yet. I wanted to merge this with #11416 in `main` before I went too crazy. ## Validation Steps Performed * [x] Scheme previewing works * [x] Adjusting the font size works * [x] focused/unfocused appearances still work * [x] mouse-wheeling opacity still works * [x] acrylic & cleartype still does the right thing * [x] saving the settings still works * [x] going wild on sliding the opacity slider in the settings doesn't crash the terminal * [x] toggling retro effects with a keybinding still works * [x] toggling retro effects with the command palette works * [x] The matrix of (`useAcrylic(true,false)`)x(`opacity(50,100)`)x(`antialiasingMode(cleartype, grayscale)`) works as expected. Slightly changed, falls back to grayscale more often, but looks more right.
2021-12-01 13:33:51 -06:00
_core = winrt::make_self<ControlCore>(settings, unfocusedAppearance, connection);
Add support for moving panes and tabs between windows (#14866) _Lo! Harken to me, for I shall divulge the heart of the tab tear-out saga. Verily, this PR shall bestow upon thee the power to move tabs and panes between windows by means of pre-defined actions. Though be warned, it does not yet grant thee the power to drag and drop them as thou mayest desire. Yet, the same plumbing that underpins this work shall remain steadfast. Behold, the majority of this undertaking concerns the elevation of the RequestMoveContent event from the TerminalPage to the very summit of the Monarch. From thence, a great AttachContent method shall descend back to the lowest depths. Furthermore, there are minor revisions to TermControl that shall enable thee to better detach the content and attach it to a new one._ This is the most important part of the tab tear-out saga. This PR enables the user to move tabs and panes between windows using pre-defined actions. It does _not_ enable the user to drag/drop them yet, but the same fundamental plumbing will still apply. Most of the PR is plumbing the `RequestMoveContent` event up from the `TerminalPage` up to the `Monarch`, and then plumbing an `AttachContent` method back down. There are also small changes to `TermControl` to better support detaching the content and attaching to a new one. For testing, I recommend: ```json { "keys": "f1", "command": { "action": "moveTab", "window": "1" } }, { "keys": "f2", "command": { "action": "moveTab", "window": "2" } }, { "keys": "f3", "command": { "action": "movePane", "window": "1" } }, { "keys": "f4", "command": { "action": "movePane", "window": "2" } }, { "keys": "shift+f3", "command": { "action": "movePane", "window": "1", "index": 3 } }, { "keys": "shift+f4", "command": { "action": "movePane", "window": "2", "index": 3 } }, ``` * Related to #1256 * Related to #5000 --------- Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2023-03-30 09:37:53 -05:00
_core->Attached([weakThis = get_weak()](auto&&, auto&&) {
if (auto self{ weakThis.get() })
{
Replace usages of `TYPED_EVENT` with `til::event` (#16837) This PR automagically finds and replaces all[^1] usages of our TYPED_EVENT macro with `til::event`. Benefits include: * less macro magic * editors are more easily able to figure out the relationship between `til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this, &Bar::FooHandler})` (whereas before the relationship between `_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by vscode & sublime. Other find & replace work that had to be done: * I added the `til::typed_event<>` == `<IInspectable, IInspectable>` thing from #16170, since that is goodness * I actually fixed `til::property_changed_event`, so you can use that for your property changed events. They're all the same anyways. * events had to come before `WINRT_PROPERTY`s, since the latter macro leaves us in a `private:` block * `Pane::SetupChildCloseHandlers` I had to swap _back_, because the script thought that was an event 🤦 * `ProfileViewModel::DeleteProfile` had to be renamed `DeleteProfileRequested`, since there was already a `DeleteProfile` method on it. * WindowManager.cpp was directly wiring up it's `winrt::event`s to the monarch & peasant. That doesn't work with `til::event`s and I'm kinda surprised it ever did <details> <summary>The script in question</summary> ```py import os import re def replace_in_file(file_path, file_name): with open(file_path, 'r', encoding="utf8") as file: content = file.read() found_matches = False # Define the pattern for matching pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);' event_matches = re.findall(pattern, content) if event_matches: found_matches = True print(f'found events in {file_path}:') for match in event_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');' new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);' typed_matches = re.findall(typed_event_pattern, content) if typed_matches: found_matches = True print(f'found typed_events in {file_path}:') for match in typed_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'TYPED_EVENT({name}, {args});' was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" ) new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};" print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) handlers_pattern = r'_(\w+)Handlers\(' handler_matches = re.findall(handlers_pattern, content) if handler_matches: found_matches = True print(f'found handlers in {file_path}:') for match in handler_matches: name = match if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'_{name}Handlers(' new_declaration = f'{name}.raise(' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) if found_matches: with open(file_path, 'w', encoding="utf8") as file: file.write(content) def find_and_replace(directory): for root, dirs, files in os.walk(directory): if 'Generated Files' in dirs: dirs.remove('Generated Files') # Exclude the "Generated Files" directory for file in files: if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'): file_path = os.path.join(root, file) try: replace_in_file(file_path, file) except Exception as e: print(f"error reading {file_path}") if file == "TermControl.cpp": print(e) # raise e # Replace in files within a specific directory directory_path = 'D:\\dev\\public\\terminal\\src' find_and_replace(directory_path) ``` </details> [^1]: there are other macros we use that were also using this macro, those weren't replaced. --------- Co-authored-by: Dustin Howett <duhowett@microsoft.com> Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2024-03-20 09:02:26 -07:00
self->Attached.raise(*self, nullptr);
Add support for moving panes and tabs between windows (#14866) _Lo! Harken to me, for I shall divulge the heart of the tab tear-out saga. Verily, this PR shall bestow upon thee the power to move tabs and panes between windows by means of pre-defined actions. Though be warned, it does not yet grant thee the power to drag and drop them as thou mayest desire. Yet, the same plumbing that underpins this work shall remain steadfast. Behold, the majority of this undertaking concerns the elevation of the RequestMoveContent event from the TerminalPage to the very summit of the Monarch. From thence, a great AttachContent method shall descend back to the lowest depths. Furthermore, there are minor revisions to TermControl that shall enable thee to better detach the content and attach it to a new one._ This is the most important part of the tab tear-out saga. This PR enables the user to move tabs and panes between windows using pre-defined actions. It does _not_ enable the user to drag/drop them yet, but the same fundamental plumbing will still apply. Most of the PR is plumbing the `RequestMoveContent` event up from the `TerminalPage` up to the `Monarch`, and then plumbing an `AttachContent` method back down. There are also small changes to `TermControl` to better support detaching the content and attaching to a new one. For testing, I recommend: ```json { "keys": "f1", "command": { "action": "moveTab", "window": "1" } }, { "keys": "f2", "command": { "action": "moveTab", "window": "2" } }, { "keys": "f3", "command": { "action": "movePane", "window": "1" } }, { "keys": "f4", "command": { "action": "movePane", "window": "2" } }, { "keys": "shift+f3", "command": { "action": "movePane", "window": "1", "index": 3 } }, { "keys": "shift+f4", "command": { "action": "movePane", "window": "2", "index": 3 } }, ``` * Related to #1256 * Related to #5000 --------- Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2023-03-30 09:37:53 -05:00
}
});
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
Introduce a ContentManager helper (#14851) ## Summary _Thus we come to the introduction of a new servant, the `ContentManager`, a singular entity that serves at the behest of the `emperor`. It is its charge to keep track of all `TermControl` instances created by the windows, for each window must seek its blessing before calling forth such an instance._ _With the aid of the `ContentManager`, the `TermControl` shall now be traced by the hand of fate through the use of unique identifying marks, known as `GUID`s. Yet, its purpose remains yet unknown, for it is merely a waypoint upon the journey yet to come._ _This act of bridging also brings a change to the handling of events within the `TermControl`. This change shall see the addition of a revoker, similar to the manner in which the `AppHost` hath employed it, to the `TermControl`. Additionally, there is a new layer of indirection between the `ControlCore` and the `App` layer, making ready for the day when the `TermControl` may be repositioned and re-parented with ease._ _Consider this but a trivial act, a mere shadow of things yet to come, for its impact shall be felt but briefly, like the passing of a gentle breeze._ Related to #5000 Related to #1256 # Detailed description This PR is another small bridge PR between the big work in #14843, and the PR that will enable panes to move between windows. This introduces a new class, called `ContentManager`. This is a global singleton object, owned by the emperor. Whenever a window wants to instantiate a new `TermControl`, it must ask the ContentManager to give it one. This allows the ContentManager to track each "content" by GUID. That's it. We don't do anything with them in this PR by itself, we just track them. This also includes a small change to the way TermControl events are handled. It adds an `AppHost`-like revoker struct, and weak_ref's all the handlers. We also add a layer of indirection between the ControlCore's raising of events and the App layer's handling. This will make reparenting content easier in the future. This is a pretty trivial change which shouldn't have any major side effects. Consider it exposition of the things to come. It's intentionally small to try and keep the reviews more managable.
2023-03-22 12:11:44 -05:00
uint64_t ControlInteractivity::Id()
{
return _id;
}
Add support for moving panes and tabs between windows (#14866) _Lo! Harken to me, for I shall divulge the heart of the tab tear-out saga. Verily, this PR shall bestow upon thee the power to move tabs and panes between windows by means of pre-defined actions. Though be warned, it does not yet grant thee the power to drag and drop them as thou mayest desire. Yet, the same plumbing that underpins this work shall remain steadfast. Behold, the majority of this undertaking concerns the elevation of the RequestMoveContent event from the TerminalPage to the very summit of the Monarch. From thence, a great AttachContent method shall descend back to the lowest depths. Furthermore, there are minor revisions to TermControl that shall enable thee to better detach the content and attach it to a new one._ This is the most important part of the tab tear-out saga. This PR enables the user to move tabs and panes between windows using pre-defined actions. It does _not_ enable the user to drag/drop them yet, but the same fundamental plumbing will still apply. Most of the PR is plumbing the `RequestMoveContent` event up from the `TerminalPage` up to the `Monarch`, and then plumbing an `AttachContent` method back down. There are also small changes to `TermControl` to better support detaching the content and attaching to a new one. For testing, I recommend: ```json { "keys": "f1", "command": { "action": "moveTab", "window": "1" } }, { "keys": "f2", "command": { "action": "moveTab", "window": "2" } }, { "keys": "f3", "command": { "action": "movePane", "window": "1" } }, { "keys": "f4", "command": { "action": "movePane", "window": "2" } }, { "keys": "shift+f3", "command": { "action": "movePane", "window": "1", "index": 3 } }, { "keys": "shift+f4", "command": { "action": "movePane", "window": "2", "index": 3 } }, ``` * Related to #1256 * Related to #5000 --------- Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2023-03-30 09:37:53 -05:00
void ControlInteractivity::Detach()
{
if (_uiaEngine)
{
// There's a potential race here where we've removed the TermControl
// from the UI tree, but the UIA engine is in the middle of a paint,
// and the UIA engine will try to dispatch to the
// TermControlAutomationPeer, which (is now)/(will very soon be) gone.
//
// To alleviate, make sure to disable the UIA engine and remove it,
// and ALSO disable the renderer. Core.Detach will take care of the
// TriggerTeardown (which will stop the renderer
Add support for moving panes and tabs between windows (#14866) _Lo! Harken to me, for I shall divulge the heart of the tab tear-out saga. Verily, this PR shall bestow upon thee the power to move tabs and panes between windows by means of pre-defined actions. Though be warned, it does not yet grant thee the power to drag and drop them as thou mayest desire. Yet, the same plumbing that underpins this work shall remain steadfast. Behold, the majority of this undertaking concerns the elevation of the RequestMoveContent event from the TerminalPage to the very summit of the Monarch. From thence, a great AttachContent method shall descend back to the lowest depths. Furthermore, there are minor revisions to TermControl that shall enable thee to better detach the content and attach it to a new one._ This is the most important part of the tab tear-out saga. This PR enables the user to move tabs and panes between windows using pre-defined actions. It does _not_ enable the user to drag/drop them yet, but the same fundamental plumbing will still apply. Most of the PR is plumbing the `RequestMoveContent` event up from the `TerminalPage` up to the `Monarch`, and then plumbing an `AttachContent` method back down. There are also small changes to `TermControl` to better support detaching the content and attaching to a new one. For testing, I recommend: ```json { "keys": "f1", "command": { "action": "moveTab", "window": "1" } }, { "keys": "f2", "command": { "action": "moveTab", "window": "2" } }, { "keys": "f3", "command": { "action": "movePane", "window": "1" } }, { "keys": "f4", "command": { "action": "movePane", "window": "2" } }, { "keys": "shift+f3", "command": { "action": "movePane", "window": "1", "index": 3 } }, { "keys": "shift+f4", "command": { "action": "movePane", "window": "2", "index": 3 } }, ``` * Related to #1256 * Related to #5000 --------- Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2023-03-30 09:37:53 -05:00
// after all current engines are done painting).
//
// Simply disabling the UIA engine is not enough, because it's
// possible that it had already started presenting here.
LOG_IF_FAILED(_uiaEngine->Disable());
_core->DetachUiaEngine(_uiaEngine.get());
}
_core->Detach();
}
void ControlInteractivity::AttachToNewControl(const Microsoft::Terminal::Control::IKeyBindings& keyBindings)
{
_core->AttachToNewControl(keyBindings);
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
// Method Description:
// - Updates our internal settings. These settings should be
// interactivity-specific. Right now, we primarily update _rowsToScroll
// with the current value of SPI_GETWHEELSCROLLLINES.
// Arguments:
// - <none>
// Return Value:
// - <none>
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
void ControlInteractivity::UpdateSettings()
{
_updateSystemParameterSettings();
}
void ControlInteractivity::Initialize()
{
_updateSystemParameterSettings();
// import value from WinUser (convert from milli-seconds to micro-seconds)
_multiClickTimer = GetDoubleClickTime() * 1000;
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
Control::ControlCore ControlInteractivity::Core()
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
return *_core;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
Introduce a ContentManager helper (#14851) ## Summary _Thus we come to the introduction of a new servant, the `ContentManager`, a singular entity that serves at the behest of the `emperor`. It is its charge to keep track of all `TermControl` instances created by the windows, for each window must seek its blessing before calling forth such an instance._ _With the aid of the `ContentManager`, the `TermControl` shall now be traced by the hand of fate through the use of unique identifying marks, known as `GUID`s. Yet, its purpose remains yet unknown, for it is merely a waypoint upon the journey yet to come._ _This act of bridging also brings a change to the handling of events within the `TermControl`. This change shall see the addition of a revoker, similar to the manner in which the `AppHost` hath employed it, to the `TermControl`. Additionally, there is a new layer of indirection between the `ControlCore` and the `App` layer, making ready for the day when the `TermControl` may be repositioned and re-parented with ease._ _Consider this but a trivial act, a mere shadow of things yet to come, for its impact shall be felt but briefly, like the passing of a gentle breeze._ Related to #5000 Related to #1256 # Detailed description This PR is another small bridge PR between the big work in #14843, and the PR that will enable panes to move between windows. This introduces a new class, called `ContentManager`. This is a global singleton object, owned by the emperor. Whenever a window wants to instantiate a new `TermControl`, it must ask the ContentManager to give it one. This allows the ContentManager to track each "content" by GUID. That's it. We don't do anything with them in this PR by itself, we just track them. This also includes a small change to the way TermControl events are handled. It adds an `AppHost`-like revoker struct, and weak_ref's all the handlers. We also add a layer of indirection between the ControlCore's raising of events and the App layer's handling. This will make reparenting content easier in the future. This is a pretty trivial change which shouldn't have any major side effects. Consider it exposition of the things to come. It's intentionally small to try and keep the reviews more managable.
2023-03-22 12:11:44 -05:00
void ControlInteractivity::Close()
{
Replace usages of `TYPED_EVENT` with `til::event` (#16837) This PR automagically finds and replaces all[^1] usages of our TYPED_EVENT macro with `til::event`. Benefits include: * less macro magic * editors are more easily able to figure out the relationship between `til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this, &Bar::FooHandler})` (whereas before the relationship between `_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by vscode & sublime. Other find & replace work that had to be done: * I added the `til::typed_event<>` == `<IInspectable, IInspectable>` thing from #16170, since that is goodness * I actually fixed `til::property_changed_event`, so you can use that for your property changed events. They're all the same anyways. * events had to come before `WINRT_PROPERTY`s, since the latter macro leaves us in a `private:` block * `Pane::SetupChildCloseHandlers` I had to swap _back_, because the script thought that was an event 🤦 * `ProfileViewModel::DeleteProfile` had to be renamed `DeleteProfileRequested`, since there was already a `DeleteProfile` method on it. * WindowManager.cpp was directly wiring up it's `winrt::event`s to the monarch & peasant. That doesn't work with `til::event`s and I'm kinda surprised it ever did <details> <summary>The script in question</summary> ```py import os import re def replace_in_file(file_path, file_name): with open(file_path, 'r', encoding="utf8") as file: content = file.read() found_matches = False # Define the pattern for matching pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);' event_matches = re.findall(pattern, content) if event_matches: found_matches = True print(f'found events in {file_path}:') for match in event_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');' new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);' typed_matches = re.findall(typed_event_pattern, content) if typed_matches: found_matches = True print(f'found typed_events in {file_path}:') for match in typed_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'TYPED_EVENT({name}, {args});' was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" ) new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};" print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) handlers_pattern = r'_(\w+)Handlers\(' handler_matches = re.findall(handlers_pattern, content) if handler_matches: found_matches = True print(f'found handlers in {file_path}:') for match in handler_matches: name = match if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'_{name}Handlers(' new_declaration = f'{name}.raise(' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) if found_matches: with open(file_path, 'w', encoding="utf8") as file: file.write(content) def find_and_replace(directory): for root, dirs, files in os.walk(directory): if 'Generated Files' in dirs: dirs.remove('Generated Files') # Exclude the "Generated Files" directory for file in files: if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'): file_path = os.path.join(root, file) try: replace_in_file(file_path, file) except Exception as e: print(f"error reading {file_path}") if file == "TermControl.cpp": print(e) # raise e # Replace in files within a specific directory directory_path = 'D:\\dev\\public\\terminal\\src' find_and_replace(directory_path) ``` </details> [^1]: there are other macros we use that were also using this macro, those weren't replaced. --------- Co-authored-by: Dustin Howett <duhowett@microsoft.com> Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2024-03-20 09:02:26 -07:00
Closed.raise(*this, nullptr);
Introduce a ContentManager helper (#14851) ## Summary _Thus we come to the introduction of a new servant, the `ContentManager`, a singular entity that serves at the behest of the `emperor`. It is its charge to keep track of all `TermControl` instances created by the windows, for each window must seek its blessing before calling forth such an instance._ _With the aid of the `ContentManager`, the `TermControl` shall now be traced by the hand of fate through the use of unique identifying marks, known as `GUID`s. Yet, its purpose remains yet unknown, for it is merely a waypoint upon the journey yet to come._ _This act of bridging also brings a change to the handling of events within the `TermControl`. This change shall see the addition of a revoker, similar to the manner in which the `AppHost` hath employed it, to the `TermControl`. Additionally, there is a new layer of indirection between the `ControlCore` and the `App` layer, making ready for the day when the `TermControl` may be repositioned and re-parented with ease._ _Consider this but a trivial act, a mere shadow of things yet to come, for its impact shall be felt but briefly, like the passing of a gentle breeze._ Related to #5000 Related to #1256 # Detailed description This PR is another small bridge PR between the big work in #14843, and the PR that will enable panes to move between windows. This introduces a new class, called `ContentManager`. This is a global singleton object, owned by the emperor. Whenever a window wants to instantiate a new `TermControl`, it must ask the ContentManager to give it one. This allows the ContentManager to track each "content" by GUID. That's it. We don't do anything with them in this PR by itself, we just track them. This also includes a small change to the way TermControl events are handled. It adds an `AppHost`-like revoker struct, and weak_ref's all the handlers. We also add a layer of indirection between the ControlCore's raising of events and the App layer's handling. This will make reparenting content easier in the future. This is a pretty trivial change which shouldn't have any major side effects. Consider it exposition of the things to come. It's intentionally small to try and keep the reviews more managable.
2023-03-22 12:11:44 -05:00
if (_core)
{
_core->Close();
}
}
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Method Description:
// - Returns the number of clicks that occurred (double and triple click support).
// Every call to this function registers a click.
// Arguments:
// - clickPos: the (x,y) position of a given cursor (i.e.: mouse cursor).
// NOTE: origin (0,0) is top-left.
// - clickTime: the timestamp that the click occurred
// Return Value:
// - if the click is in the same position as the last click and within the timeout, the number of clicks within that time window
// - otherwise, 1
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
unsigned int ControlInteractivity::_numberOfClicks(Core::Point clickPos,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
Timestamp clickTime)
{
// if click occurred at a different location or past the multiClickTimer...
Timestamp delta;
THROW_IF_FAILED(UInt64Sub(clickTime, _lastMouseClickTimestamp, &delta));
if (clickPos != _lastMouseClickPos || delta > _multiClickTimer)
{
_multiClickCounter = 1;
}
else
{
_multiClickCounter++;
}
_lastMouseClickTimestamp = clickTime;
_lastMouseClickPos = clickPos;
return _multiClickCounter;
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
void ControlInteractivity::GotFocus()
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
if (_uiaEngine.get())
{
THROW_IF_FAILED(_uiaEngine->Enable());
}
Allow windows created by console apps to appear above the Terminal (#12799) ## Window shenanigans, part the third: Hooks the Terminal's focus state up to the underlying ConPTY. This is LOAD BEARING for allowing windows created by console applications to bring themselves to the foreground. We're using the [FocusIn/FocusOut](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-FocusIn_FocusOut) sequences to communicate to ConPTY when a control gains/loses focus. Theoretically, other terminals could do this as well. ## References #11682 tracks _real_ support for this sequence in Console & conpty. When we do that, we should consider even if a client application disables this mode, the Terminal & conpty should always request this from the hosting terminal (and just ignore internally to ConPTY). See also #12515, #12526, which are the other two parts of this effort. This was tested with all three merged together, and they worked beautifully for all our scenarios. They are kept separate for ease of review. ## PR Checklist * [x] This is prototype 3 for #2988 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments This allows windows spawned by console processes to bring themselves to the foreground _when the console is focused_. (Historically, this is also called in the WndProc, when focus changes). Notably, before this, ConPTY was _never_ focused, so windows could never bring themselves to the foreground when run from a ConPTY console. We're not blanket granting the SetForeground right to all console apps when run in ConPTY. It's the responsibility of the hosting terminal emulator to always tell ConPTY when a particular instance is focused. ## Validation Steps Performed (gif below)
2022-04-19 14:19:59 -05:00
_core->GotFocus();
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
_updateSystemParameterSettings();
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
void ControlInteractivity::LostFocus()
{
if (_uiaEngine.get())
{
THROW_IF_FAILED(_uiaEngine->Disable());
}
Allow windows created by console apps to appear above the Terminal (#12799) ## Window shenanigans, part the third: Hooks the Terminal's focus state up to the underlying ConPTY. This is LOAD BEARING for allowing windows created by console applications to bring themselves to the foreground. We're using the [FocusIn/FocusOut](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-FocusIn_FocusOut) sequences to communicate to ConPTY when a control gains/loses focus. Theoretically, other terminals could do this as well. ## References #11682 tracks _real_ support for this sequence in Console & conpty. When we do that, we should consider even if a client application disables this mode, the Terminal & conpty should always request this from the hosting terminal (and just ignore internally to ConPTY). See also #12515, #12526, which are the other two parts of this effort. This was tested with all three merged together, and they worked beautifully for all our scenarios. They are kept separate for ease of review. ## PR Checklist * [x] This is prototype 3 for #2988 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments This allows windows spawned by console processes to bring themselves to the foreground _when the console is focused_. (Historically, this is also called in the WndProc, when focus changes). Notably, before this, ConPTY was _never_ focused, so windows could never bring themselves to the foreground when run from a ConPTY console. We're not blanket granting the SetForeground right to all console apps when run in ConPTY. It's the responsibility of the hosting terminal emulator to always tell ConPTY when a particular instance is focused. ## Validation Steps Performed (gif below)
2022-04-19 14:19:59 -05:00
_core->LostFocus();
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
}
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Method Description
// - Updates internal params based on system parameters
void ControlInteractivity::_updateSystemParameterSettings() noexcept
{
if (!SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &_rowsToScroll, 0))
{
LOG_LAST_ERROR();
// If SystemParametersInfoW fails, which it shouldn't, fall back to
// Windows' default value.
_rowsToScroll = 3;
}
}
// Method Description:
// - Given a copy-able selection, get the selected text from the buffer and send it to the
// Windows Clipboard (CascadiaWin32:main.cpp).
// Arguments:
// - singleLine: collapse all of the text to one line
2024-11-20 08:03:04 -08:00
// - withControlSequences: if enabled, the copied plain text contains color/style ANSI escape codes from the selection
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr
// if we should defer which formats are copied to the global setting
bool ControlInteractivity::CopySelectionToClipboard(bool singleLine,
2024-11-20 08:03:04 -08:00
bool withControlSequences,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
const Windows::Foundation::IReference<CopyFormat>& formats)
{
if (_core)
{
// Return false if there's no selection to copy. If there's no
// selection, returning false will indicate that the actions that
// triggered this should _not_ be marked as handled, so ctrl+c
// without a selection can still send ^C
if (!_core->HasSelection())
{
return false;
}
// Mark the current selection as copied
_selectionNeedsToBeCopied = false;
2024-11-20 08:03:04 -08:00
return _core->CopySelectionToClipboard(singleLine, withControlSequences, formats);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
return false;
}
// Method Description:
// - Initiate a paste operation.
void ControlInteractivity::RequestPasteTextFromClipboard()
{
auto args = winrt::make<PasteFromClipboardEventArgs>(
[core = _core](const winrt::hstring& wstr) {
core->PasteText(wstr);
},
_core->BracketedPasteEnabled());
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// send paste event up to TermApp
Replace usages of `TYPED_EVENT` with `til::event` (#16837) This PR automagically finds and replaces all[^1] usages of our TYPED_EVENT macro with `til::event`. Benefits include: * less macro magic * editors are more easily able to figure out the relationship between `til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this, &Bar::FooHandler})` (whereas before the relationship between `_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by vscode & sublime. Other find & replace work that had to be done: * I added the `til::typed_event<>` == `<IInspectable, IInspectable>` thing from #16170, since that is goodness * I actually fixed `til::property_changed_event`, so you can use that for your property changed events. They're all the same anyways. * events had to come before `WINRT_PROPERTY`s, since the latter macro leaves us in a `private:` block * `Pane::SetupChildCloseHandlers` I had to swap _back_, because the script thought that was an event 🤦 * `ProfileViewModel::DeleteProfile` had to be renamed `DeleteProfileRequested`, since there was already a `DeleteProfile` method on it. * WindowManager.cpp was directly wiring up it's `winrt::event`s to the monarch & peasant. That doesn't work with `til::event`s and I'm kinda surprised it ever did <details> <summary>The script in question</summary> ```py import os import re def replace_in_file(file_path, file_name): with open(file_path, 'r', encoding="utf8") as file: content = file.read() found_matches = False # Define the pattern for matching pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);' event_matches = re.findall(pattern, content) if event_matches: found_matches = True print(f'found events in {file_path}:') for match in event_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');' new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);' typed_matches = re.findall(typed_event_pattern, content) if typed_matches: found_matches = True print(f'found typed_events in {file_path}:') for match in typed_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'TYPED_EVENT({name}, {args});' was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" ) new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};" print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) handlers_pattern = r'_(\w+)Handlers\(' handler_matches = re.findall(handlers_pattern, content) if handler_matches: found_matches = True print(f'found handlers in {file_path}:') for match in handler_matches: name = match if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'_{name}Handlers(' new_declaration = f'{name}.raise(' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) if found_matches: with open(file_path, 'w', encoding="utf8") as file: file.write(content) def find_and_replace(directory): for root, dirs, files in os.walk(directory): if 'Generated Files' in dirs: dirs.remove('Generated Files') # Exclude the "Generated Files" directory for file in files: if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'): file_path = os.path.join(root, file) try: replace_in_file(file_path, file) except Exception as e: print(f"error reading {file_path}") if file == "TermControl.cpp": print(e) # raise e # Replace in files within a specific directory directory_path = 'D:\\dev\\public\\terminal\\src' find_and_replace(directory_path) ``` </details> [^1]: there are other macros we use that were also using this macro, those weren't replaced. --------- Co-authored-by: Dustin Howett <duhowett@microsoft.com> Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2024-03-20 09:02:26 -07:00
PasteFromClipboard.raise(*this, std::move(args));
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
void ControlInteractivity::PointerPressed(Control::MouseButtonState buttonState,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
const unsigned int pointerUpdateKind,
const uint64_t timestamp,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
const Core::Point pixelPosition)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
// Un-rounded coordinates; we only round when selecting text
const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }, false);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
const auto altEnabled = modifiers.IsAltPressed();
const auto shiftEnabled = modifiers.IsShiftPressed();
const auto ctrlEnabled = modifiers.IsCtrlPressed();
// GH#9396: we prioritize hyper-link over VT mouse events
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
auto hyperlink = _core->GetHyperlink(terminalPosition.to_core_point());
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
if (WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown) &&
ctrlEnabled &&
!hyperlink.empty())
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
const auto clickCount = _numberOfClicks(pixelPosition, timestamp);
// Handle hyper-link only on the first click to prevent multiple activations
if (clickCount == 1)
{
_hyperlinkHandler(hyperlink);
}
}
else if (_canSendVTMouseInput(modifiers))
{
_sendMouseEventHelper(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
else if (WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown))
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
const auto clickCount = _numberOfClicks(pixelPosition, timestamp);
// This formula enables the number of clicks to cycle properly
// between single-, double-, and triple-click. To increase the
// number of acceptable click states, simply increment
// MAX_CLICK_COUNT and add another if-statement
const auto multiClickMapper = clickCount > MAX_CLICK_COUNT ? ((clickCount + MAX_CLICK_COUNT - 1) % MAX_CLICK_COUNT) + 1 : clickCount;
// Capture the position of the first click when no selection is active
if (multiClickMapper == 1)
{
_singleClickTouchdownPos = pixelPosition;
if (!_core->HasSelection())
{
_lastMouseClickPosNoSelection = pixelPosition;
}
}
const auto isOnOriginalPosition = _lastMouseClickPosNoSelection == pixelPosition;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Rounded coordinates for text selection
_core->LeftClickOnTerminal(_getTerminalPosition(til::point{ pixelPosition }, true),
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
multiClickMapper,
altEnabled,
shiftEnabled,
isOnOriginalPosition,
_selectionNeedsToBeCopied);
if (_core->HasSelection())
{
// GH#9787: if selection is active we don't want to track the touchdown position
// so that dragging the mouse will extend the selection rather than starting the new one
_singleClickTouchdownPos = std::nullopt;
}
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
else if (WI_IsFlagSet(buttonState, MouseButtonState::IsRightButtonDown))
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
if (_core->Settings().RightClickContextMenu())
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
// Let the core know we're about to open a menu here. It has
// some separate conditional logic based on _where_ the user
// wanted to open the menu.
_core->AnchorContextMenu(terminalPosition);
auto contextArgs = winrt::make<ContextMenuRequestedEventArgs>(til::point{ pixelPosition }.to_winrt_point());
Replace usages of `TYPED_EVENT` with `til::event` (#16837) This PR automagically finds and replaces all[^1] usages of our TYPED_EVENT macro with `til::event`. Benefits include: * less macro magic * editors are more easily able to figure out the relationship between `til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this, &Bar::FooHandler})` (whereas before the relationship between `_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by vscode & sublime. Other find & replace work that had to be done: * I added the `til::typed_event<>` == `<IInspectable, IInspectable>` thing from #16170, since that is goodness * I actually fixed `til::property_changed_event`, so you can use that for your property changed events. They're all the same anyways. * events had to come before `WINRT_PROPERTY`s, since the latter macro leaves us in a `private:` block * `Pane::SetupChildCloseHandlers` I had to swap _back_, because the script thought that was an event 🤦 * `ProfileViewModel::DeleteProfile` had to be renamed `DeleteProfileRequested`, since there was already a `DeleteProfile` method on it. * WindowManager.cpp was directly wiring up it's `winrt::event`s to the monarch & peasant. That doesn't work with `til::event`s and I'm kinda surprised it ever did <details> <summary>The script in question</summary> ```py import os import re def replace_in_file(file_path, file_name): with open(file_path, 'r', encoding="utf8") as file: content = file.read() found_matches = False # Define the pattern for matching pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);' event_matches = re.findall(pattern, content) if event_matches: found_matches = True print(f'found events in {file_path}:') for match in event_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');' new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);' typed_matches = re.findall(typed_event_pattern, content) if typed_matches: found_matches = True print(f'found typed_events in {file_path}:') for match in typed_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'TYPED_EVENT({name}, {args});' was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" ) new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};" print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) handlers_pattern = r'_(\w+)Handlers\(' handler_matches = re.findall(handlers_pattern, content) if handler_matches: found_matches = True print(f'found handlers in {file_path}:') for match in handler_matches: name = match if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'_{name}Handlers(' new_declaration = f'{name}.raise(' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) if found_matches: with open(file_path, 'w', encoding="utf8") as file: file.write(content) def find_and_replace(directory): for root, dirs, files in os.walk(directory): if 'Generated Files' in dirs: dirs.remove('Generated Files') # Exclude the "Generated Files" directory for file in files: if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'): file_path = os.path.join(root, file) try: replace_in_file(file_path, file) except Exception as e: print(f"error reading {file_path}") if file == "TermControl.cpp": print(e) # raise e # Replace in files within a specific directory directory_path = 'D:\\dev\\public\\terminal\\src' find_and_replace(directory_path) ``` </details> [^1]: there are other macros we use that were also using this macro, those weren't replaced. --------- Co-authored-by: Dustin Howett <duhowett@microsoft.com> Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2024-03-20 09:02:26 -07:00
ContextMenuRequested.raise(*this, contextArgs);
}
else
{
// Try to copy the text and clear the selection
2024-11-20 08:03:04 -08:00
const auto successfulCopy = CopySelectionToClipboard(shiftEnabled, false, nullptr);
_core->ClearSelection();
if (_core->CopyOnSelect() || !successfulCopy)
{
// CopyOnSelect: right click always pastes!
// Otherwise: no selection --> paste
RequestPasteTextFromClipboard();
}
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
}
}
void ControlInteractivity::TouchPressed(const winrt::Windows::Foundation::Point contactPoint)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
_touchAnchor = contactPoint;
}
bool ControlInteractivity::PointerMoved(Control::MouseButtonState buttonState,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const bool focused,
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
const Core::Point pixelPosition,
const bool pointerPressedInBounds)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }, false);
// Returning true from this function indicates that the caller should do no further processing of this movement.
bool handledCompletely = false;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Short-circuit isReadOnly check to avoid warning dialog
if (focused && !_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers))
{
_sendMouseEventHelper(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
handledCompletely = true;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
// GH#4603 - don't modify the selection if the pointer press didn't
// actually start _in_ the control bounds. Case in point - someone drags
// a file into the bounds of the control. That shouldn't send the
// selection into space.
else if (focused && pointerPressedInBounds && WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown))
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
if (_singleClickTouchdownPos)
{
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
// Figure out if the user's moved a 1/4th of a cell's smaller axis
// (practically always the width) away from the clickdown point.
const auto fontSizeInDips = _core->FontSizeInDips();
const auto touchdownPoint = *_singleClickTouchdownPos;
const auto dx = pixelPosition.X - touchdownPoint.X;
const auto dy = pixelPosition.Y - touchdownPoint.Y;
const auto w = fontSizeInDips.Width;
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
const auto distanceSquared = dx * dx + dy * dy;
const auto maxDistanceSquared = w * w / 16; // (w / 4)^2
if (distanceSquared >= maxDistanceSquared)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
// GH#9955.c: Make sure to use the terminal location of the
// _touchdown_ point here. We want to start the selection
// from where the user initially clicked, not where they are
// now.
Make selection an exclusive range (#18106) Selection is generally stored as an inclusive start and end. This PR makes the end exclusive which now allows degenerate selections, namely in mark mode. This also modifies mouse selection to round to the nearest cell boundary (see #5099) and improves word boundaries to be a bit more modern and make sense for degenerate selections (similar to #15787). Closes #5099 Closes #13447 Closes #17892 ## Detailed Description of the Pull Request / Additional comments - Buffer, Viewport, and Point - Introduced a few new functions here to find word boundaries, delimiter class runs, and glyph boundaries. - 📝These new functions should be able to replace a few other functions (i.e. `GetWordStart` --> `GetWordStart2`). That migration is going to be a part of #4423 to reduce the risk of breaking UIA. - Viewport: added a few functions to handle navigating the _exclusive_ bounds (namely allowing RightExclusive as a position for buffer coordinates). This is important for selection to be able to highlight the entire line. - 📝`BottomInclusiveRightExclusive()` will replace `EndExclusive` in the UIA code - Point: `iterate_rows_exclusive` is similar to `iterate_rows`, except it has handling for RightExclusive - Renderer - Use `iterate_rows_exclusive` for proper handling (this actually fixed a lot of our issues) - Remove some workarounds in `_drawHighlighted` (this is a boundary where we got inclusive coords and made them exclusive, but now we don't need that!) - Terminal - fix selection marker rendering - `_ConvertToBufferCell()`: add a param to allow for RightExclusive or clamp it to RightInclusive (original behavior). Both are useful! - Use new `GetWordStart2` and `GetWordEnd2` to improve word boundaries and make them feel right now that the selection an exclusive range. - Convert a few `IsInBounds` --> `IsInExclusiveBounds` for safety and correctness - Add `TriggerSelection` to `SelectNewRegion` - 📝 We normally called `TriggerSelection` in a different layer, but it turns out, UIA's `Select` function wouldn't actually update the renderer. Whoops! This fixes that. - TermControl - `_getTerminalPosition` now has a new param to round to the nearest cell (see #5099) - UIA - `TermControlUIAProvider::GetSelectionRange` no need to convert from inclusive range to exclusive range anymore! - `TextBuffer::GetPlainText` now works on an exclusive range, so no need to convert the range anymore! ## Validation Steps Performed This fundamental change impacts a lot of scenarios: - ✅Rendering selections - ✅Selection markers - ✅Copy text - ✅Session restore - ✅Mark mode navigation (i.e. character, word, line, buffer) - ✅Mouse selection (i.e. click+drag, shift+click, multi-click, alt+click) - ✅Hyperlinks (interaction and rendering) - ✅Accessibility (i.e. get selection, movement, text extraction, selecting text) - [ ] Prev/Next Command/Output (untested) - ✅Unit tests ## Follow-ups - Refs #4423 - Now that selection and UIA are both exclusive ranges, it should be a lot easier to deduplicate code between selection and UIA. We should be able to remove `EndExclusive` as well when we do that. This'll also be an opportunity to modernize that code and use more `til` classes.
2025-01-28 14:54:49 -08:00
auto termPos = _getTerminalPosition(til::point{ touchdownPoint }, false);
if (dx < 0)
{
// _getTerminalPosition(_, false) will floor the x-value,
// meaning that the selection will start on the left-side
// of the current cell. This is great if the use is dragging
// towards the right.
// If the user is dragging towards the left (dx < 0),
// we want to select the current cell, so place the anchor on the right
// side of the current cell.
termPos.x++;
}
_core->SetSelectionAnchor(termPos);
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// stop tracking the touchdown point
_singleClickTouchdownPos = std::nullopt;
}
}
SetEndSelectionPoint(pixelPosition);
}
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
_core->SetHoveredCell(terminalPosition.to_core_point());
return handledCompletely;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
void ControlInteractivity::TouchMoved(const winrt::Windows::Foundation::Point newTouchPoint,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
const bool focused)
{
if (focused &&
_touchAnchor)
{
const auto anchor = _touchAnchor.value();
// Our actualFont's size is in pixels, convert to DIPs, which the
// rest of the Points here are in.
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);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Start viewport scroll after we've moved more than a half row of text
if (std::abs(dy) > (fontSizeInDips.Height / 2.0f))
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
// 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;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
const auto currentOffset = _core->ScrollOffset();
const auto newValue = numRows + currentOffset;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Update the Core's viewport position, and raise a
// ScrollPositionChanged event to update the scrollbar
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
UpdateScrollbar(newValue);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Use this point as our new scroll anchor.
_touchAnchor = newTouchPoint;
}
}
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
void ControlInteractivity::PointerReleased(Control::MouseButtonState buttonState,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
const Core::Point pixelPosition)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
Make selection an exclusive range (#18106) Selection is generally stored as an inclusive start and end. This PR makes the end exclusive which now allows degenerate selections, namely in mark mode. This also modifies mouse selection to round to the nearest cell boundary (see #5099) and improves word boundaries to be a bit more modern and make sense for degenerate selections (similar to #15787). Closes #5099 Closes #13447 Closes #17892 ## Detailed Description of the Pull Request / Additional comments - Buffer, Viewport, and Point - Introduced a few new functions here to find word boundaries, delimiter class runs, and glyph boundaries. - 📝These new functions should be able to replace a few other functions (i.e. `GetWordStart` --> `GetWordStart2`). That migration is going to be a part of #4423 to reduce the risk of breaking UIA. - Viewport: added a few functions to handle navigating the _exclusive_ bounds (namely allowing RightExclusive as a position for buffer coordinates). This is important for selection to be able to highlight the entire line. - 📝`BottomInclusiveRightExclusive()` will replace `EndExclusive` in the UIA code - Point: `iterate_rows_exclusive` is similar to `iterate_rows`, except it has handling for RightExclusive - Renderer - Use `iterate_rows_exclusive` for proper handling (this actually fixed a lot of our issues) - Remove some workarounds in `_drawHighlighted` (this is a boundary where we got inclusive coords and made them exclusive, but now we don't need that!) - Terminal - fix selection marker rendering - `_ConvertToBufferCell()`: add a param to allow for RightExclusive or clamp it to RightInclusive (original behavior). Both are useful! - Use new `GetWordStart2` and `GetWordEnd2` to improve word boundaries and make them feel right now that the selection an exclusive range. - Convert a few `IsInBounds` --> `IsInExclusiveBounds` for safety and correctness - Add `TriggerSelection` to `SelectNewRegion` - 📝 We normally called `TriggerSelection` in a different layer, but it turns out, UIA's `Select` function wouldn't actually update the renderer. Whoops! This fixes that. - TermControl - `_getTerminalPosition` now has a new param to round to the nearest cell (see #5099) - UIA - `TermControlUIAProvider::GetSelectionRange` no need to convert from inclusive range to exclusive range anymore! - `TextBuffer::GetPlainText` now works on an exclusive range, so no need to convert the range anymore! ## Validation Steps Performed This fundamental change impacts a lot of scenarios: - ✅Rendering selections - ✅Selection markers - ✅Copy text - ✅Session restore - ✅Mark mode navigation (i.e. character, word, line, buffer) - ✅Mouse selection (i.e. click+drag, shift+click, multi-click, alt+click) - ✅Hyperlinks (interaction and rendering) - ✅Accessibility (i.e. get selection, movement, text extraction, selecting text) - [ ] Prev/Next Command/Output (untested) - ✅Unit tests ## Follow-ups - Refs #4423 - Now that selection and UIA are both exclusive ranges, it should be a lot easier to deduplicate code between selection and UIA. We should be able to remove `EndExclusive` as well when we do that. This'll also be an opportunity to modernize that code and use more `til` classes.
2025-01-28 14:54:49 -08:00
const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }, false);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Short-circuit isReadOnly check to avoid warning dialog
if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers))
{
_sendMouseEventHelper(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
return;
}
// Only a left click release when copy on select is active should perform a copy.
// Right clicks and middle clicks should not need to do anything when released.
const auto isLeftMouseRelease = pointerUpdateKind == WM_LBUTTONUP;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
if (_core->CopyOnSelect() &&
isLeftMouseRelease &&
_selectionNeedsToBeCopied)
{
Miscellaneous bug fixes for Mark Mode (#13358) ## Summary of the Pull Request 1. [copy on select] when manually copying text (i.e. kbd or right-click) while in mark/quick-edit mode, we now dismiss the selection. 2. `Enter` is now bound to copy by default. - This works very well with mark mode and provides a more consistent behavior with conhost's selection experience overall. - "why not hardcode `Enter` as a way to copy when in mark mode?" - In an effort to make this as configurable as possible, I decided to make it a configurable keybinding, but am open to suggestions. 3. selection markers a. we now hide the selection markers when multi-clicking the terminal. b. selection markers are now properly shown when a single cell selection exists - Prior to this PR, any single cell selection would display both markers. Now, we actually track which endpoint we're moving and display the appropriate one. 4. ensures that when you use keyboard selection to move past the top/bottom of the scroll area, we clamp it to the origin/bottom-right respectively. The fix is also better here in that it provides consistent behavior across all of the `_MoveByX` functions. 5. adds `toggleBlockSelection` to the schema ## References #13053 ## Validation Steps Performed Did a whole flowchart of expected behavior with copy on select: - enable `copyOnSelect` - make a selection with the mouse - ✅ right-click should copy the text --> clear the selection --> paste - use keyboard selection to quick-edit the existing selection - ✅ `copy` action should clear the selection - ✅ right-click should copy the text --> clear the selection --> paste Played with selection markers a bit in mark mode and quick edit mode. Markers are updating appropriately.
2022-06-30 18:07:07 -07:00
// IMPORTANT!
// DO NOT clear the selection here!
// Otherwise, the selection will be cleared immediately after you make it.
2024-11-20 08:03:04 -08:00
CopySelectionToClipboard(false, false, nullptr);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
_singleClickTouchdownPos = std::nullopt;
}
void ControlInteractivity::TouchReleased()
{
_touchAnchor = std::nullopt;
}
// Method Description:
// - Actually handle a scrolling event, whether from a mouse wheel or a
// touchpad scroll. Depending upon what modifier keys are pressed,
// different actions will take place.
// * Attempts to first dispatch the mouse scroll as a VT event
// * If Ctrl+Shift are pressed, then attempts to change our opacity
// * If just Ctrl is pressed, we'll attempt to "zoom" by changing our font size
// * Otherwise, just scrolls the content of the viewport
// Arguments:
// - point: the location of the mouse during this event
// - modifiers: The modifiers pressed during this event, in the form of a VirtualKeyModifiers
// - delta: the mouse wheel delta that triggered this event.
bool ControlInteractivity::MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const int32_t delta,
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
const Core::Point pixelPosition,
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
const Control::MouseButtonState buttonState)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }, false);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Short-circuit isReadOnly check to avoid warning dialog.
//
// GH#3321: Alternate scroll mode is a special type of mouse input mode
// where the terminal sends arrow keys when the user mouse wheels, but
// the client app doesn't care for other mouse input. It's tracked
// separately from _canSendVTMouseInput.
if (!_core->IsInReadOnlyMode() &&
(_canSendVTMouseInput(modifiers) || _shouldSendAlternateScroll(modifiers, delta)))
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
// Most mouse event handlers call
// _trySendMouseEvent(point);
// here with a PointerPoint. However, as of #979, we don't have a
// PointerPoint to work with. So, we're just going to do a
// mousewheel event manually
return _sendMouseEventHelper(terminalPosition,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
WM_MOUSEWHEEL,
modifiers,
::base::saturated_cast<short>(delta),
buttonState);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
const auto ctrlPressed = modifiers.IsCtrlPressed();
const auto shiftPressed = modifiers.IsShiftPressed();
if (ctrlPressed && shiftPressed && _core->Settings().ScrollToChangeOpacity())
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
_mouseTransparencyHandler(delta);
}
else if (ctrlPressed && !shiftPressed && _core->Settings().ScrollToZoom())
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
_mouseZoomHandler(delta);
}
else
{
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
_mouseScrollHandler(delta, pixelPosition, WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown));
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
return false;
}
// Method Description:
// - Adjust the opacity of the acrylic background in response to a mouse
// scrolling event.
// Arguments:
// - mouseDelta: the mouse wheel delta that triggered this event.
void ControlInteractivity::_mouseTransparencyHandler(const int32_t mouseDelta) const
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
// Transparency is on a scale of [0.0,1.0], so only increment by .01.
const auto effectiveDelta = mouseDelta < 0 ? -.01f : .01f;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
_core->AdjustOpacity(effectiveDelta);
}
// Method Description:
// - Adjust the font size of the terminal in response to a mouse scrolling
// event.
// Arguments:
// - mouseDelta: the mouse wheel delta that triggered this event.
void ControlInteractivity::_mouseZoomHandler(const int32_t mouseDelta) const
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
const auto fontDelta = mouseDelta < 0 ? -1.0f : 1.0f;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
_core->AdjustFontSize(fontDelta);
}
// Method Description:
// - Scroll the visible viewport in response to a mouse wheel event.
// Arguments:
// - mouseDelta: the mouse wheel delta that triggered this event.
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
// - pixelPosition: the location of the mouse during this event
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// - isLeftButtonPressed: true iff the left mouse button was pressed during this event.
void ControlInteractivity::_mouseScrollHandler(const int32_t mouseDelta,
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
const Core::Point pixelPosition,
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
const bool isLeftButtonPressed)
{
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
// GH#9955.b: Start scrolling from our internal scrollbar position. This
// lets us accumulate fractional numbers of rows to scroll with each
// event. Especially for precision trackpads, we might be getting scroll
// deltas smaller than a single row, but we still want lots of those to
// accumulate.
//
// At the start, let's compare what we _think_ the scrollbar is, with
// what it should be. It's possible the core scrolled out from
// 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 currentCoreRow = _core->ScrollOffset();
const auto currentOffset = currentInternalRow == currentCoreRow ?
_internalScrollbarPosition :
currentCoreRow;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// negative = down, positive = up
// However, for us, the signs are flipped.
// With one of the precision mice, one click is always a multiple of 120 (WHEEL_DELTA),
// but the "smooth scrolling" mode results in non-int values
const auto rowDelta = mouseDelta / (-1.0f * WHEEL_DELTA);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// 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 newValue = rowsToScroll * rowDelta + currentOffset;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Update the Core's viewport position, and raise a
// ScrollPositionChanged event to update the scrollbar
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
UpdateScrollbar(newValue);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
if (isLeftButtonPressed)
{
// If user is mouse selecting and scrolls, they then point at new
// character. Make sure selection reflects that immediately.
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
SetEndSelectionPoint(pixelPosition);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
}
// Method Description:
// - Update the scroll position in such a way that should update the
// scrollbar. For example, when scrolling the buffer with the mouse or
// touch input. This will both update the Core's Terminal's buffer
// location, then also raise our own ScrollPositionChanged event.
// UserScrollViewport _won't_ raise the core's ScrollPositionChanged
// event, because it's assumed that's already being called from a context
// that knows about the change to the scrollbar. So we need to raise the
// event on our own.
// - The hosting control should make sure to listen to our own
// ScrollPositionChanged event and use that as an opportunity to update
// the location of the scrollbar.
// Arguments:
// - newValue: The new top of the viewport
// Return Value:
// - <none>
void ControlInteractivity::UpdateScrollbar(const float newValue)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
// 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()));
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
// 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);
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
if (viewTop != _core->ScrollOffset())
{
_core->UserScrollViewport(viewTop);
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
// _core->ScrollOffset() is now set to newValue
Replace usages of `TYPED_EVENT` with `til::event` (#16837) This PR automagically finds and replaces all[^1] usages of our TYPED_EVENT macro with `til::event`. Benefits include: * less macro magic * editors are more easily able to figure out the relationship between `til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this, &Bar::FooHandler})` (whereas before the relationship between `_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by vscode & sublime. Other find & replace work that had to be done: * I added the `til::typed_event<>` == `<IInspectable, IInspectable>` thing from #16170, since that is goodness * I actually fixed `til::property_changed_event`, so you can use that for your property changed events. They're all the same anyways. * events had to come before `WINRT_PROPERTY`s, since the latter macro leaves us in a `private:` block * `Pane::SetupChildCloseHandlers` I had to swap _back_, because the script thought that was an event 🤦 * `ProfileViewModel::DeleteProfile` had to be renamed `DeleteProfileRequested`, since there was already a `DeleteProfile` method on it. * WindowManager.cpp was directly wiring up it's `winrt::event`s to the monarch & peasant. That doesn't work with `til::event`s and I'm kinda surprised it ever did <details> <summary>The script in question</summary> ```py import os import re def replace_in_file(file_path, file_name): with open(file_path, 'r', encoding="utf8") as file: content = file.read() found_matches = False # Define the pattern for matching pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);' event_matches = re.findall(pattern, content) if event_matches: found_matches = True print(f'found events in {file_path}:') for match in event_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');' new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);' typed_matches = re.findall(typed_event_pattern, content) if typed_matches: found_matches = True print(f'found typed_events in {file_path}:') for match in typed_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'TYPED_EVENT({name}, {args});' was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" ) new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};" print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) handlers_pattern = r'_(\w+)Handlers\(' handler_matches = re.findall(handlers_pattern, content) if handler_matches: found_matches = True print(f'found handlers in {file_path}:') for match in handler_matches: name = match if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'_{name}Handlers(' new_declaration = f'{name}.raise(' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) if found_matches: with open(file_path, 'w', encoding="utf8") as file: file.write(content) def find_and_replace(directory): for root, dirs, files in os.walk(directory): if 'Generated Files' in dirs: dirs.remove('Generated Files') # Exclude the "Generated Files" directory for file in files: if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'): file_path = os.path.join(root, file) try: replace_in_file(file_path, file) except Exception as e: print(f"error reading {file_path}") if file == "TermControl.cpp": print(e) # raise e # Replace in files within a specific directory directory_path = 'D:\\dev\\public\\terminal\\src' find_and_replace(directory_path) ``` </details> [^1]: there are other macros we use that were also using this macro, those weren't replaced. --------- Co-authored-by: Dustin Howett <duhowett@microsoft.com> Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2024-03-20 09:02:26 -07:00
ScrollPositionChanged.raise(*this,
winrt::make<ScrollPositionChangedArgs>(_core->ScrollOffset(),
_core->ViewHeight(),
_core->BufferHeight()));
First three interactivity fixes (#9980) ## 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
2021-05-04 17:54:02 -05:00
}
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
void ControlInteractivity::_hyperlinkHandler(const std::wstring_view uri)
{
Replace usages of `TYPED_EVENT` with `til::event` (#16837) This PR automagically finds and replaces all[^1] usages of our TYPED_EVENT macro with `til::event`. Benefits include: * less macro magic * editors are more easily able to figure out the relationship between `til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this, &Bar::FooHandler})` (whereas before the relationship between `_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by vscode & sublime. Other find & replace work that had to be done: * I added the `til::typed_event<>` == `<IInspectable, IInspectable>` thing from #16170, since that is goodness * I actually fixed `til::property_changed_event`, so you can use that for your property changed events. They're all the same anyways. * events had to come before `WINRT_PROPERTY`s, since the latter macro leaves us in a `private:` block * `Pane::SetupChildCloseHandlers` I had to swap _back_, because the script thought that was an event 🤦 * `ProfileViewModel::DeleteProfile` had to be renamed `DeleteProfileRequested`, since there was already a `DeleteProfile` method on it. * WindowManager.cpp was directly wiring up it's `winrt::event`s to the monarch & peasant. That doesn't work with `til::event`s and I'm kinda surprised it ever did <details> <summary>The script in question</summary> ```py import os import re def replace_in_file(file_path, file_name): with open(file_path, 'r', encoding="utf8") as file: content = file.read() found_matches = False # Define the pattern for matching pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);' event_matches = re.findall(pattern, content) if event_matches: found_matches = True print(f'found events in {file_path}:') for match in event_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');' new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);' typed_matches = re.findall(typed_event_pattern, content) if typed_matches: found_matches = True print(f'found typed_events in {file_path}:') for match in typed_matches: name = match[0] args = match[1] if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'TYPED_EVENT({name}, {args});' was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" ) new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};" print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) handlers_pattern = r'_(\w+)Handlers\(' handler_matches = re.findall(handlers_pattern, content) if handler_matches: found_matches = True print(f'found handlers in {file_path}:') for match in handler_matches: name = match if name == "newConnection" and file_name == "ConptyConnection.cpp": # This one is special continue old_declaration = f'_{name}Handlers(' new_declaration = f'{name}.raise(' print(f' {old_declaration} -> {new_declaration}') content = content.replace(old_declaration, new_declaration) if found_matches: with open(file_path, 'w', encoding="utf8") as file: file.write(content) def find_and_replace(directory): for root, dirs, files in os.walk(directory): if 'Generated Files' in dirs: dirs.remove('Generated Files') # Exclude the "Generated Files" directory for file in files: if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'): file_path = os.path.join(root, file) try: replace_in_file(file_path, file) except Exception as e: print(f"error reading {file_path}") if file == "TermControl.cpp": print(e) # raise e # Replace in files within a specific directory directory_path = 'D:\\dev\\public\\terminal\\src' find_and_replace(directory_path) ``` </details> [^1]: there are other macros we use that were also using this macro, those weren't replaced. --------- Co-authored-by: Dustin Howett <duhowett@microsoft.com> Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2024-03-20 09:02:26 -07:00
OpenHyperlink.raise(*this, winrt::make<OpenHyperlinkEventArgs>(winrt::hstring{ uri }));
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
bool ControlInteractivity::_canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers)
{
// If the user is holding down Shift, suppress mouse events
// TODO GH#4875: disable/customize this functionality
if (modifiers.IsShiftPressed())
{
return false;
}
return _core->IsVtMouseModeEnabled();
}
bool ControlInteractivity::_shouldSendAlternateScroll(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta)
{
// If the user is holding down Shift, suppress mouse events
// TODO GH#4875: disable/customize this functionality
if (modifiers.IsShiftPressed())
{
return false;
}
return _core->ShouldSendAlternateScroll(WM_MOUSEWHEEL, delta);
}
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Method Description:
// - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging.
// Arguments:
// - cursorPosition: in pixels, relative to the origin of the control
Prepare til wrappers for migrating off of SMALL_RECT (#11902) This commit makes the following changes to `til::point/size/rectangle` for the following reasons: * Rename `rectangle` into `rect` This will make the naming consistent with a later `small_rect` struct as well as the existing Win32 POINT/SIZE/RECT structs. * Standardizes til wrappers on `int32_t` instead of `ptrdiff_t` Provides a consistent behavior between x86 and x64, preventing accidental errors on x86, as it's less rigorously tested than x64. Additionally it improves interop with MIDL3 which only supports fixed width integer types. * Standardizes til wrappers on throwing `gsl::narrow_error` Makes the behavior of our code more consistent. * Makes all eligible functions `constexpr` Because why not. * Removes implicit constructors and conversion operators This is a complex and controversial topic. My reasons are: You can't Ctrl+F for an implicit conversion. This breaks most non-IDE engines, like the one on GitHub or those we have internally at MS. This is important for me as these implicit conversion operators aren't cost free. Narrowing integers itself, as well as the boundary checks that need to be done have a certain, fixed overhead each time. Additionally the lack of noexcept prevents many advanced compiler optimizations. Removing their use entirely drops conhost's code segment size by around ~6.5%. ## References Preliminary work for #4015. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
2022-01-13 22:09:29 +01:00
void ControlInteractivity::SetEndSelectionPoint(const Core::Point pixelPosition)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
Make selection an exclusive range (#18106) Selection is generally stored as an inclusive start and end. This PR makes the end exclusive which now allows degenerate selections, namely in mark mode. This also modifies mouse selection to round to the nearest cell boundary (see #5099) and improves word boundaries to be a bit more modern and make sense for degenerate selections (similar to #15787). Closes #5099 Closes #13447 Closes #17892 ## Detailed Description of the Pull Request / Additional comments - Buffer, Viewport, and Point - Introduced a few new functions here to find word boundaries, delimiter class runs, and glyph boundaries. - 📝These new functions should be able to replace a few other functions (i.e. `GetWordStart` --> `GetWordStart2`). That migration is going to be a part of #4423 to reduce the risk of breaking UIA. - Viewport: added a few functions to handle navigating the _exclusive_ bounds (namely allowing RightExclusive as a position for buffer coordinates). This is important for selection to be able to highlight the entire line. - 📝`BottomInclusiveRightExclusive()` will replace `EndExclusive` in the UIA code - Point: `iterate_rows_exclusive` is similar to `iterate_rows`, except it has handling for RightExclusive - Renderer - Use `iterate_rows_exclusive` for proper handling (this actually fixed a lot of our issues) - Remove some workarounds in `_drawHighlighted` (this is a boundary where we got inclusive coords and made them exclusive, but now we don't need that!) - Terminal - fix selection marker rendering - `_ConvertToBufferCell()`: add a param to allow for RightExclusive or clamp it to RightInclusive (original behavior). Both are useful! - Use new `GetWordStart2` and `GetWordEnd2` to improve word boundaries and make them feel right now that the selection an exclusive range. - Convert a few `IsInBounds` --> `IsInExclusiveBounds` for safety and correctness - Add `TriggerSelection` to `SelectNewRegion` - 📝 We normally called `TriggerSelection` in a different layer, but it turns out, UIA's `Select` function wouldn't actually update the renderer. Whoops! This fixes that. - TermControl - `_getTerminalPosition` now has a new param to round to the nearest cell (see #5099) - UIA - `TermControlUIAProvider::GetSelectionRange` no need to convert from inclusive range to exclusive range anymore! - `TextBuffer::GetPlainText` now works on an exclusive range, so no need to convert the range anymore! ## Validation Steps Performed This fundamental change impacts a lot of scenarios: - ✅Rendering selections - ✅Selection markers - ✅Copy text - ✅Session restore - ✅Mark mode navigation (i.e. character, word, line, buffer) - ✅Mouse selection (i.e. click+drag, shift+click, multi-click, alt+click) - ✅Hyperlinks (interaction and rendering) - ✅Accessibility (i.e. get selection, movement, text extraction, selecting text) - [ ] Prev/Next Command/Output (untested) - ✅Unit tests ## Follow-ups - Refs #4423 - Now that selection and UIA are both exclusive ranges, it should be a lot easier to deduplicate code between selection and UIA. We should be able to remove `EndExclusive` as well when we do that. This'll also be an opportunity to modernize that code and use more `til` classes.
2025-01-28 14:54:49 -08:00
_core->SetEndSelectionPoint(_getTerminalPosition(til::point{ pixelPosition }, true));
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
_selectionNeedsToBeCopied = true;
}
// Method Description:
// - Gets the corresponding viewport terminal position for the point in
// pixels, by normalizing with the font size.
// Arguments:
// - pixelPosition: the (x,y) position of a given point (i.e.: mouse cursor).
// NOTE: origin (0,0) is top-left.
Make selection an exclusive range (#18106) Selection is generally stored as an inclusive start and end. This PR makes the end exclusive which now allows degenerate selections, namely in mark mode. This also modifies mouse selection to round to the nearest cell boundary (see #5099) and improves word boundaries to be a bit more modern and make sense for degenerate selections (similar to #15787). Closes #5099 Closes #13447 Closes #17892 ## Detailed Description of the Pull Request / Additional comments - Buffer, Viewport, and Point - Introduced a few new functions here to find word boundaries, delimiter class runs, and glyph boundaries. - 📝These new functions should be able to replace a few other functions (i.e. `GetWordStart` --> `GetWordStart2`). That migration is going to be a part of #4423 to reduce the risk of breaking UIA. - Viewport: added a few functions to handle navigating the _exclusive_ bounds (namely allowing RightExclusive as a position for buffer coordinates). This is important for selection to be able to highlight the entire line. - 📝`BottomInclusiveRightExclusive()` will replace `EndExclusive` in the UIA code - Point: `iterate_rows_exclusive` is similar to `iterate_rows`, except it has handling for RightExclusive - Renderer - Use `iterate_rows_exclusive` for proper handling (this actually fixed a lot of our issues) - Remove some workarounds in `_drawHighlighted` (this is a boundary where we got inclusive coords and made them exclusive, but now we don't need that!) - Terminal - fix selection marker rendering - `_ConvertToBufferCell()`: add a param to allow for RightExclusive or clamp it to RightInclusive (original behavior). Both are useful! - Use new `GetWordStart2` and `GetWordEnd2` to improve word boundaries and make them feel right now that the selection an exclusive range. - Convert a few `IsInBounds` --> `IsInExclusiveBounds` for safety and correctness - Add `TriggerSelection` to `SelectNewRegion` - 📝 We normally called `TriggerSelection` in a different layer, but it turns out, UIA's `Select` function wouldn't actually update the renderer. Whoops! This fixes that. - TermControl - `_getTerminalPosition` now has a new param to round to the nearest cell (see #5099) - UIA - `TermControlUIAProvider::GetSelectionRange` no need to convert from inclusive range to exclusive range anymore! - `TextBuffer::GetPlainText` now works on an exclusive range, so no need to convert the range anymore! ## Validation Steps Performed This fundamental change impacts a lot of scenarios: - ✅Rendering selections - ✅Selection markers - ✅Copy text - ✅Session restore - ✅Mark mode navigation (i.e. character, word, line, buffer) - ✅Mouse selection (i.e. click+drag, shift+click, multi-click, alt+click) - ✅Hyperlinks (interaction and rendering) - ✅Accessibility (i.e. get selection, movement, text extraction, selecting text) - [ ] Prev/Next Command/Output (untested) - ✅Unit tests ## Follow-ups - Refs #4423 - Now that selection and UIA are both exclusive ranges, it should be a lot easier to deduplicate code between selection and UIA. We should be able to remove `EndExclusive` as well when we do that. This'll also be an opportunity to modernize that code and use more `til` classes.
2025-01-28 14:54:49 -08:00
// - roundToNearestCell: if true, round the x-value. Otherwise, floor it (standard int division)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Return Value:
// - the corresponding viewport terminal position for the given Point parameter
Make selection an exclusive range (#18106) Selection is generally stored as an inclusive start and end. This PR makes the end exclusive which now allows degenerate selections, namely in mark mode. This also modifies mouse selection to round to the nearest cell boundary (see #5099) and improves word boundaries to be a bit more modern and make sense for degenerate selections (similar to #15787). Closes #5099 Closes #13447 Closes #17892 ## Detailed Description of the Pull Request / Additional comments - Buffer, Viewport, and Point - Introduced a few new functions here to find word boundaries, delimiter class runs, and glyph boundaries. - 📝These new functions should be able to replace a few other functions (i.e. `GetWordStart` --> `GetWordStart2`). That migration is going to be a part of #4423 to reduce the risk of breaking UIA. - Viewport: added a few functions to handle navigating the _exclusive_ bounds (namely allowing RightExclusive as a position for buffer coordinates). This is important for selection to be able to highlight the entire line. - 📝`BottomInclusiveRightExclusive()` will replace `EndExclusive` in the UIA code - Point: `iterate_rows_exclusive` is similar to `iterate_rows`, except it has handling for RightExclusive - Renderer - Use `iterate_rows_exclusive` for proper handling (this actually fixed a lot of our issues) - Remove some workarounds in `_drawHighlighted` (this is a boundary where we got inclusive coords and made them exclusive, but now we don't need that!) - Terminal - fix selection marker rendering - `_ConvertToBufferCell()`: add a param to allow for RightExclusive or clamp it to RightInclusive (original behavior). Both are useful! - Use new `GetWordStart2` and `GetWordEnd2` to improve word boundaries and make them feel right now that the selection an exclusive range. - Convert a few `IsInBounds` --> `IsInExclusiveBounds` for safety and correctness - Add `TriggerSelection` to `SelectNewRegion` - 📝 We normally called `TriggerSelection` in a different layer, but it turns out, UIA's `Select` function wouldn't actually update the renderer. Whoops! This fixes that. - TermControl - `_getTerminalPosition` now has a new param to round to the nearest cell (see #5099) - UIA - `TermControlUIAProvider::GetSelectionRange` no need to convert from inclusive range to exclusive range anymore! - `TextBuffer::GetPlainText` now works on an exclusive range, so no need to convert the range anymore! ## Validation Steps Performed This fundamental change impacts a lot of scenarios: - ✅Rendering selections - ✅Selection markers - ✅Copy text - ✅Session restore - ✅Mark mode navigation (i.e. character, word, line, buffer) - ✅Mouse selection (i.e. click+drag, shift+click, multi-click, alt+click) - ✅Hyperlinks (interaction and rendering) - ✅Accessibility (i.e. get selection, movement, text extraction, selecting text) - [ ] Prev/Next Command/Output (untested) - ✅Unit tests ## Follow-ups - Refs #4423 - Now that selection and UIA are both exclusive ranges, it should be a lot easier to deduplicate code between selection and UIA. We should be able to remove `EndExclusive` as well when we do that. This'll also be an opportunity to modernize that code and use more `til` classes.
2025-01-28 14:54:49 -08:00
til::point ControlInteractivity::_getTerminalPosition(const til::point pixelPosition, bool roundToNearestCell)
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
{
// Get the size of the font, which is in pixels
Make selection an exclusive range (#18106) Selection is generally stored as an inclusive start and end. This PR makes the end exclusive which now allows degenerate selections, namely in mark mode. This also modifies mouse selection to round to the nearest cell boundary (see #5099) and improves word boundaries to be a bit more modern and make sense for degenerate selections (similar to #15787). Closes #5099 Closes #13447 Closes #17892 ## Detailed Description of the Pull Request / Additional comments - Buffer, Viewport, and Point - Introduced a few new functions here to find word boundaries, delimiter class runs, and glyph boundaries. - 📝These new functions should be able to replace a few other functions (i.e. `GetWordStart` --> `GetWordStart2`). That migration is going to be a part of #4423 to reduce the risk of breaking UIA. - Viewport: added a few functions to handle navigating the _exclusive_ bounds (namely allowing RightExclusive as a position for buffer coordinates). This is important for selection to be able to highlight the entire line. - 📝`BottomInclusiveRightExclusive()` will replace `EndExclusive` in the UIA code - Point: `iterate_rows_exclusive` is similar to `iterate_rows`, except it has handling for RightExclusive - Renderer - Use `iterate_rows_exclusive` for proper handling (this actually fixed a lot of our issues) - Remove some workarounds in `_drawHighlighted` (this is a boundary where we got inclusive coords and made them exclusive, but now we don't need that!) - Terminal - fix selection marker rendering - `_ConvertToBufferCell()`: add a param to allow for RightExclusive or clamp it to RightInclusive (original behavior). Both are useful! - Use new `GetWordStart2` and `GetWordEnd2` to improve word boundaries and make them feel right now that the selection an exclusive range. - Convert a few `IsInBounds` --> `IsInExclusiveBounds` for safety and correctness - Add `TriggerSelection` to `SelectNewRegion` - 📝 We normally called `TriggerSelection` in a different layer, but it turns out, UIA's `Select` function wouldn't actually update the renderer. Whoops! This fixes that. - TermControl - `_getTerminalPosition` now has a new param to round to the nearest cell (see #5099) - UIA - `TermControlUIAProvider::GetSelectionRange` no need to convert from inclusive range to exclusive range anymore! - `TextBuffer::GetPlainText` now works on an exclusive range, so no need to convert the range anymore! ## Validation Steps Performed This fundamental change impacts a lot of scenarios: - ✅Rendering selections - ✅Selection markers - ✅Copy text - ✅Session restore - ✅Mark mode navigation (i.e. character, word, line, buffer) - ✅Mouse selection (i.e. click+drag, shift+click, multi-click, alt+click) - ✅Hyperlinks (interaction and rendering) - ✅Accessibility (i.e. get selection, movement, text extraction, selecting text) - [ ] Prev/Next Command/Output (untested) - ✅Unit tests ## Follow-ups - Refs #4423 - Now that selection and UIA are both exclusive ranges, it should be a lot easier to deduplicate code between selection and UIA. We should be able to remove `EndExclusive` as well when we do that. This'll also be an opportunity to modernize that code and use more `til` classes.
2025-01-28 14:54:49 -08:00
const auto fontSize{ _core->GetFont().GetSize() };
if (roundToNearestCell)
{
// GH#5099: round the x-value to the nearest cell
til::point result;
result.x = gsl::narrow_cast<til::CoordType>(std::round(gsl::narrow_cast<double>(pixelPosition.x) / fontSize.width));
result.y = pixelPosition.y / fontSize.height;
return result;
}
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
// Convert the location in pixels to characters within the current viewport.
return pixelPosition / fontSize;
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
bool ControlInteractivity::_sendMouseEventHelper(const 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));
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
// Method Description:
// - Creates an automation peer for the Terminal Control, enabling
// accessibility on our control.
// - Our implementation implements the ITextProvider pattern, and the
// IControlAccessibilityInfo, to connect to the UiaEngine, which must be
// attached to the core's renderer.
// - The TermControlAutomationPeer will connect this to the UI tree.
// Arguments:
// - None
// Return Value:
// - The automation peer for our control
Control::InteractivityAutomationPeer ControlInteractivity::OnCreateAutomationPeer()
try
{
const auto autoPeer = winrt::make_self<implementation::InteractivityAutomationPeer>(this);
Add support for moving panes and tabs between windows (#14866) _Lo! Harken to me, for I shall divulge the heart of the tab tear-out saga. Verily, this PR shall bestow upon thee the power to move tabs and panes between windows by means of pre-defined actions. Though be warned, it does not yet grant thee the power to drag and drop them as thou mayest desire. Yet, the same plumbing that underpins this work shall remain steadfast. Behold, the majority of this undertaking concerns the elevation of the RequestMoveContent event from the TerminalPage to the very summit of the Monarch. From thence, a great AttachContent method shall descend back to the lowest depths. Furthermore, there are minor revisions to TermControl that shall enable thee to better detach the content and attach it to a new one._ This is the most important part of the tab tear-out saga. This PR enables the user to move tabs and panes between windows using pre-defined actions. It does _not_ enable the user to drag/drop them yet, but the same fundamental plumbing will still apply. Most of the PR is plumbing the `RequestMoveContent` event up from the `TerminalPage` up to the `Monarch`, and then plumbing an `AttachContent` method back down. There are also small changes to `TermControl` to better support detaching the content and attaching to a new one. For testing, I recommend: ```json { "keys": "f1", "command": { "action": "moveTab", "window": "1" } }, { "keys": "f2", "command": { "action": "moveTab", "window": "2" } }, { "keys": "f3", "command": { "action": "movePane", "window": "1" } }, { "keys": "f4", "command": { "action": "movePane", "window": "2" } }, { "keys": "shift+f3", "command": { "action": "movePane", "window": "1", "index": 3 } }, { "keys": "shift+f4", "command": { "action": "movePane", "window": "2", "index": 3 } }, ``` * Related to #1256 * Related to #5000 --------- Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2023-03-30 09:37:53 -05:00
if (_uiaEngine)
{
_core->DetachUiaEngine(_uiaEngine.get());
}
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
_uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(autoPeer.get());
_core->AttachUiaEngine(_uiaEngine.get());
return *autoPeer;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return nullptr;
}
::Microsoft::Console::Render::IRenderData* ControlInteractivity::GetRenderData() const
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
{
return _core->GetRenderData();
Only access ControlInteractivity through the projection (#10051) ## Summary of the Pull Request This forces the `TermControl` to only use `ControlCore` and `ControlInteractivity` via their WinRT projections. We want this, because WinRT projections can be used across process boundaries. In the future, `ControlCore` and `ControlInteractivity` are going to be living in a different process entirely from `TermControl`. By enforcing this boundary now, we can make sure that they will work seamlessly in the future. ## References * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760270 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Most all this was just converting pure c++ types to winrt types when possible. I've added a couple helper projections with `til` converters, which made most of this really easy. The "`MouseButtonState` needs to be composed of `Int32`s instead of `bool`s" is MENTAL. I have no idea why this is, but when I had the control OOP in the sample, that would crash when trying to de-marshal the bools. BODGY. The biggest changes are in the way the UIA stuff is hooked up. The UiaEngine needs to be attached directly to the `Renderer`, and it can't be easily projected, so it needs to live next to the `ControlCore`. But the `TermControlAutomationPeer` needed the `UiaEngine` to help implement some interfaces. Now, there's a new layer we've introduced. `InteractivityAutomationPeer` does the `ITextProvider`, `IControlAccessibilityInfo` and the `IUiaEventDispatcher` thing. `TermControlAutomationPeer` now has a `InteractivityAutomationPeer` stashed inside itself, so that it can ask the interactivity layer to do the real work. We still need the `TermControlAutomationPeer` though, to be able to attach to the real UI tree. ## Validation Steps Performed The terminal behaves basically the same as before. Most importantly, I whipped out Accessibility Insights, and the Terminal looks the same as before.
2021-07-19 11:59:30 -05:00
}
Split `TermControl` into a Core, Interactivity, and Control layer (#9820) ## 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 the `Terminal` instance, the `DxEngine` and `Renderer`, and the `Connection`. 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 the `ControlCore`, 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 now By splitting into smaller pieces, it will enable us to * write unit tests for the `Core` and `Interactivity` bits, which we desparately need * Combine `ControlCore` and `ControlInteractivity` 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 * In pursuit of #1256 * Proc Model: #5000 * https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes #6842 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760258 * [x] I work here * [x] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments * I don't love the names `ControlCore` and `ControlInteractivity`. Open to other names. * I added a `ICoreState` interface for "properties that come from the `ControlCore`, but consumers of the `TermControl` 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. * I've added more `EventArgs` to make more events proper `TypedEvent`s. * I've changed how the TerminalApp layer requests updated TaskbarProgress state. It doesn't need to pump TermControl to raise a new event anymore. * ~~Something that snuck into this branch in the very long history is the switch to `DCompositionCreateSurfaceHandle` for the `DxEngine`. @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.~~ * I reverted this in c113b65d9. We can revert _that_ commit when we want to come back to it. * I've changed the acrylic handler a decent amount. But added tests! * All the `ThrottledFunc` things are left in `TermControl`. 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). * I've undoubtably messed up the merging of the locking around the appearance config stuff recently ## Validation Steps Performed I've got a rolling list in https://github.com/microsoft/terminal/issues/6842#issuecomment-810990460 that I'm updating as I go.
2021-04-27 10:50:45 -05:00
}