2019-06-07 23:56:44 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "Pane.h"
|
2020-09-09 22:49:53 +02:00
|
|
|
#include "AppLogic.h"
|
2019-11-25 23:22:29 +01:00
|
|
|
|
2020-10-16 00:27:27 +02:00
|
|
|
#include <Mmsystem.h>
|
|
|
|
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
using namespace winrt::Windows::Foundation;
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
using namespace winrt::Windows::Graphics::Display;
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
using namespace winrt::Windows::UI;
|
2019-06-07 23:56:44 +02:00
|
|
|
using namespace winrt::Windows::UI::Xaml;
|
|
|
|
using namespace winrt::Windows::UI::Core;
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
using namespace winrt::Windows::UI::Xaml::Media;
|
2020-10-06 18:56:59 +02:00
|
|
|
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
2021-03-17 21:47:24 +01:00
|
|
|
using namespace winrt::Microsoft::Terminal::Control;
|
2019-11-25 23:22:29 +01:00
|
|
|
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
using namespace winrt::TerminalApp;
|
2019-11-25 23:22:29 +01:00
|
|
|
using namespace TerminalApp;
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
static const int PaneBorderSize = 2;
|
|
|
|
static const int CombinedPaneBorderSize = 2 * PaneBorderSize;
|
2019-06-07 23:56:44 +02:00
|
|
|
|
2020-10-10 01:06:40 +02:00
|
|
|
// WARNING: Don't do this! This won't work
|
|
|
|
// Duration duration{ std::chrono::milliseconds{ 200 } };
|
|
|
|
// Instead, make a duration from a TimeSpan from the time in millis
|
|
|
|
//
|
|
|
|
// 200ms was chosen because it's quick enough that it doesn't break your
|
|
|
|
// flow, but not too quick to see
|
|
|
|
static const int AnimationDurationInMilliseconds = 200;
|
|
|
|
static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(AnimationDurationInMilliseconds)));
|
|
|
|
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr };
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr };
|
2021-11-16 16:40:23 +01:00
|
|
|
winrt::Windows::Media::Playback::MediaPlayer Pane::s_bellPlayer = { nullptr };
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
2021-08-23 19:11:53 +02:00
|
|
|
Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFocused) :
|
2019-06-07 23:56:44 +02:00
|
|
|
_control{ control },
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
_lastActive{ lastFocused },
|
2019-06-07 23:56:44 +02:00
|
|
|
_profile{ profile }
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_root.Children().Append(_borderFirst);
|
|
|
|
_borderFirst.Child(_control);
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
2019-11-25 23:22:29 +01:00
|
|
|
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
|
2020-10-16 00:27:27 +02:00
|
|
|
_warningBellToken = _control.WarningBell({ this, &Pane::_ControlWarningBellHandler });
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// On the first Pane's creation, lookup resources we'll use to theme the
|
|
|
|
// Pane, including the brushed to use for the focused/unfocused border
|
|
|
|
// color.
|
|
|
|
if (s_focusedBorderBrush == nullptr || s_unfocusedBorderBrush == nullptr)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
_SetupResources();
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// Register an event with the control to have it inform us when it gains focus.
|
2021-08-26 00:49:26 +02:00
|
|
|
_gotFocusRevoker = _control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
|
|
|
|
_lostFocusRevoker = _control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
|
|
|
|
// When our border is tapped, make sure to transfer focus to our control.
|
|
|
|
// LOAD-BEARING: This will NOT work if the border's BorderBrush is set to
|
|
|
|
// Colors::Transparent! The border won't get Tapped events, and they'll fall
|
|
|
|
// through to something else.
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_borderFirst.Tapped([this](auto&, auto& e) {
|
|
|
|
_FocusFirstChild();
|
|
|
|
e.Handled(true);
|
|
|
|
});
|
|
|
|
_borderSecond.Tapped([this](auto&, auto& e) {
|
|
|
|
_FocusFirstChild();
|
|
|
|
e.Handled(true);
|
|
|
|
});
|
2021-11-01 18:46:00 +01:00
|
|
|
|
2021-11-16 16:40:23 +01:00
|
|
|
if (!s_bellPlayer)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
s_bellPlayer = winrt::Windows::Media::Playback::MediaPlayer();
|
2021-11-16 16:51:33 +01:00
|
|
|
if (s_bellPlayer)
|
|
|
|
{
|
|
|
|
// BODGY
|
|
|
|
//
|
|
|
|
// Manually leak a ref to the MediaPlayer we just instantiated.
|
|
|
|
// We're doing this just like the way we do in AppHost with the
|
|
|
|
// App itself.
|
|
|
|
//
|
|
|
|
// We have to do this because there's some bug in the OS with
|
|
|
|
// the way a MediaPlayer gets torn down. At time fo writing (Nov
|
|
|
|
// 2021), if you search for `remove_SoundLevelChanged` in the OS
|
|
|
|
// repo, you'll find a pile of bugs.
|
|
|
|
//
|
|
|
|
// We tried moving the MediaPlayer singleton up to the
|
|
|
|
// TerminalPage, but alas, that teardown had the same problem.
|
|
|
|
// So _whatever_. We'll leak it here. It needs to last the
|
|
|
|
// lifetim of the app anyways, and it'll get cleaned up when the
|
|
|
|
// Termnial is closed, so whatever.
|
|
|
|
winrt::Windows::Media::Playback::MediaPlayer p{ s_bellPlayer };
|
|
|
|
::winrt::detach_abi(p);
|
|
|
|
}
|
2021-11-16 16:40:23 +01:00
|
|
|
}
|
|
|
|
CATCH_LOG();
|
|
|
|
}
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Pane::Pane(std::shared_ptr<Pane> first,
|
|
|
|
std::shared_ptr<Pane> second,
|
|
|
|
const SplitState splitState,
|
|
|
|
const float splitPosition,
|
|
|
|
const bool lastFocused) :
|
|
|
|
_firstChild{ first },
|
|
|
|
_secondChild{ second },
|
|
|
|
_splitState{ splitState },
|
|
|
|
_desiredSplitPosition{ splitPosition },
|
|
|
|
_lastActive{ lastFocused }
|
|
|
|
{
|
|
|
|
_CreateRowColDefinitions();
|
|
|
|
_borderFirst.Child(_firstChild->GetRootElement());
|
|
|
|
_borderSecond.Child(_secondChild->GetRootElement());
|
|
|
|
|
|
|
|
// Use the unfocused border color as the pane background, so an actual color
|
|
|
|
// appears behind panes as we animate them sliding in.
|
|
|
|
_root.Background(s_unfocusedBorderBrush);
|
|
|
|
|
|
|
|
_root.Children().Append(_borderFirst);
|
|
|
|
_root.Children().Append(_borderSecond);
|
|
|
|
|
|
|
|
_ApplySplitDefinitions();
|
|
|
|
|
|
|
|
// Register event handlers on our children to handle their Close events
|
|
|
|
_SetupChildCloseHandlers();
|
|
|
|
|
|
|
|
// When our border is tapped, make sure to transfer focus to our control.
|
|
|
|
// LOAD-BEARING: This will NOT work if the border's BorderBrush is set to
|
|
|
|
// Colors::Transparent! The border won't get Tapped events, and they'll fall
|
|
|
|
// through to something else.
|
|
|
|
_borderFirst.Tapped([this](auto&, auto& e) {
|
|
|
|
_FocusFirstChild();
|
|
|
|
e.Handled(true);
|
|
|
|
});
|
|
|
|
_borderSecond.Tapped([this](auto&, auto& e) {
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
_FocusFirstChild();
|
|
|
|
e.Handled(true);
|
|
|
|
});
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
Persist window layout on window close (#10972)
This commit adds initial support for saving window layout on application
close.
Done:
- Add user setting for if tabs should be maintained.
- Added events to track the number of open windows for the monarch, and
then save if you are the last window closing.
- Saves layout when the user explicitly hits the "Close Window" button.
- If the user manually closed all of their tabs (through the tab x
button or through closing all panes on the tab) then remove any saved
state.
- Saves in the ApplicationState file a list of actions the terminal can
perform to restore its layout and the window size/position
information.
- This saves an action to focus the correct pane, but this won't
actually work without #10978. Note that if you have a pane zoomed, it
does still zoom the correct pane, but when you unzoom it will have a
different pane selected.
Todo:
- multiple windows? Right now it can only handle loading/saving one
window.
- PR #11083 will save multiple windows.
- This also sometimes runs into the existing bug where multiple tabs
appear to be focused on opening.
Next Steps:
- The business logic of when the save is triggered can be adjusted as
necessary.
- Right now I am taking the pragmatic approach and just saving the state
as an array of objects, but only ever populate it with 1, that way
saving multiple windows in the future could be added without breaking
schema compatibility. Selfishly I'm hoping that handling multiple
windows could be spun off into another pr/feature for now.
- One possible thing that can maybe be done is that the commandline can
be augmented with a "--saved ##" attribute that would load from the
nth saved state if it exists. e.g. if there are 3 saved windows, on
first load it can spawn three wt --saved {0,1,2} that would reopen the
windows? This way there also exists a way to load a copy of a previous
window (if it is in the saved state).
- Is the application state something that is planned to be public/user
editable? In theory the user could since it is just json, but I don't
know what it buys them over just modifying their settings and
startupActions.
Validation Steps Performed:
- The happy path: open terminal -> set setting to true -> close terminal
-> reopen and see tabs. Tested with powershell/cmd/wsl windows.
- That closing all panes/tabs on their own will remove the saved
session.
- Open multiple windows, close windows and confirm that the last window
closed saves its state.
The generated file stores a sequence of actions that will be executed to
restore the terminal to its saved form.
References #8324
This is also one of the items on microsoft/terminal#5000
Closes #766
2021-09-09 00:44:53 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Extract the terminal settings from the current (leaf) pane's control
|
|
|
|
// to be used to create an equivalent control
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - Arguments appropriate for a SplitPane or NewTab action
|
|
|
|
NewTerminalArgs Pane::GetTerminalArgsForPane() const
|
|
|
|
{
|
|
|
|
// Leaves are the only things that have controls
|
|
|
|
assert(_IsLeaf());
|
|
|
|
|
|
|
|
NewTerminalArgs args{};
|
|
|
|
auto controlSettings = _control.Settings().as<TerminalSettings>();
|
|
|
|
|
|
|
|
args.Profile(controlSettings.ProfileName());
|
2021-10-04 14:39:29 +02:00
|
|
|
// If we know the user's working directory use it instead of the profile.
|
|
|
|
if (const auto dir = _control.WorkingDirectory(); !dir.empty())
|
|
|
|
{
|
|
|
|
args.StartingDirectory(dir);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
args.StartingDirectory(controlSettings.StartingDirectory());
|
|
|
|
}
|
Persist window layout on window close (#10972)
This commit adds initial support for saving window layout on application
close.
Done:
- Add user setting for if tabs should be maintained.
- Added events to track the number of open windows for the monarch, and
then save if you are the last window closing.
- Saves layout when the user explicitly hits the "Close Window" button.
- If the user manually closed all of their tabs (through the tab x
button or through closing all panes on the tab) then remove any saved
state.
- Saves in the ApplicationState file a list of actions the terminal can
perform to restore its layout and the window size/position
information.
- This saves an action to focus the correct pane, but this won't
actually work without #10978. Note that if you have a pane zoomed, it
does still zoom the correct pane, but when you unzoom it will have a
different pane selected.
Todo:
- multiple windows? Right now it can only handle loading/saving one
window.
- PR #11083 will save multiple windows.
- This also sometimes runs into the existing bug where multiple tabs
appear to be focused on opening.
Next Steps:
- The business logic of when the save is triggered can be adjusted as
necessary.
- Right now I am taking the pragmatic approach and just saving the state
as an array of objects, but only ever populate it with 1, that way
saving multiple windows in the future could be added without breaking
schema compatibility. Selfishly I'm hoping that handling multiple
windows could be spun off into another pr/feature for now.
- One possible thing that can maybe be done is that the commandline can
be augmented with a "--saved ##" attribute that would load from the
nth saved state if it exists. e.g. if there are 3 saved windows, on
first load it can spawn three wt --saved {0,1,2} that would reopen the
windows? This way there also exists a way to load a copy of a previous
window (if it is in the saved state).
- Is the application state something that is planned to be public/user
editable? In theory the user could since it is just json, but I don't
know what it buys them over just modifying their settings and
startupActions.
Validation Steps Performed:
- The happy path: open terminal -> set setting to true -> close terminal
-> reopen and see tabs. Tested with powershell/cmd/wsl windows.
- That closing all panes/tabs on their own will remove the saved
session.
- Open multiple windows, close windows and confirm that the last window
closed saves its state.
The generated file stores a sequence of actions that will be executed to
restore the terminal to its saved form.
References #8324
This is also one of the items on microsoft/terminal#5000
Closes #766
2021-09-09 00:44:53 +02:00
|
|
|
args.TabTitle(controlSettings.StartingTitle());
|
|
|
|
args.Commandline(controlSettings.Commandline());
|
|
|
|
args.SuppressApplicationTitle(controlSettings.SuppressApplicationTitle());
|
|
|
|
if (controlSettings.TabColor() || controlSettings.StartingTabColor())
|
|
|
|
{
|
|
|
|
til::color c;
|
|
|
|
// StartingTabColor is prioritized over other colors
|
|
|
|
if (const auto color = controlSettings.StartingTabColor())
|
|
|
|
{
|
|
|
|
c = til::color(color.Value());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = til::color(controlSettings.TabColor().Value());
|
|
|
|
}
|
|
|
|
|
|
|
|
args.TabColor(winrt::Windows::Foundation::IReference<winrt::Windows::UI::Color>(c));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (controlSettings.AppliedColorScheme())
|
|
|
|
{
|
|
|
|
auto name = controlSettings.AppliedColorScheme().Name();
|
Persist window layout cont. save multiple windows (#11083)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Continuation of https://github.com/microsoft/terminal/pull/10972 to handle multiple windows, requires that to be merged first.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Also closes #766
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Rough changelog:
Normally saving is triggered to occur every 30s, or sooner if a window is created/closed. The existing behavior of saving on last close is maintained to bypass that throttling. The automatic saving allows for crash recovery. Additionally all window layouts will be saved upon taking the `quit` action.
For loading we will check if we are the first window, that there are any saved layouts, and if the setting is enabled, and then depending on if we were given command line args or startup actions.
- create a new window for each saved layout, or
- take the first layout for our self and then a new window for each other layout.
This also saves the layout when the quit action is taken.
Misc changes
- A -s,--saved argument was added to the command line to facilitate opening all of the windows with the right settings. This also means that while a terminal session is running you can do wt -s idx to open a copy of window idx. There isn't a stable ordering of which idx each window gets saved as (it is whatever the iteration order of _peasants is), so it is just a cute hack for now.
- All position calculation has been moved up to AppHost this does mean we need to awkwardly pass around positions in a couple of unexpected places, but no solution was perfect.
- Renamed "Open tabs from a previous session" to "Open windows from a previous session". (not reflected in video below)
- Now save runtime tab color and window names
- Only enabled for non-elevated windows
- Add some change tracking to ApplicationState
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
![output](https://user-images.githubusercontent.com/6185249/131163473-d649d204-a589-41ad-b9d9-c4c0528cb684.gif)
2021-09-27 23:18:39 +02:00
|
|
|
// Only save the color scheme if it is different than the profile color
|
|
|
|
// scheme to not override any other profile appearance choices.
|
|
|
|
if (_profile.DefaultAppearance().ColorSchemeName() != name)
|
|
|
|
{
|
|
|
|
args.ColorScheme(name);
|
|
|
|
}
|
Persist window layout on window close (#10972)
This commit adds initial support for saving window layout on application
close.
Done:
- Add user setting for if tabs should be maintained.
- Added events to track the number of open windows for the monarch, and
then save if you are the last window closing.
- Saves layout when the user explicitly hits the "Close Window" button.
- If the user manually closed all of their tabs (through the tab x
button or through closing all panes on the tab) then remove any saved
state.
- Saves in the ApplicationState file a list of actions the terminal can
perform to restore its layout and the window size/position
information.
- This saves an action to focus the correct pane, but this won't
actually work without #10978. Note that if you have a pane zoomed, it
does still zoom the correct pane, but when you unzoom it will have a
different pane selected.
Todo:
- multiple windows? Right now it can only handle loading/saving one
window.
- PR #11083 will save multiple windows.
- This also sometimes runs into the existing bug where multiple tabs
appear to be focused on opening.
Next Steps:
- The business logic of when the save is triggered can be adjusted as
necessary.
- Right now I am taking the pragmatic approach and just saving the state
as an array of objects, but only ever populate it with 1, that way
saving multiple windows in the future could be added without breaking
schema compatibility. Selfishly I'm hoping that handling multiple
windows could be spun off into another pr/feature for now.
- One possible thing that can maybe be done is that the commandline can
be augmented with a "--saved ##" attribute that would load from the
nth saved state if it exists. e.g. if there are 3 saved windows, on
first load it can spawn three wt --saved {0,1,2} that would reopen the
windows? This way there also exists a way to load a copy of a previous
window (if it is in the saved state).
- Is the application state something that is planned to be public/user
editable? In theory the user could since it is just json, but I don't
know what it buys them over just modifying their settings and
startupActions.
Validation Steps Performed:
- The happy path: open terminal -> set setting to true -> close terminal
-> reopen and see tabs. Tested with powershell/cmd/wsl windows.
- That closing all panes/tabs on their own will remove the saved
session.
- Open multiple windows, close windows and confirm that the last window
closed saves its state.
The generated file stores a sequence of actions that will be executed to
restore the terminal to its saved form.
References #8324
This is also one of the items on microsoft/terminal#5000
Closes #766
2021-09-09 00:44:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Serializes the state of this tab as a series of commands that can be
|
|
|
|
// executed to recreate it.
|
|
|
|
// - This will always result in the right-most child being the focus
|
|
|
|
// after the commands finish executing.
|
|
|
|
// Arguments:
|
|
|
|
// - currentId: the id to use for the current/first pane
|
|
|
|
// - nextId: the id to use for a new pane if we split
|
|
|
|
// Return Value:
|
|
|
|
// - The state from building the startup actions, includes a vector of commands,
|
|
|
|
// the original root pane, the id of the focused pane, and the number of panes
|
|
|
|
// created.
|
|
|
|
Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t nextId)
|
|
|
|
{
|
|
|
|
// if we are a leaf then all there is to do is defer to the parent.
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
if (_lastActive)
|
|
|
|
{
|
|
|
|
return { {}, shared_from_this(), currentId, 0 };
|
|
|
|
}
|
|
|
|
|
|
|
|
return { {}, shared_from_this(), std::nullopt, 0 };
|
|
|
|
}
|
|
|
|
|
|
|
|
auto buildSplitPane = [&](auto newPane) {
|
|
|
|
ActionAndArgs actionAndArgs;
|
|
|
|
actionAndArgs.Action(ShortcutAction::SplitPane);
|
|
|
|
const auto terminalArgs{ newPane->GetTerminalArgsForPane() };
|
|
|
|
// When creating a pane the split size is the size of the new pane
|
|
|
|
// and not position.
|
2021-09-15 22:14:57 +02:00
|
|
|
const auto splitDirection = _splitState == SplitState::Horizontal ? SplitDirection::Down : SplitDirection::Right;
|
|
|
|
SplitPaneArgs args{ SplitType::Manual, splitDirection, 1. - _desiredSplitPosition, terminalArgs };
|
Persist window layout on window close (#10972)
This commit adds initial support for saving window layout on application
close.
Done:
- Add user setting for if tabs should be maintained.
- Added events to track the number of open windows for the monarch, and
then save if you are the last window closing.
- Saves layout when the user explicitly hits the "Close Window" button.
- If the user manually closed all of their tabs (through the tab x
button or through closing all panes on the tab) then remove any saved
state.
- Saves in the ApplicationState file a list of actions the terminal can
perform to restore its layout and the window size/position
information.
- This saves an action to focus the correct pane, but this won't
actually work without #10978. Note that if you have a pane zoomed, it
does still zoom the correct pane, but when you unzoom it will have a
different pane selected.
Todo:
- multiple windows? Right now it can only handle loading/saving one
window.
- PR #11083 will save multiple windows.
- This also sometimes runs into the existing bug where multiple tabs
appear to be focused on opening.
Next Steps:
- The business logic of when the save is triggered can be adjusted as
necessary.
- Right now I am taking the pragmatic approach and just saving the state
as an array of objects, but only ever populate it with 1, that way
saving multiple windows in the future could be added without breaking
schema compatibility. Selfishly I'm hoping that handling multiple
windows could be spun off into another pr/feature for now.
- One possible thing that can maybe be done is that the commandline can
be augmented with a "--saved ##" attribute that would load from the
nth saved state if it exists. e.g. if there are 3 saved windows, on
first load it can spawn three wt --saved {0,1,2} that would reopen the
windows? This way there also exists a way to load a copy of a previous
window (if it is in the saved state).
- Is the application state something that is planned to be public/user
editable? In theory the user could since it is just json, but I don't
know what it buys them over just modifying their settings and
startupActions.
Validation Steps Performed:
- The happy path: open terminal -> set setting to true -> close terminal
-> reopen and see tabs. Tested with powershell/cmd/wsl windows.
- That closing all panes/tabs on their own will remove the saved
session.
- Open multiple windows, close windows and confirm that the last window
closed saves its state.
The generated file stores a sequence of actions that will be executed to
restore the terminal to its saved form.
References #8324
This is also one of the items on microsoft/terminal#5000
Closes #766
2021-09-09 00:44:53 +02:00
|
|
|
actionAndArgs.Args(args);
|
|
|
|
|
|
|
|
return actionAndArgs;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto buildMoveFocus = [](auto direction) {
|
|
|
|
MoveFocusArgs args{ direction };
|
|
|
|
|
|
|
|
ActionAndArgs actionAndArgs{};
|
|
|
|
actionAndArgs.Action(ShortcutAction::MoveFocus);
|
|
|
|
actionAndArgs.Args(args);
|
|
|
|
|
|
|
|
return actionAndArgs;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Handle simple case of a single split (a minor optimization for clarity)
|
|
|
|
// Here we just create the second child (by splitting) and return the first
|
|
|
|
// child for the parent to deal with.
|
|
|
|
if (_firstChild->_IsLeaf() && _secondChild->_IsLeaf())
|
|
|
|
{
|
|
|
|
auto actionAndArgs = buildSplitPane(_secondChild);
|
|
|
|
std::optional<uint32_t> focusedPaneId = std::nullopt;
|
|
|
|
if (_firstChild->_lastActive)
|
|
|
|
{
|
|
|
|
focusedPaneId = currentId;
|
|
|
|
}
|
|
|
|
else if (_secondChild->_lastActive)
|
|
|
|
{
|
|
|
|
focusedPaneId = nextId;
|
|
|
|
}
|
|
|
|
|
|
|
|
return { { actionAndArgs }, _firstChild, focusedPaneId, 1 };
|
|
|
|
}
|
|
|
|
|
|
|
|
// We now need to execute the commands for each side of the tree
|
|
|
|
// We've done one split, so the first-most child will have currentId, and the
|
|
|
|
// one after it will be incremented.
|
|
|
|
auto firstState = _firstChild->BuildStartupActions(currentId, nextId + 1);
|
|
|
|
// the next id for the second branch depends on how many splits were in the
|
|
|
|
// first child.
|
|
|
|
auto secondState = _secondChild->BuildStartupActions(nextId, nextId + firstState.panesCreated + 1);
|
|
|
|
|
|
|
|
std::vector<ActionAndArgs> actions{};
|
|
|
|
actions.reserve(firstState.args.size() + secondState.args.size() + 3);
|
|
|
|
|
|
|
|
// first we make our split
|
|
|
|
const auto newSplit = buildSplitPane(secondState.firstPane);
|
|
|
|
actions.emplace_back(std::move(newSplit));
|
|
|
|
|
|
|
|
if (firstState.args.size() > 0)
|
|
|
|
{
|
|
|
|
// Then move to the first child and execute any actions on the left branch
|
|
|
|
// then move back
|
|
|
|
actions.emplace_back(buildMoveFocus(FocusDirection::PreviousInOrder));
|
|
|
|
actions.insert(actions.end(), std::make_move_iterator(std::begin(firstState.args)), std::make_move_iterator(std::end(firstState.args)));
|
|
|
|
actions.emplace_back(buildMoveFocus(FocusDirection::NextInOrder));
|
|
|
|
}
|
|
|
|
|
|
|
|
// And if there are any commands to run on the right branch do so
|
|
|
|
if (secondState.args.size() > 0)
|
|
|
|
{
|
|
|
|
actions.insert(actions.end(), std::make_move_iterator(secondState.args.begin()), std::make_move_iterator(secondState.args.end()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the tree is well-formed then f1.has_value and f2.has_value are
|
|
|
|
// mutually exclusive.
|
|
|
|
const auto focusedPaneId = firstState.focusedPaneId.has_value() ? firstState.focusedPaneId : secondState.focusedPaneId;
|
|
|
|
|
|
|
|
return { actions, firstState.firstPane, focusedPaneId, firstState.panesCreated + secondState.panesCreated + 1 };
|
|
|
|
}
|
|
|
|
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Update the size of this pane. Resizes each of our columns so they have the
|
|
|
|
// same relative sizes, given the newSize.
|
|
|
|
// - Because we're just manually setting the row/column sizes in pixels, we have
|
|
|
|
// to be told our new size, we can't just use our own OnSized event, because
|
|
|
|
// that _won't fire when we get smaller_.
|
|
|
|
// Arguments:
|
|
|
|
// - newSize: the amount of space that this pane has to fill now.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::ResizeContent(const Size& newSize)
|
|
|
|
{
|
|
|
|
const auto width = newSize.Width;
|
|
|
|
const auto height = newSize.Height;
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
_CreateRowColDefinitions();
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
if (_splitState == SplitState::Vertical)
|
|
|
|
{
|
2020-01-08 22:19:23 +01:00
|
|
|
const auto paneSizes = _CalcChildrenSizes(width);
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
const Size firstSize{ paneSizes.first, height };
|
|
|
|
const Size secondSize{ paneSizes.second, height };
|
|
|
|
_firstChild->ResizeContent(firstSize);
|
|
|
|
_secondChild->ResizeContent(secondSize);
|
|
|
|
}
|
|
|
|
else if (_splitState == SplitState::Horizontal)
|
|
|
|
{
|
2020-01-08 22:19:23 +01:00
|
|
|
const auto paneSizes = _CalcChildrenSizes(height);
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
const Size firstSize{ width, paneSizes.first };
|
|
|
|
const Size secondSize{ width, paneSizes.second };
|
|
|
|
_firstChild->ResizeContent(firstSize);
|
|
|
|
_secondChild->ResizeContent(secondSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Recalculates and reapplies sizes of all descendant panes.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::Relayout()
|
|
|
|
{
|
|
|
|
ResizeContent(_root.ActualSize());
|
|
|
|
}
|
|
|
|
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Adjust our child percentages to increase the size of one of our children
|
|
|
|
// and decrease the size of the other.
|
|
|
|
// - Adjusts the separation amount by 5%
|
|
|
|
// - Does nothing if the direction doesn't match our current split direction
|
|
|
|
// Arguments:
|
|
|
|
// - direction: the direction to move our separator. If it's down or right,
|
|
|
|
// we'll be increasing the size of the first of our children. Else, we'll be
|
|
|
|
// decreasing the size of our first child.
|
|
|
|
// Return Value:
|
|
|
|
// - false if we couldn't resize this pane in the given direction, else true.
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
bool Pane::_Resize(const ResizeDirection& direction)
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
{
|
|
|
|
if (!DirectionMatchesSplit(direction, _splitState))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
float amount = .05f;
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
if (direction == ResizeDirection::Right || direction == ResizeDirection::Down)
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
{
|
|
|
|
amount = -amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure we're not making a pane explode here by resizing it to 0 characters.
|
|
|
|
const bool changeWidth = _splitState == SplitState::Vertical;
|
|
|
|
|
|
|
|
const Size actualSize{ gsl::narrow_cast<float>(_root.ActualWidth()),
|
|
|
|
gsl::narrow_cast<float>(_root.ActualHeight()) };
|
|
|
|
// actualDimension is the size in DIPs of this pane in the direction we're
|
|
|
|
// resizing.
|
2020-01-08 22:19:23 +01:00
|
|
|
const auto actualDimension = changeWidth ? actualSize.Width : actualSize.Height;
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
_desiredSplitPosition = _ClampSplitPosition(changeWidth, _desiredSplitPosition - amount, actualDimension);
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
// Resize our columns to match the new percentages.
|
|
|
|
ResizeContent(actualSize);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Moves the separator between panes, as to resize each child on either size
|
|
|
|
// of the separator. Tries to move a separator in the given direction. The
|
|
|
|
// separator moved is the separator that's closest depth-wise to the
|
|
|
|
// currently focused pane, that's also in the correct direction to be moved.
|
|
|
|
// If there isn't such a separator, then this method returns false, as we
|
|
|
|
// couldn't handle the resize.
|
|
|
|
// Arguments:
|
|
|
|
// - direction: The direction to move the separator in.
|
|
|
|
// Return Value:
|
|
|
|
// - true if we or a child handled this resize request.
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
bool Pane::ResizePane(const ResizeDirection& direction)
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
{
|
|
|
|
// If we're a leaf, do nothing. We can't possibly have a descendant with a
|
|
|
|
// separator the correct direction.
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Check if either our first or second child is the currently focused pane.
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// If it is, and the requested resize direction matches our separator, then
|
|
|
|
// we're the pane that needs to adjust its separator.
|
|
|
|
// If our separator is the wrong direction, then we can't handle it.
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
const bool firstIsFocused = _firstChild->_lastActive;
|
|
|
|
const bool secondIsFocused = _secondChild->_lastActive;
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
if (firstIsFocused || secondIsFocused)
|
|
|
|
{
|
|
|
|
return _Resize(direction);
|
|
|
|
}
|
2019-08-28 16:40:16 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If neither of our children were the focused pane, then recurse into
|
2019-08-28 16:40:16 +02:00
|
|
|
// our children and see if they can handle the resize.
|
|
|
|
// For each child, if it has a focused descendant, try having that child
|
|
|
|
// handle the resize.
|
|
|
|
// If the child wasn't able to handle the resize, it's possible that
|
|
|
|
// there were no descendants with a separator the correct direction. If
|
|
|
|
// our separator _is_ the correct direction, then we should be the pane
|
|
|
|
// to resize. Otherwise, just return false, as we couldn't handle it
|
|
|
|
// either.
|
|
|
|
if ((!_firstChild->_IsLeaf()) && _firstChild->_HasFocusedChild())
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
{
|
2019-08-28 16:40:16 +02:00
|
|
|
return _firstChild->ResizePane(direction) || _Resize(direction);
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
}
|
2019-08-28 16:40:16 +02:00
|
|
|
|
|
|
|
if ((!_secondChild->_IsLeaf()) && _secondChild->_HasFocusedChild())
|
|
|
|
{
|
|
|
|
return _secondChild->ResizePane(direction) || _Resize(direction);
|
|
|
|
}
|
|
|
|
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-07-17 16:30:15 +02:00
|
|
|
// Method Description:
|
2021-08-17 00:33:23 +02:00
|
|
|
// - Attempt to navigate from the sourcePane according to direction.
|
|
|
|
// - If the direction is NextInOrder or PreviousInOrder, the next or previous
|
|
|
|
// leaf in the tree, respectively, will be returned.
|
|
|
|
// - If the direction is {Up, Down, Left, Right} then the visually-adjacent
|
|
|
|
// neighbor (if it exists) will be returned. If there are multiple options
|
|
|
|
// then the first-most leaf will be selected.
|
2019-07-17 16:30:15 +02:00
|
|
|
// Arguments:
|
2021-08-17 00:33:23 +02:00
|
|
|
// - sourcePane: the pane to navigate from
|
|
|
|
// - direction: which direction to go in
|
2021-09-02 16:36:17 +02:00
|
|
|
// - mruPanes: the list of most recently used panes, in order
|
2019-07-17 16:30:15 +02:00
|
|
|
// Return Value:
|
2021-08-17 00:33:23 +02:00
|
|
|
// - The result of navigating from source according to direction, which may be
|
|
|
|
// nullptr (i.e. no pane was found in that direction).
|
2021-09-02 16:36:17 +02:00
|
|
|
std::shared_ptr<Pane> Pane::NavigateDirection(const std::shared_ptr<Pane> sourcePane, const FocusDirection& direction, const std::vector<uint32_t>& mruPanes)
|
2019-07-17 16:30:15 +02:00
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
// Can't navigate anywhere if we are a leaf
|
2019-07-17 16:30:15 +02:00
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-09-02 16:36:17 +02:00
|
|
|
if (direction == FocusDirection::None)
|
2021-08-17 00:33:23 +02:00
|
|
|
{
|
|
|
|
return nullptr;
|
2019-07-17 16:30:15 +02:00
|
|
|
}
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Check if moving up or down the tree
|
|
|
|
if (direction == FocusDirection::Parent)
|
|
|
|
{
|
|
|
|
if (const auto parent = _FindParentOfPane(sourcePane))
|
|
|
|
{
|
|
|
|
// Keep a reference to which child we came from
|
|
|
|
parent->_parentChildPath = sourcePane->weak_from_this();
|
|
|
|
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (direction == FocusDirection::Child)
|
|
|
|
{
|
|
|
|
if (!sourcePane->_IsLeaf())
|
|
|
|
{
|
|
|
|
auto child = sourcePane->_firstChild;
|
|
|
|
// If we've recorded path try to go back down it
|
|
|
|
if (const auto prevFocus = sourcePane->_parentChildPath.lock())
|
|
|
|
{
|
|
|
|
child = prevFocus;
|
|
|
|
}
|
|
|
|
// clean up references
|
|
|
|
sourcePane->_parentChildPath.reset();
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-09-02 16:36:17 +02:00
|
|
|
// Previous movement relies on the last used panes
|
|
|
|
if (direction == FocusDirection::Previous)
|
|
|
|
{
|
|
|
|
// If there is actually a previous pane.
|
|
|
|
if (mruPanes.size() > 1)
|
|
|
|
{
|
|
|
|
// This could return nullptr if the id is not actually in the tree.
|
|
|
|
return FindPane(mruPanes.at(1));
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-08-17 00:33:23 +02:00
|
|
|
// Check if we in-order traversal is requested
|
|
|
|
if (direction == FocusDirection::NextInOrder)
|
|
|
|
{
|
|
|
|
return NextPane(sourcePane);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (direction == FocusDirection::PreviousInOrder)
|
|
|
|
{
|
|
|
|
return PreviousPane(sourcePane);
|
|
|
|
}
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Fixed movement
|
2021-08-26 19:58:56 +02:00
|
|
|
if (direction == FocusDirection::First)
|
|
|
|
{
|
|
|
|
std::shared_ptr<Pane> firstPane = nullptr;
|
|
|
|
WalkTree([&](auto p) {
|
|
|
|
if (p->_IsLeaf())
|
|
|
|
{
|
|
|
|
firstPane = p;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Don't need to do any movement if we are the source and target pane.
|
|
|
|
if (firstPane == sourcePane)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return firstPane;
|
|
|
|
}
|
|
|
|
|
2021-08-17 00:33:23 +02:00
|
|
|
// We are left with directional traversal now
|
|
|
|
// If the focus direction does not match the split direction, the source pane
|
2021-07-23 02:09:47 +02:00
|
|
|
// and its neighbor must necessarily be contained within the same child.
|
|
|
|
if (!DirectionMatchesSplit(direction, _splitState))
|
2019-07-17 16:30:15 +02:00
|
|
|
{
|
2021-09-02 16:36:17 +02:00
|
|
|
if (const auto p = _firstChild->NavigateDirection(sourcePane, direction, mruPanes))
|
2021-08-17 00:33:23 +02:00
|
|
|
{
|
|
|
|
return p;
|
|
|
|
}
|
2021-09-02 16:36:17 +02:00
|
|
|
return _secondChild->NavigateDirection(sourcePane, direction, mruPanes);
|
2019-07-17 16:30:15 +02:00
|
|
|
}
|
2019-08-28 16:40:16 +02:00
|
|
|
|
2021-07-23 02:09:47 +02:00
|
|
|
// Since the direction is the same as our split, it is possible that we must
|
|
|
|
// move focus from from one child to another child.
|
|
|
|
// We now must keep track of state while we recurse.
|
2021-08-24 17:27:21 +02:00
|
|
|
// If we have it, get the size of this pane.
|
|
|
|
const auto scaleX = _root.ActualWidth() > 0 ? gsl::narrow_cast<float>(_root.ActualWidth()) : 1.f;
|
|
|
|
const auto scaleY = _root.ActualHeight() > 0 ? gsl::narrow_cast<float>(_root.ActualHeight()) : 1.f;
|
|
|
|
const auto paneNeighborPair = _FindPaneAndNeighbor(sourcePane, direction, { 0, 0, scaleX, scaleY });
|
2019-08-28 16:40:16 +02:00
|
|
|
|
2021-08-17 00:33:23 +02:00
|
|
|
if (paneNeighborPair.source && paneNeighborPair.neighbor)
|
2019-08-28 16:40:16 +02:00
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
return paneNeighborPair.neighbor;
|
2019-08-28 16:40:16 +02:00
|
|
|
}
|
|
|
|
|
2021-08-17 00:33:23 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Attempts to find the succeeding pane of the provided pane.
|
|
|
|
// - NB: If targetPane is not a leaf, then this will return one of its children.
|
|
|
|
// Arguments:
|
|
|
|
// - targetPane: The pane to search for.
|
|
|
|
// Return Value:
|
|
|
|
// - The next pane in tree order after the target pane (if found)
|
|
|
|
std::shared_ptr<Pane> Pane::NextPane(const std::shared_ptr<Pane> targetPane)
|
|
|
|
{
|
|
|
|
// if we are a leaf pane there is no next pane.
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<Pane> firstLeaf = nullptr;
|
|
|
|
std::shared_ptr<Pane> nextPane = nullptr;
|
|
|
|
bool foundTarget = false;
|
|
|
|
|
|
|
|
auto foundNext = WalkTree([&](auto pane) {
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If we are a parent pane we don't want to move to one of our children
|
|
|
|
if (foundTarget && targetPane->_HasChild(pane))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2021-08-17 00:33:23 +02:00
|
|
|
// In case the target pane is the last pane in the tree, keep a reference
|
|
|
|
// to the first leaf so we can wrap around.
|
|
|
|
if (firstLeaf == nullptr && pane->_IsLeaf())
|
|
|
|
{
|
|
|
|
firstLeaf = pane;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we've found the target pane already, get the next leaf pane.
|
|
|
|
if (foundTarget && pane->_IsLeaf())
|
|
|
|
{
|
|
|
|
nextPane = pane;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test if we're the target pane so we know to return the next pane.
|
|
|
|
if (pane == targetPane)
|
|
|
|
{
|
|
|
|
foundTarget = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
// If we found the desired pane just return it
|
|
|
|
if (foundNext)
|
|
|
|
{
|
|
|
|
return nextPane;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we found the target pane, but not the next pane it means we were the
|
|
|
|
// last leaf in the tree.
|
|
|
|
if (foundTarget)
|
|
|
|
{
|
|
|
|
return firstLeaf;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Attempts to find the preceding pane of the provided pane.
|
|
|
|
// Arguments:
|
|
|
|
// - targetPane: The pane to search for.
|
|
|
|
// Return Value:
|
|
|
|
// - The previous pane in tree order before the target pane (if found)
|
|
|
|
std::shared_ptr<Pane> Pane::PreviousPane(const std::shared_ptr<Pane> targetPane)
|
|
|
|
{
|
|
|
|
// if we are a leaf pane there is no previous pane.
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<Pane> lastLeaf = nullptr;
|
|
|
|
bool foundTarget = false;
|
|
|
|
|
|
|
|
WalkTree([&](auto pane) {
|
|
|
|
if (pane == targetPane)
|
|
|
|
{
|
|
|
|
foundTarget = true;
|
|
|
|
// If we were not the first leaf, then return the previous leaf.
|
|
|
|
// Otherwise keep walking the tree to get the last pane.
|
|
|
|
if (lastLeaf != nullptr)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pane->_IsLeaf())
|
|
|
|
{
|
|
|
|
lastLeaf = pane;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
// If we found the target pane then lastLeaf will either be the preceding
|
|
|
|
// pane or the last pane in the tree if targetPane is the first leaf.
|
|
|
|
if (foundTarget)
|
|
|
|
{
|
|
|
|
return lastLeaf;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2019-07-17 16:30:15 +02:00
|
|
|
}
|
|
|
|
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Attempts to find the parent pane of the provided pane.
|
|
|
|
// Arguments:
|
|
|
|
// - pane: The pane to search for.
|
|
|
|
// Return Value:
|
|
|
|
// - the parent of `pane` if pane is in this tree.
|
|
|
|
std::shared_ptr<Pane> Pane::_FindParentOfPane(const std::shared_ptr<Pane> pane)
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_firstChild == pane || _secondChild == pane)
|
|
|
|
{
|
|
|
|
return shared_from_this();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto p = _firstChild->_FindParentOfPane(pane))
|
|
|
|
{
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _secondChild->_FindParentOfPane(pane);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Attempts to swap the location of the two given panes in the tree.
|
|
|
|
// Searches the tree starting at this pane to find the parent pane for each of
|
|
|
|
// the arguments, and if both parents are found, replaces the appropriate
|
|
|
|
// child in each.
|
|
|
|
// Arguments:
|
|
|
|
// - first: A pointer to the first pane to switch.
|
|
|
|
// - second: A pointer to the second pane to switch.
|
|
|
|
// Return Value:
|
|
|
|
// - true if a swap was performed.
|
|
|
|
bool Pane::SwapPanes(std::shared_ptr<Pane> first, std::shared_ptr<Pane> second)
|
|
|
|
{
|
|
|
|
// If there is nothing to swap, just return.
|
|
|
|
if (first == second || _IsLeaf())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Similarly don't swap if we have a circular reference
|
|
|
|
if (first->_HasChild(second) || second->_HasChild(first))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
std::unique_lock lock{ _createCloseLock };
|
|
|
|
|
|
|
|
// Recurse through the tree to find the parent panes of each pane that is
|
|
|
|
// being swapped.
|
|
|
|
std::shared_ptr<Pane> firstParent = _FindParentOfPane(first);
|
|
|
|
std::shared_ptr<Pane> secondParent = _FindParentOfPane(second);
|
|
|
|
|
|
|
|
// We should have found either no elements, or both elements.
|
|
|
|
// If we only found one parent then the pane SwapPane was called on did not
|
|
|
|
// contain both panes as leaves, as could happen if the tree was modified
|
|
|
|
// after the pointers were found but before we reached this function.
|
|
|
|
if (firstParent && secondParent)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Before we swap anything get the borders for the parents so that
|
|
|
|
// it can be propagated to the swapped child.
|
|
|
|
firstParent->_borders = firstParent->_GetCommonBorders();
|
|
|
|
secondParent->_borders = secondParent->_GetCommonBorders();
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
|
|
|
|
// Replace the old child with new one, and revoke appropriate event
|
|
|
|
// handlers.
|
|
|
|
auto replaceChild = [](auto& parent, auto oldChild, auto newChild) {
|
|
|
|
// Revoke the old handlers
|
|
|
|
if (parent->_firstChild == oldChild)
|
|
|
|
{
|
|
|
|
parent->_firstChild->Closed(parent->_firstClosedToken);
|
|
|
|
parent->_firstChild = newChild;
|
|
|
|
}
|
|
|
|
else if (parent->_secondChild == oldChild)
|
|
|
|
{
|
|
|
|
parent->_secondChild->Closed(parent->_secondClosedToken);
|
|
|
|
parent->_secondChild = newChild;
|
|
|
|
}
|
|
|
|
// Clear now to ensure that we can add the child's grid to us later
|
|
|
|
parent->_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
parent->_borderFirst.Child(nullptr);
|
|
|
|
parent->_borderSecond.Child(nullptr);
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Make sure that the right event handlers are set, and the children
|
|
|
|
// are placed in the appropriate locations in the grid.
|
|
|
|
auto updateParent = [](auto& parent) {
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// just always revoke the old helpers since we are making new ones.
|
|
|
|
parent->_firstChild->Closed(parent->_firstClosedToken);
|
|
|
|
parent->_secondChild->Closed(parent->_secondClosedToken);
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
parent->_SetupChildCloseHandlers();
|
|
|
|
parent->_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
parent->_borderFirst.Child(nullptr);
|
|
|
|
parent->_borderSecond.Child(nullptr);
|
|
|
|
parent->_borderFirst.Child(parent->_firstChild->GetRootElement());
|
|
|
|
parent->_borderSecond.Child(parent->_secondChild->GetRootElement());
|
|
|
|
|
|
|
|
parent->_root.Children().Append(parent->_borderFirst);
|
|
|
|
parent->_root.Children().Append(parent->_borderSecond);
|
|
|
|
|
|
|
|
// reset split definitions to clear any set row/column
|
|
|
|
parent->_root.ColumnDefinitions().Clear();
|
|
|
|
parent->_root.RowDefinitions().Clear();
|
|
|
|
parent->_CreateRowColDefinitions();
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// If the firstParent and secondParent are the same, then we are just
|
|
|
|
// swapping the first child and second child of that parent.
|
|
|
|
if (firstParent == secondParent)
|
|
|
|
{
|
|
|
|
firstParent->_firstChild->Closed(firstParent->_firstClosedToken);
|
|
|
|
firstParent->_secondChild->Closed(firstParent->_secondClosedToken);
|
|
|
|
std::swap(firstParent->_firstChild, firstParent->_secondChild);
|
|
|
|
|
|
|
|
updateParent(firstParent);
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
firstParent->_ApplySplitDefinitions();
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Replace both children before updating display to ensure
|
|
|
|
// that the grid elements are not attached to multiple panes
|
|
|
|
replaceChild(firstParent, first, second);
|
|
|
|
replaceChild(secondParent, second, first);
|
|
|
|
updateParent(firstParent);
|
|
|
|
updateParent(secondParent);
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
|
|
|
|
// If one of the two parents is a child of the other we only want
|
|
|
|
// to apply the split definitions to the greatest parent to make
|
|
|
|
// sure that all panes get the correct borders. if this is not done
|
|
|
|
// and the ordering happens to be bad one parent's children will lose
|
|
|
|
// a border.
|
|
|
|
if (firstParent->_HasChild(secondParent))
|
|
|
|
{
|
|
|
|
firstParent->_ApplySplitDefinitions();
|
|
|
|
}
|
|
|
|
else if (secondParent->_HasChild(firstParent))
|
|
|
|
{
|
|
|
|
secondParent->_ApplySplitDefinitions();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
firstParent->_ApplySplitDefinitions();
|
|
|
|
secondParent->_ApplySplitDefinitions();
|
|
|
|
}
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Refocus the last pane if there was a pane focused
|
|
|
|
first->WalkTree([](auto p) {
|
|
|
|
if (p->_lastActive)
|
|
|
|
{
|
|
|
|
p->_Focus();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
second->WalkTree([](auto p) {
|
|
|
|
if (p->_lastActive)
|
|
|
|
{
|
|
|
|
p->_Focus();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
2021-08-17 00:33:23 +02:00
|
|
|
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2021-09-02 16:36:17 +02:00
|
|
|
// - Given two panes' offsets, test whether the `direction` side of first is adjacent to second.
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// Arguments:
|
2021-09-02 16:36:17 +02:00
|
|
|
// - firstOffset: The offset for the reference pane
|
|
|
|
// - secondOffset: the offset to test adjacency with.
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// - direction: The direction to search in from the reference pane.
|
|
|
|
// Return Value:
|
|
|
|
// - true if the two panes are adjacent.
|
2021-09-02 16:36:17 +02:00
|
|
|
bool Pane::_IsAdjacent(const PanePoint firstOffset,
|
2021-08-24 17:27:21 +02:00
|
|
|
const PanePoint secondOffset,
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
const FocusDirection& direction) const
|
|
|
|
{
|
|
|
|
// Since float equality is tricky (arithmetic is non-associative, commutative),
|
|
|
|
// test if the two numbers are within an epsilon distance of each other.
|
|
|
|
auto floatEqual = [](float left, float right) {
|
|
|
|
return abs(left - right) < 1e-4F;
|
|
|
|
};
|
|
|
|
|
2021-09-02 16:36:17 +02:00
|
|
|
auto getXMax = [](PanePoint offset) {
|
2021-08-24 17:27:21 +02:00
|
|
|
return offset.x + offset.scaleX;
|
|
|
|
};
|
|
|
|
|
2021-09-02 16:36:17 +02:00
|
|
|
auto getYMax = [](PanePoint offset) {
|
2021-08-24 17:27:21 +02:00
|
|
|
return offset.y + offset.scaleY;
|
|
|
|
};
|
|
|
|
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// When checking containment in a range, the range is half-closed, i.e. [x, x+w).
|
|
|
|
// If the direction is left test that the left side of the first element is
|
|
|
|
// next to the right side of the second element, and that the top left
|
|
|
|
// corner of the first element is within the second element's height
|
|
|
|
if (direction == FocusDirection::Left)
|
|
|
|
{
|
2021-09-02 16:36:17 +02:00
|
|
|
const auto sharesBorders = floatEqual(firstOffset.x, getXMax(secondOffset));
|
|
|
|
const auto withinHeight = (firstOffset.y >= secondOffset.y) && (firstOffset.y < getYMax(secondOffset));
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
|
|
|
|
return sharesBorders && withinHeight;
|
|
|
|
}
|
|
|
|
// If the direction is right test that the right side of the first element is
|
|
|
|
// next to the left side of the second element, and that the top left
|
|
|
|
// corner of the first element is within the second element's height
|
|
|
|
else if (direction == FocusDirection::Right)
|
|
|
|
{
|
2021-09-02 16:36:17 +02:00
|
|
|
const auto sharesBorders = floatEqual(getXMax(firstOffset), secondOffset.x);
|
|
|
|
const auto withinHeight = (firstOffset.y >= secondOffset.y) && (firstOffset.y < getYMax(secondOffset));
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
|
|
|
|
return sharesBorders && withinHeight;
|
|
|
|
}
|
|
|
|
// If the direction is up test that the top side of the first element is
|
|
|
|
// next to the bottom side of the second element, and that the top left
|
|
|
|
// corner of the first element is within the second element's width
|
|
|
|
else if (direction == FocusDirection::Up)
|
|
|
|
{
|
2021-09-02 16:36:17 +02:00
|
|
|
const auto sharesBorders = floatEqual(firstOffset.y, getYMax(secondOffset));
|
|
|
|
const auto withinWidth = (firstOffset.x >= secondOffset.x) && (firstOffset.x < getXMax(secondOffset));
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
|
|
|
|
return sharesBorders && withinWidth;
|
|
|
|
}
|
|
|
|
// If the direction is down test that the bottom side of the first element is
|
|
|
|
// next to the top side of the second element, and that the top left
|
|
|
|
// corner of the first element is within the second element's width
|
|
|
|
else if (direction == FocusDirection::Down)
|
|
|
|
{
|
2021-09-02 16:36:17 +02:00
|
|
|
const auto sharesBorders = floatEqual(getYMax(firstOffset), secondOffset.y);
|
|
|
|
const auto withinWidth = (firstOffset.x >= secondOffset.x) && (firstOffset.x < getXMax(secondOffset));
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
|
|
|
|
return sharesBorders && withinWidth;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-08-24 17:27:21 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Gets the offsets for the two children of this parent pane
|
|
|
|
// - If real dimensions are not available, simulated ones based on the split size
|
|
|
|
// will be used instead.
|
|
|
|
// Arguments:
|
|
|
|
// - parentOffset the location and scale information of this pane.
|
|
|
|
// Return Value:
|
|
|
|
// - the two location/scale points for the children panes.
|
|
|
|
std::pair<Pane::PanePoint, Pane::PanePoint> Pane::_GetOffsetsForPane(const PanePoint parentOffset) const
|
|
|
|
{
|
|
|
|
assert(!_IsLeaf());
|
|
|
|
auto firstOffset = parentOffset;
|
|
|
|
auto secondOffset = parentOffset;
|
|
|
|
|
2021-09-02 16:36:17 +02:00
|
|
|
// Make up fake dimensions using an exponential layout. This is useful
|
|
|
|
// since we might need to navigate when there are panes not attached to
|
|
|
|
// the ui tree, such as initialization, command running, and zoom.
|
|
|
|
// Basically create the tree layout on the fly by partitioning [0,1].
|
|
|
|
// This could run into issues if the tree depth is >127 (or other
|
|
|
|
// degenerate splits) as a float's mantissa only has so many bits of
|
|
|
|
// precision.
|
|
|
|
|
|
|
|
if (_splitState == SplitState::Horizontal)
|
2021-08-24 17:27:21 +02:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
secondOffset.y += _desiredSplitPosition * parentOffset.scaleY;
|
2021-09-02 16:36:17 +02:00
|
|
|
firstOffset.scaleY *= _desiredSplitPosition;
|
|
|
|
secondOffset.scaleY *= (1 - _desiredSplitPosition);
|
2021-08-24 17:27:21 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
secondOffset.x += _desiredSplitPosition * parentOffset.scaleX;
|
2021-09-02 16:36:17 +02:00
|
|
|
firstOffset.scaleX *= _desiredSplitPosition;
|
|
|
|
secondOffset.scaleX *= (1 - _desiredSplitPosition);
|
2021-08-24 17:27:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return { firstOffset, secondOffset };
|
|
|
|
}
|
|
|
|
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// Method Description:
|
2021-08-17 00:33:23 +02:00
|
|
|
// - Given the source pane, and its relative position in the tree, attempt to
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// find its visual neighbor within the current pane's tree.
|
|
|
|
// The neighbor, if it exists, will be a leaf pane.
|
|
|
|
// Arguments:
|
2021-08-17 00:33:23 +02:00
|
|
|
// - direction: The direction to search in from the source pane.
|
|
|
|
// - searchResult: the source pane and its relative position.
|
|
|
|
// - sourceIsSecondSide: If the source pane is on the "second" side (down/right of split)
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// relative to the branch being searched
|
|
|
|
// - offset: the offset of the current pane
|
|
|
|
// Return Value:
|
|
|
|
// - A tuple of Panes, the first being the focused pane if found, and the second
|
|
|
|
// being the adjacent pane if it exists, and a bool that represents if the move
|
|
|
|
// goes out of bounds.
|
2021-08-17 00:33:23 +02:00
|
|
|
Pane::PaneNeighborSearch Pane::_FindNeighborForPane(const FocusDirection& direction,
|
|
|
|
PaneNeighborSearch searchResult,
|
|
|
|
const bool sourceIsSecondSide,
|
|
|
|
const Pane::PanePoint offset)
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
|
|
|
// Test if the move will go out of boundaries. E.g. if the focus is already
|
|
|
|
// on the second child of some pane and it attempts to move right, there
|
|
|
|
// can't possibly be a neighbor to be found in the first child.
|
2021-08-17 00:33:23 +02:00
|
|
|
if ((sourceIsSecondSide && (direction == FocusDirection::Right || direction == FocusDirection::Down)) ||
|
|
|
|
(!sourceIsSecondSide && (direction == FocusDirection::Left || direction == FocusDirection::Up)))
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
|
|
|
return searchResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we are a leaf node test if we adjacent to the focus node
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
2021-09-02 16:36:17 +02:00
|
|
|
if (_IsAdjacent(searchResult.sourceOffset, offset, direction))
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
|
|
|
searchResult.neighbor = shared_from_this();
|
|
|
|
}
|
|
|
|
return searchResult;
|
|
|
|
}
|
|
|
|
|
2021-08-24 17:27:21 +02:00
|
|
|
auto [firstOffset, secondOffset] = _GetOffsetsForPane(offset);
|
2021-08-17 00:33:23 +02:00
|
|
|
auto sourceNeighborSearch = _firstChild->_FindNeighborForPane(direction, searchResult, sourceIsSecondSide, firstOffset);
|
|
|
|
if (sourceNeighborSearch.neighbor)
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
return sourceNeighborSearch;
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
|
2021-08-17 00:33:23 +02:00
|
|
|
return _secondChild->_FindNeighborForPane(direction, searchResult, sourceIsSecondSide, secondOffset);
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2021-08-17 00:33:23 +02:00
|
|
|
// - Searches the tree to find the source pane, and if it exists, the
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// visually adjacent pane by direction.
|
|
|
|
// Arguments:
|
2021-08-17 00:33:23 +02:00
|
|
|
// - sourcePane: The pane to find the neighbor of.
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// - direction: The direction to search in from the focused pane.
|
|
|
|
// - offset: The offset, with the top-left corner being (0,0), that the current pane is relative to the root.
|
|
|
|
// Return Value:
|
2021-08-17 00:33:23 +02:00
|
|
|
// - The (partial) search result. If the search was successful, the pane and its neighbor will be returned.
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// Otherwise, the neighbor will be null and the focus will be null/non-null if it was found.
|
2021-08-17 00:33:23 +02:00
|
|
|
Pane::PaneNeighborSearch Pane::_FindPaneAndNeighbor(const std::shared_ptr<Pane> sourcePane, const FocusDirection& direction, const Pane::PanePoint offset)
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
// If we are the source pane, return ourselves
|
|
|
|
if (this == sourcePane.get())
|
|
|
|
{
|
|
|
|
return { shared_from_this(), nullptr, offset };
|
|
|
|
}
|
|
|
|
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
return { nullptr, nullptr, offset };
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
|
2021-08-24 17:27:21 +02:00
|
|
|
auto [firstOffset, secondOffset] = _GetOffsetsForPane(offset);
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
|
2021-08-17 00:33:23 +02:00
|
|
|
auto sourceNeighborSearch = _firstChild->_FindPaneAndNeighbor(sourcePane, direction, firstOffset);
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// If we have both the focus element and its neighbor, we are done
|
2021-08-17 00:33:23 +02:00
|
|
|
if (sourceNeighborSearch.source && sourceNeighborSearch.neighbor)
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
return sourceNeighborSearch;
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
// if we only found the focus, then we search the second branch for the
|
|
|
|
// neighbor.
|
2021-08-17 00:33:23 +02:00
|
|
|
if (sourceNeighborSearch.source)
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
|
|
|
// If we can possibly have both sides of a direction, check if the sibling has the neighbor
|
|
|
|
if (DirectionMatchesSplit(direction, _splitState))
|
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
return _secondChild->_FindNeighborForPane(direction, sourceNeighborSearch, false, secondOffset);
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
2021-08-17 00:33:23 +02:00
|
|
|
return sourceNeighborSearch;
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we didn't find the focus at all, we need to search the second branch
|
|
|
|
// for the focus (and possibly its neighbor).
|
2021-08-17 00:33:23 +02:00
|
|
|
sourceNeighborSearch = _secondChild->_FindPaneAndNeighbor(sourcePane, direction, secondOffset);
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// We found both so we are done.
|
2021-08-17 00:33:23 +02:00
|
|
|
if (sourceNeighborSearch.source && sourceNeighborSearch.neighbor)
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
return sourceNeighborSearch;
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
// We only found the focus, which means that its neighbor might be in the
|
|
|
|
// first branch.
|
2021-08-17 00:33:23 +02:00
|
|
|
if (sourceNeighborSearch.source)
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
{
|
|
|
|
// If we can possibly have both sides of a direction, check if the sibling has the neighbor
|
|
|
|
if (DirectionMatchesSplit(direction, _splitState))
|
|
|
|
{
|
2021-08-17 00:33:23 +02:00
|
|
|
return _firstChild->_FindNeighborForPane(direction, sourceNeighborSearch, true, firstOffset);
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
2021-08-17 00:33:23 +02:00
|
|
|
return sourceNeighborSearch;
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return { nullptr, nullptr, offset };
|
|
|
|
}
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Called when our attached control is closed. Triggers listeners to our close
|
|
|
|
// event, if we're a leaf pane.
|
|
|
|
// - If this was called, and we became a parent pane (due to work on another
|
|
|
|
// thread), this function will do nothing (allowing the control's new parent
|
|
|
|
// to handle the event instead).
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2021-03-18 23:02:39 +01:00
|
|
|
void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
2020-10-16 00:27:27 +02:00
|
|
|
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
|
|
|
std::unique_lock lock{ _createCloseLock };
|
|
|
|
// It's possible that this event handler started being executed, then before
|
|
|
|
// we got the lock, another thread created another child. So our control is
|
|
|
|
// actually no longer _our_ control, and instead could be a descendant.
|
|
|
|
//
|
|
|
|
// When the control's new Pane takes ownership of the control, the new
|
|
|
|
// parent will register it's own event handler. That event handler will get
|
|
|
|
// fired after this handler returns, and will properly cleanup state.
|
|
|
|
if (!_IsLeaf())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-25 23:22:29 +01:00
|
|
|
const auto newConnectionState = _control.ConnectionState();
|
2021-05-28 21:22:43 +02:00
|
|
|
const auto previousConnectionState = std::exchange(_connectionState, newConnectionState);
|
2019-11-25 23:22:29 +01:00
|
|
|
|
|
|
|
if (newConnectionState < ConnectionState::Closed)
|
|
|
|
{
|
|
|
|
// Pane doesn't care if the connection isn't entering a terminal state.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-05-28 21:22:43 +02:00
|
|
|
if (previousConnectionState < ConnectionState::Connected && newConnectionState >= ConnectionState::Failed)
|
|
|
|
{
|
|
|
|
// A failure to complete the connection (before it has _connected_) is not covered by "closeOnExit".
|
|
|
|
// This is to prevent a misconfiguration (closeOnExit: always, startingDirectory: garbage) resulting
|
|
|
|
// in Terminal flashing open and immediately closed.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-08-23 19:11:53 +02:00
|
|
|
if (_profile)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
2021-08-23 19:11:53 +02:00
|
|
|
const auto mode = _profile.CloseOnExit();
|
2020-10-06 18:56:59 +02:00
|
|
|
if ((mode == CloseOnExitMode::Always) ||
|
|
|
|
(mode == CloseOnExitMode::Graceful && newConnectionState == ConnectionState::Closed))
|
2019-11-25 23:22:29 +01:00
|
|
|
{
|
2020-10-10 01:06:40 +02:00
|
|
|
Close();
|
2019-11-25 23:22:29 +01:00
|
|
|
}
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-01 18:46:00 +01:00
|
|
|
winrt::fire_and_forget Pane::_playBellSound(winrt::Windows::Foundation::Uri uri)
|
|
|
|
{
|
|
|
|
auto weakThis{ shared_from_this() };
|
|
|
|
|
|
|
|
co_await winrt::resume_foreground(_root.Dispatcher());
|
|
|
|
if (auto pane{ weakThis.get() })
|
|
|
|
{
|
2021-11-16 16:40:23 +01:00
|
|
|
if (s_bellPlayer)
|
|
|
|
{
|
|
|
|
auto source{ winrt::Windows::Media::Core::MediaSource::CreateFromUri(uri) };
|
|
|
|
auto item{ winrt::Windows::Media::Playback::MediaPlaybackItem(source) };
|
|
|
|
s_bellPlayer.Source(item);
|
|
|
|
s_bellPlayer.Play();
|
|
|
|
}
|
2021-11-01 18:46:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-16 00:27:27 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Plays a warning note when triggered by the BEL control character,
|
|
|
|
// using the sound configured for the "Critical Stop" system event.`
|
|
|
|
// This matches the behavior of the Windows Console host.
|
2020-11-18 23:55:10 +01:00
|
|
|
// - Will also flash the taskbar if the bellStyle setting for this profile
|
|
|
|
// has the 'visual' flag set
|
2020-10-16 00:27:27 +02:00
|
|
|
// Arguments:
|
|
|
|
// - <unused>
|
|
|
|
void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
|
|
|
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
|
|
|
{
|
|
|
|
if (!_IsLeaf())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2021-08-23 19:11:53 +02:00
|
|
|
if (_profile)
|
2020-10-16 00:27:27 +02:00
|
|
|
{
|
2021-01-23 00:48:20 +01:00
|
|
|
// We don't want to do anything if nothing is set, so check for that first
|
2021-08-23 19:11:53 +02:00
|
|
|
if (static_cast<int>(_profile.BellStyle()) != 0)
|
2020-10-16 00:27:27 +02:00
|
|
|
{
|
2021-08-23 19:11:53 +02:00
|
|
|
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible))
|
2021-01-23 00:48:20 +01:00
|
|
|
{
|
|
|
|
// Audible is set, play the sound
|
2021-10-14 19:57:58 +02:00
|
|
|
auto sounds{ _profile.BellSound() };
|
|
|
|
if (sounds && sounds.Size() > 0)
|
|
|
|
{
|
2021-11-01 20:52:27 +01:00
|
|
|
winrt::hstring soundPath{ wil::ExpandEnvironmentStringsW<std::wstring>(sounds.GetAt(rand() % sounds.Size()).c_str()) };
|
2021-11-01 20:57:53 +01:00
|
|
|
winrt::Windows::Foundation::Uri uri{ soundPath };
|
2021-11-01 18:46:00 +01:00
|
|
|
_playBellSound(uri);
|
2021-10-14 19:57:58 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
|
|
|
|
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
|
|
|
|
}
|
2021-01-23 00:48:20 +01:00
|
|
|
}
|
|
|
|
|
2021-08-23 19:11:53 +02:00
|
|
|
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
|
2021-05-25 00:51:03 +02:00
|
|
|
{
|
|
|
|
_control.BellLightOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
// raise the event with the bool value corresponding to the taskbar flag
|
2021-08-23 19:11:53 +02:00
|
|
|
_PaneRaiseBellHandlers(nullptr, WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Taskbar));
|
2020-11-18 23:55:10 +01:00
|
|
|
}
|
2020-10-16 00:27:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
// Event Description:
|
|
|
|
// - Called when our control gains focus. We'll use this to trigger our GotFocus
|
|
|
|
// callback. The tab that's hosting us should have registered a callback which
|
|
|
|
// can be used to mark us as active.
|
|
|
|
// Arguments:
|
|
|
|
// - <unused>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
void Pane::_ControlGotFocusHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
2020-01-08 22:19:23 +01:00
|
|
|
RoutedEventArgs const& /* args */)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
FocusState f = FocusState::Programmatic;
|
|
|
|
if (const auto o = sender.try_as<winrt::Windows::UI::Xaml::Controls::Control>())
|
|
|
|
{
|
|
|
|
f = o.FocusState();
|
|
|
|
}
|
|
|
|
_GotFocusHandlers(shared_from_this(), f);
|
2020-01-08 22:19:23 +01:00
|
|
|
}
|
|
|
|
|
2021-01-23 00:48:20 +01:00
|
|
|
// Event Description:
|
|
|
|
// - Called when our control loses focus. We'll use this to trigger our LostFocus
|
|
|
|
// callback. The tab that's hosting us should have registered a callback which
|
|
|
|
// can be used to update its own internal focus state
|
|
|
|
void Pane::_ControlLostFocusHandler(winrt::Windows::Foundation::IInspectable const& /* sender */,
|
|
|
|
RoutedEventArgs const& /* args */)
|
|
|
|
{
|
|
|
|
_LostFocusHandlers(shared_from_this());
|
|
|
|
}
|
|
|
|
|
2019-07-19 02:23:40 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Fire our Closed event to tell our parent that we should be removed.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::Close()
|
|
|
|
{
|
Separate between Close Tab Requested and Tab Closed flows (#9574)
## Summary of the Pull Request
Currently, both when the tab is already closed, and when there is a
request to close a tab (might be rejected), we go through the same flow
in TerminalPage.
This might leave the system in inconsistent state, as the side-effects
of closing will persist even if the closing was aborted.
This PR separates between the two flows, by introducing a CloseRequested
event to the TabBase.
This event is used to inform the upper tier (the terminal page) about
the request and to trigger the same logic that happens when the tab is
closed directly from the terminal page (e.g., by clicking close on the
tab view).
The Closed event will be used only to handle the actual closing of the
tab. It will ensure that the tab gets removed from the terminal page if
required.
As a result, it a read-only pane will be closed non-interactively (aka
connection exits), the tab closed flow will be invoked, and no user
prompt will be shown.
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9572
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.
2021-03-30 17:58:35 +02:00
|
|
|
// Fire our Closed event to tell our parent that we should be removed.
|
|
|
|
_ClosedHandlers(nullptr, nullptr);
|
2019-07-19 02:23:40 +02:00
|
|
|
}
|
|
|
|
|
2020-01-23 23:12:20 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Prepare this pane to be removed from the UI hierarchy by closing all controls
|
|
|
|
// and connections beneath it.
|
|
|
|
void Pane::Shutdown()
|
|
|
|
{
|
|
|
|
// Lock the create/close lock so that another operation won't concurrently
|
|
|
|
// modify our tree
|
|
|
|
std::unique_lock lock{ _createCloseLock };
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
_control.Close();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_firstChild->Shutdown();
|
|
|
|
_secondChild->Shutdown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Get the root UIElement of this pane. There may be a single TermControl as a
|
|
|
|
// child, or an entire tree of grids and panes as children of this element.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - the Grid acting as the root of this pane.
|
|
|
|
Controls::Grid Pane::GetRootElement()
|
|
|
|
{
|
|
|
|
return _root;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - If this is the last focused pane, returns itself. Returns nullptr if this
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// is a leaf and it's not focused. If it's a parent, it returns nullptr if it nor
|
|
|
|
// any children of this pane were the last pane to be focused, or the Pane that
|
2019-06-07 23:56:44 +02:00
|
|
|
// _was_ the last pane to be focused (if there was one).
|
|
|
|
// - This Pane's control might not currently be focused, if the tab itself is
|
|
|
|
// not currently focused.
|
|
|
|
// Return Value:
|
|
|
|
// - nullptr if we're a leaf and unfocused, or no children were marked
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// `_lastActive`, else returns this
|
|
|
|
std::shared_ptr<Pane> Pane::GetActivePane()
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (_lastActive)
|
|
|
|
{
|
|
|
|
return shared_from_this();
|
|
|
|
}
|
2019-06-07 23:56:44 +02:00
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
return nullptr;
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
2019-08-28 16:40:16 +02:00
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
auto firstFocused = _firstChild->GetActivePane();
|
2019-08-28 16:40:16 +02:00
|
|
|
if (firstFocused != nullptr)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
2019-08-28 16:40:16 +02:00
|
|
|
return firstFocused;
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
return _secondChild->GetActivePane();
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// - Gets the TermControl of this pane. If this Pane is not a leaf but is
|
|
|
|
// focused, this will return the control of the last leaf pane that had focus.
|
|
|
|
// Otherwise, this will return the control of the first child of this pane.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - nullptr if this Pane is an unfocused parent, otherwise the TermControl of this Pane.
|
|
|
|
TermControl Pane::GetLastFocusedTerminalControl()
|
|
|
|
{
|
|
|
|
if (!_IsLeaf())
|
|
|
|
{
|
|
|
|
if (_lastActive)
|
|
|
|
{
|
|
|
|
std::shared_ptr<Pane> pane = shared_from_this();
|
|
|
|
while (const auto p = pane->_parentChildPath.lock())
|
|
|
|
{
|
|
|
|
if (p->_IsLeaf())
|
|
|
|
{
|
|
|
|
return p->_control;
|
|
|
|
}
|
|
|
|
pane = p;
|
|
|
|
}
|
|
|
|
// We didn't find our child somehow, they might have closed under us.
|
|
|
|
}
|
|
|
|
return _firstChild->GetLastFocusedTerminalControl();
|
|
|
|
}
|
|
|
|
return _control;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Gets the TermControl of this pane. If this Pane is not a leaf this will
|
|
|
|
// return the nullptr;
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - nullptr if this Pane is a parent, otherwise the TermControl of this Pane.
|
|
|
|
TermControl Pane::GetTerminalControl()
|
|
|
|
{
|
|
|
|
return _IsLeaf() ? _control : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Recursively remove the "Active" state from this Pane and all it's children.
|
|
|
|
// - Updates our visuals to match our new state, including highlighting our borders.
|
2019-06-07 23:56:44 +02:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// - <none>
|
|
|
|
void Pane::ClearActive()
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
_lastActive = false;
|
|
|
|
if (!_IsLeaf())
|
|
|
|
{
|
|
|
|
_firstChild->ClearActive();
|
|
|
|
_secondChild->ClearActive();
|
|
|
|
}
|
|
|
|
UpdateVisuals();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Sets the "Active" state on this Pane. Only one Pane in a tree of Panes
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// should be "active".
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// - Updates our visuals to match our new state, including highlighting our borders.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::SetActive()
|
|
|
|
{
|
|
|
|
_lastActive = true;
|
|
|
|
UpdateVisuals();
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2021-08-23 19:11:53 +02:00
|
|
|
// - Returns nullptr if no children of this pane were the last control to be
|
|
|
|
// focused, or the profile of the last control to be focused (if there was
|
|
|
|
// one).
|
2019-06-07 23:56:44 +02:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
2021-08-23 19:11:53 +02:00
|
|
|
// - nullptr if no children of this pane were the last control to be
|
|
|
|
// focused, else the profile of the last control to be focused
|
|
|
|
Profile Pane::GetFocusedProfile()
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
auto lastFocused = GetActivePane();
|
2021-08-23 19:11:53 +02:00
|
|
|
return lastFocused ? lastFocused->_profile : nullptr;
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Returns true if this pane was the last pane to be focused in a tree of panes.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - true iff we were the last pane focused in this tree of panes.
|
|
|
|
bool Pane::WasLastFocused() const noexcept
|
|
|
|
{
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
return _lastActive;
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Returns true iff this pane has no child panes.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - true iff this pane has no child panes.
|
|
|
|
bool Pane::_IsLeaf() const noexcept
|
|
|
|
{
|
|
|
|
return _splitState == SplitState::None;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Returns true if this pane is currently focused, or there is a pane which is
|
|
|
|
// a child of this pane that is actively focused
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - true if the currently focused pane is either this pane, or one of this
|
|
|
|
// pane's descendants
|
|
|
|
bool Pane::_HasFocusedChild() const noexcept
|
|
|
|
{
|
|
|
|
// We're intentionally making this one giant expression, so the compiler
|
|
|
|
// will skip the following lookups if one of the lookups before it returns
|
|
|
|
// true
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
return (_lastActive) ||
|
2019-06-07 23:56:44 +02:00
|
|
|
(_firstChild && _firstChild->_HasFocusedChild()) ||
|
|
|
|
(_secondChild && _secondChild->_HasFocusedChild());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// - Update the focus state of this pane. We'll make sure to colorize our
|
|
|
|
// borders depending on if we are the active pane or not.
|
2019-06-07 23:56:44 +02:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
void Pane::UpdateVisuals()
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If we are the focused pane, but not a leaf we should add borders
|
|
|
|
if (!_IsLeaf())
|
|
|
|
{
|
|
|
|
_UpdateBorders();
|
|
|
|
}
|
|
|
|
_borderFirst.BorderBrush(_lastActive ? s_focusedBorderBrush : s_unfocusedBorderBrush);
|
|
|
|
_borderSecond.BorderBrush(_lastActive ? s_focusedBorderBrush : s_unfocusedBorderBrush);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Focus the current pane. Also trigger focus on the control, or if not a leaf
|
|
|
|
// the control belonging to the last focused leaf.
|
|
|
|
// This makes sure that focus exists within the tab (since panes aren't proper controls)
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::_Focus()
|
|
|
|
{
|
|
|
|
_GotFocusHandlers(shared_from_this(), FocusState::Programmatic);
|
|
|
|
if (const auto& control = GetLastFocusedTerminalControl())
|
|
|
|
{
|
|
|
|
control.Focus(FocusState::Programmatic);
|
|
|
|
}
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Focuses this control if we're a leaf, or attempts to focus the first leaf
|
|
|
|
// of our first child, recursively.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::_FocusFirstChild()
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
2021-05-21 23:55:57 +02:00
|
|
|
// Originally, we would only raise a GotFocus event here when:
|
|
|
|
//
|
|
|
|
// if (_root.ActualWidth() == 0 && _root.ActualHeight() == 0)
|
|
|
|
//
|
|
|
|
// When these sizes are 0, then the pane might still be in startup,
|
|
|
|
// and doesn't yet have a real size. In that case, the control.Focus
|
|
|
|
// event won't be handled until _after_ the startup events are all
|
|
|
|
// processed. This will lead to the Tab not being notified that the
|
|
|
|
// focus moved to a different Pane.
|
|
|
|
//
|
|
|
|
// However, with the ability to execute multiple actions at a time, in
|
|
|
|
// already existing windows, we need to always raise this event manually
|
|
|
|
// here, to correctly inform the Tab that we're now focused. This will
|
|
|
|
// take care of commandlines like:
|
|
|
|
//
|
|
|
|
// `wtd -w 0 mf down ; sp`
|
|
|
|
// `wtd -w 0 fp -t 1 ; sp`
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_Focus();
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_firstChild->_FocusFirstChild();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2021-08-23 21:20:08 +02:00
|
|
|
// - Updates the settings of this pane, presuming that it is a leaf.
|
2019-06-07 23:56:44 +02:00
|
|
|
// Arguments:
|
|
|
|
// - settings: The new TerminalSettings to apply to any matching controls
|
2021-08-23 19:11:53 +02:00
|
|
|
// - profile: The profile from which these settings originated.
|
2019-06-07 23:56:44 +02:00
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2021-08-23 19:11:53 +02:00
|
|
|
void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
2021-08-23 21:20:08 +02:00
|
|
|
assert(_IsLeaf());
|
|
|
|
|
|
|
|
_profile = profile;
|
|
|
|
auto controlSettings = _control.Settings().as<TerminalSettings>();
|
|
|
|
// Update the parent of the control's settings object (and not the object itself) so
|
|
|
|
// that any overrides made by the control don't get affected by the reload
|
|
|
|
controlSettings.SetParent(settings.DefaultSettings());
|
|
|
|
auto unfocusedSettings{ settings.UnfocusedSettings() };
|
|
|
|
if (unfocusedSettings)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
2021-08-23 21:20:08 +02:00
|
|
|
// Note: the unfocused settings needs to be entirely unchanged _except_ we need to
|
|
|
|
// set its parent to the settings object that lives in the control. This is because
|
|
|
|
// the overrides made by the control live in that settings object, so we want to make
|
|
|
|
// sure the unfocused settings inherit from that.
|
|
|
|
unfocusedSettings.SetParent(controlSettings);
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
2021-08-23 21:20:08 +02:00
|
|
|
_control.UnfocusedAppearance(unfocusedSettings);
|
|
|
|
_control.UpdateSettings();
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Attempts to add the provided pane as a split of the current pane.
|
|
|
|
// Arguments:
|
|
|
|
// - pane: the new pane to add
|
|
|
|
// - splitType: How the pane should be attached
|
|
|
|
// Return Value:
|
|
|
|
// - the new reference to the child created from the current pane.
|
2021-09-15 22:14:57 +02:00
|
|
|
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType)
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
{
|
|
|
|
// Splice the new pane into the tree
|
|
|
|
const auto [first, _] = _Split(splitType, .5, pane);
|
|
|
|
|
|
|
|
// If the new pane has a child that was the focus, re-focus it
|
|
|
|
// to steal focus from the currently focused pane.
|
|
|
|
if (pane->_HasFocusedChild())
|
|
|
|
{
|
|
|
|
pane->WalkTree([](auto p) {
|
|
|
|
if (p->_lastActive)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
p->_Focus();
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Attempts to find the parent of the target pane,
|
|
|
|
// if found remove the pane from the tree and return it.
|
|
|
|
// - If the removed pane was (or contained the focus) the first sibling will
|
|
|
|
// gain focus.
|
|
|
|
// Arguments:
|
|
|
|
// - pane: the pane to detach
|
|
|
|
// Return Value:
|
|
|
|
// - The removed pane, if found.
|
|
|
|
std::shared_ptr<Pane> Pane::DetachPane(std::shared_ptr<Pane> pane)
|
|
|
|
{
|
|
|
|
// We can't remove a pane if we only have a reference to a leaf, even if we
|
|
|
|
// are the pane.
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if either of our children matches the search
|
|
|
|
const auto isFirstChild = _firstChild == pane;
|
|
|
|
const auto isSecondChild = _secondChild == pane;
|
|
|
|
|
|
|
|
if (isFirstChild || isSecondChild)
|
|
|
|
{
|
|
|
|
// Keep a reference to the child we are removing
|
|
|
|
auto detached = isFirstChild ? _firstChild : _secondChild;
|
|
|
|
// Remove the child from the tree, replace the current node with the
|
|
|
|
// other child.
|
2021-08-26 00:49:26 +02:00
|
|
|
_CloseChild(isFirstChild, true);
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Update the borders on this pane and any children to match if we have
|
|
|
|
// no parent.
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
detached->_borders = Borders::None;
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
detached->_ApplySplitDefinitions();
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
|
|
|
|
// Trigger the detached event on each child
|
|
|
|
detached->WalkTree([](auto pane) {
|
|
|
|
pane->_PaneDetachedHandlers(pane);
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
return detached;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const auto detached = _firstChild->DetachPane(pane))
|
|
|
|
{
|
|
|
|
return detached;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _secondChild->DetachPane(pane);
|
|
|
|
}
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Closes one of our children. In doing so, takes the control from the other
|
|
|
|
// child, and makes this pane a leaf node again.
|
|
|
|
// Arguments:
|
|
|
|
// - closeFirst: if true, the first child should be closed, and the second
|
|
|
|
// should be preserved, and vice-versa for false.
|
2021-08-26 00:49:26 +02:00
|
|
|
// - isDetaching: if true, then the pane event handlers for the closed child
|
|
|
|
// should be kept, this way they don't have to be recreated when it is later
|
|
|
|
// reattached to a tree somewhere as the control moves with the pane.
|
2019-06-07 23:56:44 +02:00
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2021-08-26 00:49:26 +02:00
|
|
|
void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
|
|
|
// Lock the create/close lock so that another operation won't concurrently
|
|
|
|
// modify our tree
|
|
|
|
std::unique_lock lock{ _createCloseLock };
|
|
|
|
|
|
|
|
// If we're a leaf, then chances are both our children closed in close
|
|
|
|
// succession. We waited on the lock while the other child was closed, so
|
|
|
|
// now we don't have a child to close anymore. Return here. When we moved
|
|
|
|
// the non-closed child into us, we also set up event handlers that will be
|
|
|
|
// triggered when we return from this.
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto closedChild = closeFirst ? _firstChild : _secondChild;
|
|
|
|
auto remainingChild = closeFirst ? _secondChild : _firstChild;
|
2021-08-26 00:49:26 +02:00
|
|
|
auto closedChildClosedToken = closeFirst ? _firstClosedToken : _secondClosedToken;
|
|
|
|
auto remainingChildClosedToken = closeFirst ? _secondClosedToken : _firstClosedToken;
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If we were a parent pane, and we pointed into the now closed child
|
|
|
|
// clear it. We will set it to something else later if
|
|
|
|
bool usedToFocusClosedChildsTerminal = false;
|
|
|
|
if (const auto prev = _parentChildPath.lock())
|
|
|
|
{
|
|
|
|
if (closedChild == prev)
|
|
|
|
{
|
|
|
|
_parentChildPath.reset();
|
|
|
|
usedToFocusClosedChildsTerminal = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// If the only child left is a leaf, that means we're a leaf now.
|
|
|
|
if (remainingChild->_IsLeaf())
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Find what borders need to persist after we close the child
|
|
|
|
_borders = _GetCommonBorders();
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
// take the control, profile and id of the pane that _wasn't_ closed.
|
2019-06-07 23:56:44 +02:00
|
|
|
_control = remainingChild->_control;
|
2021-05-28 21:22:43 +02:00
|
|
|
_connectionState = remainingChild->_connectionState;
|
2019-06-07 23:56:44 +02:00
|
|
|
_profile = remainingChild->_profile;
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
_id = remainingChild->Id();
|
2019-06-07 23:56:44 +02:00
|
|
|
|
|
|
|
// Add our new event handler before revoking the old one.
|
2019-11-25 23:22:29 +01:00
|
|
|
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
|
2020-10-16 00:27:27 +02:00
|
|
|
_warningBellToken = _control.WarningBell({ this, &Pane::_ControlWarningBellHandler });
|
2019-06-07 23:56:44 +02:00
|
|
|
|
|
|
|
// Revoke the old event handlers. Remove both the handlers for the panes
|
|
|
|
// themselves closing, and remove their handlers for their controls
|
|
|
|
// closing. At this point, if the remaining child's control is closed,
|
|
|
|
// they'll trigger only our event handler for the control's close.
|
2021-08-26 00:49:26 +02:00
|
|
|
|
|
|
|
// However, if we are detaching the pane we want to keep its control
|
|
|
|
// handlers since it is just getting moved.
|
|
|
|
if (!isDetaching)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
closedChild->WalkTree([](auto p) {
|
|
|
|
if (p->_IsLeaf())
|
|
|
|
{
|
|
|
|
p->_control.ConnectionStateChanged(p->_connectionStateChangedToken);
|
|
|
|
p->_control.WarningBell(p->_warningBellToken);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
2021-08-26 00:49:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
closedChild->Closed(closedChildClosedToken);
|
|
|
|
remainingChild->Closed(remainingChildClosedToken);
|
2019-11-25 23:22:29 +01:00
|
|
|
remainingChild->_control.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
|
2020-10-16 00:27:27 +02:00
|
|
|
remainingChild->_control.WarningBell(remainingChild->_warningBellToken);
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If we or either of our children was focused, we want to take that
|
|
|
|
// focus from them.
|
|
|
|
_lastActive = _lastActive || _firstChild->_lastActive || _secondChild->_lastActive;
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
// Remove all the ui elements of the remaining child. This'll make sure
|
|
|
|
// we can re-attach the TermControl to our Grid.
|
|
|
|
remainingChild->_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
remainingChild->_borderFirst.Child(nullptr);
|
2019-06-07 23:56:44 +02:00
|
|
|
|
|
|
|
// Reset our UI:
|
|
|
|
_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_borderFirst.Child(nullptr);
|
|
|
|
_borderSecond.Child(nullptr);
|
2019-06-07 23:56:44 +02:00
|
|
|
_root.ColumnDefinitions().Clear();
|
|
|
|
_root.RowDefinitions().Clear();
|
|
|
|
|
|
|
|
// Reattach the TermControl to our grid.
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_root.Children().Append(_borderFirst);
|
|
|
|
_borderFirst.Child(_control);
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// Make sure to set our _splitState before focusing the control. If you
|
|
|
|
// fail to do this, when the tab handles the GotFocus event and asks us
|
|
|
|
// what our active control is, we won't technically be a "leaf", and
|
|
|
|
// GetTerminalControl will return null.
|
|
|
|
_splitState = SplitState::None;
|
|
|
|
|
|
|
|
// re-attach our handler for the control's GotFocus event.
|
|
|
|
_gotFocusRevoker = _control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
|
2021-01-23 00:48:20 +01:00
|
|
|
_lostFocusRevoker = _control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
|
|
|
|
// If we're inheriting the "last active" state from one of our children,
|
|
|
|
// focus our control now. This should trigger our own GotFocus event.
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (usedToFocusClosedChildsTerminal || _lastActive)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Accessibility: TermControl Automation Peer (#2083)
Builds on the work of #1691 and #1915
Let's start with the easy change:
- `TermControl`'s `controlRoot` was removed. `TermControl` is a `UserControl`
now.
Ok. Now we've got a story to tell here....
### TermControlAP - the Automation Peer
Here's an in-depth guide on custom automation peers:
https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers
We have a custom XAML element (TermControl). So XAML can't really hold our
hands and determine an accessible behavior for us. So this automation peer is
responsible for enabling that interaction.
We made it a FrameworkElementAutomationPeer to get as much accessibility as
possible from it just being a XAML element (i.e.: where are we on the screen?
what are my dimensions?). This is recommended. Any functions with "Core" at the
end, are overwritten here to tweak this automation peer into what we really
need.
But what kind of interactions can a user expect from this XAML element?
Introducing ControlPatterns! There's a ton of interfaces that just define "what
can I do". Thankfully, we already know that we're supposed to be
`ScreenInfoUiaProvider` and that was an `ITextProvider`, so let's just make the
TermControlAP an `ITextProvider` too.
So now we have a way to define what accessible actions can be performed on us,
but what should those actions do? Well let's just use the automation providers
from ConHost that are now in a shared space! (Note: this is a great place to
stop and get some coffee. We're about to hop into the .cpp file in the next
section)
### Wrapping our shared Automation Providers
Unfortunately, we can't just use the automation providers from ConHost. Or, at
least not just hook them up as easily as we wish. ConHost's UIA Providers were
written using UIAutomationCore and ITextRangeProiuder. XAML's interfaces
ITextProvider and ITextRangeProvider are lined up to be exactly the same.
So we need to wrap our ConHost UIA Providers (UIAutomationCore) with the XAML
ones. We had two providers, so that means we have two wrappers.
#### TermControlAP (XAML) <----> ScreenInfoUiaProvider (UIAutomationCore)
Each of the functions in the pragma region `ITextProvider` for
TermControlAP.cpp is just wrapping what we do in `ScreenInfoUiaProvider`, and
returning an acceptable version of it.
Most of `ScreenInfoUiaProvider`'s functions return `UiaTextRange`s. So we need
to wrap that too. That's this next section...
#### XamlUiaTextRange (XAML) <----> UiaTextRange (UIAutomationCore)
Same idea. We're wrapping everything that we could do with `UiaTextRange` and
putting it inside of `XamlUiaTextRange`.
### Additional changes to `UiaTextRange` and `ScreenInfoUiaProvider`
If you don't know what I just said, please read this background:
- #1691: how accessibility works and the general responsibility of these two
classes
- #1915: how we pulled these Accessibility Providers into a shared area
TL;DR: `ScreenInfoUiaProvider` lets you interact with the displayed text.
`UiaTextRange` is specific ranges of text in the display and navigate the text.
Thankfully, we didn't do many changes here. I feel like some of it is hacked
together but now that we have a somewhat working system, making changes
shouldn't be too hard...I hope.
#### UiaTextRange
We don't have access to the window handle. We really only need it to draw the
bounding rects using WinUser's `ScreenToClient()` and `ClientToScreen()`. I
need to figure out how to get around this.
In the meantime, I made the window handle optional. And if we don't have
one....well, we need to figure that out. But other than that, we have a
`UiaTextRange`.
#### ScreenInfoUiaProvider
At some point, we need to hook up this automation provider to the
WindowUiaProvider. This should help with navigation of the UIA Tree and make
everything just look waaaay better. For now, let's just do the same approach
and make the pUiaParent optional.
This one's the one I'm not that proud of, but it works. We need the parent to
get a bounding rect of the terminal. While we figure out how to attach the
WindowUiaProvider, we should at the very least be able to get a bunch of info
from our xaml automation peer. So, I've added a _getBoundingRect optional
function. This is what's called when we don't have a WindowUiaProvider as our
parent.
## Validation Steps Performed
I've been using inspect.exe to see the UIA tree.
I was able to interact with the terminal mostly fine. A few known issues below.
Unfortunately, I tried running Narrator on this and it didn't seem to like it
(by that I mean WT crashed). Then again, I don't really know how to use
narrator other than "click on object" --> "listen voice". I feel like there's a
way to get the other interactions with narrator, but I'll be looking into more
of that soon. I bet if I fix the two issues below, Narrator will be happy.
## Miscellaneous Known Issues
- `GetSelection()` and `GetVisibleRanges()` crashes. I need to debug through
these. I want to include them in this PR.
Fixes #1353.
2019-07-31 01:43:10 +02:00
|
|
|
_control.Focus(FocusState::Programmatic);
|
Fix `exit`ing a zoomed pane (#7973)
## Summary of the Pull Request
Fixes the bug where `exit`ing inside a closed pane would leave the Terminal blank.
Additionally, removes `Tab::GetRootElement` and replaces it with the _observable_ `Tab::Content`. This should be more resilient in the future.
Also adds some tests, though admittedly not for this exact scenario. This scenario requires a cooperating TerminalConnection that I can drive for the sake of testing, and _ain't nobody got time for that_.
## References
* Introduced in #6989
## PR Checklist
* [x] Closes #7252
* [x] I work here
* [x] Tests added/passed 🎉
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
From notes I had left in `Tab.cpp` while I was working on this:
```
OKAY I see what's happening here the ActivePaneChanged Handler in TerminalPage
doesn't re-attach the tab content to the tree, it just updates the title of the
window.
So when the pane is `exit`ed, the pane's control is removed and re-attached to
the parent grid, which _isn't in the XAML tree_. And no one can go tell the
TerminalPage that it needs to re set up the tab content again.
The Page _manually_ does this in a few places, when various pane actions are
about to take place, it'll unzoom. It would be way easier if the Tab could just
manage the content of the page.
Or if the Tab just had a Content that was observable, that when that changed,
the page would auto readjust. That does sound like a LOT of work though.
```
## Validation Steps Performed
Opened panes, closed panes, exited panes, zoomed panes, moved focus between panes, panes, panes, panes
2020-10-21 23:33:56 +02:00
|
|
|
|
|
|
|
// See GH#7252
|
|
|
|
// Manually fire off the GotFocus event. Typically, this is done
|
|
|
|
// automatically when the control gets focused. However, if we're
|
|
|
|
// `exit`ing a zoomed pane, then the other sibling isn't in the UI
|
|
|
|
// tree currently. So the above call to Focus won't actually focus
|
|
|
|
// the control. Because Tab is relying on GotFocus to know who the
|
|
|
|
// active pane in the tree is, without this call, _no one_ will be
|
|
|
|
// the active pane any longer.
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_GotFocusHandlers(shared_from_this(), FocusState::Programmatic);
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
_UpdateBorders();
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Release our children.
|
|
|
|
_firstChild = nullptr;
|
|
|
|
_secondChild = nullptr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
// Find what borders need to persist after we close the child
|
|
|
|
auto remainingBorders = _GetCommonBorders();
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Steal all the state from our child
|
|
|
|
_splitState = remainingChild->_splitState;
|
|
|
|
_firstChild = remainingChild->_firstChild;
|
|
|
|
_secondChild = remainingChild->_secondChild;
|
|
|
|
|
|
|
|
// Set up new close handlers on the children
|
|
|
|
_SetupChildCloseHandlers();
|
|
|
|
|
2019-06-29 03:17:31 +02:00
|
|
|
// Revoke the old event handlers on our new children
|
|
|
|
_firstChild->Closed(remainingChild->_firstClosedToken);
|
|
|
|
_secondChild->Closed(remainingChild->_secondClosedToken);
|
|
|
|
|
2021-08-26 00:49:26 +02:00
|
|
|
// Remove the event handlers on the old children
|
|
|
|
remainingChild->Closed(remainingChildClosedToken);
|
|
|
|
closedChild->Closed(closedChildClosedToken);
|
|
|
|
if (!isDetaching)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
closedChild->WalkTree([](auto p) {
|
|
|
|
if (p->_IsLeaf())
|
|
|
|
{
|
|
|
|
p->_control.ConnectionStateChanged(p->_connectionStateChangedToken);
|
|
|
|
p->_control.WarningBell(p->_warningBellToken);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
2021-08-26 00:49:26 +02:00
|
|
|
}
|
2019-06-07 23:56:44 +02:00
|
|
|
|
|
|
|
// Reset our UI:
|
|
|
|
_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_borderFirst.Child(nullptr);
|
|
|
|
_borderSecond.Child(nullptr);
|
2019-06-07 23:56:44 +02:00
|
|
|
_root.ColumnDefinitions().Clear();
|
|
|
|
_root.RowDefinitions().Clear();
|
|
|
|
|
|
|
|
// Copy the old UI over to our grid.
|
|
|
|
// Start by copying the row/column definitions. Iterate over the
|
|
|
|
// rows/cols, and remove each one from the old grid, and attach it to
|
|
|
|
// our grid instead.
|
|
|
|
while (remainingChild->_root.ColumnDefinitions().Size() > 0)
|
|
|
|
{
|
|
|
|
auto col = remainingChild->_root.ColumnDefinitions().GetAt(0);
|
|
|
|
remainingChild->_root.ColumnDefinitions().RemoveAt(0);
|
|
|
|
_root.ColumnDefinitions().Append(col);
|
|
|
|
}
|
|
|
|
while (remainingChild->_root.RowDefinitions().Size() > 0)
|
|
|
|
{
|
|
|
|
auto row = remainingChild->_root.RowDefinitions().GetAt(0);
|
|
|
|
remainingChild->_root.RowDefinitions().RemoveAt(0);
|
|
|
|
_root.RowDefinitions().Append(row);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the child's UI elements from the child's grid, so we can
|
|
|
|
// attach them to us instead.
|
|
|
|
remainingChild->_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
remainingChild->_borderFirst.Child(nullptr);
|
|
|
|
remainingChild->_borderSecond.Child(nullptr);
|
|
|
|
|
|
|
|
_borderFirst.Child(_firstChild->GetRootElement());
|
|
|
|
_borderSecond.Child(_secondChild->GetRootElement());
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_root.Children().Append(_borderFirst);
|
|
|
|
_root.Children().Append(_borderSecond);
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
// Propagate the new borders down to the children.
|
|
|
|
_borders = remainingBorders;
|
|
|
|
_ApplySplitDefinitions();
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If our child had focus and closed, just transfer to the first remaining
|
|
|
|
// child
|
|
|
|
if (closedChild->_HasFocusedChild())
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
|
|
|
_FocusFirstChild();
|
|
|
|
}
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// We might not have focus currently, but if our parent does then we
|
|
|
|
// want to make sure we have a valid path to one of our children.
|
|
|
|
// We should only update the path if our other child doesn't have focus itself.
|
|
|
|
else if (usedToFocusClosedChildsTerminal && !_secondChild->_HasFocusedChild())
|
|
|
|
{
|
|
|
|
// update our path to our first remaining leaf
|
|
|
|
_parentChildPath = _firstChild;
|
|
|
|
_firstChild->WalkTree([](auto p) {
|
|
|
|
if (p->_IsLeaf())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
p->_parentChildPath = p->_firstChild;
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
// This will focus the first terminal, and will set that leaf pane
|
|
|
|
// to the active pane if we nor one of our parents is not itself focused.
|
|
|
|
_FocusFirstChild();
|
|
|
|
}
|
2019-06-07 23:56:44 +02:00
|
|
|
|
|
|
|
// Release the pointers that the child was holding.
|
|
|
|
remainingChild->_firstChild = nullptr;
|
|
|
|
remainingChild->_secondChild = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst)
|
|
|
|
{
|
|
|
|
auto weakThis{ shared_from_this() };
|
|
|
|
|
|
|
|
co_await winrt::resume_foreground(_root.Dispatcher());
|
|
|
|
|
|
|
|
if (auto pane{ weakThis.get() })
|
|
|
|
{
|
2020-10-10 01:06:40 +02:00
|
|
|
// This will query if animations are enabled via the "Show animations in
|
|
|
|
// Windows" setting in the OS
|
|
|
|
winrt::Windows::UI::ViewManagement::UISettings uiSettings;
|
|
|
|
const auto animationsEnabledInOS = uiSettings.AnimationsEnabled();
|
|
|
|
const auto animationsEnabledInApp = Media::Animation::Timeline::AllowDependentAnimations();
|
|
|
|
|
Fix `exit`ing a zoomed pane (#7973)
## Summary of the Pull Request
Fixes the bug where `exit`ing inside a closed pane would leave the Terminal blank.
Additionally, removes `Tab::GetRootElement` and replaces it with the _observable_ `Tab::Content`. This should be more resilient in the future.
Also adds some tests, though admittedly not for this exact scenario. This scenario requires a cooperating TerminalConnection that I can drive for the sake of testing, and _ain't nobody got time for that_.
## References
* Introduced in #6989
## PR Checklist
* [x] Closes #7252
* [x] I work here
* [x] Tests added/passed 🎉
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
From notes I had left in `Tab.cpp` while I was working on this:
```
OKAY I see what's happening here the ActivePaneChanged Handler in TerminalPage
doesn't re-attach the tab content to the tree, it just updates the title of the
window.
So when the pane is `exit`ed, the pane's control is removed and re-attached to
the parent grid, which _isn't in the XAML tree_. And no one can go tell the
TerminalPage that it needs to re set up the tab content again.
The Page _manually_ does this in a few places, when various pane actions are
about to take place, it'll unzoom. It would be way easier if the Tab could just
manage the content of the page.
Or if the Tab just had a Content that was observable, that when that changed,
the page would auto readjust. That does sound like a LOT of work though.
```
## Validation Steps Performed
Opened panes, closed panes, exited panes, zoomed panes, moved focus between panes, panes, panes, panes
2020-10-21 23:33:56 +02:00
|
|
|
// GH#7252: If either child is zoomed, just skip the animation. It won't work.
|
|
|
|
const bool eitherChildZoomed = pane->_firstChild->_zoomed || pane->_secondChild->_zoomed;
|
2020-10-10 01:06:40 +02:00
|
|
|
// If animations are disabled, just skip this and go straight to
|
|
|
|
// _CloseChild. Curiously, the pane opening animation doesn't need this,
|
|
|
|
// and will skip straight to Completed when animations are disabled, but
|
|
|
|
// this one doesn't seem to.
|
Fix `exit`ing a zoomed pane (#7973)
## Summary of the Pull Request
Fixes the bug where `exit`ing inside a closed pane would leave the Terminal blank.
Additionally, removes `Tab::GetRootElement` and replaces it with the _observable_ `Tab::Content`. This should be more resilient in the future.
Also adds some tests, though admittedly not for this exact scenario. This scenario requires a cooperating TerminalConnection that I can drive for the sake of testing, and _ain't nobody got time for that_.
## References
* Introduced in #6989
## PR Checklist
* [x] Closes #7252
* [x] I work here
* [x] Tests added/passed 🎉
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
From notes I had left in `Tab.cpp` while I was working on this:
```
OKAY I see what's happening here the ActivePaneChanged Handler in TerminalPage
doesn't re-attach the tab content to the tree, it just updates the title of the
window.
So when the pane is `exit`ed, the pane's control is removed and re-attached to
the parent grid, which _isn't in the XAML tree_. And no one can go tell the
TerminalPage that it needs to re set up the tab content again.
The Page _manually_ does this in a few places, when various pane actions are
about to take place, it'll unzoom. It would be way easier if the Tab could just
manage the content of the page.
Or if the Tab just had a Content that was observable, that when that changed,
the page would auto readjust. That does sound like a LOT of work though.
```
## Validation Steps Performed
Opened panes, closed panes, exited panes, zoomed panes, moved focus between panes, panes, panes, panes
2020-10-21 23:33:56 +02:00
|
|
|
if (!animationsEnabledInOS || !animationsEnabledInApp || eitherChildZoomed)
|
2020-10-10 01:06:40 +02:00
|
|
|
{
|
2021-08-26 00:49:26 +02:00
|
|
|
pane->_CloseChild(closeFirst, false);
|
2020-10-10 01:06:40 +02:00
|
|
|
co_return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup the animation
|
|
|
|
|
|
|
|
auto removedChild = closeFirst ? _firstChild : _secondChild;
|
|
|
|
auto remainingChild = closeFirst ? _secondChild : _firstChild;
|
|
|
|
const bool splitWidth = _splitState == SplitState::Vertical;
|
|
|
|
|
|
|
|
Size removedOriginalSize{
|
|
|
|
::base::saturated_cast<float>(removedChild->_root.ActualWidth()),
|
|
|
|
::base::saturated_cast<float>(removedChild->_root.ActualHeight())
|
|
|
|
};
|
|
|
|
Size remainingOriginalSize{
|
|
|
|
::base::saturated_cast<float>(remainingChild->_root.ActualWidth()),
|
|
|
|
::base::saturated_cast<float>(remainingChild->_root.ActualHeight())
|
|
|
|
};
|
|
|
|
|
|
|
|
// Remove both children from the grid
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_borderFirst.Child(nullptr);
|
|
|
|
_borderSecond.Child(nullptr);
|
|
|
|
|
2020-10-10 01:06:40 +02:00
|
|
|
if (_splitState == SplitState::Vertical)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
Controls::Grid::SetColumn(_borderFirst, 0);
|
|
|
|
Controls::Grid::SetColumn(_borderSecond, 1);
|
2020-10-10 01:06:40 +02:00
|
|
|
}
|
|
|
|
else if (_splitState == SplitState::Horizontal)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
Controls::Grid::SetRow(_borderFirst, 0);
|
|
|
|
Controls::Grid::SetRow(_borderSecond, 1);
|
2020-10-10 01:06:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create the dummy grid. This grid will be the one we actually animate,
|
|
|
|
// in the place of the closed pane.
|
|
|
|
Controls::Grid dummyGrid;
|
2021-09-20 19:08:13 +02:00
|
|
|
// GH#603 - we can safely add a BG here, as the control is gone right
|
|
|
|
// away, to fill the space as the rest of the pane expands.
|
2020-10-10 01:06:40 +02:00
|
|
|
dummyGrid.Background(s_unfocusedBorderBrush);
|
|
|
|
// It should be the size of the closed pane.
|
|
|
|
dummyGrid.Width(removedOriginalSize.Width);
|
|
|
|
dummyGrid.Height(removedOriginalSize.Height);
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
|
|
|
|
_borderFirst.Child(closeFirst ? dummyGrid : remainingChild->GetRootElement());
|
|
|
|
_borderSecond.Child(closeFirst ? remainingChild->GetRootElement() : dummyGrid);
|
2020-10-10 01:06:40 +02:00
|
|
|
|
|
|
|
// Set up the rows/cols as auto/auto, so they'll only use the size of
|
|
|
|
// the elements in the grid.
|
|
|
|
//
|
|
|
|
// * For the closed pane, we want to make that row/col "auto" sized, so
|
|
|
|
// it takes up as much space as is available.
|
|
|
|
// * For the remaining pane, we'll make that row/col "*" sized, so it
|
|
|
|
// takes all the remaining space. As the dummy grid is resized down,
|
|
|
|
// the remaining pane will expand to take the rest of the space.
|
|
|
|
_root.ColumnDefinitions().Clear();
|
|
|
|
_root.RowDefinitions().Clear();
|
|
|
|
if (_splitState == SplitState::Vertical)
|
|
|
|
{
|
|
|
|
auto firstColDef = Controls::ColumnDefinition();
|
|
|
|
auto secondColDef = Controls::ColumnDefinition();
|
|
|
|
firstColDef.Width(!closeFirst ? GridLengthHelper::FromValueAndType(1, GridUnitType::Star) : GridLengthHelper::Auto());
|
|
|
|
secondColDef.Width(closeFirst ? GridLengthHelper::FromValueAndType(1, GridUnitType::Star) : GridLengthHelper::Auto());
|
|
|
|
_root.ColumnDefinitions().Append(firstColDef);
|
|
|
|
_root.ColumnDefinitions().Append(secondColDef);
|
|
|
|
}
|
|
|
|
else if (_splitState == SplitState::Horizontal)
|
|
|
|
{
|
|
|
|
auto firstRowDef = Controls::RowDefinition();
|
|
|
|
auto secondRowDef = Controls::RowDefinition();
|
|
|
|
firstRowDef.Height(!closeFirst ? GridLengthHelper::FromValueAndType(1, GridUnitType::Star) : GridLengthHelper::Auto());
|
|
|
|
secondRowDef.Height(closeFirst ? GridLengthHelper::FromValueAndType(1, GridUnitType::Star) : GridLengthHelper::Auto());
|
|
|
|
_root.RowDefinitions().Append(firstRowDef);
|
|
|
|
_root.RowDefinitions().Append(secondRowDef);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Animate the dummy grid from its current size down to 0
|
|
|
|
Media::Animation::DoubleAnimation animation{};
|
|
|
|
animation.Duration(AnimationDuration);
|
|
|
|
animation.From(splitWidth ? removedOriginalSize.Width : removedOriginalSize.Height);
|
|
|
|
animation.To(0.0);
|
|
|
|
// This easing is the same as the entrance animation.
|
|
|
|
animation.EasingFunction(Media::Animation::QuadraticEase{});
|
|
|
|
animation.EnableDependentAnimation(true);
|
|
|
|
|
|
|
|
Media::Animation::Storyboard s;
|
|
|
|
s.Duration(AnimationDuration);
|
|
|
|
s.Children().Append(animation);
|
|
|
|
s.SetTarget(animation, dummyGrid);
|
|
|
|
s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height");
|
|
|
|
|
|
|
|
// Start the animation.
|
|
|
|
s.Begin();
|
|
|
|
|
|
|
|
std::weak_ptr<Pane> weakThis{ shared_from_this() };
|
|
|
|
|
|
|
|
// When the animation is completed, reparent the child's content up to
|
|
|
|
// us, and remove the child nodes from the tree.
|
|
|
|
animation.Completed([weakThis, closeFirst](auto&&, auto&&) {
|
|
|
|
if (auto pane{ weakThis.lock() })
|
|
|
|
{
|
|
|
|
// We don't need to manually undo any of the above trickiness.
|
|
|
|
// We're going to re-parent the child's content into us anyways
|
2021-08-26 00:49:26 +02:00
|
|
|
pane->_CloseChild(closeFirst, false);
|
2020-10-10 01:06:40 +02:00
|
|
|
}
|
|
|
|
});
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Adds event handlers to our children to handle their close events.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::_SetupChildCloseHandlers()
|
|
|
|
{
|
2019-11-25 23:22:29 +01:00
|
|
|
_firstClosedToken = _firstChild->Closed([this](auto&& /*s*/, auto&& /*e*/) {
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
_CloseChildRoutine(true);
|
2019-06-07 23:56:44 +02:00
|
|
|
});
|
|
|
|
|
2019-11-25 23:22:29 +01:00
|
|
|
_secondClosedToken = _secondChild->Closed([this](auto&& /*s*/, auto&& /*e*/) {
|
Converts Dispatcher().RunAsync to WinRT Coroutines (#4051)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
This PR turns all* instances of `Dispatcher().RunAsync` to WinRT coroutines 👌.
This was good coding fodder to fill my plane ride ✈️. Enjoy your holidays everyone!
*With the exception of three functions whose signatures cannot be changed due to inheritance and function overriding in `TermControlAutomationPeer` [`L44`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L44), [`L58`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L58), [`L72`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp#L72).
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #3919
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3919
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
My thought pattern here was to minimally disturb the existing code where possible. So where I could, I converted existing functions into coroutine using functions (like in the [core example](https://github.com/microsoft/terminal/issues/3919#issue-536598706)). For ~the most part~ all instances, I used the format where [`this` is accessed safely within a locked scope](https://github.com/microsoft/terminal/issues/3919#issuecomment-564730620). Some function signatures were changed to take objects by value instead of reference, so the coroutines don't crash when the objects are accessed past their original lifetime. The [copy](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1132) and [paste](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/TerminalPage.cpp#L1170) event handler entry points were originally set to a high priority; however, the WinRT coroutines don't appear to support a priority scheme so this priority setting was not preserved in the translation.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Compiles and runs, and for every event with a clear trigger repro, I triggered it to ensure crashes weren't introduced.
2020-01-10 04:29:49 +01:00
|
|
|
_CloseChildRoutine(false);
|
2019-06-07 23:56:44 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// - Sets up row/column definitions for this pane. There are three total
|
|
|
|
// row/cols. The middle one is for the separator. The first and third are for
|
|
|
|
// each of the child panes, and are given a size in pixels, based off the
|
2020-02-10 21:40:01 +01:00
|
|
|
// available space, and the percent of the space they respectively consume,
|
2020-01-08 22:19:23 +01:00
|
|
|
// which is stored in _desiredSplitPosition
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// - Does nothing if our split state is currently set to SplitState::None
|
2019-06-07 23:56:44 +02:00
|
|
|
// Arguments:
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// - <none>
|
2019-06-07 23:56:44 +02:00
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
void Pane::_CreateRowColDefinitions()
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
const auto first = _desiredSplitPosition * 100.0f;
|
|
|
|
const auto second = 100.0f - first;
|
2019-06-07 23:56:44 +02:00
|
|
|
if (_splitState == SplitState::Vertical)
|
|
|
|
{
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
_root.ColumnDefinitions().Clear();
|
|
|
|
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
// Create two columns in this grid: one for each pane
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
auto firstColDef = Controls::ColumnDefinition();
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
firstColDef.Width(GridLengthHelper::FromValueAndType(first, GridUnitType::Star));
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
auto secondColDef = Controls::ColumnDefinition();
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
secondColDef.Width(GridLengthHelper::FromValueAndType(second, GridUnitType::Star));
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
_root.ColumnDefinitions().Append(firstColDef);
|
|
|
|
_root.ColumnDefinitions().Append(secondColDef);
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
else if (_splitState == SplitState::Horizontal)
|
|
|
|
{
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
_root.RowDefinitions().Clear();
|
|
|
|
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
// Create two rows in this grid: one for each pane
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
auto firstRowDef = Controls::RowDefinition();
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
firstRowDef.Height(GridLengthHelper::FromValueAndType(first, GridUnitType::Star));
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
auto secondRowDef = Controls::RowDefinition();
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
secondRowDef.Height(GridLengthHelper::FromValueAndType(second, GridUnitType::Star));
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
|
|
|
|
_root.RowDefinitions().Append(firstRowDef);
|
|
|
|
_root.RowDefinitions().Append(secondRowDef);
|
|
|
|
}
|
|
|
|
}
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Sets the thickness of each side of our borders to match our _borders state.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::_UpdateBorders()
|
|
|
|
{
|
|
|
|
double top = 0, bottom = 0, left = 0, right = 0;
|
|
|
|
|
|
|
|
Thickness newBorders{ 0 };
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Zoomed panes, and focused parents should have full borders
|
|
|
|
if (_zoomed || (!_IsLeaf() && _lastActive))
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
{
|
2020-08-08 01:11:44 +02:00
|
|
|
top = bottom = right = left = PaneBorderSize;
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
}
|
2020-08-08 01:11:44 +02:00
|
|
|
else
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
{
|
2020-08-08 01:11:44 +02:00
|
|
|
if (WI_IsFlagSet(_borders, Borders::Top))
|
|
|
|
{
|
|
|
|
top = PaneBorderSize;
|
|
|
|
}
|
|
|
|
if (WI_IsFlagSet(_borders, Borders::Bottom))
|
|
|
|
{
|
|
|
|
bottom = PaneBorderSize;
|
|
|
|
}
|
|
|
|
if (WI_IsFlagSet(_borders, Borders::Left))
|
|
|
|
{
|
|
|
|
left = PaneBorderSize;
|
|
|
|
}
|
|
|
|
if (WI_IsFlagSet(_borders, Borders::Right))
|
|
|
|
{
|
|
|
|
right = PaneBorderSize;
|
|
|
|
}
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
}
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
_borderFirst.BorderThickness(ThicknessHelper::FromLengths(left, top, right, bottom));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If we are not a leaf we don't want to duplicate the shared border
|
|
|
|
// between our children.
|
|
|
|
if (_splitState == SplitState::Vertical)
|
|
|
|
{
|
|
|
|
_borderFirst.BorderThickness(ThicknessHelper::FromLengths(left, top, 0, bottom));
|
|
|
|
_borderSecond.BorderThickness(ThicknessHelper::FromLengths(0, top, right, bottom));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_borderFirst.BorderThickness(ThicknessHelper::FromLengths(left, top, right, 0));
|
|
|
|
_borderSecond.BorderThickness(ThicknessHelper::FromLengths(left, 0, right, bottom));
|
|
|
|
}
|
|
|
|
}
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
2021-08-02 23:04:57 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Find the borders for the leaf pane, or the shared borders for child panes.
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// - This deliberately ignores if a focused parent has borders.
|
2021-08-02 23:04:57 +02:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
Borders Pane::_GetCommonBorders()
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return _borders;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _firstChild->_GetCommonBorders() & _secondChild->_GetCommonBorders();
|
|
|
|
}
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Sets the row/column of our child UI elements, to match our current split type.
|
2021-08-02 23:04:57 +02:00
|
|
|
// - In case the split definition or parent borders were changed, this recursively
|
|
|
|
// updates the children as well.
|
2019-06-07 23:56:44 +02:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::_ApplySplitDefinitions()
|
|
|
|
{
|
|
|
|
if (_splitState == SplitState::Vertical)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
Controls::Grid::SetColumn(_borderFirst, 0);
|
|
|
|
Controls::Grid::SetColumn(_borderSecond, 1);
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
|
|
|
_firstChild->_borders = _borders | Borders::Right;
|
|
|
|
_secondChild->_borders = _borders | Borders::Left;
|
|
|
|
_borders = Borders::None;
|
|
|
|
|
2021-08-02 23:04:57 +02:00
|
|
|
_firstChild->_ApplySplitDefinitions();
|
|
|
|
_secondChild->_ApplySplitDefinitions();
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
else if (_splitState == SplitState::Horizontal)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
Controls::Grid::SetRow(_borderFirst, 0);
|
|
|
|
Controls::Grid::SetRow(_borderSecond, 1);
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
|
|
|
_firstChild->_borders = _borders | Borders::Bottom;
|
|
|
|
_secondChild->_borders = _borders | Borders::Top;
|
|
|
|
_borders = Borders::None;
|
|
|
|
|
2021-08-02 23:04:57 +02:00
|
|
|
_firstChild->_ApplySplitDefinitions();
|
|
|
|
_secondChild->_ApplySplitDefinitions();
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
2021-08-02 23:04:57 +02:00
|
|
|
_UpdateBorders();
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
2020-10-10 01:06:40 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Create a pair of animations when a new control enters this pane. This
|
|
|
|
// should _ONLY_ be called in _Split, AFTER the first and second child panes
|
|
|
|
// have been set up.
|
|
|
|
void Pane::_SetupEntranceAnimation()
|
|
|
|
{
|
|
|
|
// This will query if animations are enabled via the "Show animations in
|
|
|
|
// Windows" setting in the OS
|
|
|
|
winrt::Windows::UI::ViewManagement::UISettings uiSettings;
|
|
|
|
const auto animationsEnabledInOS = uiSettings.AnimationsEnabled();
|
2020-11-13 02:34:38 +01:00
|
|
|
const auto animationsEnabledInApp = Media::Animation::Timeline::AllowDependentAnimations();
|
2020-10-10 01:06:40 +02:00
|
|
|
|
|
|
|
const bool splitWidth = _splitState == SplitState::Vertical;
|
|
|
|
const auto totalSize = splitWidth ? _root.ActualWidth() : _root.ActualHeight();
|
|
|
|
// If we don't have a size yet, it's likely that we're in startup, or we're
|
|
|
|
// being executed as a sequence of actions. In that case, just skip the
|
|
|
|
// animation.
|
2020-11-13 02:34:38 +01:00
|
|
|
if (totalSize <= 0 || !animationsEnabledInOS || !animationsEnabledInApp)
|
2020-10-10 01:06:40 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-09-20 19:08:13 +02:00
|
|
|
// Use the unfocused border color as the pane background, so an actual color
|
|
|
|
// appears behind panes as we animate them sliding in.
|
|
|
|
//
|
|
|
|
// GH#603 - We set only the background of the new pane, while it animates
|
|
|
|
// in. Once the animation is done, we'll remove that background, so if the
|
|
|
|
// user wants vintage opacity, they'll be able to see what's under the
|
|
|
|
// window.
|
|
|
|
// * If we don't give it a background, then the BG will be entirely transparent.
|
|
|
|
// * If we give the parent (us) root BG a color, then a transparent pane
|
|
|
|
// will flash opaque during the animation, then back to transparent, which
|
|
|
|
// looks bad.
|
|
|
|
_secondChild->_root.Background(s_unfocusedBorderBrush);
|
|
|
|
|
2020-10-10 01:06:40 +02:00
|
|
|
const auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast<float>(totalSize));
|
|
|
|
|
|
|
|
// This is safe to capture this, because it's only being called in the
|
|
|
|
// context of this method (not on another thread)
|
|
|
|
auto setupAnimation = [&](const auto& size, const bool isFirstChild) {
|
|
|
|
auto child = isFirstChild ? _firstChild : _secondChild;
|
|
|
|
auto childGrid = child->_root;
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If we are splitting a parent pane this may be null
|
2020-10-10 01:06:40 +02:00
|
|
|
auto control = child->_control;
|
|
|
|
// Build up our animation:
|
|
|
|
// * it'll take as long as our duration (200ms)
|
|
|
|
// * it'll change the value of our property from 0 to secondSize
|
|
|
|
// * it'll animate that value using a quadratic function (like f(t) = t^2)
|
|
|
|
// * IMPORTANT! We'll manually tell the animation that "yes we know what
|
|
|
|
// we're doing, we want an animation here."
|
|
|
|
Media::Animation::DoubleAnimation animation{};
|
|
|
|
animation.Duration(AnimationDuration);
|
|
|
|
if (isFirstChild)
|
|
|
|
{
|
|
|
|
// If we're animating the first pane, the size should decrease, from
|
|
|
|
// the full size down to the given size.
|
|
|
|
animation.From(totalSize);
|
|
|
|
animation.To(size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Otherwise, we want to show the pane getting larger, so animate
|
|
|
|
// from 0 to the requested size.
|
|
|
|
animation.From(0.0);
|
|
|
|
animation.To(size);
|
|
|
|
}
|
|
|
|
animation.EasingFunction(Media::Animation::QuadraticEase{});
|
|
|
|
animation.EnableDependentAnimation(true);
|
|
|
|
|
|
|
|
// Now we're going to set up the Storyboard. This is a unit that uses the
|
|
|
|
// Animation from above, and actually applies it to a property.
|
|
|
|
// * we'll set it up for the same duration as the animation we have
|
|
|
|
// * Apply the animation to the grid of the new pane we're adding to the tree.
|
|
|
|
// * apply the animation to the Width or Height property.
|
|
|
|
Media::Animation::Storyboard s;
|
|
|
|
s.Duration(AnimationDuration);
|
|
|
|
s.Children().Append(animation);
|
|
|
|
s.SetTarget(animation, childGrid);
|
|
|
|
s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height");
|
|
|
|
|
|
|
|
// BE TRICKY:
|
|
|
|
// We're animating the width or height of our child pane's grid.
|
|
|
|
//
|
|
|
|
// We DON'T want to change the size of the control itself, because the
|
|
|
|
// terminal has to reflow the buffer every time the control changes size. So
|
|
|
|
// what we're going to do there is manually set the control's size to how
|
|
|
|
// big we _actually know_ the control will be.
|
|
|
|
//
|
|
|
|
// We're also going to be changing alignment of our child pane and the
|
|
|
|
// control. This way, we'll be able to have the control stick to the inside
|
|
|
|
// of the child pane's grid (the side that's moving), while we also have the
|
|
|
|
// pane's grid stick to "outside" of the grid (the side that's not moving)
|
|
|
|
if (splitWidth)
|
|
|
|
{
|
|
|
|
// If we're animating the first child, then stick to the top/left of
|
|
|
|
// the parent pane, otherwise use the bottom/right. This is always
|
|
|
|
// the "outside" of the parent pane.
|
|
|
|
childGrid.HorizontalAlignment(isFirstChild ? HorizontalAlignment::Left : HorizontalAlignment::Right);
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (control)
|
|
|
|
{
|
|
|
|
control.HorizontalAlignment(HorizontalAlignment::Left);
|
|
|
|
control.Width(isFirstChild ? totalSize : size);
|
|
|
|
}
|
2020-11-18 22:31:37 +01:00
|
|
|
|
|
|
|
// When the animation is completed, undo the trickiness from before, to
|
|
|
|
// restore the controls to the behavior they'd usually have.
|
2021-09-20 19:08:13 +02:00
|
|
|
animation.Completed([childGrid, control, root = _secondChild->_root](auto&&, auto&&) {
|
2020-11-18 22:31:37 +01:00
|
|
|
childGrid.Width(NAN);
|
|
|
|
childGrid.HorizontalAlignment(HorizontalAlignment::Stretch);
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (control)
|
|
|
|
{
|
|
|
|
control.Width(NAN);
|
|
|
|
control.HorizontalAlignment(HorizontalAlignment::Stretch);
|
|
|
|
}
|
2021-09-20 19:08:13 +02:00
|
|
|
root.Background(nullptr);
|
2020-11-18 22:31:37 +01:00
|
|
|
});
|
2020-10-10 01:06:40 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If we're animating the first child, then stick to the top/left of
|
|
|
|
// the parent pane, otherwise use the bottom/right. This is always
|
|
|
|
// the "outside" of the parent pane.
|
|
|
|
childGrid.VerticalAlignment(isFirstChild ? VerticalAlignment::Top : VerticalAlignment::Bottom);
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (control)
|
|
|
|
{
|
|
|
|
control.VerticalAlignment(VerticalAlignment::Top);
|
|
|
|
control.Height(isFirstChild ? totalSize : size);
|
|
|
|
}
|
2020-11-18 22:31:37 +01:00
|
|
|
|
|
|
|
// When the animation is completed, undo the trickiness from before, to
|
|
|
|
// restore the controls to the behavior they'd usually have.
|
2021-09-20 19:08:13 +02:00
|
|
|
animation.Completed([childGrid, control, root = _secondChild->_root](auto&&, auto&&) {
|
2020-11-18 22:31:37 +01:00
|
|
|
childGrid.Height(NAN);
|
|
|
|
childGrid.VerticalAlignment(VerticalAlignment::Stretch);
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (control)
|
|
|
|
{
|
|
|
|
control.Height(NAN);
|
|
|
|
control.VerticalAlignment(VerticalAlignment::Stretch);
|
|
|
|
}
|
2021-09-20 19:08:13 +02:00
|
|
|
root.Background(nullptr);
|
2020-11-18 22:31:37 +01:00
|
|
|
});
|
2020-10-10 01:06:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Start the animation.
|
|
|
|
s.Begin();
|
|
|
|
};
|
|
|
|
|
|
|
|
// TODO: GH#7365 - animating the first child right now doesn't _really_ do
|
|
|
|
// anything. We could do better though.
|
|
|
|
setupAnimation(firstSize, true);
|
|
|
|
setupAnimation(secondSize, false);
|
|
|
|
}
|
|
|
|
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
// Method Description:
|
|
|
|
// - This is a helper to determine if a given Pane can be split, but without
|
|
|
|
// using the ActualWidth() and ActualHeight() methods. This is used during
|
|
|
|
// processing of many "split-pane" commands, which could happen _before_ we've
|
|
|
|
// laid out a Pane for the first time. When this happens, the Pane's don't
|
|
|
|
// have an actual size yet. However, we'd still like to figure out if the pane
|
|
|
|
// could be split, once they're all laid out.
|
|
|
|
// - This method assumes that the Pane we're attempting to split is `target`,
|
|
|
|
// and this method should be called on the root of a tree of Panes.
|
|
|
|
// - We'll walk down the tree attempting to find `target`. As we traverse the
|
|
|
|
// tree, we'll reduce the size passed to each subsequent recursive call. The
|
|
|
|
// size passed to this method represents how much space this Pane _will_ have
|
|
|
|
// to use.
|
|
|
|
// * If this pane is a leaf, and it's the pane we're looking for, use the
|
|
|
|
// available space to calculate which direction to split in.
|
|
|
|
// * If this pane is _any other leaf_, then just return nullopt, to indicate
|
|
|
|
// that the `target` Pane is not down this branch.
|
|
|
|
// * If this pane is a parent, calculate how much space our children will be
|
|
|
|
// able to use, and recurse into them.
|
|
|
|
// Arguments:
|
|
|
|
// - target: The Pane we're attempting to split.
|
|
|
|
// - splitType: The direction we're attempting to split in.
|
|
|
|
// - availableSpace: The theoretical space that's available for this pane to be able to split.
|
|
|
|
// Return Value:
|
|
|
|
// - nullopt if `target` is not this pane or a child of this pane, otherwise
|
|
|
|
// true iff we could split this pane, given `availableSpace`
|
|
|
|
// Note:
|
|
|
|
// - This method is highly similar to Pane::PreCalculateAutoSplit
|
|
|
|
std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> target,
|
2021-09-15 22:14:57 +02:00
|
|
|
SplitDirection splitType,
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
const float splitSize,
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
const winrt::Windows::Foundation::Size availableSpace) const
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (target.get() == this)
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
const auto firstPercent = 1.0f - splitSize;
|
|
|
|
const auto secondPercent = splitSize;
|
|
|
|
// If this pane is a leaf, and it's the pane we're looking for, use
|
|
|
|
// the available space to calculate which direction to split in.
|
|
|
|
const Size minSize = _GetMinSize();
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (splitType == SplitDirection::Left || splitType == SplitDirection::Right)
|
|
|
|
{
|
|
|
|
const auto widthMinusSeparator = availableSpace.Width - CombinedPaneBorderSize;
|
|
|
|
const auto newFirstWidth = widthMinusSeparator * firstPercent;
|
|
|
|
const auto newSecondWidth = widthMinusSeparator * secondPercent;
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
return { newFirstWidth > minSize.Width && newSecondWidth > minSize.Width };
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
}
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
|
|
|
|
else if (splitType == SplitDirection::Up || splitType == SplitDirection::Down)
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
const auto heightMinusSeparator = availableSpace.Height - CombinedPaneBorderSize;
|
|
|
|
const auto newFirstHeight = heightMinusSeparator * firstPercent;
|
|
|
|
const auto newSecondHeight = heightMinusSeparator * secondPercent;
|
|
|
|
|
|
|
|
return { newFirstHeight > minSize.Height && newSecondHeight > minSize.Height };
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
}
|
|
|
|
}
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
else if (_IsLeaf())
|
|
|
|
{
|
|
|
|
// If this pane is _any other leaf_, then just return nullopt, to
|
|
|
|
// indicate that the `target` Pane is not down this branch.
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// If this pane is a parent, calculate how much space our children will
|
|
|
|
// be able to use, and recurse into them.
|
|
|
|
|
|
|
|
const bool isVerticalSplit = _splitState == SplitState::Vertical;
|
|
|
|
const float firstWidth = isVerticalSplit ?
|
|
|
|
(availableSpace.Width * _desiredSplitPosition) - PaneBorderSize :
|
|
|
|
availableSpace.Width;
|
|
|
|
const float secondWidth = isVerticalSplit ?
|
|
|
|
(availableSpace.Width - firstWidth) - PaneBorderSize :
|
|
|
|
availableSpace.Width;
|
|
|
|
const float firstHeight = !isVerticalSplit ?
|
|
|
|
(availableSpace.Height * _desiredSplitPosition) - PaneBorderSize :
|
|
|
|
availableSpace.Height;
|
|
|
|
const float secondHeight = !isVerticalSplit ?
|
|
|
|
(availableSpace.Height - firstHeight) - PaneBorderSize :
|
|
|
|
availableSpace.Height;
|
|
|
|
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
const auto firstResult = _firstChild->PreCalculateCanSplit(target, splitType, splitSize, { firstWidth, firstHeight });
|
|
|
|
return firstResult.has_value() ? firstResult : _secondChild->PreCalculateCanSplit(target, splitType, splitSize, { secondWidth, secondHeight });
|
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537)
## Summary of the Pull Request
Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_.
## References
* Related to #4472
* Related to #5400 - I need this for the commandline mode of the Command Palette
* Related to #5970
## PR Checklist
* [x] Closes oh, there's not actually an issue for this.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - yes it does
## Detailed Description of the Pull Request / Additional comments
One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again.
We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up.
This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out.
This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized.
## Validation Steps Performed
This was what the json blob I was using for testing evolved into
```json
{
"command": {
"action":"wt",
"commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0",
},
"keys": ["ctrl+shift+n"]
}
```
I also added some tests.
# TODO
* [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process?
- Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// We should not possibly be getting here - both the above branches should
|
|
|
|
// return a value.
|
|
|
|
FAIL_FAST();
|
|
|
|
}
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Method Description:
|
2021-11-04 23:29:58 +01:00
|
|
|
// - The same as above, except this takes in the pane directly instead of a
|
|
|
|
// profile and control to make a pane with
|
2019-06-07 23:56:44 +02:00
|
|
|
// Arguments:
|
2019-08-28 16:40:16 +02:00
|
|
|
// - splitType: what type of split we want to create.
|
2021-11-04 23:29:58 +01:00
|
|
|
// - splitSize: the desired size of the split
|
|
|
|
// - newPane: the new pane
|
2019-06-07 23:56:44 +02:00
|
|
|
// Return Value:
|
2021-09-15 22:14:57 +02:00
|
|
|
// - The two newly created Panes, with the original pane first
|
|
|
|
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitDirection splitType,
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
const float splitSize,
|
2021-11-04 23:29:58 +01:00
|
|
|
std::shared_ptr<Pane> newPane)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (!_lastActive)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (_firstChild && _firstChild->_HasFocusedChild())
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
2021-11-04 23:29:58 +01:00
|
|
|
return _firstChild->Split(splitType, splitSize, newPane);
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
else if (_secondChild && _secondChild->_HasFocusedChild())
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
2021-11-04 23:29:58 +01:00
|
|
|
return _secondChild->Split(splitType, splitSize, newPane);
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
return { nullptr, nullptr };
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
return _Split(splitType, splitSize, newPane);
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
2021-08-02 23:04:57 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Toggle the split orientation of the currently focused pane
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - true if a split was changed
|
|
|
|
bool Pane::ToggleSplitOrientation()
|
|
|
|
{
|
|
|
|
// If we are a leaf there is no split to toggle.
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If a parent pane is focused, or if one of its children are a leaf and is
|
|
|
|
// focused then switch the split orientation on the current pane.
|
2021-08-02 23:04:57 +02:00
|
|
|
const bool firstIsFocused = _firstChild->_IsLeaf() && _firstChild->_lastActive;
|
|
|
|
const bool secondIsFocused = _secondChild->_IsLeaf() && _secondChild->_lastActive;
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (_lastActive || firstIsFocused || secondIsFocused)
|
2021-08-02 23:04:57 +02:00
|
|
|
{
|
|
|
|
// Switch the split orientation
|
|
|
|
_splitState = _splitState == SplitState::Horizontal ? SplitState::Vertical : SplitState::Horizontal;
|
|
|
|
|
|
|
|
// then update the borders and positioning on ourselves and our children.
|
|
|
|
_borders = _GetCommonBorders();
|
|
|
|
// Since we changed if we are using rows/columns, make sure we remove the old definitions
|
|
|
|
_root.ColumnDefinitions().Clear();
|
|
|
|
_root.RowDefinitions().Clear();
|
|
|
|
_CreateRowColDefinitions();
|
|
|
|
_ApplySplitDefinitions();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _firstChild->ToggleSplitOrientation() || _secondChild->ToggleSplitOrientation();
|
|
|
|
}
|
|
|
|
|
2019-12-19 22:47:19 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Converts an "automatic" split type into either Vertical or Horizontal,
|
|
|
|
// based upon the current dimensions of the Pane.
|
2021-09-15 22:14:57 +02:00
|
|
|
// - Similarly, if Up/Down or Left/Right are provided a Horizontal or Vertical
|
|
|
|
// split type will be returned.
|
2019-12-19 22:47:19 +01:00
|
|
|
// Arguments:
|
2021-09-15 22:14:57 +02:00
|
|
|
// - splitType: The SplitDirection to attempt to convert
|
2019-12-19 22:47:19 +01:00
|
|
|
// Return Value:
|
2021-09-15 22:14:57 +02:00
|
|
|
// - One of Horizontal or Vertical
|
|
|
|
SplitState Pane::_convertAutomaticOrDirectionalSplitState(const SplitDirection& splitType) const
|
2019-12-19 22:47:19 +01:00
|
|
|
{
|
|
|
|
// Careful here! If the pane doesn't yet have a size, these dimensions will
|
|
|
|
// be 0, and we'll always return Vertical.
|
|
|
|
|
2021-09-15 22:14:57 +02:00
|
|
|
if (splitType == SplitDirection::Automatic)
|
2019-12-19 22:47:19 +01:00
|
|
|
{
|
|
|
|
// If the requested split type was "auto", determine which direction to
|
|
|
|
// split based on our current dimensions
|
|
|
|
const Size actualSize{ gsl::narrow_cast<float>(_root.ActualWidth()),
|
|
|
|
gsl::narrow_cast<float>(_root.ActualHeight()) };
|
|
|
|
return actualSize.Width >= actualSize.Height ? SplitState::Vertical : SplitState::Horizontal;
|
|
|
|
}
|
2021-09-15 22:14:57 +02:00
|
|
|
if (splitType == SplitDirection::Up || splitType == SplitDirection::Down)
|
|
|
|
{
|
|
|
|
return SplitState::Horizontal;
|
|
|
|
}
|
|
|
|
// All that is left is Left / Right which are vertical splits
|
|
|
|
return SplitState::Vertical;
|
2019-12-19 22:47:19 +01:00
|
|
|
}
|
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Does the bulk of the work of creating a new split. Initializes our UI,
|
|
|
|
// creates a new Pane to host the control, registers event handlers.
|
|
|
|
// Arguments:
|
|
|
|
// - splitType: what type of split we should create.
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
// - splitSize: what fraction of the pane the new pane should get
|
|
|
|
// - newPane: the pane to add as a child
|
2019-06-07 23:56:44 +02:00
|
|
|
// Return Value:
|
2021-09-15 22:14:57 +02:00
|
|
|
// - The two newly created Panes, with the original pane as the first pane.
|
|
|
|
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirection splitType,
|
Add `size` param to `splitPane` action, `split-pane` subcommand (#8543)
## Summary of the Pull Request
Adds a `size` parameter to `splitPane`. This takes a `float`, and specifies the portion of the parent pane that should be used to create the new one.
This also adds the param to the `split-pane` subcommand.
### Examples
| commandline | result |
| -- | -- |
| `wt ; sp -s .25` | ![image](https://user-images.githubusercontent.com/18356694/101784317-fb595680-3ac0-11eb-8248-782dc61957cf.png) |
| `wt ; sp -s .8` | ![image](https://user-images.githubusercontent.com/18356694/101784442-20e66000-3ac1-11eb-8f9b-fb45a73c9334.png) |
| `wt ; sp -s .8 ; sp -H -s .3` | ![image](https://user-images.githubusercontent.com/18356694/101784552-470c0000-3ac1-11eb-9deb-df37aaa36f01.png) |
## PR Checklist
* [x] Closes #6298
* [x] I work here
* [x] Tests added/passed
* [x] Docs PR: MicrosoftDocs/terminal#208
## Detailed Description of the Pull Request / Additional comments
I went with `size`, `--size,-s` rather than `percent`, because the arg is the (0,1) version of the size, not the (0%,100%) version.
## Validation Steps Performed
Added actions, played with the commandline, ran tests
2020-12-18 04:51:53 +01:00
|
|
|
const float splitSize,
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
std::shared_ptr<Pane> newPane)
|
2019-06-07 23:56:44 +02:00
|
|
|
{
|
2021-09-15 22:14:57 +02:00
|
|
|
auto actualSplitType = _convertAutomaticOrDirectionalSplitState(splitType);
|
2019-12-19 22:47:19 +01:00
|
|
|
|
2019-06-07 23:56:44 +02:00
|
|
|
// Lock the create/close lock so that another operation won't concurrently
|
|
|
|
// modify our tree
|
|
|
|
std::unique_lock lock{ _createCloseLock };
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
// revoke our handler - the child will take care of the control now.
|
|
|
|
_control.ConnectionStateChanged(_connectionStateChangedToken);
|
|
|
|
_connectionStateChangedToken.value = 0;
|
|
|
|
_control.WarningBell(_warningBellToken);
|
|
|
|
_warningBellToken.value = 0;
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Remove our old GotFocus handler from the control. We don't want the
|
|
|
|
// control telling us that it's now focused, we want it telling its new
|
|
|
|
// parent.
|
|
|
|
_gotFocusRevoker.revoke();
|
|
|
|
_lostFocusRevoker.revoke();
|
|
|
|
}
|
2019-06-07 23:56:44 +02:00
|
|
|
|
|
|
|
// Remove any children we currently have. We can't add the existing
|
|
|
|
// TermControl to a new grid until we do this.
|
|
|
|
_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_borderFirst.Child(nullptr);
|
|
|
|
_borderSecond.Child(nullptr);
|
2019-06-07 23:56:44 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Create a new pane from ourself
|
|
|
|
if (!_IsLeaf())
|
|
|
|
{
|
|
|
|
// Since we are a parent we don't have borders normally,
|
|
|
|
// so set them temporarily for when we update our split definition.
|
|
|
|
_borders = _GetCommonBorders();
|
|
|
|
_firstChild->Closed(_firstClosedToken);
|
|
|
|
_secondChild->Closed(_secondClosedToken);
|
|
|
|
// If we are not a leaf we should create a new pane that contains our children
|
|
|
|
auto first = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
|
|
|
|
_firstChild = first;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Move our control, guid into the first one.
|
|
|
|
_firstChild = std::make_shared<Pane>(_profile, _control);
|
|
|
|
_firstChild->_connectionState = std::exchange(_connectionState, ConnectionState::NotConnected);
|
|
|
|
_profile = nullptr;
|
|
|
|
_control = { nullptr };
|
|
|
|
}
|
2021-09-15 22:14:57 +02:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_splitState = actualSplitType;
|
|
|
|
_desiredSplitPosition = 1.0f - splitSize;
|
|
|
|
_secondChild = newPane;
|
2021-09-15 22:14:57 +02:00
|
|
|
// If we want the new pane to be the first child, swap the children
|
|
|
|
if (splitType == SplitDirection::Up || splitType == SplitDirection::Left)
|
|
|
|
{
|
|
|
|
std::swap(_firstChild, _secondChild);
|
|
|
|
}
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_root.ColumnDefinitions().Clear();
|
|
|
|
_root.RowDefinitions().Clear();
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
_CreateRowColDefinitions();
|
2020-01-08 22:19:23 +01:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_borderFirst.Child(_firstChild->GetRootElement());
|
|
|
|
_borderSecond.Child(_secondChild->GetRootElement());
|
|
|
|
|
|
|
|
_root.Children().Append(_borderFirst);
|
|
|
|
_root.Children().Append(_borderSecond);
|
2019-06-07 23:56:44 +02:00
|
|
|
|
|
|
|
_ApplySplitDefinitions();
|
|
|
|
|
|
|
|
// Register event handlers on our children to handle their Close events
|
|
|
|
_SetupChildCloseHandlers();
|
|
|
|
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
_lastActive = false;
|
|
|
|
|
2020-10-10 01:06:40 +02:00
|
|
|
_SetupEntranceAnimation();
|
|
|
|
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
// Clear out our ID, only leaves should have IDs
|
|
|
|
_id = {};
|
|
|
|
|
2021-09-15 22:14:57 +02:00
|
|
|
// Regardless of which child the new child is, we want to return the
|
|
|
|
// original one first.
|
|
|
|
if (splitType == SplitDirection::Up || splitType == SplitDirection::Left)
|
|
|
|
{
|
|
|
|
return { _secondChild, _firstChild };
|
|
|
|
}
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
return { _firstChild, _secondChild };
|
2019-06-07 23:56:44 +02:00
|
|
|
}
|
|
|
|
|
2020-08-08 01:11:44 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Recursively attempt to "zoom" the given pane. When the pane is zoomed, it
|
|
|
|
// won't be displayed as part of the tab tree, instead it'll take up the full
|
|
|
|
// content of the tab. When we find the given pane, we'll need to remove it
|
|
|
|
// from the UI tree, so that the caller can re-add it. We'll also set some
|
|
|
|
// internal state, so the pane can display all of its borders.
|
|
|
|
// Arguments:
|
|
|
|
// - zoomedPane: This is the pane which we're attempting to zoom on.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::Maximize(std::shared_ptr<Pane> zoomedPane)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_zoomed = (zoomedPane == shared_from_this());
|
|
|
|
_UpdateBorders();
|
|
|
|
if (!_IsLeaf())
|
2020-08-08 01:11:44 +02:00
|
|
|
{
|
|
|
|
if (zoomedPane == _firstChild || zoomedPane == _secondChild)
|
|
|
|
{
|
|
|
|
// When we're zooming the pane, we'll need to remove it from our UI
|
|
|
|
// tree. Easy way: just remove both children. We'll re-attach both
|
|
|
|
// when we un-zoom.
|
|
|
|
_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_borderFirst.Child(nullptr);
|
|
|
|
_borderSecond.Child(nullptr);
|
2020-08-08 01:11:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Always recurse into both children. If the (un)zoomed pane was one of
|
|
|
|
// our direct children, we'll still want to update it's borders.
|
|
|
|
_firstChild->Maximize(zoomedPane);
|
|
|
|
_secondChild->Maximize(zoomedPane);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Recursively attempt to "un-zoom" the given pane. This does the opposite of
|
|
|
|
// Pane::Maximize. When we find the given pane, we should return the pane to our
|
|
|
|
// UI tree. We'll also clear the internal state, so the pane can display its
|
|
|
|
// borders correctly.
|
|
|
|
// - The caller should make sure to have removed the zoomed pane from the UI
|
|
|
|
// tree _before_ calling this.
|
|
|
|
// Arguments:
|
|
|
|
// - zoomedPane: This is the pane which we're attempting to un-zoom.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::Restore(std::shared_ptr<Pane> zoomedPane)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_zoomed = false;
|
|
|
|
_UpdateBorders();
|
|
|
|
if (!_IsLeaf())
|
2020-08-08 01:11:44 +02:00
|
|
|
{
|
|
|
|
if (zoomedPane == _firstChild || zoomedPane == _secondChild)
|
|
|
|
{
|
|
|
|
// When we're un-zooming the pane, we'll need to re-add it to our UI
|
|
|
|
// tree where it originally belonged. easy way: just re-add both.
|
|
|
|
_root.Children().Clear();
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
|
|
|
|
_borderFirst.Child(_firstChild->GetRootElement());
|
|
|
|
_borderSecond.Child(_secondChild->GetRootElement());
|
|
|
|
|
|
|
|
_root.Children().Append(_borderFirst);
|
|
|
|
_root.Children().Append(_borderSecond);
|
2020-08-08 01:11:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Always recurse into both children. If the (un)zoomed pane was one of
|
|
|
|
// our direct children, we'll still want to update it's borders.
|
|
|
|
_firstChild->Restore(zoomedPane);
|
|
|
|
_secondChild->Restore(zoomedPane);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Retrieves the ID of this pane
|
|
|
|
// - NOTE: The caller should make sure that this pane is a leaf,
|
|
|
|
// otherwise the ID value will not make sense (leaves have IDs, parents do not)
|
|
|
|
// Return Value:
|
|
|
|
// - The ID of this pane
|
2021-05-21 23:55:57 +02:00
|
|
|
std::optional<uint32_t> Pane::Id() noexcept
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
{
|
2021-02-04 19:13:26 +01:00
|
|
|
return _id;
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Sets this pane's ID
|
|
|
|
// - Panes are given IDs upon creation by TerminalTab
|
|
|
|
// Arguments:
|
|
|
|
// - The number to set this pane's ID to
|
2021-05-21 23:55:57 +02:00
|
|
|
void Pane::Id(uint32_t id) noexcept
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
{
|
|
|
|
_id = id;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Recursive function that focuses a pane with the given ID
|
|
|
|
// Arguments:
|
|
|
|
// - The ID of the pane we want to focus
|
2021-05-21 23:55:57 +02:00
|
|
|
bool Pane::FocusPane(const uint32_t id)
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Always clear the parent child path if we are focusing a leaf
|
|
|
|
_parentChildPath.reset();
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
if (_IsLeaf() && id == _id)
|
|
|
|
{
|
2021-05-21 23:55:57 +02:00
|
|
|
// Make sure to use _FocusFirstChild here - that'll properly update the
|
|
|
|
// focus if we're in startup.
|
|
|
|
_FocusFirstChild();
|
|
|
|
return true;
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (_firstChild && _secondChild)
|
|
|
|
{
|
2021-05-21 23:55:57 +02:00
|
|
|
return _firstChild->FocusPane(id) ||
|
|
|
|
_secondChild->FocusPane(id);
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
}
|
|
|
|
}
|
2021-05-21 23:55:57 +02:00
|
|
|
return false;
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
}
|
2021-08-17 00:33:23 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Focuses the given pane if it is in the tree.
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// - This is different than FocusPane(id) in that it allows focusing
|
|
|
|
// panes that are not leaves.
|
2021-08-17 00:33:23 +02:00
|
|
|
// Arguments:
|
|
|
|
// - the pane to focus
|
|
|
|
// Return Value:
|
|
|
|
// - true if focus was set
|
|
|
|
bool Pane::FocusPane(const std::shared_ptr<Pane> pane)
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (this == pane.get())
|
2021-08-17 00:33:23 +02:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
_Focus();
|
2021-08-17 00:33:23 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// clear the parent child path if we are not the pane being focused.
|
|
|
|
_parentChildPath.reset();
|
2021-08-17 00:33:23 +02:00
|
|
|
if (_firstChild && _secondChild)
|
|
|
|
{
|
|
|
|
return _firstChild->FocusPane(pane) ||
|
|
|
|
_secondChild->FocusPane(pane);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
Support for navigating panes by MRU (#8183)
Adds a "move to previous pane" and "move to next pane" keybinding, which
navigates to the last/first focused pane
We assign pane IDs on creation and maintain a vector of active pane IDs
in MRU order. Navigating panes by MRU then requires specifying which
pane ID we want to focus.
From our offline discussion (thanks @zadjii-msft for the concise
description):
> For the record, the full spec I'm imagining is:
>
> { command": { "action": "focus(Next|Prev)Pane", "order": "inOrder"|"mru", "useSwitcher": true|false } },
>
> and order defaults to mru, and useSwitcher will default to true, when
> there is a switcher. So
>
> { command": { "action": "focusNextPane" } },
> { command": { "action": "focusNextPane", "order": "mru" } },
>
> these are the same action. (but right now we don't support the order
> param)
>
> Then there'll be another PR for "focusPane(target=id)"
>
> Then a third PR for "focus(Next|Prev)Pane(order=inOrder)"
> for the record, I prefer this approach over the "one action to rule
> them all" version with both target and order/direction as params,
> because I don't like the confusion of what happens if there's both
> target and order/direction provided.
References #1000
Closes #2871
2020-12-11 19:36:05 +01:00
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Check if this pane contains the the argument as a child anywhere along the tree.
|
|
|
|
// Arguments:
|
|
|
|
// - child: the child to search for.
|
|
|
|
// Return Value:
|
|
|
|
// - true if the child was found.
|
|
|
|
bool Pane::_HasChild(const std::shared_ptr<Pane> child)
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_firstChild == child || _secondChild == child)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _firstChild->_HasChild(child) || _secondChild->_HasChild(child);
|
|
|
|
}
|
|
|
|
|
Preliminary work to add Swap Panes functionality (GH Issues 1000, 4922) (#10638)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to swap a pane with an adjacent (Up/Down/Left/Right) neighbor.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
This work potentially touches on: #1000 #2398 and #4922
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes a component of #1000 (partially, comment), #4922 (partially, `SwapPanes` function is added but not hooked up, no detach functionality)
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Its been a while since I've written C++ code, and it is my first time working on a Windows application. I hope that I have not made too many mistakes.
Work currently done:
- Add boilerplate/infrastructure for argument parsing, hotkeys, event handling
- Adds the `MovePane` function that finds the focused pane, and then tries to find
a pane that is visually adjacent to according to direction.
- First pass at the `SwapPanes` function that swaps the tree location of two panes
- First working version of helpers `_FindFocusAndNeighbor` and `_FindNeighborFromFocus`
that search the tree for the currently focused pane, and then climbs back up the tree
to try to find a sibling pane that is adjacent to it.
- An `_IsAdjacent' function that tests whether two panes, given their relative offsets, are adjacent to each other according to the direction.
Next steps:
- Once working these functions (`_FindFocusAndNeighbor`, etc) could be utilized to also solve #2398 by updating the `NavigateFocus` function.
- Do we want default hotkeys for the new actions?
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
At this point, compilation and manual testing of functionality (with hotkeys) by creating panes, adding distinguishers to each pane, and then swapping them around to confirm they went to the right location.
2021-07-22 14:53:03 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Recursive function that finds a pane with the given ID
|
|
|
|
// Arguments:
|
|
|
|
// - The ID of the pane we want to find
|
|
|
|
// Return Value:
|
|
|
|
// - A pointer to the pane with the given ID, if found.
|
|
|
|
std::shared_ptr<Pane> Pane::FindPane(const uint32_t id)
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
if (id == _id)
|
|
|
|
{
|
|
|
|
return shared_from_this();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (auto pane = _firstChild->FindPane(id))
|
|
|
|
{
|
|
|
|
return pane;
|
|
|
|
}
|
|
|
|
if (auto pane = _secondChild->FindPane(id))
|
|
|
|
{
|
|
|
|
return pane;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Gets the size in pixels of each of our children, given the full size they
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
// should fill. Since these children own their own separators (borders), this
|
2020-01-08 22:19:23 +01:00
|
|
|
// size is their portion of our _entire_ size. If specified size is lower than
|
|
|
|
// required then children will be of minimum size. Snaps first child to grid
|
|
|
|
// but not the second.
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// Arguments:
|
|
|
|
// - fullSize: the amount of space in pixels that should be filled by our
|
2020-01-08 22:19:23 +01:00
|
|
|
// children and their separators. Can be arbitrarily low.
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// Return Value:
|
|
|
|
// - a pair with the size of our first child and the size of our second child,
|
|
|
|
// respectively.
|
2020-01-08 22:19:23 +01:00
|
|
|
std::pair<float, float> Pane::_CalcChildrenSizes(const float fullSize) const
|
|
|
|
{
|
|
|
|
const auto widthOrHeight = _splitState == SplitState::Vertical;
|
|
|
|
const auto snappedSizes = _CalcSnappedChildrenSizes(widthOrHeight, fullSize).lower;
|
|
|
|
|
|
|
|
// Keep the first pane snapped and give the second pane all remaining size
|
|
|
|
return {
|
|
|
|
snappedSizes.first,
|
|
|
|
fullSize - snappedSizes.first
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Gets the size in pixels of each of our children, given the full size they should
|
|
|
|
// fill. Each child is snapped to char grid as close as possible. If called multiple
|
|
|
|
// times with fullSize argument growing, then both returned sizes are guaranteed to be
|
|
|
|
// non-decreasing (it's a monotonically increasing function). This is important so that
|
|
|
|
// user doesn't get any pane shrank when they actually expand the window or parent pane.
|
|
|
|
// That is also required by the layout algorithm.
|
|
|
|
// Arguments:
|
|
|
|
// - widthOrHeight: if true, operates on width, otherwise on height.
|
|
|
|
// - fullSize: the amount of space in pixels that should be filled by our children and
|
|
|
|
// their separator. Can be arbitrarily low.
|
|
|
|
// Return Value:
|
|
|
|
// - a structure holding the result of this calculation. The 'lower' field represents the
|
|
|
|
// children sizes that would fit in the fullSize, but might (and usually do) not fill it
|
|
|
|
// completely. The 'higher' field represents the size of the children if they slightly exceed
|
|
|
|
// the fullSize, but are snapped. If the children can be snapped and also exactly match
|
|
|
|
// the fullSize, then both this fields have the same value that represent this situation.
|
|
|
|
Pane::SnapChildrenSizeResult Pane::_CalcSnappedChildrenSizes(const bool widthOrHeight, const float fullSize) const
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
THROW_HR(E_FAIL);
|
|
|
|
}
|
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
// First we build a tree of nodes corresponding to the tree of our descendant panes.
|
|
|
|
// Each node represents a size of given pane. At the beginning, each node has the minimum
|
|
|
|
// size that the corresponding pane can have; so has the our (root) node. We then gradually
|
|
|
|
// expand our node (which in turn expands some of the child nodes) until we hit the desired
|
|
|
|
// size. Since each expand step (done in _AdvanceSnappedDimension()) guarantees that all the
|
|
|
|
// sizes will be snapped, our return values is also snapped.
|
|
|
|
// Why do we do it this, iterative way? Why can't we just split the given size by
|
|
|
|
// _desiredSplitPosition and snap it latter? Because it's hardly doable, if possible, to also
|
|
|
|
// fulfill the monotonicity requirement that way. As the fullSize increases, the proportional
|
|
|
|
// point that separates children panes also moves and cells sneak in the available area in
|
|
|
|
// unpredictable way, regardless which child has the snap priority or whether we snap them
|
|
|
|
// upward, downward or to nearest.
|
|
|
|
// With present way we run the same sequence of actions regardless to the fullSize value and
|
|
|
|
// only just stop at various moments when the built sizes reaches it. Eventually, this could
|
|
|
|
// be optimized for simple cases like when both children are both leaves with the same character
|
|
|
|
// size, but it doesn't seem to be beneficial.
|
|
|
|
|
|
|
|
auto sizeTree = _CreateMinSizeTree(widthOrHeight);
|
|
|
|
LayoutSizeNode lastSizeTree{ sizeTree };
|
|
|
|
|
|
|
|
while (sizeTree.size < fullSize)
|
|
|
|
{
|
|
|
|
lastSizeTree = sizeTree;
|
|
|
|
_AdvanceSnappedDimension(widthOrHeight, sizeTree);
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
if (sizeTree.size == fullSize)
|
|
|
|
{
|
|
|
|
// If we just hit exactly the requested value, then just return the
|
|
|
|
// current state of children.
|
|
|
|
return { { sizeTree.firstChild->size, sizeTree.secondChild->size },
|
|
|
|
{ sizeTree.firstChild->size, sizeTree.secondChild->size } };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We exceeded the requested size in the loop above, so lastSizeTree will have
|
|
|
|
// the last good sizes (so that children fit in) and sizeTree has the next possible
|
|
|
|
// snapped sizes. Return them as lower and higher snap possibilities.
|
|
|
|
return { { lastSizeTree.firstChild->size, lastSizeTree.secondChild->size },
|
|
|
|
{ sizeTree.firstChild->size, sizeTree.secondChild->size } };
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Adjusts given dimension (width or height) so that all descendant terminals
|
|
|
|
// align with their character grids as close as possible. Snaps to closes match
|
|
|
|
// (either upward or downward). Also makes sure to fit in minimal sizes of the panes.
|
|
|
|
// Arguments:
|
|
|
|
// - widthOrHeight: if true operates on width, otherwise on height
|
|
|
|
// - dimension: a dimension (width or height) to snap
|
|
|
|
// Return Value:
|
|
|
|
// - A value corresponding to the next closest snap size for this Pane, either upward or downward
|
|
|
|
float Pane::CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
|
|
|
|
{
|
|
|
|
const auto [lower, higher] = _CalcSnappedDimension(widthOrHeight, dimension);
|
|
|
|
return dimension - lower < higher - dimension ? lower : higher;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Adjusts given dimension (width or height) so that all descendant terminals
|
|
|
|
// align with their character grids as close as possible. Also makes sure to
|
|
|
|
// fit in minimal sizes of the panes.
|
|
|
|
// Arguments:
|
|
|
|
// - widthOrHeight: if true operates on width, otherwise on height
|
|
|
|
// - dimension: a dimension (width or height) to be snapped
|
|
|
|
// Return Value:
|
|
|
|
// - pair of floats, where first value is the size snapped downward (not greater then
|
|
|
|
// requested size) and second is the size snapped upward (not lower than requested size).
|
|
|
|
// If requested size is already snapped, then both returned values equal this value.
|
|
|
|
Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
// If we're a leaf pane, align to the grid of controlling terminal
|
|
|
|
|
|
|
|
const auto minSize = _GetMinSize();
|
|
|
|
const auto minDimension = widthOrHeight ? minSize.Width : minSize.Height;
|
|
|
|
|
|
|
|
if (dimension <= minDimension)
|
|
|
|
{
|
|
|
|
return { minDimension, minDimension };
|
|
|
|
}
|
|
|
|
|
|
|
|
float lower = _control.SnapDimensionToGrid(widthOrHeight, dimension);
|
|
|
|
if (widthOrHeight)
|
|
|
|
{
|
|
|
|
lower += WI_IsFlagSet(_borders, Borders::Left) ? PaneBorderSize : 0;
|
|
|
|
lower += WI_IsFlagSet(_borders, Borders::Right) ? PaneBorderSize : 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lower += WI_IsFlagSet(_borders, Borders::Top) ? PaneBorderSize : 0;
|
|
|
|
lower += WI_IsFlagSet(_borders, Borders::Bottom) ? PaneBorderSize : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lower == dimension)
|
|
|
|
{
|
|
|
|
// If we happen to be already snapped, then just return this size
|
|
|
|
// as both lower and higher values.
|
|
|
|
return { lower, lower };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const auto cellSize = _control.CharacterDimensions();
|
|
|
|
const auto higher = lower + (widthOrHeight ? cellSize.Width : cellSize.Height);
|
|
|
|
return { lower, higher };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (_splitState == (widthOrHeight ? SplitState::Horizontal : SplitState::Vertical))
|
|
|
|
{
|
|
|
|
// If we're resizing along separator axis, snap to the closest possibility
|
|
|
|
// given by our children panes.
|
|
|
|
|
|
|
|
const auto firstSnapped = _firstChild->_CalcSnappedDimension(widthOrHeight, dimension);
|
|
|
|
const auto secondSnapped = _secondChild->_CalcSnappedDimension(widthOrHeight, dimension);
|
|
|
|
return {
|
|
|
|
std::max(firstSnapped.lower, secondSnapped.lower),
|
|
|
|
std::min(firstSnapped.higher, secondSnapped.higher)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If we're resizing perpendicularly to separator axis, calculate the sizes
|
|
|
|
// of child panes that would fit the given size. We use same algorithm that
|
|
|
|
// is used for real resize routine, but exclude the remaining empty space that
|
|
|
|
// would appear after the second pane. This will be the 'downward' snap possibility,
|
|
|
|
// while the 'upward' will be given as a side product of the layout function.
|
|
|
|
|
|
|
|
const auto childSizes = _CalcSnappedChildrenSizes(widthOrHeight, dimension);
|
|
|
|
return {
|
|
|
|
childSizes.lower.first + childSizes.lower.second,
|
|
|
|
childSizes.higher.first + childSizes.higher.second
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Increases size of given LayoutSizeNode to match next possible 'snap'. In case of leaf
|
|
|
|
// pane this means the next cell of the terminal. Otherwise it means that one of its children
|
|
|
|
// advances (recursively). It expects the given node and its descendants to have either
|
|
|
|
// already snapped or minimum size.
|
|
|
|
// Arguments:
|
|
|
|
// - widthOrHeight: if true operates on width, otherwise on height.
|
ci: run spell check in CI, fix remaining issues (#4799)
This commit introduces a github action to check our spelling and fixes
the following misspelled words so that we come up green.
It also renames TfEditSes to TfEditSession, because Ses is not a word.
currently, excerpt, fallthrough, identified, occurred, propagate,
provided, rendered, resetting, separate, succeeded, successfully,
terminal, transferred, adheres, breaks, combining, preceded,
architecture, populated, previous, setter, visible, window, within,
appxmanifest, hyphen, control, offset, powerpoint, suppress, parsing,
prioritized, aforementioned, check in, build, filling, indices, layout,
mapping, trying, scroll, terabyte, vetoes, viewport, whose
2020-03-25 19:02:53 +01:00
|
|
|
// - sizeNode: a layout size node that corresponds to this pane.
|
2020-01-08 22:19:23 +01:00
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& sizeNode) const
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
// We're a leaf pane, so just add one more row or column (unless isMinimumSize
|
|
|
|
// is true, see below).
|
|
|
|
|
|
|
|
if (sizeNode.isMinimumSize)
|
|
|
|
{
|
|
|
|
// If the node is of its minimum size, this size might not be snapped (it might
|
|
|
|
// be, say, half a character, or fixed 10 pixels), so snap it upward. It might
|
|
|
|
// however be already snapped, so add 1 to make sure it really increases
|
|
|
|
// (not strictly necessary but to avoid surprises).
|
|
|
|
sizeNode.size = _CalcSnappedDimension(widthOrHeight, sizeNode.size + 1).higher;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const auto cellSize = _control.CharacterDimensions();
|
|
|
|
sizeNode.size += widthOrHeight ? cellSize.Width : cellSize.Height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// We're a parent pane, so we have to advance dimension of our children panes. In
|
|
|
|
// fact, we advance only one child (chosen later) to keep the growth fine-grained.
|
|
|
|
|
|
|
|
// To choose which child pane to advance, we actually need to know their advanced sizes
|
|
|
|
// in advance (oh), to see which one would 'fit' better. Often, this is already cached
|
|
|
|
// by the previous invocation of this function in nextFirstChild and nextSecondChild
|
|
|
|
// fields of given node. If not, we need to calculate them now.
|
|
|
|
if (sizeNode.nextFirstChild == nullptr)
|
|
|
|
{
|
|
|
|
sizeNode.nextFirstChild = std::make_unique<LayoutSizeNode>(*sizeNode.firstChild);
|
|
|
|
_firstChild->_AdvanceSnappedDimension(widthOrHeight, *sizeNode.nextFirstChild);
|
|
|
|
}
|
|
|
|
if (sizeNode.nextSecondChild == nullptr)
|
|
|
|
{
|
|
|
|
sizeNode.nextSecondChild = std::make_unique<LayoutSizeNode>(*sizeNode.secondChild);
|
|
|
|
_secondChild->_AdvanceSnappedDimension(widthOrHeight, *sizeNode.nextSecondChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto nextFirstSize = sizeNode.nextFirstChild->size;
|
|
|
|
const auto nextSecondSize = sizeNode.nextSecondChild->size;
|
|
|
|
|
|
|
|
// Choose which child pane to advance.
|
|
|
|
bool advanceFirstOrSecond;
|
|
|
|
if (_splitState == (widthOrHeight ? SplitState::Horizontal : SplitState::Vertical))
|
|
|
|
{
|
|
|
|
// If we're growing along separator axis, choose the child that
|
|
|
|
// wants to be smaller than the other, so that the resulting size
|
|
|
|
// will be the smallest.
|
|
|
|
advanceFirstOrSecond = nextFirstSize < nextSecondSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If we're growing perpendicularly to separator axis, choose a
|
|
|
|
// child so that their size ratio is closer to that we're trying
|
|
|
|
// to maintain (this is, the relative separator position is closer
|
|
|
|
// to the _desiredSplitPosition field).
|
|
|
|
|
|
|
|
const auto firstSize = sizeNode.firstChild->size;
|
|
|
|
const auto secondSize = sizeNode.secondChild->size;
|
|
|
|
|
|
|
|
// Because we rely on equality check, these calculations have to be
|
|
|
|
// immune to floating point errors. In common situation where both panes
|
|
|
|
// have the same character sizes and _desiredSplitPosition is 0.5 (or
|
|
|
|
// some simple fraction) both ratios will often be the same, and if so
|
|
|
|
// we always take the left child. It could be right as well, but it's
|
|
|
|
// important that it's consistent: that it would always go
|
|
|
|
// 1 -> 2 -> 1 -> 2 -> 1 -> 2 and not like 1 -> 1 -> 2 -> 2 -> 2 -> 1
|
|
|
|
// which would look silly to the user but which occur if there was
|
|
|
|
// a non-floating-point-safe math.
|
|
|
|
const auto deviation1 = nextFirstSize - (nextFirstSize + secondSize) * _desiredSplitPosition;
|
|
|
|
const auto deviation2 = -1 * (firstSize - (firstSize + nextSecondSize) * _desiredSplitPosition);
|
|
|
|
advanceFirstOrSecond = deviation1 <= deviation2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Here we advance one of our children. Because we already know the appropriate
|
|
|
|
// (advanced) size that given child would need to have, we simply assign that size
|
|
|
|
// to it. We then advance its 'next*' size (nextFirstChild or nextSecondChild) so
|
|
|
|
// the invariant holds (as it will likely be used by the next invocation of this
|
|
|
|
// function). The other child's next* size remains unchanged because its size
|
|
|
|
// haven't changed either.
|
|
|
|
if (advanceFirstOrSecond)
|
|
|
|
{
|
|
|
|
*sizeNode.firstChild = *sizeNode.nextFirstChild;
|
|
|
|
_firstChild->_AdvanceSnappedDimension(widthOrHeight, *sizeNode.nextFirstChild);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*sizeNode.secondChild = *sizeNode.nextSecondChild;
|
|
|
|
_secondChild->_AdvanceSnappedDimension(widthOrHeight, *sizeNode.nextSecondChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Since the size of one of our children has changed we need to update our size as well.
|
|
|
|
if (_splitState == (widthOrHeight ? SplitState::Horizontal : SplitState::Vertical))
|
|
|
|
{
|
|
|
|
sizeNode.size = std::max(sizeNode.firstChild->size, sizeNode.secondChild->size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sizeNode.size = sizeNode.firstChild->size + sizeNode.secondChild->size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Because we have grown, we're certainly no longer of our
|
|
|
|
// minimal size (if we've ever been).
|
|
|
|
sizeNode.isMinimumSize = false;
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Get the absolute minimum size that this pane can be resized to and still
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
// have 1x1 character visible, in each of its children. If we're a leaf, we'll
|
|
|
|
// include the space needed for borders _within_ us.
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - The minimum size that this pane can be resized to and still have a visible
|
|
|
|
// character.
|
|
|
|
Size Pane::_GetMinSize() const
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
auto controlSize = _control.MinimumSize();
|
|
|
|
auto newWidth = controlSize.Width;
|
|
|
|
auto newHeight = controlSize.Height;
|
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
newWidth += WI_IsFlagSet(_borders, Borders::Left) ? PaneBorderSize : 0;
|
|
|
|
newWidth += WI_IsFlagSet(_borders, Borders::Right) ? PaneBorderSize : 0;
|
|
|
|
newHeight += WI_IsFlagSet(_borders, Borders::Top) ? PaneBorderSize : 0;
|
|
|
|
newHeight += WI_IsFlagSet(_borders, Borders::Bottom) ? PaneBorderSize : 0;
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
|
|
|
|
return { newWidth, newHeight };
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
}
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
const auto firstSize = _firstChild->_GetMinSize();
|
|
|
|
const auto secondSize = _secondChild->_GetMinSize();
|
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
const auto minWidth = _splitState == SplitState::Vertical ?
|
|
|
|
firstSize.Width + secondSize.Width :
|
|
|
|
std::max(firstSize.Width, secondSize.Width);
|
|
|
|
const auto minHeight = _splitState == SplitState::Horizontal ?
|
|
|
|
firstSize.Height + secondSize.Height :
|
|
|
|
std::max(firstSize.Height, secondSize.Height);
|
2019-08-28 16:40:16 +02:00
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
return { minWidth, minHeight };
|
Indicate which pane is focused with the Accent color on the pan… (#3060)
## Summary of the Pull Request
Adds a small border with the accent color to indicate a pane is focused
<img src="https://user-images.githubusercontent.com/18356694/66218711-560e4b80-e68f-11e9-85b0-1f387d35bb92.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66218757-6f16fc80-e68f-11e9-8d39-db9ab748c4de.png" width="480">
<img src="https://user-images.githubusercontent.com/18356694/66219194-55c28000-e690-11e9-9835-8b5212e70e8a.png" width="480">
## PR Checklist
* [x] Closes #994
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've removed the simple Grid we were using as the pane separator, and replaced it with a Border that might appear on any side of a pane.
When we add a split, we'll create each child with one of the `Border` flags set (each child with one of a pair of flags). E.g. creating a horizontal split creates one child with the `Top` border, and another with the `Bottom`.
Then, if one of those panes is split, it will pass it's border flag to is new children, with the additional flag set. So adding another Vertical split to the above scenario would create a set of panes with either (`Top|Left`, `Top|Right`) or (`Bottom|Left`, `Bottom|Right`) borders set, depending on which pane was split.
<hr>
* start work on this by tracking border state
* Colorize the border
* Use the accent color for highlighting
* Cleanup the accent color code
* Don't buy any rural real estate when closing a pane
* Closing panes works well now too
* Cleanup for review
* Update src/cascadia/TerminalApp/Pane.cpp
* try some things that don't work to fix the resizing crash
* Revert "try some things that don't work to fix the resizing crash"
This reverts commit 3fc14da1130318add37a98d8de8d7ff440bbed59.
* this _does_ work, but I think it's not semantically correct
* This doesn't seem to work either.
I tried adding the pane seperators to the Pane::_GetMinWidth calculation. That
works for prevent the crash, but the resizing is wonky now. If you add a
Vertical split, then a second, then resize the middle pane really small,
you'll see that the _last_ resize doesn't work properly. The text seems to
overhand into the border.
Additionally, there's really weird behavior resizing panes to be small. They
don't always seem to be resizable to the smallest size.
* Revert "This doesn't seem to work either."
This reverts commit 2fd8323e7ba84527963f051a4e70751e846be87a.
* Merge the changes from the "this is the one" branch
Again, no idea what I really did that worked, but it does
* Cleanup from my mess of a commit
This makes so much more sense now
* Other PR feedback from @carlos-zamora
* Fix a typo
2019-11-01 21:06:11 +01:00
|
|
|
}
|
Enable resizing the panes with the keyboard. (#1207)
Adds the ability to resize panes with the keyboard.
This is accomplished by making the Column/RowDefinitions for a Pane use `GridLengthHelper::FromPixels` to set their size. We store a pair of floats that represents the relative amount that each pane takes out of the parent pane. When the window is resized, we use that percentage to figure out the new size of each child in pixels, and manually size each column.
Then, when the user presses the keybindings for resizePane{Left/Right/Up/Down}, we'll adjust those percentages, and resize the rows/cols as appropriate.
Currently, each pane adjusts the width/height by 5% of the total size at a time. I am not in love with this, but it works for now. I think when we get support for keybindings with arbitrary arg blobs, then we could do either a percent movement, or a number of characters at a time. The number of characters one would be trickier, because we'd have to get the focused control, and get the number of pixels per character, as adjacent panes might not have the same font sizes.
2019-07-10 15:27:12 +02:00
|
|
|
}
|
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Builds a tree of LayoutSizeNode that matches the tree of panes. Each node
|
|
|
|
// has minimum size that the corresponding pane can have.
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// Arguments:
|
2020-01-08 22:19:23 +01:00
|
|
|
// - widthOrHeight: if true operates on width, otherwise on height
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
// Return Value:
|
2020-01-08 22:19:23 +01:00
|
|
|
// - Root node of built tree that matches this pane.
|
|
|
|
Pane::LayoutSizeNode Pane::_CreateMinSizeTree(const bool widthOrHeight) const
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
{
|
2020-01-08 22:19:23 +01:00
|
|
|
const auto size = _GetMinSize();
|
|
|
|
LayoutSizeNode node(widthOrHeight ? size.Width : size.Height);
|
|
|
|
if (!_IsLeaf())
|
|
|
|
{
|
|
|
|
node.firstChild = std::make_unique<LayoutSizeNode>(_firstChild->_CreateMinSizeTree(widthOrHeight));
|
|
|
|
node.secondChild = std::make_unique<LayoutSizeNode>(_secondChild->_CreateMinSizeTree(widthOrHeight));
|
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Adjusts split position so that no child pane is smaller then its
|
|
|
|
// minimum size
|
|
|
|
// Arguments:
|
|
|
|
// - widthOrHeight: if true, operates on width, otherwise on height.
|
|
|
|
// - requestedValue: split position value to be clamped
|
|
|
|
// - totalSize: size (width or height) of the parent pane
|
|
|
|
// Return Value:
|
|
|
|
// - split position (value in range <0.0, 1.0>)
|
|
|
|
float Pane::_ClampSplitPosition(const bool widthOrHeight, const float requestedValue, const float totalSize) const
|
|
|
|
{
|
|
|
|
const auto firstMinSize = _firstChild->_GetMinSize();
|
|
|
|
const auto secondMinSize = _secondChild->_GetMinSize();
|
|
|
|
|
|
|
|
const auto firstMinDimension = widthOrHeight ? firstMinSize.Width : firstMinSize.Height;
|
|
|
|
const auto secondMinDimension = widthOrHeight ? secondMinSize.Width : secondMinSize.Height;
|
|
|
|
|
|
|
|
const auto minSplitPosition = firstMinDimension / totalSize;
|
|
|
|
const auto maxSplitPosition = 1.0f - (secondMinDimension / totalSize);
|
|
|
|
|
|
|
|
return std::clamp(requestedValue, minSplitPosition, maxSplitPosition);
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Function Description:
|
|
|
|
// - Attempts to load some XAML resources that the Pane will need. This includes:
|
|
|
|
// * The Color we'll use for active Panes's borders - SystemAccentColor
|
|
|
|
// * The Brush we'll use for inactive Panes - TabViewBackground (to match the
|
|
|
|
// color of the titlebar)
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::_SetupResources()
|
|
|
|
{
|
|
|
|
const auto res = Application::Current().Resources();
|
|
|
|
const auto accentColorKey = winrt::box_value(L"SystemAccentColor");
|
|
|
|
if (res.HasKey(accentColorKey))
|
|
|
|
{
|
|
|
|
const auto colorFromResources = res.Lookup(accentColorKey);
|
|
|
|
// If SystemAccentColor is _not_ a Color for some reason, use
|
|
|
|
// Transparent as the color, so we don't do this process again on
|
|
|
|
// the next pane (by leaving s_focusedBorderBrush nullptr)
|
|
|
|
auto actualColor = winrt::unbox_value_or<Color>(colorFromResources, Colors::Black());
|
|
|
|
s_focusedBorderBrush = SolidColorBrush(actualColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// DON'T use Transparent here - if it's "Transparent", then it won't
|
|
|
|
// be able to hittest for clicks, and then clicking on the border
|
|
|
|
// will eat focus.
|
|
|
|
s_focusedBorderBrush = SolidColorBrush{ Colors::Black() };
|
|
|
|
}
|
|
|
|
|
2021-08-23 18:40:25 +02:00
|
|
|
const auto unfocusedBorderBrushKey = winrt::box_value(L"UnfocusedBorderBrush");
|
|
|
|
if (res.HasKey(unfocusedBorderBrushKey))
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
{
|
2021-08-23 18:40:25 +02:00
|
|
|
winrt::Windows::Foundation::IInspectable obj = res.Lookup(unfocusedBorderBrushKey);
|
Decouple "Active Terminal" and "Focused Control" (#3540)
## Summary of the Pull Request
Unties the concept of "focused control" from "active control".
Previously, we were exclusively using the "Focused" state of `TermControl`s to determine which one was active. This was fraught with gotchas - if anything else became focused, then suddenly there was _no_ pane focused in the Tab. This happened especially frequently if the user clicked on a tab to focus the window. Furthermore, in experimental branches with more UI added to the Terminal (such as [dev/migrie/f/2046-command-palette](https://github.com/microsoft/terminal/tree/dev/migrie/f/2046-command-palette)), when these UIs were added to the Terminal, they'd take focus, which again meant that there was no focused pane.
This fixes these issue by having each Tab manually track which Pane is active in that tab. The Tab is now the arbiter of who in the tree is "active". Panes still track this state, for them to be able to MoveFocus appropriately.
It also contains a related fix to prevent the tab separator from stealing focus from the TermControl. This required us to set the color of the un-focused Pane border to some color other that Transparent, so I went with the TabViewBackground. Panes now look like the following:
![image](https://user-images.githubusercontent.com/18356694/68697343-41ea2380-0544-11ea-8218-601b57fdd835.png)
## References
See also: #2046
## PR Checklist
* [x] Closes #1205
* [x] Closes #522
* [x] Closes #999
* [x] I work here
* [😢] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually opening panes, closing panes, clicking around panes, the whole dance.
---------------------------------------------------
* this is janky but is close for some reason?
* This is _almost_ right to solve #1205
If I want to double up and also fix #522 (which I do), then I need to also
* when a tab GetsFocus, send the focus instead to the Pane
* When the border is clicked on, focus that pane's control
And like a lot of cleanup, because this is horrifying
* hey this autorevoker is really nice
* Encapsulate Pane::pfnGotFocus
* Propogate the events back up on close
* Encapsulate Tab::pfnFocusChanged, and clean up TerminalPage a bit
* Mostly just code cleanup, commenting
* This works to hittest on the borders
If the border is `Transparent`, then it can't hittest for Tapped events, and it'll fall through (to someone)
THis at least works, but looks garish
* Match the pane border to the TabViewHeader
* Fix a bit of dead code and a bad copy-pasta
* This _works_ to use a winrt event, but it's dirty
* Clean up everything from the winrt::event debacle.
* This is dead code that shouldn't have been there
* Turn Tab's callback into a winrt::event as well
2019-11-18 22:41:25 +01:00
|
|
|
s_unfocusedBorderBrush = obj.try_as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// DON'T use Transparent here - if it's "Transparent", then it won't
|
|
|
|
// be able to hittest for clicks, and then clicking on the border
|
|
|
|
// will eat focus.
|
|
|
|
s_unfocusedBorderBrush = SolidColorBrush{ Colors::Black() };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
int Pane::GetLeafPaneCount() const noexcept
|
|
|
|
{
|
|
|
|
return _IsLeaf() ? 1 : (_firstChild->GetLeafPaneCount() + _secondChild->GetLeafPaneCount());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - This is a helper to determine which direction an "Automatic" split should
|
|
|
|
// happen in for a given pane, but without using the ActualWidth() and
|
|
|
|
// ActualHeight() methods. This is used during the initialization of the
|
|
|
|
// Terminal, when we could be processing many "split-pane" commands _before_
|
|
|
|
// we've ever laid out the Terminal for the first time. When this happens, the
|
|
|
|
// Pane's don't have an actual size yet. However, we'd still like to figure
|
|
|
|
// out how to do an "auto" split when these Panes are all laid out.
|
|
|
|
// - This method assumes that the Pane we're attempting to split is `target`,
|
|
|
|
// and this method should be called on the root of a tree of Panes.
|
|
|
|
// - We'll walk down the tree attempting to find `target`. As we traverse the
|
|
|
|
// tree, we'll reduce the size passed to each subsequent recursive call. The
|
|
|
|
// size passed to this method represents how much space this Pane _will_ have
|
|
|
|
// to use.
|
|
|
|
// * If this pane is a leaf, and it's the pane we're looking for, use the
|
|
|
|
// available space to calculate which direction to split in.
|
|
|
|
// * If this pane is _any other leaf_, then just return nullopt, to indicate
|
|
|
|
// that the `target` Pane is not down this branch.
|
|
|
|
// * If this pane is a parent, calculate how much space our children will be
|
|
|
|
// able to use, and recurse into them.
|
|
|
|
// Arguments:
|
|
|
|
// - target: The Pane we're attempting to split.
|
|
|
|
// - availableSpace: The theoretical space that's available for this pane to be able to split.
|
|
|
|
// Return Value:
|
|
|
|
// - nullopt if `target` is not this pane or a child of this pane, otherwise the
|
2021-09-15 22:14:57 +02:00
|
|
|
// SplitDirection that `target` would use for an `Automatic` split given
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
// `availableSpace`
|
2021-09-15 22:14:57 +02:00
|
|
|
std::optional<SplitDirection> Pane::PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
|
|
|
const winrt::Windows::Foundation::Size availableSpace) const
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
if (target.get() == this)
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
{
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
// If this pane is the pane we are looking for, use the available space
|
|
|
|
// to calculate which direction to split in.
|
|
|
|
return availableSpace.Width > availableSpace.Height ? SplitDirection::Right : SplitDirection::Down;
|
|
|
|
}
|
|
|
|
else if (_IsLeaf())
|
|
|
|
{
|
|
|
|
// If this pane is _any other leaf_, then just return nullopt, to
|
|
|
|
// indicate that the `target` Pane is not down this branch.
|
|
|
|
return std::nullopt;
|
Process actions sync. on startup; don't dupe nonexistent profile (#5090)
This PR has evolved to encapsulate two related fixes that I can't really
untie anymore.
#2455 - Duplicating a tab that doesn't exist anymore
This was the bug I was originally fixing in #4429.
When the user tries to `duplicateTab` with a profile that doesn't exist
anymore (like might happen after a settings reload), don't crash.
As I was going about adding tests for this, got blocked by the fact that
the Terminal couldn't open _any_ panes while the `TerminalPage` was size
0x0. This had two theoretical solutions:
* Fake the `TerminalPage` into thinking it had a real size in the test -
probably possible, though I'm unsure how it would work in practice.
* Change `Pane`s to not require an `ActualWidth`, `ActualHeight` on
initialization.
Fortuately, the second option was something else that was already on my
backlog of bugs.
#4618 - `wt` command-line can't consistently parse more than one arg
Presently, the Terminal just arbitrarily dispatches a bunch of handlers
to try and handle all the commands provided on the commandline. That's
lead to a bunch of reports that not all the commands will always get
executed, nor will they all get executed in the same order.
This PR also changes the `TerminalPage` to be able to dispatch all the
commands sequentially, all at once in the startup. No longer will there
be a hot second where the commands seem to execute themselves in from of
the user - they'll all happen behind the scenes on startup.
This involved a couple other changes areound the `TerminalPage`
* I had to make sure that panes could be opened at a 0x0 size. Now they
use a star sizing based off the percentage of the parent they're
supposed to consume, so that when the parent _does_ get laid out,
they'll take the appropriate size of that parent.
* I had to do some math ahead of time to try and calculate what a
`SplitState::Automatic` would be evaluated as, despite the fact that
we don't actually know how big the pane will be.
* I had to ensure that `focus-tab` commands appropriately mark a single
tab as focused while we're in startup, without roundtripping to the
Dispatcher thread and back
## References
#4429 - the original PR for #2455
#5047 - a follow-up task from discussion in #4429
#4953 - a PR for making panes use star sizing, which was immensly
helpful for this PR.
## Detailed Description of the Pull Request / Additional comments
`CascadiaSettings::BuildSettings` can throw if the GUID doesn't exist.
This wraps those calls up with a try/catch.
It also adds a couple tests - a few `SettingsTests` for try/catching
this state. It also adds a XAML-y test in `TabTests` that creates a
`TerminalPage` and then performs som UI-like actions on it. This test
required a minor change to how we generate the new tab dropdown - in the
tests, `Application::Current()` is _not_ a `TerminalApp::App`, so it
doesn't have a `Logic()` to query. So wrap that in a try/catch as well.
While working on these tests, I found that we'd crash pretty agressively
for mysterious reasons if the TestHostApp became focused while the test
was running. This was due to a call in
`TSFInputControl::NotifyFocusEnter` that would callback to
`TSFInputControl::_layoutRequested`, which would crash on setting the
`MaxSize` of the canvas to a negative value. This PR includes a hotfix
for that bug as well.
## Validation Steps Performed
* Manual testing with a _lot_ of commands in a commandline
* run the tests
* Team tested in selfhost
Closes #2455
Closes #4618
2020-03-26 01:03:32 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If this pane is a parent, calculate how much space our children will
|
|
|
|
// be able to use, and recurse into them.
|
|
|
|
|
|
|
|
const bool isVerticalSplit = _splitState == SplitState::Vertical;
|
|
|
|
const float firstWidth = isVerticalSplit ? (availableSpace.Width * _desiredSplitPosition) : availableSpace.Width;
|
|
|
|
const float secondWidth = isVerticalSplit ? (availableSpace.Width - firstWidth) : availableSpace.Width;
|
|
|
|
const float firstHeight = !isVerticalSplit ? (availableSpace.Height * _desiredSplitPosition) : availableSpace.Height;
|
|
|
|
const float secondHeight = !isVerticalSplit ? (availableSpace.Height - firstHeight) : availableSpace.Height;
|
|
|
|
|
|
|
|
const auto firstResult = _firstChild->PreCalculateAutoSplit(target, { firstWidth, firstHeight });
|
|
|
|
return firstResult.has_value() ? firstResult : _secondChild->PreCalculateAutoSplit(target, { secondWidth, secondHeight });
|
|
|
|
}
|
|
|
|
|
|
|
|
// We should not possibly be getting here - both the above branches should
|
|
|
|
// return a value.
|
|
|
|
FAIL_FAST();
|
|
|
|
}
|
|
|
|
|
2021-02-08 19:03:55 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Returns true if the pane or one of its descendants is read-only
|
|
|
|
bool Pane::ContainsReadOnly() const
|
|
|
|
{
|
|
|
|
return _IsLeaf() ? _control.ReadOnly() : (_firstChild->ContainsReadOnly() || _secondChild->ContainsReadOnly());
|
|
|
|
}
|
|
|
|
|
2021-08-10 13:16:17 +02:00
|
|
|
// Method Description:
|
|
|
|
// - If we're a parent, place the taskbar state for all our leaves into the
|
|
|
|
// provided vector.
|
|
|
|
// - If we're a leaf, place our own state into the vector.
|
|
|
|
// Arguments:
|
|
|
|
// - states: a vector that will receive all the states of all leaves in the tree
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void Pane::CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states)
|
|
|
|
{
|
|
|
|
if (_IsLeaf())
|
|
|
|
{
|
|
|
|
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(_control.TaskbarState(),
|
|
|
|
_control.TaskbarProgress()) };
|
|
|
|
states.push_back(tbState);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_firstChild->CollectTaskbarStates(states);
|
|
|
|
_secondChild->CollectTaskbarStates(states);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add the ability to interact with subtrees of panes (#11153)
This commit adds the ability to interact with subtrees of panes.
Have you ever thought that you don't have enough regression testing to
do? Boy do I have the PR for you! This breaks all kinds of assumptions
about what is or is not focused, largely complicated by the fact that a
pane is not a proper control. I did my best to cover as many cases as I
could, but I wouldn't be surprised if there are some things broken that
I am unaware of.
Done:
- Add `parent` and `child` movement directions to move up and down the
tree respectively
- When a parent pane is selected it will have borders all around it in
addition to any borders the children have.
- Fix focus, swap, split, zoom, toggle orientation, resize, and move to
all handle interacting with more than one pane.
- Similarly the actions for font size changing, closing, read-only, clearing
buffer, and changing color scheme will distribute to all children.
- This technically leaves control focus on the original control in the
focused subtree because panes aren't proper controls themselves. This
is also used to make sure we go back down the same path with the
`child` movement.
- You can zoom a parent pane, and click between different zoomed
sub-panes and it won't unzoom you until you use moveFocus or another
action. This wasn't explicitly programmed behavior so it is probably
buggy (I've quashed a couple at least). It is a natural consequence of
showing multiple terminals and allowing you to focus a terminal and a
parent separately, since changing the active pane directly does not
unzoom. This also means there can be a disconnect between what pane is
zoomed and what pane is active.
## Validation Steps Performed
Tested focus movement, swapping, moving panes, and zooming.
Closes #10733
2021-09-28 21:16:05 +02:00
|
|
|
DEFINE_EVENT(Pane, GotFocus, _GotFocusHandlers, Pane::gotFocusArgs);
|
2021-01-23 00:48:20 +01:00
|
|
|
DEFINE_EVENT(Pane, LostFocus, _LostFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
|
|
|
DEFINE_EVENT(Pane, PaneRaiseBell, _PaneRaiseBellHandlers, winrt::Windows::Foundation::EventHandler<bool>);
|
Move Pane to Tab (GH7075) (#10780)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Add functionality to move a pane to another tab. If the tab index is greater than the number of current tabs a new tab will be created with the pane as its root. Similarly, if the last pane on a tab is moved to another tab, the original tab will be closed.
This is largely complete, but I know that I'm messing around with things that I am unfamiliar with, and would like to avoid footguns where possible.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4587
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #7075
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [x] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [x] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Things done:
- Moving a pane to a new tab appears to work. Moving a pane to an existing tab mostly works. Moving a pane back to its original tab appears to work.
- Set up {Attach,Detach}Pane methods to add or remove a pane from a pane. Detach is slightly different than Close in that we want to persist the tree structure and terminal controls.
- Add `Detached` event on a pane that can be subscribed to to remove other event handlers if desired.
- Added simple WalkTree abstraction for one-off recursion use cases that calls a provided function on each pane in order (and optionally terminates early).
- Fixed an in-prod bug with closing panes. Specifically, if you have a tree (1; 2 3) and close the 1 pane, then 3 will lose its borders because of these lines clearing the border on both children https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalApp/Pane.cpp#L1197-L1201 .
To do:
- Right now I have `TerminalTab` as a friend class of `Pane` so I can access some extra properties in my `WalkTree` callbacks, but there is probably a better choice for the abstraction boundary.
Next Steps:
- In a future PR Drag & Drop handlers could be added that utilize the Attach/Detach infrastructure to provide a better UI.
- Similarly once this is working, it should be possible to convert an entire tab into a pane on an existing tab (Tab::DetachRoot on original tab followed by Tab::AttachPane on the target tab).
- Its been 10 years, I just really want to use concepts already.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing by creating pane(s), and moving them between tabs and creating new tabs and destroying tabs by moving the last remaining pane.
2021-08-12 18:41:17 +02:00
|
|
|
DEFINE_EVENT(Pane, Detached, _PaneDetachedHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|