2021-04-05 11:07:55 -05:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
|
#include "../TerminalControl/EventArgs.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 "../TerminalControl/ControlCore.h"
|
|
|
|
|
#include "MockControlSettings.h"
|
|
|
|
|
#include "MockConnection.h"
|
2022-03-29 17:16:57 -05:00
|
|
|
#include "../../inc/TestUtils.h"
|
2021-04-05 11:07:55 -05:00
|
|
|
|
|
|
|
|
using namespace Microsoft::Console;
|
|
|
|
|
using namespace WEX::Logging;
|
|
|
|
|
using namespace WEX::TestExecution;
|
|
|
|
|
using namespace WEX::Common;
|
|
|
|
|
|
|
|
|
|
using namespace winrt;
|
|
|
|
|
using namespace winrt::Microsoft::Terminal;
|
|
|
|
|
|
|
|
|
|
namespace ControlUnitTests
|
|
|
|
|
{
|
|
|
|
|
class ControlCoreTests
|
|
|
|
|
{
|
|
|
|
|
BEGIN_TEST_CLASS(ControlCoreTests)
|
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
|
|
|
TEST_CLASS_PROPERTY(L"TestTimeout", L"0:0:10") // 10s timeout
|
2021-04-05 11:07:55 -05:00
|
|
|
END_TEST_CLASS()
|
|
|
|
|
|
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
|
|
|
TEST_METHOD(ComPtrSettings);
|
|
|
|
|
TEST_METHOD(InstantiateCore);
|
|
|
|
|
TEST_METHOD(TestInitialize);
|
|
|
|
|
TEST_METHOD(TestAdjustAcrylic);
|
2026-06-08 16:47:10 -07:00
|
|
|
TEST_METHOD(TestRuntimeOpacitySurvivesSettingsReload);
|
|
|
|
|
TEST_METHOD(TestReadOnlySurvivesSettingsReload);
|
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
|
|
|
|
|
|
|
|
TEST_METHOD(TestFreeAfterClose);
|
|
|
|
|
|
|
|
|
|
TEST_METHOD(TestFontInitializedInCtor);
|
|
|
|
|
|
2021-09-02 09:59:42 -05:00
|
|
|
TEST_METHOD(TestClearScrollback);
|
|
|
|
|
TEST_METHOD(TestClearScreen);
|
|
|
|
|
TEST_METHOD(TestClearAll);
|
2022-11-12 23:31:10 +00:00
|
|
|
TEST_METHOD(TestReadEntireBuffer);
|
2021-09-02 09:59:42 -05:00
|
|
|
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
TEST_METHOD(TestSelectCommandSimple);
|
|
|
|
|
TEST_METHOD(TestSelectOutputSimple);
|
2024-05-13 12:36:27 -05:00
|
|
|
TEST_METHOD(TestCommandContext);
|
2024-08-23 14:24:34 -05:00
|
|
|
TEST_METHOD(TestCommandContextWithPwshGhostText);
|
|
|
|
|
|
2024-05-01 10:06:33 -05:00
|
|
|
TEST_METHOD(TestSelectOutputScrolling);
|
|
|
|
|
TEST_METHOD(TestSelectOutputExactWrap);
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
|
2023-08-14 07:37:13 -05:00
|
|
|
TEST_METHOD(TestSimpleClickSelection);
|
|
|
|
|
|
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
|
|
|
TEST_CLASS_SETUP(ModuleSetup)
|
|
|
|
|
{
|
|
|
|
|
winrt::init_apartment(winrt::apartment_type::single_threaded);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
TEST_CLASS_CLEANUP(ClassCleanup)
|
|
|
|
|
{
|
|
|
|
|
winrt::uninit_apartment();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::tuple<winrt::com_ptr<MockControlSettings>, winrt::com_ptr<MockConnection>> _createSettingsAndConnection()
|
|
|
|
|
{
|
|
|
|
|
Log::Comment(L"Create settings object");
|
|
|
|
|
auto settings = winrt::make_self<MockControlSettings>();
|
|
|
|
|
VERIFY_IS_NOT_NULL(settings);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Create connection object");
|
|
|
|
|
auto conn = winrt::make_self<MockConnection>();
|
|
|
|
|
VERIFY_IS_NOT_NULL(conn);
|
|
|
|
|
|
|
|
|
|
return { settings, conn };
|
|
|
|
|
}
|
Allow `ThrottledFunc` to work on different types of dispatcher (#10187)
#### ⚠️ targets #10051
## Summary of the Pull Request
This updates our `ThrottledFunc`s to take a dispatcher parameter. This means that we can use the `Windows::UI::Core::CoreDispatcher` in the `TermControl`, where there's always a `CoreDispatcher`, and use a `Windows::System::DispatcherQueue` in `ControlCore`/`ControlInteractivity`. When running in-proc, these are always the _same thing_. However, out-of-proc, the core needs a dispatcher queue that's not tied to a UI thread (because the content proces _doesn't have a UI thread!_).
This lets us get rid of the output event, because we don't need to bubble that event out to the `TermControl` to let it throttle that update anymore.
## References
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5
## PR Checklist
* [x] This is a part of #1256
* [x] I work here
* [n/a] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Fortunately, `winrt::resume_foreground` works the same on both a `CoreDispatcher` and a `DispatcherQueue`, so this wasn't too hard!
## Validation Steps Performed
This was validated in `dev/migrie/oop/the-whole-thing` (or `dev/migrie/oop/connection-factory`, I forget which), and I made sure that it worked both in-proc and x-proc. Not only that, _it wasn't any slower_!This reverts commit 04b751faa70680bf0296063deacec4657c6ff9d6.
2021-08-09 10:21:59 -05:00
|
|
|
|
|
|
|
|
winrt::com_ptr<Control::implementation::ControlCore> createCore(Control::IControlSettings settings,
|
|
|
|
|
TerminalConnection::ITerminalConnection conn)
|
|
|
|
|
{
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
|
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
|
|
|
auto core = winrt::make_self<Control::implementation::ControlCore>(settings, settings, conn);
|
Allow `ThrottledFunc` to work on different types of dispatcher (#10187)
#### ⚠️ targets #10051
## Summary of the Pull Request
This updates our `ThrottledFunc`s to take a dispatcher parameter. This means that we can use the `Windows::UI::Core::CoreDispatcher` in the `TermControl`, where there's always a `CoreDispatcher`, and use a `Windows::System::DispatcherQueue` in `ControlCore`/`ControlInteractivity`. When running in-proc, these are always the _same thing_. However, out-of-proc, the core needs a dispatcher queue that's not tied to a UI thread (because the content proces _doesn't have a UI thread!_).
This lets us get rid of the output event, because we don't need to bubble that event out to the `TermControl` to let it throttle that update anymore.
## References
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5
## PR Checklist
* [x] This is a part of #1256
* [x] I work here
* [n/a] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Fortunately, `winrt::resume_foreground` works the same on both a `CoreDispatcher` and a `DispatcherQueue`, so this wasn't too hard!
## Validation Steps Performed
This was validated in `dev/migrie/oop/the-whole-thing` (or `dev/migrie/oop/connection-factory`, I forget which), and I made sure that it worked both in-proc and x-proc. Not only that, _it wasn't any slower_!This reverts commit 04b751faa70680bf0296063deacec4657c6ff9d6.
2021-08-09 10:21:59 -05:00
|
|
|
core->_inUnitTests = true;
|
|
|
|
|
return core;
|
|
|
|
|
}
|
2021-09-02 09:59:42 -05:00
|
|
|
|
|
|
|
|
void _standardInit(winrt::com_ptr<Control::implementation::ControlCore> core)
|
|
|
|
|
{
|
2023-12-04 21:29:34 +01:00
|
|
|
// "Consolas" ends up with an actual size of 9x19 at 96DPI. So
|
|
|
|
|
// let's just arbitrarily start with a 270x380px (30x20 chars) window
|
|
|
|
|
core->Initialize(270, 380, 1.0);
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
core->_terminal->_suppressLockChecks = true;
|
|
|
|
|
#endif
|
2021-09-02 09:59:42 -05:00
|
|
|
VERIFY_IS_TRUE(core->_initializedTerminal);
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
|
|
|
|
|
}
|
2021-04-05 11:07:55 -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 ControlCoreTests::ComPtrSettings()
|
|
|
|
|
{
|
|
|
|
|
Log::Comment(L"Just make sure we can instantiate a settings obj in a com_ptr");
|
|
|
|
|
auto settings = winrt::make_self<MockControlSettings>();
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Verify literally any setting, it doesn't matter");
|
|
|
|
|
VERIFY_ARE_EQUAL(DEFAULT_FOREGROUND, settings->DefaultForeground());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlCoreTests::InstantiateCore()
|
2021-04-05 11:07:55 -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
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
|
Allow `ThrottledFunc` to work on different types of dispatcher (#10187)
#### ⚠️ targets #10051
## Summary of the Pull Request
This updates our `ThrottledFunc`s to take a dispatcher parameter. This means that we can use the `Windows::UI::Core::CoreDispatcher` in the `TermControl`, where there's always a `CoreDispatcher`, and use a `Windows::System::DispatcherQueue` in `ControlCore`/`ControlInteractivity`. When running in-proc, these are always the _same thing_. However, out-of-proc, the core needs a dispatcher queue that's not tied to a UI thread (because the content proces _doesn't have a UI thread!_).
This lets us get rid of the output event, because we don't need to bubble that event out to the `TermControl` to let it throttle that update anymore.
## References
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5
## PR Checklist
* [x] This is a part of #1256
* [x] I work here
* [n/a] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Fortunately, `winrt::resume_foreground` works the same on both a `CoreDispatcher` and a `DispatcherQueue`, so this wasn't too hard!
## Validation Steps Performed
This was validated in `dev/migrie/oop/the-whole-thing` (or `dev/migrie/oop/connection-factory`, I forget which), and I made sure that it worked both in-proc and x-proc. Not only that, _it wasn't any slower_!This reverts commit 04b751faa70680bf0296063deacec4657c6ff9d6.
2021-08-09 10:21:59 -05:00
|
|
|
auto core = createCore(*settings, *conn);
|
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
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlCoreTests::TestInitialize()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
|
Allow `ThrottledFunc` to work on different types of dispatcher (#10187)
#### ⚠️ targets #10051
## Summary of the Pull Request
This updates our `ThrottledFunc`s to take a dispatcher parameter. This means that we can use the `Windows::UI::Core::CoreDispatcher` in the `TermControl`, where there's always a `CoreDispatcher`, and use a `Windows::System::DispatcherQueue` in `ControlCore`/`ControlInteractivity`. When running in-proc, these are always the _same thing_. However, out-of-proc, the core needs a dispatcher queue that's not tied to a UI thread (because the content proces _doesn't have a UI thread!_).
This lets us get rid of the output event, because we don't need to bubble that event out to the `TermControl` to let it throttle that update anymore.
## References
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5
## PR Checklist
* [x] This is a part of #1256
* [x] I work here
* [n/a] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Fortunately, `winrt::resume_foreground` works the same on both a `CoreDispatcher` and a `DispatcherQueue`, so this wasn't too hard!
## Validation Steps Performed
This was validated in `dev/migrie/oop/the-whole-thing` (or `dev/migrie/oop/connection-factory`, I forget which), and I made sure that it worked both in-proc and x-proc. Not only that, _it wasn't any slower_!This reverts commit 04b751faa70680bf0296063deacec4657c6ff9d6.
2021-08-09 10:21:59 -05:00
|
|
|
auto core = createCore(*settings, *conn);
|
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
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_FALSE(core->_initializedTerminal);
|
2023-12-04 21:29:34 +01:00
|
|
|
// "Consolas" ends up with an actual size of 9x19 at 96DPI. So
|
|
|
|
|
// let's just arbitrarily start with a 270x380px (30x20 chars) window
|
|
|
|
|
core->Initialize(270, 380, 1.0);
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
core->_terminal->_suppressLockChecks = true;
|
|
|
|
|
#endif
|
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
|
|
|
VERIFY_IS_TRUE(core->_initializedTerminal);
|
|
|
|
|
VERIFY_ARE_EQUAL(30, core->_terminal->GetViewport().Width());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlCoreTests::TestAdjustAcrylic()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
|
|
|
|
|
settings->UseAcrylic(true);
|
2021-09-20 12:08:13 -05:00
|
|
|
settings->Opacity(0.5f);
|
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
|
|
|
|
Allow `ThrottledFunc` to work on different types of dispatcher (#10187)
#### ⚠️ targets #10051
## Summary of the Pull Request
This updates our `ThrottledFunc`s to take a dispatcher parameter. This means that we can use the `Windows::UI::Core::CoreDispatcher` in the `TermControl`, where there's always a `CoreDispatcher`, and use a `Windows::System::DispatcherQueue` in `ControlCore`/`ControlInteractivity`. When running in-proc, these are always the _same thing_. However, out-of-proc, the core needs a dispatcher queue that's not tied to a UI thread (because the content proces _doesn't have a UI thread!_).
This lets us get rid of the output event, because we don't need to bubble that event out to the `TermControl` to let it throttle that update anymore.
## References
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5
## PR Checklist
* [x] This is a part of #1256
* [x] I work here
* [n/a] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Fortunately, `winrt::resume_foreground` works the same on both a `CoreDispatcher` and a `DispatcherQueue`, so this wasn't too hard!
## Validation Steps Performed
This was validated in `dev/migrie/oop/the-whole-thing` (or `dev/migrie/oop/connection-factory`, I forget which), and I made sure that it worked both in-proc and x-proc. Not only that, _it wasn't any slower_!This reverts commit 04b751faa70680bf0296063deacec4657c6ff9d6.
2021-08-09 10:21:59 -05:00
|
|
|
auto core = createCore(*settings, *conn);
|
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
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
|
|
|
|
|
// A callback to make sure that we're raising TransparencyChanged events
|
2024-04-23 02:07:00 +02:00
|
|
|
auto expectedOpacity = 0.5f;
|
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
|
|
|
auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable {
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity());
|
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
|
|
|
VERIFY_ARE_EQUAL(expectedOpacity, core->Opacity());
|
|
|
|
|
// The Settings object's opacity shouldn't be changed
|
2024-04-23 02:07:00 +02:00
|
|
|
VERIFY_ARE_EQUAL(0.5f, settings->Opacity());
|
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
|
|
|
|
2024-04-23 02:07:00 +02:00
|
|
|
if (expectedOpacity < 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
|
|
|
{
|
|
|
|
|
VERIFY_IS_TRUE(settings->UseAcrylic());
|
Remove TerminalSettings from the TerminalSettingsModel project (#19262)
The idea with IControlSettings (and friends) was always that a consumer
of the terminal control could implement it in whatever way they pleased.
Windows Terminal (the application) was intended to be only one
consumer. It has a whole JSON settings model. Nobody wants to think
about JSON at the Terminal Control level. We could have an "adapter" in
TerminalApp, which spoke Terminal JSON Settings on one side and Terminal
Control on the other side.
That worked until we added the settings editor. The settings editor
needed to display a control, and that control's settings needed to be
based on the JSON settings. Oops. We took the expedient route of moving
the adapter into TerminalSettingsModel itself, and poking a bunch of
holes in it so that TerminalApp and TerminalSettingsEditor could tweak
it as needed.
Later, we doubled down on the control settings interface by having every
Terminal Control _make its own ControlSettings_ when we were going to do
the multi-process model. This reduced the number of IPC round trips for
every settings query to 0. Later we built color scheme previewing on top
of that--adding structs to carry color schemes and stuff which was
already in the Appearance config. Sheesh. Layers and layers and layers.
This pull request moves it back into its own library and strips it from
the surface of TerminalSettingsModel. It also deletes `ControlSettings`
and `struct CoreScheme`. That library is called
`TerminalSettingsAppAdapterLib`, and it contains a hidden WinRT
_implements_ type rather than a full-fledged activatable `runtimeclass`.
It also implements one-level inheritance on its own rather than using
IInheritable.
It adheres to the following principles:
- The control will never modify its settings in a way that is visible to
the control's consumer; therefore, none of the properties have setters
- The settings should never contain things of interest only to the
Application that the Application uses to communicate data _back to
itself_ (see `ProfileName`, removed in 68b723c and `KeyBindings`,
removed in fa09141). This generalizes to "we should never store stuff
in an unrelated object passed between layers solely for the purpose of
getting it back".
I made a few changes to the settings interface, including introducing a
new `ICoreScheme` interface that _only_ contains color scheme info. This
is designed to support the Preview/Set color scheme actions, which no
longer work by _app backing up the scheme and restoring it later._ All
of that machinery lives inside TermControl/ControlCore now.
`ICoreScheme` no longer supports `GetColorAtIndex`; you must read all 16
colors at the same time. I am not sorry. Every consumer did that
already, so now we have 15 fewer COM calls for every color scheme.
The new TerminalSettings is mostly consumed via
`com_ptr<TerminalSettings>`, so a bunch of `.` (projected) accesses had
to turn into `->` (com_ptr dereferencing) accesses.
I also realized, in the course of this work, that the old
TerminalSettings contained a partial hand-written reimplementation of
_every setting_ in `ControlProperties`. Every contributor had to add
every new setting to both places--why? I can't figure it out. I'm using
ControlProperties comprehensively now. I propagated any setting whose
default value was different from that in ControlProperties back to
ControlProperties.
This is part X in a series of pull requests that will remove all mention
of Microsoft.Terminal.Control and Microsoft.Terminal.Core from the
settings model. Once that is done, the settings model can consume _only_
the base WinRT types and build very early and test more easily.
Previewing is fun. I introduced a new place to stash an entire color
table on ControlCore, which we use to save the "active" colors while we
temporarily overwrite them. SetColorScheme is _also_ fun. We now have a
slot for overriding only the focused color scheme on ControlCore. It's
fine. It's clearer than "back up the focused appearance, overwrite the
focused appearance, create a child of the user's settings and apply the
color scheme to it, etc.".
There is a bug/design choice in color scheme overriding, which may or
may not matter: overlaying a color scheme on a terminal with an
unfocused appearance which _does not_ have its own color scheme will
result in the previously-deleted overridden focused color scheme peeking
through when the terminal is not focused.
I also got rid of our only in-product use of
`Terminal::CreateFromSettings` which required us to set `InitialRows`
and `InitialCols` on the incoming settings object (see core tenet 2).
Refs #19261
Refs #19314
Refs #19254
2025-09-03 14:01:36 -05:00
|
|
|
VERIFY_IS_TRUE(core->_settings.UseAcrylic());
|
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
|
|
|
}
|
2021-09-20 12:08:13 -05:00
|
|
|
|
|
|
|
|
// GH#603: Adjusting opacity shouldn't change whether or not we
|
|
|
|
|
// requested acrylic.
|
2021-10-07 06:39:20 -05:00
|
|
|
|
2024-04-23 02:07:00 +02:00
|
|
|
auto expectedUseAcrylic = expectedOpacity < 1.0f;
|
Remove TerminalSettings from the TerminalSettingsModel project (#19262)
The idea with IControlSettings (and friends) was always that a consumer
of the terminal control could implement it in whatever way they pleased.
Windows Terminal (the application) was intended to be only one
consumer. It has a whole JSON settings model. Nobody wants to think
about JSON at the Terminal Control level. We could have an "adapter" in
TerminalApp, which spoke Terminal JSON Settings on one side and Terminal
Control on the other side.
That worked until we added the settings editor. The settings editor
needed to display a control, and that control's settings needed to be
based on the JSON settings. Oops. We took the expedient route of moving
the adapter into TerminalSettingsModel itself, and poking a bunch of
holes in it so that TerminalApp and TerminalSettingsEditor could tweak
it as needed.
Later, we doubled down on the control settings interface by having every
Terminal Control _make its own ControlSettings_ when we were going to do
the multi-process model. This reduced the number of IPC round trips for
every settings query to 0. Later we built color scheme previewing on top
of that--adding structs to carry color schemes and stuff which was
already in the Appearance config. Sheesh. Layers and layers and layers.
This pull request moves it back into its own library and strips it from
the surface of TerminalSettingsModel. It also deletes `ControlSettings`
and `struct CoreScheme`. That library is called
`TerminalSettingsAppAdapterLib`, and it contains a hidden WinRT
_implements_ type rather than a full-fledged activatable `runtimeclass`.
It also implements one-level inheritance on its own rather than using
IInheritable.
It adheres to the following principles:
- The control will never modify its settings in a way that is visible to
the control's consumer; therefore, none of the properties have setters
- The settings should never contain things of interest only to the
Application that the Application uses to communicate data _back to
itself_ (see `ProfileName`, removed in 68b723c and `KeyBindings`,
removed in fa09141). This generalizes to "we should never store stuff
in an unrelated object passed between layers solely for the purpose of
getting it back".
I made a few changes to the settings interface, including introducing a
new `ICoreScheme` interface that _only_ contains color scheme info. This
is designed to support the Preview/Set color scheme actions, which no
longer work by _app backing up the scheme and restoring it later._ All
of that machinery lives inside TermControl/ControlCore now.
`ICoreScheme` no longer supports `GetColorAtIndex`; you must read all 16
colors at the same time. I am not sorry. Every consumer did that
already, so now we have 15 fewer COM calls for every color scheme.
The new TerminalSettings is mostly consumed via
`com_ptr<TerminalSettings>`, so a bunch of `.` (projected) accesses had
to turn into `->` (com_ptr dereferencing) accesses.
I also realized, in the course of this work, that the old
TerminalSettings contained a partial hand-written reimplementation of
_every setting_ in `ControlProperties`. Every contributor had to add
every new setting to both places--why? I can't figure it out. I'm using
ControlProperties comprehensively now. I propagated any setting whose
default value was different from that in ControlProperties back to
ControlProperties.
This is part X in a series of pull requests that will remove all mention
of Microsoft.Terminal.Control and Microsoft.Terminal.Core from the
settings model. Once that is done, the settings model can consume _only_
the base WinRT types and build very early and test more easily.
Previewing is fun. I introduced a new place to stash an entire color
table on ControlCore, which we use to save the "active" colors while we
temporarily overwrite them. SetColorScheme is _also_ fun. We now have a
slot for overriding only the focused color scheme on ControlCore. It's
fine. It's clearer than "back up the focused appearance, overwrite the
focused appearance, create a child of the user's settings and apply the
color scheme to it, etc.".
There is a bug/design choice in color scheme overriding, which may or
may not matter: overlaying a color scheme on a terminal with an
unfocused appearance which _does not_ have its own color scheme will
result in the previously-deleted overridden focused color scheme peeking
through when the terminal is not focused.
I also got rid of our only in-product use of
`Terminal::CreateFromSettings` which required us to set `InitialRows`
and `InitialCols` on the incoming settings object (see core tenet 2).
Refs #19261
Refs #19314
Refs #19254
2025-09-03 14:01:36 -05:00
|
|
|
VERIFY_IS_TRUE(core->_settings.UseAcrylic());
|
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
|
|
|
VERIFY_ARE_EQUAL(expectedUseAcrylic, core->UseAcrylic());
|
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->TransparencyChanged(opacityCallback);
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_FALSE(core->_initializedTerminal);
|
|
|
|
|
// "Cascadia Mono" ends up with an actual size of 9x19 at 96DPI. So
|
|
|
|
|
// let's just arbitrarily start with a 270x380px (30x20 chars) window
|
|
|
|
|
core->Initialize(270, 380, 1.0);
|
|
|
|
|
VERIFY_IS_TRUE(core->_initializedTerminal);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Increasing opacity till fully opaque");
|
2024-04-23 02:07:00 +02:00
|
|
|
expectedOpacity += 0.1f; // = 0.6;
|
|
|
|
|
core->AdjustOpacity(0.1f);
|
|
|
|
|
expectedOpacity += 0.1f; // = 0.7;
|
|
|
|
|
core->AdjustOpacity(0.1f);
|
|
|
|
|
expectedOpacity += 0.1f; // = 0.8;
|
|
|
|
|
core->AdjustOpacity(0.1f);
|
|
|
|
|
expectedOpacity += 0.1f; // = 0.9;
|
|
|
|
|
core->AdjustOpacity(0.1f);
|
|
|
|
|
expectedOpacity += 0.1f; // = 1.0;
|
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
|
|
|
// cast to float because floating point numbers are mean
|
2024-04-23 02:07:00 +02:00
|
|
|
VERIFY_ARE_EQUAL(1.0f, expectedOpacity);
|
|
|
|
|
core->AdjustOpacity(0.1f);
|
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
|
|
|
|
|
|
|
|
Log::Comment(L"Increasing opacity more doesn't actually change it to be >1.0");
|
|
|
|
|
|
2024-04-23 02:07:00 +02:00
|
|
|
expectedOpacity = 1.0f;
|
|
|
|
|
core->AdjustOpacity(0.1f);
|
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
|
|
|
|
|
|
|
|
Log::Comment(L"Decrease opacity");
|
2024-04-23 02:07:00 +02:00
|
|
|
expectedOpacity -= 0.25f; // = 0.75;
|
|
|
|
|
core->AdjustOpacity(-0.25f);
|
|
|
|
|
expectedOpacity -= 0.25f; // = 0.5;
|
|
|
|
|
core->AdjustOpacity(-0.25f);
|
|
|
|
|
expectedOpacity -= 0.25f; // = 0.25;
|
|
|
|
|
core->AdjustOpacity(-0.25f);
|
|
|
|
|
expectedOpacity -= 0.25f; // = 0.05;
|
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
|
|
|
// cast to float because floating point numbers are mean
|
2024-04-23 02:07:00 +02:00
|
|
|
VERIFY_ARE_EQUAL(0.0f, expectedOpacity);
|
|
|
|
|
core->AdjustOpacity(-0.25f);
|
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
|
|
|
|
|
|
|
|
Log::Comment(L"Decreasing opacity more doesn't actually change it to be < 0");
|
2024-04-23 02:07:00 +02:00
|
|
|
expectedOpacity = 0.0f;
|
|
|
|
|
core->AdjustOpacity(-0.25f);
|
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
|
|
|
}
|
|
|
|
|
|
2026-06-08 16:47:10 -07:00
|
|
|
void ControlCoreTests::TestRuntimeOpacitySurvivesSettingsReload()
|
|
|
|
|
{
|
|
|
|
|
// GH#12424: a runtime opacity adjustment (Ctrl+Shift+scroll / adjustOpacity)
|
|
|
|
|
// must survive a settings reload as a delta over the new settings opacity,
|
|
|
|
|
// rather than snapping back to the configured value.
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
|
|
|
|
|
settings->UseAcrylic(true);
|
|
|
|
|
settings->Opacity(0.5f);
|
|
|
|
|
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
core->Initialize(270, 380, 1.0);
|
|
|
|
|
VERIFY_IS_TRUE(core->_initializedTerminal);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Adjust opacity at runtime: 0.5 -> 0.7 (delta +0.2)");
|
|
|
|
|
core->AdjustOpacity(0.2f);
|
|
|
|
|
VERIFY_ARE_EQUAL(0.7f, core->Opacity());
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Reload settings with a different opacity (0.4). A reload builds a "
|
|
|
|
|
L"fresh settings object, so use a separate mock here.");
|
|
|
|
|
auto reloaded = winrt::make_self<MockControlSettings>();
|
|
|
|
|
reloaded->UseAcrylic(true);
|
|
|
|
|
reloaded->Opacity(0.4f);
|
|
|
|
|
core->UpdateSettings(*reloaded, *reloaded);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"The runtime delta (+0.2) rides on top of the new settings opacity "
|
|
|
|
|
L"(0.4) -> 0.6, instead of being stomped back to 0.4.");
|
|
|
|
|
VERIFY_ARE_EQUAL(0.6f, core->Opacity());
|
|
|
|
|
// Acrylic follows the resolved (runtime-preserved) opacity, which is < 1.0.
|
|
|
|
|
VERIFY_IS_TRUE(core->UseAcrylic());
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"With no runtime adjustment, a reload follows the settings opacity.");
|
|
|
|
|
auto core2 = createCore(*settings, *conn);
|
|
|
|
|
core2->Initialize(270, 380, 1.0);
|
|
|
|
|
VERIFY_ARE_EQUAL(0.5f, core2->Opacity());
|
|
|
|
|
auto reloaded2 = winrt::make_self<MockControlSettings>();
|
|
|
|
|
reloaded2->UseAcrylic(true);
|
|
|
|
|
reloaded2->Opacity(0.3f);
|
|
|
|
|
core2->UpdateSettings(*reloaded2, *reloaded2);
|
|
|
|
|
VERIFY_ARE_EQUAL(0.3f, core2->Opacity());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlCoreTests::TestReadOnlySurvivesSettingsReload()
|
|
|
|
|
{
|
|
|
|
|
// GH#12424: a runtime read-only toggle must not be reset by a settings reload.
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
core->Initialize(270, 380, 1.0);
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_FALSE(core->IsInReadOnlyMode());
|
|
|
|
|
core->SetReadOnlyMode(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->IsInReadOnlyMode());
|
|
|
|
|
|
|
|
|
|
auto reloaded = winrt::make_self<MockControlSettings>();
|
|
|
|
|
core->UpdateSettings(*reloaded, *reloaded);
|
|
|
|
|
VERIFY_IS_TRUE(core->IsInReadOnlyMode());
|
|
|
|
|
}
|
|
|
|
|
|
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 ControlCoreTests::TestFreeAfterClose()
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
|
Allow `ThrottledFunc` to work on different types of dispatcher (#10187)
#### ⚠️ targets #10051
## Summary of the Pull Request
This updates our `ThrottledFunc`s to take a dispatcher parameter. This means that we can use the `Windows::UI::Core::CoreDispatcher` in the `TermControl`, where there's always a `CoreDispatcher`, and use a `Windows::System::DispatcherQueue` in `ControlCore`/`ControlInteractivity`. When running in-proc, these are always the _same thing_. However, out-of-proc, the core needs a dispatcher queue that's not tied to a UI thread (because the content proces _doesn't have a UI thread!_).
This lets us get rid of the output event, because we don't need to bubble that event out to the `TermControl` to let it throttle that update anymore.
## References
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5
## PR Checklist
* [x] This is a part of #1256
* [x] I work here
* [n/a] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Fortunately, `winrt::resume_foreground` works the same on both a `CoreDispatcher` and a `DispatcherQueue`, so this wasn't too hard!
## Validation Steps Performed
This was validated in `dev/migrie/oop/the-whole-thing` (or `dev/migrie/oop/connection-factory`, I forget which), and I made sure that it worked both in-proc and x-proc. Not only that, _it wasn't any slower_!This reverts commit 04b751faa70680bf0296063deacec4657c6ff9d6.
2021-08-09 10:21:59 -05:00
|
|
|
auto core = createCore(*settings, *conn);
|
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
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Close the Core, like a TermControl would");
|
|
|
|
|
core->Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_TRUE(true, L"Make sure that the test didn't crash when the core when out of scope");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlCoreTests::TestFontInitializedInCtor()
|
|
|
|
|
{
|
|
|
|
|
// This is to catch a dumb programming mistake I made while working on
|
|
|
|
|
// the core/control split. We want the font initialized in the ctor,
|
|
|
|
|
// before we even get to Core::Initialize.
|
|
|
|
|
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
|
|
|
|
|
// Make sure to use something dumb like "Impact" as a font name here so
|
|
|
|
|
// that you don't default to Cascadia*
|
|
|
|
|
settings->FontFace(L"Impact");
|
|
|
|
|
|
Allow `ThrottledFunc` to work on different types of dispatcher (#10187)
#### ⚠️ targets #10051
## Summary of the Pull Request
This updates our `ThrottledFunc`s to take a dispatcher parameter. This means that we can use the `Windows::UI::Core::CoreDispatcher` in the `TermControl`, where there's always a `CoreDispatcher`, and use a `Windows::System::DispatcherQueue` in `ControlCore`/`ControlInteractivity`. When running in-proc, these are always the _same thing_. However, out-of-proc, the core needs a dispatcher queue that's not tied to a UI thread (because the content proces _doesn't have a UI thread!_).
This lets us get rid of the output event, because we don't need to bubble that event out to the `TermControl` to let it throttle that update anymore.
## References
* Tear-out: #1256
* Megathread: #5000
* Project: https://github.com/microsoft/terminal/projects/5
## PR Checklist
* [x] This is a part of #1256
* [x] I work here
* [n/a] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Fortunately, `winrt::resume_foreground` works the same on both a `CoreDispatcher` and a `DispatcherQueue`, so this wasn't too hard!
## Validation Steps Performed
This was validated in `dev/migrie/oop/the-whole-thing` (or `dev/migrie/oop/connection-factory`, I forget which), and I made sure that it worked both in-proc and x-proc. Not only that, _it wasn't any slower_!This reverts commit 04b751faa70680bf0296063deacec4657c6ff9d6.
2021-08-09 10:21:59 -05:00
|
|
|
auto core = createCore(*settings, *conn);
|
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
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
|
|
|
|
|
VERIFY_ARE_EQUAL(L"Impact", std::wstring_view{ core->_actualFont.GetFaceName() });
|
2021-04-05 11:07:55 -05:00
|
|
|
}
|
|
|
|
|
|
2021-09-02 09:59:42 -05:00
|
|
|
void ControlCoreTests::TestClearScrollback()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
2021-09-20 12:08:13 -05:00
|
|
|
auto core = createCore(*settings, *conn);
|
2021-09-02 09:59:42 -05:00
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print 40 rows of 'Foo', and a single row of 'Bar' "
|
2025-06-25 18:31:28 +02:00
|
|
|
L"(leaving the cursor after 'Bar')");
|
2022-04-25 17:40:47 +02:00
|
|
|
for (auto i = 0; i < 40; ++i)
|
2021-09-02 09:59:42 -05:00
|
|
|
{
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
|
2021-09-02 09:59:42 -05:00
|
|
|
}
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Bar"));
|
2021-09-02 09:59:42 -05:00
|
|
|
|
|
|
|
|
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
|
|
|
|
|
Log::Comment(L"Check the buffer viewport before the clear");
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
|
|
|
|
|
VERIFY_ARE_EQUAL(21, core->ScrollOffset());
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->ViewHeight());
|
|
|
|
|
VERIFY_ARE_EQUAL(41, core->BufferHeight());
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Clear the buffer");
|
|
|
|
|
core->ClearBuffer(Control::ClearBufferType::Scrollback);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the buffer after the clear");
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
|
|
|
|
|
VERIFY_ARE_EQUAL(0, core->ScrollOffset());
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->ViewHeight());
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->BufferHeight());
|
|
|
|
|
|
|
|
|
|
// In this test, we can't actually check if we cleared the buffer
|
|
|
|
|
// contents. ConPTY will handle the actual clearing of the buffer
|
|
|
|
|
// contents. We can only ensure that the viewport moved when we did a
|
|
|
|
|
// clear scrollback.
|
|
|
|
|
}
|
|
|
|
|
void ControlCoreTests::TestClearScreen()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
2021-09-20 12:08:13 -05:00
|
|
|
auto core = createCore(*settings, *conn);
|
2021-09-02 09:59:42 -05:00
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print 40 rows of 'Foo', and a single row of 'Bar' "
|
2025-06-25 18:31:28 +02:00
|
|
|
L"(leaving the cursor after 'Bar')");
|
2022-04-25 17:40:47 +02:00
|
|
|
for (auto i = 0; i < 40; ++i)
|
2021-09-02 09:59:42 -05:00
|
|
|
{
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
|
2021-09-02 09:59:42 -05:00
|
|
|
}
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Bar"));
|
2021-09-02 09:59:42 -05:00
|
|
|
|
|
|
|
|
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
|
|
|
|
|
Log::Comment(L"Check the buffer viewport before the clear");
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
|
|
|
|
|
VERIFY_ARE_EQUAL(21, core->ScrollOffset());
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->ViewHeight());
|
|
|
|
|
VERIFY_ARE_EQUAL(41, core->BufferHeight());
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Clear the buffer");
|
|
|
|
|
core->ClearBuffer(Control::ClearBufferType::Screen);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the buffer after the clear");
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
|
2025-06-25 18:31:28 +02:00
|
|
|
VERIFY_ARE_EQUAL(21, core->ScrollOffset());
|
2021-09-02 09:59:42 -05:00
|
|
|
VERIFY_ARE_EQUAL(20, core->ViewHeight());
|
2025-06-25 18:31:28 +02:00
|
|
|
VERIFY_ARE_EQUAL(41, core->BufferHeight());
|
2021-09-02 09:59:42 -05:00
|
|
|
|
|
|
|
|
// In this test, we can't actually check if we cleared the buffer
|
|
|
|
|
// contents. ConPTY will handle the actual clearing of the buffer
|
|
|
|
|
// contents. We can only ensure that the viewport moved when we did a
|
|
|
|
|
// clear scrollback.
|
|
|
|
|
}
|
|
|
|
|
void ControlCoreTests::TestClearAll()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
2021-09-20 12:08:13 -05:00
|
|
|
auto core = createCore(*settings, *conn);
|
2021-09-02 09:59:42 -05:00
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print 40 rows of 'Foo', and a single row of 'Bar' "
|
2025-06-25 18:31:28 +02:00
|
|
|
L"(leaving the cursor after 'Bar')");
|
2022-04-25 17:40:47 +02:00
|
|
|
for (auto i = 0; i < 40; ++i)
|
2021-09-02 09:59:42 -05:00
|
|
|
{
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo\r\n"));
|
2021-09-02 09:59:42 -05:00
|
|
|
}
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Bar"));
|
2021-09-02 09:59:42 -05:00
|
|
|
|
|
|
|
|
// We printed that 40 times, but the final \r\n bumped the view down one MORE row.
|
|
|
|
|
Log::Comment(L"Check the buffer viewport before the clear");
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
|
|
|
|
|
VERIFY_ARE_EQUAL(21, core->ScrollOffset());
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->ViewHeight());
|
|
|
|
|
VERIFY_ARE_EQUAL(41, core->BufferHeight());
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Clear the buffer");
|
|
|
|
|
core->ClearBuffer(Control::ClearBufferType::All);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the buffer after the clear");
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->_terminal->GetViewport().Height());
|
|
|
|
|
VERIFY_ARE_EQUAL(0, core->ScrollOffset());
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->ViewHeight());
|
|
|
|
|
VERIFY_ARE_EQUAL(20, core->BufferHeight());
|
|
|
|
|
|
|
|
|
|
// In this test, we can't actually check if we cleared the buffer
|
|
|
|
|
// contents. ConPTY will handle the actual clearing of the buffer
|
|
|
|
|
// contents. We can only ensure that the viewport moved when we did a
|
|
|
|
|
// clear scrollback.
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-12 23:31:10 +00:00
|
|
|
void ControlCoreTests::TestReadEntireBuffer()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print some text");
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
|
2022-11-12 23:31:10 +00:00
|
|
|
|
|
|
|
|
Log::Comment(L"Check the buffer contents");
|
|
|
|
|
VERIFY_ARE_EQUAL(L"This is some text\r\nwith varying amounts\r\nof whitespace\r\n",
|
|
|
|
|
core->ReadEntireBuffer());
|
|
|
|
|
}
|
2024-08-14 04:35:47 +02:00
|
|
|
|
|
|
|
|
static void _writePrompt(const winrt::com_ptr<MockConnection>& conn, const std::wstring_view& path)
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
{
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;D\x7"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\x7"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]9;9;"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(path));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x7"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"PWSH "));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(path));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"> "));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;B\x7"));
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlCoreTests::TestSelectCommandSimple()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print some text");
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the buffer contents");
|
|
|
|
|
const auto& buffer = core->_terminal->GetTextBuffer();
|
|
|
|
|
const auto& cursor = buffer.GetCursor();
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const til::point expectedCursor{ 17, 4 };
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition());
|
|
|
|
|
}
|
2022-11-12 23:31:10 +00:00
|
|
|
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
VERIFY_IS_FALSE(core->HasSelection());
|
|
|
|
|
core->SelectCommand(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 17, 0 };
|
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 til::point expectedEnd{ 24, 0 };
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
core->_terminal->ClearSelection();
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Boo-far"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
|
|
|
|
|
VERIFY_IS_FALSE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const til::point expectedCursor{ 24, 4 };
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition());
|
|
|
|
|
}
|
|
|
|
|
VERIFY_IS_FALSE(core->HasSelection());
|
|
|
|
|
core->SelectCommand(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 17, 4 };
|
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 til::point expectedEnd{ 24, 4 };
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
core->SelectCommand(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 17, 0 };
|
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 til::point expectedEnd{ 24, 0 };
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
core->SelectCommand(false);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 17, 4 };
|
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 til::point expectedEnd{ 24, 4 };
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void ControlCoreTests::TestSelectOutputSimple()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print some text");
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the buffer contents");
|
|
|
|
|
const auto& buffer = core->_terminal->GetTextBuffer();
|
|
|
|
|
const auto& cursor = buffer.GetCursor();
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const til::point expectedCursor{ 17, 4 };
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_FALSE(core->HasSelection());
|
|
|
|
|
core->SelectOutput(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
2024-05-01 10:06:33 -05:00
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 24, 0 }; // The character after the prompt
|
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 til::point expectedEnd{ 22, 3 }; // x = the end of the text + 1 (exclusive end)
|
2024-05-01 10:06:33 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-13 12:36:27 -05:00
|
|
|
void ControlCoreTests::TestCommandContext()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print some text");
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
2024-05-13 12:36:27 -05:00
|
|
|
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
|
2024-05-13 12:36:27 -05:00
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the command context");
|
|
|
|
|
|
|
|
|
|
const WEX::TestExecution::DisableVerifyExceptions disableExceptionsScope;
|
|
|
|
|
{
|
|
|
|
|
auto historyContext{ core->CommandHistory() };
|
|
|
|
|
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
|
|
|
|
|
VERIFY_ARE_EQUAL(L"", historyContext.CurrentCommandline());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Write 'Bar' to the command...");
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Bar"));
|
2024-05-13 12:36:27 -05:00
|
|
|
{
|
|
|
|
|
auto historyContext{ core->CommandHistory() };
|
|
|
|
|
// Bar shouldn't be in the history, it should be the current command
|
|
|
|
|
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
|
|
|
|
|
VERIFY_ARE_EQUAL(L"Bar", historyContext.CurrentCommandline());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"then delete it");
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\b \b"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\b \b"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\b \b"));
|
2024-05-13 12:36:27 -05:00
|
|
|
{
|
|
|
|
|
auto historyContext{ core->CommandHistory() };
|
|
|
|
|
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
|
|
|
|
|
// The current commandline is now empty
|
|
|
|
|
VERIFY_ARE_EQUAL(L"", historyContext.CurrentCommandline());
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-01 10:06:33 -05:00
|
|
|
|
2024-08-23 14:24:34 -05:00
|
|
|
void ControlCoreTests::TestCommandContextWithPwshGhostText()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print some text");
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
|
|
|
|
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the command context");
|
|
|
|
|
|
|
|
|
|
const WEX::TestExecution::DisableVerifyExceptions disableExceptionsScope;
|
|
|
|
|
{
|
|
|
|
|
auto historyContext{ core->CommandHistory() };
|
|
|
|
|
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
|
|
|
|
|
VERIFY_ARE_EQUAL(L"", historyContext.CurrentCommandline());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Write 'BarBar' to the command...");
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"BarBar"));
|
|
|
|
|
{
|
|
|
|
|
auto historyContext{ core->CommandHistory() };
|
|
|
|
|
// BarBar shouldn't be in the history, it should be the current command
|
|
|
|
|
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
|
|
|
|
|
VERIFY_ARE_EQUAL(L"BarBar", historyContext.CurrentCommandline());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"then move the cursor to the left");
|
Refresh check-spelling metadata for v0.0.26 (#20141)
This is a refresh of spell-check-this, more or less as of
https://github.com/check-spelling/spell-check-this/tree/e089393b4e834a8b44d585e684f06d5642537818.
## References and Relevant Issues
A number of changes take advantage of features from
http://github.com/check-spelling/check-spelling/releases/v0.0.26
1.
[`load-config-from`](https://docs.check-spelling.dev/Configuration#load-config-from)
will allow future PRs to switch cleanly w/o the mess that this PR has --
once this merges, the `config.json` file will be used for the three
dictionary configuration elements instead of the ones in the workflow.
2. `contents: read` is no longer needed by the comment jobs as the data
is provided by the main job
Contains fixes for the following specific issues:
`without`, `with`, `with the`, `with the window`, `will be`,
`whether or not`, `where the`, `using`, `uppercase or lowercase`,
`unit testing`, `to`, `to which...`, `to which`,
`to which the view refers`, `to which the pane was moved`,
`to run a command/switch to a tab/...`,
`to retrieve the user selected command`, `time,`, `the...that the`,
`the session's initial directory`, `that`, `that will ask`, `that the`,
`that opened the first flyout`, `same as terminal,`, `results,`,
`queue,`, `please`, `pane,`, `out-of-date`, `our`, `one`, `on-screen`,
`often`, `off-screen`, `of a`, `little-endian`, `left over`,
`includes, at a minimum,`, `know of`, `its`,
`if, after the calculation,`, `if`, `if we have an`, `if dragging`,
`if commands`, `guard,`, `given process information in a list`,
`from which`, `from creating`, `for which...`, `for the axis`,
`for initializing the buffer`, `containing the cursor`, `console-wait`,
`change`, `bytes`, `be`, `baseline,`, `aumid`, `at`, `ask me *again*`,
`an`, `also need to`, `again`, `add`, `add event`, `about spelunking`,
(rewrite `Appearances::_UpdateWithNewViewModel` comment), `'a'`, and ` (`
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2026-04-24 18:50:42 -04:00
|
|
|
// This emulates the state the buffer is in when pwsh does its "ghost
|
2024-08-23 14:24:34 -05:00
|
|
|
// text" thing. We don't want to include all that ghost text in the
|
|
|
|
|
// current commandline.
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b[D"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b[D"));
|
|
|
|
|
{
|
|
|
|
|
auto historyContext{ core->CommandHistory() };
|
|
|
|
|
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
|
|
|
|
|
// The current commandline is only the text to the left of the cursor
|
|
|
|
|
auto curr{ historyContext.CurrentCommandline() };
|
|
|
|
|
VERIFY_ARE_EQUAL(4u, curr.size());
|
|
|
|
|
VERIFY_ARE_EQUAL(L"BarB", curr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 10:06:33 -05:00
|
|
|
void ControlCoreTests::TestSelectOutputScrolling()
|
|
|
|
|
{
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print some text");
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows"); // row 0
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar")); // row 0
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
2024-05-01 10:06:33 -05:00
|
|
|
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n")); // row 1
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n")); // row 2
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n")); // row 3
|
2024-05-01 10:06:33 -05:00
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows"); // row 4
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"gci"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
|
2024-05-01 10:06:33 -05:00
|
|
|
|
|
|
|
|
// enough to scroll
|
|
|
|
|
for (auto i = 0; i < 30; i++) // row 5-34
|
|
|
|
|
{
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"-a--- 2/8/2024 9:47 README\r\n"));
|
2024-05-01 10:06:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the buffer contents");
|
|
|
|
|
const auto& buffer = core->_terminal->GetTextBuffer();
|
|
|
|
|
const auto& cursor = buffer.GetCursor();
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const til::point expectedCursor{ 17, 35 };
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_FALSE(core->HasSelection());
|
|
|
|
|
|
|
|
|
|
// The second mark is the first one we'll see
|
|
|
|
|
core->SelectOutput(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 20, 4 }; // The character after the prompt
|
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 til::point expectedEnd{ 27, 34 }; // x = the end of the text + 1 (exclusive end)
|
2024-05-01 10:06:33 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
core->SelectOutput(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 24, 0 }; // The character after the prompt
|
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 til::point expectedEnd{ 22, 3 }; // x = the end of the text + 1 (exclusive end)
|
2024-05-01 10:06:33 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ControlCoreTests::TestSelectOutputExactWrap()
|
|
|
|
|
{
|
|
|
|
|
// Just like the TestSelectOutputScrolling test, but these lines will
|
Refresh check-spelling metadata for v0.0.26 (#20141)
This is a refresh of spell-check-this, more or less as of
https://github.com/check-spelling/spell-check-this/tree/e089393b4e834a8b44d585e684f06d5642537818.
## References and Relevant Issues
A number of changes take advantage of features from
http://github.com/check-spelling/check-spelling/releases/v0.0.26
1.
[`load-config-from`](https://docs.check-spelling.dev/Configuration#load-config-from)
will allow future PRs to switch cleanly w/o the mess that this PR has --
once this merges, the `config.json` file will be used for the three
dictionary configuration elements instead of the ones in the workflow.
2. `contents: read` is no longer needed by the comment jobs as the data
is provided by the main job
Contains fixes for the following specific issues:
`without`, `with`, `with the`, `with the window`, `will be`,
`whether or not`, `where the`, `using`, `uppercase or lowercase`,
`unit testing`, `to`, `to which...`, `to which`,
`to which the view refers`, `to which the pane was moved`,
`to run a command/switch to a tab/...`,
`to retrieve the user selected command`, `time,`, `the...that the`,
`the session's initial directory`, `that`, `that will ask`, `that the`,
`that opened the first flyout`, `same as terminal,`, `results,`,
`queue,`, `please`, `pane,`, `out-of-date`, `our`, `one`, `on-screen`,
`often`, `off-screen`, `of a`, `little-endian`, `left over`,
`includes, at a minimum,`, `know of`, `its`,
`if, after the calculation,`, `if`, `if we have an`, `if dragging`,
`if commands`, `guard,`, `given process information in a list`,
`from which`, `from creating`, `for which...`, `for the axis`,
`for initializing the buffer`, `containing the cursor`, `console-wait`,
`change`, `bytes`, `be`, `baseline,`, `aumid`, `at`, `ask me *again*`,
`an`, `also need to`, `again`, `add`, `add event`, `about spelunking`,
(rewrite `Appearances::_UpdateWithNewViewModel` comment), `'a'`, and ` (`
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2026-04-24 18:50:42 -04:00
|
|
|
// exactly wrap to the right edge of the buffer, to catch an edge case
|
2024-05-01 10:06:33 -05:00
|
|
|
// present in `ControlCore::_selectSpan`
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Print some text");
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows"); // row 0
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar")); // row 0
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
2024-05-01 10:06:33 -05:00
|
|
|
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n")); // row 1
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n")); // row 2
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n")); // row 3
|
2024-05-01 10:06:33 -05:00
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows"); // row 4
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"gci"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
|
|
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
|
2024-05-01 10:06:33 -05:00
|
|
|
|
|
|
|
|
// enough to scroll
|
|
|
|
|
for (auto i = 0; i < 30; i++) // row 5-35
|
|
|
|
|
{
|
2024-08-14 04:35:47 +02:00
|
|
|
conn->WriteInput(winrt_wstring_to_array_view(L"-a--- 2/8/2024 9:47 README.md\r\n"));
|
2024-05-01 10:06:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_writePrompt(conn, L"C:\\Windows");
|
|
|
|
|
|
|
|
|
|
Log::Comment(L"Check the buffer contents");
|
|
|
|
|
const auto& buffer = core->_terminal->GetTextBuffer();
|
|
|
|
|
const auto& cursor = buffer.GetCursor();
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const til::point expectedCursor{ 17, 35 };
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_FALSE(core->HasSelection());
|
|
|
|
|
// The second mark is the first one we'll see
|
|
|
|
|
core->SelectOutput(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 20, 4 }; // The character after the prompt
|
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 til::point expectedEnd{ 30, 34 }; // x = the end of the text + 1 (exclusive end)
|
2024-05-01 10:06:33 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
core->SelectOutput(true);
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 24, 0 }; // The character after the prompt
|
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 til::point expectedEnd{ 22, 3 }; // x = the end of the text + 1 (exclusive end)
|
Add the ability to select a whole command (or its output) (#14807)
Adds two new commands, `selectOutput` and `selectCommand`. These don't
do much without shell integration enabled, unfortunately. If you do
enable it, however, you can use these commands to quickly navigate the
history to select whole commands (or their output).
Some sample JSON:
```json
{ "keys": "ctrl+shift+<", "command": { "action": "selectCommand", "direction": "prev" } },
{ "keys": "ctrl+shift+>", "command": { "action": "selectCommand", "direction": "next" } },
{ "keys": "ctrl+shift+[", "command": { "action": "selectOutput", "direction": "prev" } },
{ "keys": "ctrl+shift+]", "command": { "action": "selectOutput", "direction": "next" } },
```
**Demo gifs** in
https://github.com/microsoft/terminal/issues/4588#issuecomment-1352042789
closes #4588
Tested manually.
<details>
<summary>CMD.exe user? It's dangerous to go alone! Take this.</summary>
Surely, there's a simpler way to do it, this is adapted from my own
script.
```cmd
prompt $e]133;D$e\$e]133;A$e\$e\$e]9;9;$P$e\$e[30;107m[$T]$e[97;46m$g$P$e[36;49m$g$e[0m$e[K$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e\
```
</details>
2023-04-20 07:34:58 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-14 07:37:13 -05:00
|
|
|
|
|
|
|
|
void ControlCoreTests::TestSimpleClickSelection()
|
|
|
|
|
{
|
|
|
|
|
// Create a simple selection with the mouse, then click somewhere else,
|
|
|
|
|
// and confirm the selection got updated.
|
|
|
|
|
|
|
|
|
|
auto [settings, conn] = _createSettingsAndConnection();
|
|
|
|
|
Log::Comment(L"Create ControlCore object");
|
|
|
|
|
auto core = createCore(*settings, *conn);
|
|
|
|
|
VERIFY_IS_NOT_NULL(core);
|
|
|
|
|
_standardInit(core);
|
|
|
|
|
|
|
|
|
|
// Here, we're using the UpdateSelectionMarkers as a stand-in to check
|
|
|
|
|
// if the selection got updated with the renderer. Standing up a whole
|
|
|
|
|
// dummy renderer for this test would be not very ergonomic. Instead, we
|
|
|
|
|
// are relying on ControlCore::_updateSelectionUI both
|
|
|
|
|
// TriggerSelection()'ing and also rasing this event
|
|
|
|
|
bool expectedSelectionUpdate = false;
|
|
|
|
|
bool gotSelectionUpdate = false;
|
|
|
|
|
core->UpdateSelectionMarkers([&](auto&& /*sender*/, auto&& /*args*/) {
|
|
|
|
|
VERIFY_IS_TRUE(expectedSelectionUpdate);
|
|
|
|
|
expectedSelectionUpdate = false;
|
|
|
|
|
gotSelectionUpdate = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
auto needToCopy = false;
|
|
|
|
|
expectedSelectionUpdate = true;
|
|
|
|
|
core->LeftClickOnTerminal(til::point{ 1, 1 },
|
|
|
|
|
1,
|
|
|
|
|
false,
|
|
|
|
|
true,
|
|
|
|
|
false,
|
|
|
|
|
needToCopy);
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 1, 1 };
|
|
|
|
|
const til::point expectedEnd{ 1, 1 };
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
VERIFY_IS_TRUE(gotSelectionUpdate);
|
|
|
|
|
|
|
|
|
|
expectedSelectionUpdate = true;
|
|
|
|
|
core->LeftClickOnTerminal(til::point{ 1, 2 },
|
|
|
|
|
1,
|
|
|
|
|
false,
|
|
|
|
|
true,
|
|
|
|
|
false,
|
|
|
|
|
needToCopy);
|
|
|
|
|
|
|
|
|
|
VERIFY_IS_TRUE(core->HasSelection());
|
|
|
|
|
{
|
|
|
|
|
const auto& start = core->_terminal->GetSelectionAnchor();
|
|
|
|
|
const auto& end = core->_terminal->GetSelectionEnd();
|
|
|
|
|
const til::point expectedStart{ 1, 1 };
|
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 til::point expectedEnd{ 2, 2 };
|
2023-08-14 07:37:13 -05:00
|
|
|
VERIFY_ARE_EQUAL(expectedStart, start);
|
|
|
|
|
VERIFY_ARE_EQUAL(expectedEnd, end);
|
|
|
|
|
}
|
|
|
|
|
VERIFY_IS_TRUE(gotSelectionUpdate);
|
|
|
|
|
}
|
2021-04-05 11:07:55 -05:00
|
|
|
}
|