2019-05-03 00:29:04 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "AppHost.h"
|
|
|
|
#include "../types/inc/Viewport.hpp"
|
2019-06-25 22:06:11 +02:00
|
|
|
#include "../types/inc/utils.hpp"
|
2020-01-27 16:34:12 +01:00
|
|
|
#include "../types/inc/User32Utils.hpp"
|
2021-04-29 00:13:28 +02:00
|
|
|
#include "../WinRTUtils/inc/WtExeUtils.h"
|
2020-01-27 16:34:12 +01:00
|
|
|
#include "resource.h"
|
2021-04-29 00:25:48 +02:00
|
|
|
#include "VirtualDesktopUtils.h"
|
2021-07-08 17:25:43 +02:00
|
|
|
#include "icon.h"
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
using namespace winrt::Windows::UI;
|
|
|
|
using namespace winrt::Windows::UI::Composition;
|
|
|
|
using namespace winrt::Windows::UI::Xaml;
|
|
|
|
using namespace winrt::Windows::UI::Xaml::Hosting;
|
|
|
|
using namespace winrt::Windows::Foundation::Numerics;
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
using namespace winrt::Microsoft::Terminal;
|
2020-10-06 18:56:59 +02:00
|
|
|
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
2019-06-05 01:31:36 +02:00
|
|
|
using namespace ::Microsoft::Console;
|
2019-05-03 00:29:04 +02:00
|
|
|
using namespace ::Microsoft::Console::Types;
|
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
|
|
|
using namespace std::chrono_literals;
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-08-08 01:21:09 +02:00
|
|
|
// This magic flag is "documented" at https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx
|
|
|
|
// "If the high-order bit is 1, the key is down; otherwise, it is up."
|
|
|
|
static constexpr short KeyPressed{ gsl::narrow_cast<short>(0x8000) };
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
AppHost::AppHost() noexcept :
|
|
|
|
_app{},
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
_windowManager{},
|
2019-11-07 22:10:58 +01:00
|
|
|
_logic{ nullptr }, // don't make one, we're going to take a ref on app's
|
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
|
|
|
_window{ nullptr },
|
|
|
|
_getWindowLayoutThrottler{} // this will get set if we become the monarch
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
2019-11-07 22:10:58 +01:00
|
|
|
_logic = _app.Logic(); // get a ref to app's logic
|
|
|
|
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
// Inform the WindowManager that it can use us to find the target window for
|
|
|
|
// a set of commandline args. This needs to be done before
|
|
|
|
// _HandleCommandlineArgs, because WE might end up being the monarch. That
|
|
|
|
// would mean we'd need to be responsible for looking that up.
|
|
|
|
_windowManager.FindTargetWindowRequested({ this, &AppHost::_FindTargetWindow });
|
|
|
|
|
2020-01-27 16:34:12 +01:00
|
|
|
// If there were commandline args to our process, try and process them here.
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
// Do this before AppLogic::Create, otherwise this will have no effect.
|
|
|
|
//
|
|
|
|
// This will send our commandline to the Monarch, to ask if we should make a
|
|
|
|
// new window or not. If not, exit immediately.
|
2020-01-27 16:34:12 +01:00
|
|
|
_HandleCommandlineArgs();
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
if (!_shouldCreateWindow)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-01-27 16:34:12 +01:00
|
|
|
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
_useNonClientArea = _logic.GetShowTabsInTitlebar();
|
2019-05-03 00:29:04 +02:00
|
|
|
if (_useNonClientArea)
|
|
|
|
{
|
2019-11-07 22:10:58 +01:00
|
|
|
_window = std::make_unique<NonClientIslandWindow>(_logic.GetRequestedTheme());
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_window = std::make_unique<IslandWindow>();
|
|
|
|
}
|
|
|
|
|
2021-04-26 21:36:23 +02:00
|
|
|
// Update our own internal state tracking if we're in quake mode or not.
|
|
|
|
_IsQuakeWindowChanged(nullptr, nullptr);
|
|
|
|
|
2021-09-14 18:12:40 +02:00
|
|
|
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
|
2021-08-12 21:54:39 +02:00
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
// Tell the window to callback to us when it's about to handle a WM_CREATE
|
|
|
|
auto pfn = std::bind(&AppHost::_HandleCreateWindow,
|
|
|
|
this,
|
|
|
|
std::placeholders::_1,
|
Enable setting an initial position and maximized launch (#2817)
This PR includes the code changes that enable users to set an initial position
(top left corner) and launch maximized. There are some corner cases:
1. Multiple monitors. The user should be able to set the initial position to
any monitors attached. For the monitors on the left side of the major monitor,
the initial position values are negative.
2. If the initial position is larger than the screen resolution and the window
is off-screen, the current solution is to check if the top left corner of the
window intersect with any monitors. If it is not, we set the initial position
to the top left corner of the nearest monitor.
3. If the user wants to launch maximized and provides an initial position, we
launch the maximized window on the monitor where the position is located.
# Testing
To test:
1. Check-out this branch and build on VS2019
2. Launch Terminal, and open Settings. Then close the terminal.
3. Add the following setting into Json settings file as part of "globals", just
after "initialRows":
"initialPosition": "1000, 1000",
"launchMode": "default"
My test data:
I have already tested with the following variables:
1. showTabsInTitlebar true or false
2. The initial position of the top left corner of the window
3. Whether to launch maximized
4. The DPI of the monitor
Test data combination:
Non-client island window (showTabsInTitlebar true)
1. Three monitors with the same DPI (100%), left, middle and right, with the
middle one as the primary, resolution: 1980 * 1200, 1920 * 1200, 1920 * 1080
launchMode: default
In-Screen test: (0, 0), (1000, 500), (2000, 300), (-1000, 400),
(-100, 200), (-2000, 100), (0, 1119)
out-of-screen:
(200, -200): initialize to (0, 0)
(200, 1500): initialize to (0, 0)
(2000, -200): initialize to (1920, 0)
(2500, 2000): initialize to (1920, 0)
(4000 100): initialize to (1920, 0)
(-1000, -100): initialize to (-1920, 0)
(-3000, 100): initialize to (-1920, 0)
(10000, -10000): initialize to (1920, 0)
(-10000, 10000): initialize to (-1920, 0)
(0, -10000): initialize to (0, 0)
(0, -1): initialize to (0, 0)
(0, 1200): initialize to (0, 0)
launch mode: maximize
(100, 100)
(-1000, 100): On the left monitor
(0, -2000): On the primary monitor
(10000, 10000): On the primary monitor
2. Left monitor 200% DPI, primary monitor 100% DPI
In screen: (-1900, 100), (-3000, 100), (-1000, 100)
our-of-screen: (-8000, 100): initialize at (-1920, 0)
launch Maximized: (-100, 100): launch maximized on the left monitor
correctly
3. Left monitor 100% DPI, primary monitor 200% DPI
In-screen: (-1900, 100), (300, 100), (-800, 100), (-200, 100)
out-of-screen: (-3000, 100): initialize at (-1920, 0)
launch maximized: (100, 100), (-1000, 100)
For client island window, the test data is the same as above.
Issues:
1. If we set the initial position on the monitor with a different DPI as the
primary monitor, and the window "lays" across two monitors, then the window
still renders as it is on the primary monitor. The size of the window is
correct.
Closes #1043
2019-10-17 06:51:50 +02:00
|
|
|
std::placeholders::_2,
|
|
|
|
std::placeholders::_3);
|
2019-05-03 00:29:04 +02:00
|
|
|
_window->SetCreateCallback(pfn);
|
|
|
|
|
2020-01-08 22:19:23 +01:00
|
|
|
_window->SetSnapDimensionCallback(std::bind(&winrt::TerminalApp::AppLogic::CalcSnappedDimension,
|
|
|
|
_logic,
|
|
|
|
std::placeholders::_1,
|
|
|
|
std::placeholders::_2));
|
Manually pass mouse wheel messages to TermControls (#5131)
## Summary of the Pull Request
As we've learned in #979, not all touchpads are created equal. Some of them have bad drivers that makes scrolling inactive windows not work. For whatever reason, these devices think the Terminal is all one giant inactive window, so we don't get the mouse wheel events through the XAML stack. We do however get the event as a `WM_MOUSEWHEEL` on those devices (a message we don't get on devices with normally functioning trackpads).
This PR attempts to take that `WM_MOUSEWHEEL` and manually dispatch it to the `TermControl`, so we can at least scroll the terminal content.
Unfortunately, this solution is not very general purpose. This only works to scroll controls that manually implement our own `IMouseWheelListener` interface. As we add more controls, we'll need to continue manually implementing this interface, until the underlying XAML Islands bug is fixed. **I don't love this**. I'd rather have a better solution, but it seems that we can't synthesize a more general-purpose `PointerWheeled` event that could get routed through the XAML tree as normal.
## References
* #2606 and microsoft/microsoft-ui-xaml#2101 - these bugs are also tracking a similar "inactive windows" / "scaled mouse events" issue in XAML
## PR Checklist
* [x] Closes #979
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've also added a `til::point` conversion _to_ `winrt::Windows::Foundation::Point`, and some scaling operators for `point`
## Validation Steps Performed
* It works on my HP Spectre 2017 with a synaptics trackpad
- I also made sure to test that `tmux` works in panes on this laptop
* It works on my slaptop, and DOESN'T follow this hack codepath on this machine.
2020-04-01 18:58:16 +02:00
|
|
|
_window->MouseScrolled({ this, &AppHost::_WindowMouseWheeled });
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
_window->WindowActivated({ this, &AppHost::_WindowActivated });
|
Manually dismiss popups when the window moves, or the SUI scrolls (#10922)
## Summary of the Pull Request
BODGY!
This solution was suggested in https://github.com/microsoft/microsoft-ui-xaml/issues/4554#issuecomment-887815332.
When the window moves, or when a ScrollViewer scrolls, dismiss any popups that are visible. This happens automagically when an app is a real XAML app, but it doesn't work for XAML Islands.
## References
* upstream at https://github.com/microsoft/microsoft-ui-xaml/issues/4554
## PR Checklist
* [x] Closes #9320
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Unfortunately, we've got a bunch of scroll viewers in our SUI. So I did something bodgyx2 to make our life a little easier.
`DismissAllPopups` can be used to dismiss all popups for a particular UI element. However, we've got a bunch of pages with scroll viewers that may or may not have popups in them. Rather than define the same exact body for all their `ViewChanging` events, the `HasScrollViewer` struct will just do it for you!
Inside the `HasScrollViewer` stuct, we can't get at the `XamlRoot()` that our subclass implements. I mean, _we_ can, but when XAML does it's codegen, _XAML_ won't be able to figure it out.
Fortunately for us, we don't need to! The sender is a UIElement, so we can just get _their_ `XamlRoot()`.
So, you can fix this for any SUI page with just a simple
```diff
- <ScrollViewer>
+ <ScrollViewer ViewChanging="ViewChanging">
```
```diff
- struct AddProfile : AddProfileT<AddProfile>
+ struct AddProfile : public HasScrollViewer<AddProfile>, AddProfileT<AddProfile>
```
## Validation Steps Performed
* the window doesn't close when you move it
* the popups _do_ close when you move the window
* the popups close when you scroll any SUI page
2021-08-16 15:41:17 +02:00
|
|
|
_window->WindowMoved({ this, &AppHost::_WindowMoved });
|
2021-04-29 00:13:28 +02:00
|
|
|
_window->HotkeyPressed({ this, &AppHost::_GlobalHotkeyPressed });
|
2020-11-02 19:51:29 +01:00
|
|
|
_window->SetAlwaysOnTop(_logic.GetInitialAlwaysOnTop());
|
2019-05-03 00:29:04 +02:00
|
|
|
_window->MakeWindow();
|
2021-04-29 00:13:28 +02:00
|
|
|
|
2021-10-20 02:12:18 +02:00
|
|
|
_GetWindowLayoutRequestedToken = _windowManager.GetWindowLayoutRequested([this](auto&&, const winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs& args) {
|
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
|
|
|
// The peasants are running on separate threads, so they'll need to
|
|
|
|
// swap what context they are in to the ui thread to get the actual layout.
|
|
|
|
args.WindowLayoutJsonAsync(_GetWindowLayoutAsync());
|
|
|
|
});
|
|
|
|
|
2021-04-29 00:13:28 +02:00
|
|
|
_windowManager.BecameMonarch({ this, &AppHost::_BecomeMonarch });
|
|
|
|
if (_windowManager.IsMonarch())
|
|
|
|
{
|
|
|
|
_BecomeMonarch(nullptr, nullptr);
|
|
|
|
}
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
AppHost::~AppHost()
|
|
|
|
{
|
2021-08-12 21:54:39 +02:00
|
|
|
// destruction order is important for proper teardown here
|
2019-06-27 00:15:01 +02:00
|
|
|
_window = nullptr;
|
2019-06-25 22:06:11 +02:00
|
|
|
_app.Close();
|
2019-06-27 00:15:01 +02:00
|
|
|
_app = nullptr;
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
2020-08-15 01:44:39 +02:00
|
|
|
bool AppHost::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
|
2020-03-05 21:35:46 +01:00
|
|
|
{
|
|
|
|
if (_logic)
|
|
|
|
{
|
2020-08-15 01:44:39 +02:00
|
|
|
return _logic.OnDirectKeyEvent(vkey, scanCode, down);
|
2020-03-05 21:35:46 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-11-18 23:24:11 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Event handler to update the taskbar progress indicator
|
|
|
|
// - Upon receiving the event, we ask the underlying logic for the taskbar state/progress values
|
|
|
|
// of the last active control
|
|
|
|
// Arguments:
|
|
|
|
// - sender: not used
|
|
|
|
// - args: not used
|
2021-08-10 13:16:17 +02:00
|
|
|
void AppHost::SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
|
|
|
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
2020-11-18 23:24:11 +01:00
|
|
|
{
|
|
|
|
if (_logic)
|
|
|
|
{
|
2021-08-10 13:16:17 +02:00
|
|
|
const auto state = _logic.TaskbarState();
|
|
|
|
_window->SetTaskbarProgress(gsl::narrow_cast<size_t>(state.State()),
|
|
|
|
gsl::narrow_cast<size_t>(state.Progress()));
|
2020-11-18 23:24:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
void _buildArgsFromCommandline(std::vector<winrt::hstring>& args)
|
|
|
|
{
|
|
|
|
if (auto commandline{ GetCommandLineW() })
|
|
|
|
{
|
|
|
|
int argc = 0;
|
|
|
|
|
|
|
|
// Get the argv, and turn them into a hstring array to pass to the app.
|
|
|
|
wil::unique_any<LPWSTR*, decltype(&::LocalFree), ::LocalFree> argv{ CommandLineToArgvW(commandline, &argc) };
|
|
|
|
if (argv)
|
|
|
|
{
|
|
|
|
for (auto& elem : wil::make_range(argv.get(), argc))
|
|
|
|
{
|
|
|
|
args.emplace_back(elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (args.empty())
|
|
|
|
{
|
|
|
|
args.emplace_back(L"wt.exe");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-27 16:34:12 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Retrieve any commandline args passed on the commandline, and pass them to
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
// the WindowManager, to ask if we should become a window process.
|
|
|
|
// - If we should create a window, then pass the arguments to the app logic for
|
|
|
|
// processing.
|
|
|
|
// - If we shouldn't become a window, set _shouldCreateWindow to false and exit
|
|
|
|
// immediately.
|
2020-01-27 16:34:12 +01:00
|
|
|
// - If the logic determined there's an error while processing that commandline,
|
|
|
|
// display a message box to the user with the text of the error, and exit.
|
|
|
|
// * We display a message box because we're a Win32 application (not a
|
|
|
|
// console app), and the shell has undoubtedly returned to the foreground
|
|
|
|
// of the console. Text emitted here might mix unexpectedly with output
|
|
|
|
// from the shell process.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void AppHost::_HandleCommandlineArgs()
|
|
|
|
{
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
std::vector<winrt::hstring> args;
|
|
|
|
_buildArgsFromCommandline(args);
|
|
|
|
std::wstring cwd{ wil::GetCurrentDirectoryW<std::wstring>() };
|
|
|
|
|
|
|
|
Remoting::CommandlineArgs eventArgs{ { args }, { cwd } };
|
|
|
|
_windowManager.ProposeCommandline(eventArgs);
|
|
|
|
|
|
|
|
_shouldCreateWindow = _windowManager.ShouldCreateWindow();
|
|
|
|
if (!_shouldCreateWindow)
|
2020-01-27 16:34:12 +01:00
|
|
|
{
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
return;
|
|
|
|
}
|
2020-01-27 16:34:12 +01:00
|
|
|
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
if (auto peasant{ _windowManager.CurrentWindow() })
|
|
|
|
{
|
|
|
|
if (auto args{ peasant.InitialArgs() })
|
2020-01-27 16:34:12 +01:00
|
|
|
{
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
const auto result = _logic.SetStartupCommandline(args.Commandline());
|
2020-05-04 22:56:15 +02:00
|
|
|
const auto message = _logic.ParseCommandlineMessage();
|
2020-01-27 16:34:12 +01:00
|
|
|
if (!message.empty())
|
|
|
|
{
|
|
|
|
const auto displayHelp = result == 0;
|
|
|
|
const auto messageTitle = displayHelp ? IDS_HELP_DIALOG_TITLE : IDS_ERROR_DIALOG_TITLE;
|
|
|
|
const auto messageIcon = displayHelp ? MB_ICONWARNING : MB_ICONERROR;
|
|
|
|
// TODO:GH#4134: polish this dialog more, to make the text more
|
|
|
|
// like msiexec /?
|
|
|
|
MessageBoxW(nullptr,
|
|
|
|
message.data(),
|
|
|
|
GetStringResource(messageTitle).data(),
|
|
|
|
MB_OK | messageIcon);
|
|
|
|
|
2020-05-04 22:56:15 +02:00
|
|
|
if (_logic.ShouldExitEarly())
|
|
|
|
{
|
|
|
|
ExitProcess(result);
|
|
|
|
}
|
2020-01-27 16:34:12 +01:00
|
|
|
}
|
|
|
|
}
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
|
|
|
|
// After handling the initial args, hookup the callback for handling
|
|
|
|
// future commandline invocations. When our peasant is told to execute a
|
|
|
|
// commandline (in the future), it'll trigger this callback, that we'll
|
|
|
|
// use to send the actions to the app.
|
|
|
|
peasant.ExecuteCommandlineRequested({ this, &AppHost::_DispatchCommandline });
|
2021-04-29 00:13:28 +02:00
|
|
|
peasant.SummonRequested({ this, &AppHost::_HandleSummon });
|
2021-03-30 18:08:03 +02:00
|
|
|
|
|
|
|
peasant.DisplayWindowIdRequested({ this, &AppHost::_DisplayWindowId });
|
2021-09-09 16:03:03 +02:00
|
|
|
peasant.QuitRequested({ this, &AppHost::_QuitRequested });
|
2021-03-30 18:08:03 +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
|
|
|
// We need this property to be set before we get the InitialSize/Position
|
|
|
|
// and BecameMonarch which normally sets it is only run after the window
|
|
|
|
// is created.
|
|
|
|
if (_windowManager.IsMonarch())
|
|
|
|
{
|
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
|
|
|
const auto numPeasants = _windowManager.GetNumberOfPeasants();
|
|
|
|
const auto layouts = ApplicationState::SharedInstance().PersistedWindowLayouts();
|
|
|
|
if (_logic.ShouldUsePersistedLayout() && layouts && layouts.Size() > 0)
|
|
|
|
{
|
|
|
|
uint32_t startIdx = 0;
|
|
|
|
// We want to create a window for every saved layout.
|
|
|
|
// If we are the only window, and no commandline arguments were provided
|
|
|
|
// then we should just use the current window to load the first layout.
|
|
|
|
// Otherwise create this window normally with its commandline, and create
|
|
|
|
// a new window using the first saved layout information.
|
|
|
|
// The 2nd+ layout will always get a new window.
|
|
|
|
if (numPeasants == 1 && !_logic.HasCommandlineArguments() && !_logic.HasSettingsStartupActions())
|
|
|
|
{
|
|
|
|
_logic.SetPersistedLayoutIdx(startIdx);
|
|
|
|
startIdx += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create new windows for each of the other saved layouts.
|
|
|
|
for (const auto size = layouts.Size(); startIdx < size; startIdx += 1)
|
|
|
|
{
|
|
|
|
auto newWindowArgs = fmt::format(L"{0} -w new -s {1}", args[0], startIdx);
|
|
|
|
|
|
|
|
STARTUPINFO si;
|
|
|
|
memset(&si, 0, sizeof(si));
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
wil::unique_process_information pi;
|
|
|
|
|
|
|
|
LOG_IF_WIN32_BOOL_FALSE(CreateProcessW(nullptr,
|
|
|
|
newWindowArgs.data(),
|
|
|
|
nullptr, // lpProcessAttributes
|
|
|
|
nullptr, // lpThreadAttributes
|
|
|
|
false, // bInheritHandles
|
|
|
|
DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT, // doCreationFlags
|
|
|
|
nullptr, // lpEnvironment
|
|
|
|
nullptr, // lpStartingDirectory
|
|
|
|
&si, // lpStartupInfo
|
|
|
|
&pi // lpProcessInformation
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_logic.SetNumberOfOpenWindows(numPeasants);
|
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
|
|
|
}
|
2021-03-30 18:08:03 +02:00
|
|
|
_logic.WindowName(peasant.WindowName());
|
|
|
|
_logic.WindowId(peasant.GetID());
|
2020-01-27 16:34:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Initializes the XAML island, creates the terminal app, and sets the
|
|
|
|
// island's content to that of the terminal app's content. Also registers some
|
|
|
|
// callbacks with TermApp.
|
|
|
|
// !!! IMPORTANT!!!
|
|
|
|
// This must be called *AFTER* WindowsXamlManager::InitializeForCurrentThread.
|
|
|
|
// If it isn't, then we won't be able to create the XAML island.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void AppHost::Initialize()
|
|
|
|
{
|
|
|
|
_window->Initialize();
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
|
2020-11-30 20:51:42 +01:00
|
|
|
if (auto withWindow{ _logic.try_as<IInitializeWithWindow>() })
|
|
|
|
{
|
|
|
|
withWindow->Initialize(_window->GetHandle());
|
|
|
|
}
|
|
|
|
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
if (_useNonClientArea)
|
|
|
|
{
|
2020-02-10 21:40:01 +01:00
|
|
|
// Register our callback for when the app's non-client content changes.
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
// This has to be done _before_ App::Create, as the app might set the
|
|
|
|
// content in Create.
|
2019-11-07 22:10:58 +01:00
|
|
|
_logic.SetTitleBarContent({ this, &AppHost::_UpdateTitleBarContent });
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
}
|
2019-08-16 23:18:29 +02:00
|
|
|
|
2019-10-11 02:09:07 +02:00
|
|
|
// Register the 'X' button of the window for a warning experience of multiple
|
|
|
|
// tabs opened, this is consistent with Alt+F4 closing
|
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
|
|
|
_window->WindowCloseButtonClicked([this]() {
|
|
|
|
const auto pos = _GetWindowLaunchPosition();
|
|
|
|
_logic.CloseWindow(pos);
|
|
|
|
});
|
|
|
|
// If the user requests a close in another way handle the same as if the 'X'
|
|
|
|
// was clicked.
|
|
|
|
_logic.CloseRequested([this](auto&&, auto&&) {
|
|
|
|
const auto pos = _GetWindowLaunchPosition();
|
|
|
|
_logic.CloseWindow(pos);
|
|
|
|
});
|
2019-10-11 02:09:07 +02:00
|
|
|
|
2019-08-16 23:18:29 +02:00
|
|
|
// Add an event handler to plumb clicks in the titlebar area down to the
|
|
|
|
// application layer.
|
2019-11-07 22:10:58 +01:00
|
|
|
_window->DragRegionClicked([this]() { _logic.TitlebarClicked(); });
|
2019-08-16 23:18:29 +02:00
|
|
|
|
2019-11-07 22:10:58 +01:00
|
|
|
_logic.RequestedThemeChanged({ this, &AppHost::_UpdateTheme });
|
2020-07-14 23:02:18 +02:00
|
|
|
_logic.FullscreenChanged({ this, &AppHost::_FullscreenChanged });
|
|
|
|
_logic.FocusModeChanged({ this, &AppHost::_FocusModeChanged });
|
|
|
|
_logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged });
|
2020-11-18 23:55:10 +01:00
|
|
|
_logic.RaiseVisualBell({ this, &AppHost::_RaiseVisualBell });
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
|
2019-11-07 22:10:58 +01:00
|
|
|
_logic.Create();
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2019-11-07 22:10:58 +01:00
|
|
|
_logic.TitleChanged({ this, &AppHost::AppTitleChanged });
|
|
|
|
_logic.LastTabClosed({ this, &AppHost::LastTabClosed });
|
2020-11-18 23:24:11 +01:00
|
|
|
_logic.SetTaskbarProgress({ this, &AppHost::SetTaskbarProgress });
|
2021-03-30 18:08:03 +02:00
|
|
|
_logic.IdentifyWindowsRequested({ this, &AppHost::_IdentifyWindowsRequested });
|
Add support for renaming windows (#9662)
## Summary of the Pull Request
This PR adds support for renaming windows.
![window-renaming-000](https://user-images.githubusercontent.com/18356694/113034344-9a30be00-9157-11eb-9443-975f3c294f56.gif)
![window-renaming-001](https://user-images.githubusercontent.com/18356694/113034452-b5033280-9157-11eb-9e35-e5ac80fef0bc.gif)
It does so through two new actions:
* `renameWindow` takes a `name` parameter, and attempts to set the window's name
to the provided name. This is useful if you always want to hit <kbd>F3</kbd>
and rename a window to "foo" (READ: probably not that useful)
* `openWindowRenamer` is more interesting: it opens a `TeachingTip` with a
`TextBox`. When the user hits Ok, it'll request a rename for the provided
value. This lets the user pick a new name for the window at runtime.
In both cases, if there's already a window with that name, then the monarch will
reject the rename, and pop a `Toast` in the window informing the user that the
rename failed. Nifty!
## References
* Builds on the toasts from #9523
* #5000 - process model megathread
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50771747
* [x] I work here
* [x] Tests addded (and pass with the help of #9660)
* [ ] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I'm sending this PR while finishing up the tests. I figured I'll have time to sneak them in before I get the necessary reviews.
> PAIN: We can't immediately focus the textbox in the TeachingTip. It's
> not technically focusable until it is opened. However, it doesn't
> provide an even tto tell us when it is opened. That's tracked in
> microsoft/microsoft-ui-xaml#1607. So for now, the user _needs_ to
> click on the text box manually.
> We're also not using a ContentDialog for this, because in Xaml
> Islands a text box in a ContentDialog won't recieve _any_ keypresses.
> Fun!
## Validation Steps Performed
I've been playing with
```json
{ "keys": "f1", "command": "identifyWindow" },
{ "keys": "f2", "command": "identifyWindows" },
{ "keys": "f3", "command": "openWindowRenamer" },
{ "keys": "f4", "command": { "action": "renameWindow", "name": "foo" } },
{ "keys": "f5", "command": { "action": "renameWindow", "name": "bar" } },
```
and they seem to work as expected
2021-04-02 18:00:04 +02:00
|
|
|
_logic.RenameWindowRequested({ this, &AppHost::_RenameWindowRequested });
|
2021-04-29 00:13:28 +02:00
|
|
|
_logic.SettingsChanged({ this, &AppHost::_HandleSettingsChanged });
|
2021-04-26 21:36:23 +02:00
|
|
|
_logic.IsQuakeWindowChanged({ this, &AppHost::_IsQuakeWindowChanged });
|
2021-05-27 19:14:12 +02:00
|
|
|
_logic.SummonWindowRequested({ this, &AppHost::_SummonWindowRequested });
|
2021-09-10 20:25:43 +02:00
|
|
|
_logic.OpenSystemMenu({ this, &AppHost::_OpenSystemMenu });
|
2021-09-09 16:03:03 +02:00
|
|
|
_logic.QuitRequested({ this, &AppHost::_RequestQuitAll });
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2019-11-07 22:10:58 +01:00
|
|
|
_window->UpdateTitle(_logic.Title());
|
2019-05-03 00:29:04 +02:00
|
|
|
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
// Set up the content of the application. If the app has a custom titlebar,
|
|
|
|
// set that content as well.
|
2019-11-07 22:10:58 +01:00
|
|
|
_window->SetContent(_logic.GetRoot());
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
_window->OnAppInitialized();
|
Intentionally leak our Application, so that we DON'T crash on exit (#5629)
We've got a weird crash that happens terribly inconsistently, but pretty
readily on migrie's laptop, only in Debug mode. Apparently, there's some
weird ref-counting magic that goes on during teardown, and our
Application doesn't get closed quite right, which can cause us to crash
into the debugger. This of course, only happens on exit, and happens
somewhere in the `...XamlHost.dll` code.
Crazily, if we _manually leak the `Application`_ here, then the crash
doesn't happen. This doesn't matter, because we really want the
Application to live for _the entire lifetime of the process_, so the only
time when this object would actually need to get cleaned up is _during
exit_. So we can safely leak this `Application` object, and have it just
get cleaned up normally when our process exits.
* [x] I discussed this with @DHowett-MSFT and we both agree this is mental
* [x] I'm pretty sure there's not an actual bug on our repo for this
* [x] I verified on my machine where I can crash the terminal 100% of the time on exit in debug, this fixes it
* [x] I verified that it doesn't introduce a _new_ crash in Release on my machine
2020-04-30 21:36:02 +02:00
|
|
|
|
|
|
|
// THIS IS A HACK
|
|
|
|
//
|
|
|
|
// We've got a weird crash that happens terribly inconsistently, but pretty
|
|
|
|
// readily on migrie's laptop, only in Debug mode. Apparently, there's some
|
|
|
|
// weird ref-counting magic that goes on during teardown, and our
|
|
|
|
// Application doesn't get closed quite right, which can cause us to crash
|
|
|
|
// into the debugger. This of course, only happens on exit, and happens
|
|
|
|
// somewhere in the XamlHost.dll code.
|
|
|
|
//
|
|
|
|
// Crazily, if we _manually leak the Application_ here, then the crash
|
|
|
|
// doesn't happen. This doesn't matter, because we really want the
|
|
|
|
// Application to live for _the entire lifetime of the process_, so the only
|
|
|
|
// time when this object would actually need to get cleaned up is _during
|
|
|
|
// exit_. So we can safely leak this Application object, and have it just
|
|
|
|
// get cleaned up normally when our process exits.
|
|
|
|
::winrt::TerminalApp::App a{ _app };
|
|
|
|
::winrt::detach_abi(a);
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2021-09-03 20:32:23 +02:00
|
|
|
// - Called everytime when the active tab's title changes. We'll also fire off
|
|
|
|
// a window message so we can update the window's title on the main thread,
|
|
|
|
// though we'll only do so if the settings are configured for that.
|
2019-05-03 00:29:04 +02:00
|
|
|
// Arguments:
|
2019-09-04 23:34:06 +02:00
|
|
|
// - sender: unused
|
2019-05-03 00:29:04 +02:00
|
|
|
// - newTitle: the string to use as the new window title
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2019-09-05 01:43:45 +02:00
|
|
|
void AppHost::AppTitleChanged(const winrt::Windows::Foundation::IInspectable& /*sender*/, winrt::hstring newTitle)
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
2021-09-03 20:32:23 +02:00
|
|
|
if (_logic.GetShowTitleInTitlebar())
|
|
|
|
{
|
|
|
|
_window->UpdateTitle(newTitle);
|
|
|
|
}
|
|
|
|
_windowManager.UpdateActiveTabTitle(newTitle);
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
2019-05-15 14:22:16 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Called when no tab is remaining to close the window.
|
|
|
|
// Arguments:
|
2019-09-04 23:34:06 +02:00
|
|
|
// - sender: unused
|
|
|
|
// - LastTabClosedEventArgs: unused
|
2019-05-15 14:22:16 +02:00
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2019-09-05 01:43:45 +02:00
|
|
|
void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::TerminalApp::LastTabClosedEventArgs& /*args*/)
|
2019-06-11 22:27:09 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
if (_windowManager.IsMonarch() && _notificationIcon)
|
2021-08-19 19:38:18 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_DestroyNotificationIcon();
|
2021-08-19 19:38:18 +02:00
|
|
|
}
|
|
|
|
else if (_window->IsQuakeWindow())
|
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_HideNotificationIconRequested();
|
2021-08-19 19:38:18 +02:00
|
|
|
}
|
|
|
|
|
2021-10-20 02:12:18 +02:00
|
|
|
// We don't want to try to save layouts if we are about to close
|
|
|
|
_getWindowLayoutThrottler.reset();
|
|
|
|
_windowManager.GetWindowLayoutRequested(_GetWindowLayoutRequestedToken);
|
|
|
|
// Remove ourself from the list of peasants so that we aren't included in
|
|
|
|
// any future requests. This will also mean we block until any existing
|
|
|
|
// event handler finishes.
|
|
|
|
_windowManager.SignalClose();
|
|
|
|
|
2019-05-15 14:22:16 +02:00
|
|
|
_window->Close();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
LaunchPosition AppHost::_GetWindowLaunchPosition()
|
|
|
|
{
|
2021-10-20 02:12:18 +02:00
|
|
|
LaunchPosition pos{};
|
|
|
|
// If we started saving before closing, but didn't resume the event handler
|
|
|
|
// until after _window might be a nullptr.
|
|
|
|
if (!_window)
|
|
|
|
{
|
|
|
|
return pos;
|
|
|
|
}
|
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
|
|
|
|
2021-10-20 02:12:18 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// Get the position of the current window. This includes the
|
|
|
|
// non-client already.
|
|
|
|
const auto window = _window->GetWindowRect();
|
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
|
|
|
|
2021-10-20 02:12:18 +02:00
|
|
|
const auto dpi = _window->GetCurrentDpi();
|
|
|
|
const auto nonClientArea = _window->GetNonClientFrame(dpi);
|
|
|
|
|
|
|
|
// The nonClientArea adjustment is negative, so subtract that out.
|
|
|
|
// This way we save the user-visible location of the terminal.
|
|
|
|
pos.X = window.left - nonClientArea.left;
|
|
|
|
pos.Y = window.top;
|
|
|
|
}
|
|
|
|
CATCH_LOG();
|
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
|
|
|
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Resize the window we're about to create to the appropriate dimensions, as
|
|
|
|
// specified in the settings. This will be called during the handling of
|
|
|
|
// WM_CREATE. We'll load the settings for the app, then get the proposed size
|
|
|
|
// of the terminal from the app. Using that proposed size, we'll resize the
|
|
|
|
// window we're creating, so that it'll match the values in the settings.
|
|
|
|
// Arguments:
|
|
|
|
// - hwnd: The HWND of the window we're about to create.
|
|
|
|
// - proposedRect: The location and size of the window that we're about to
|
|
|
|
// create. We'll use this rect to determine which monitor the window is about
|
|
|
|
// to appear on.
|
Enable setting an initial position and maximized launch (#2817)
This PR includes the code changes that enable users to set an initial position
(top left corner) and launch maximized. There are some corner cases:
1. Multiple monitors. The user should be able to set the initial position to
any monitors attached. For the monitors on the left side of the major monitor,
the initial position values are negative.
2. If the initial position is larger than the screen resolution and the window
is off-screen, the current solution is to check if the top left corner of the
window intersect with any monitors. If it is not, we set the initial position
to the top left corner of the nearest monitor.
3. If the user wants to launch maximized and provides an initial position, we
launch the maximized window on the monitor where the position is located.
# Testing
To test:
1. Check-out this branch and build on VS2019
2. Launch Terminal, and open Settings. Then close the terminal.
3. Add the following setting into Json settings file as part of "globals", just
after "initialRows":
"initialPosition": "1000, 1000",
"launchMode": "default"
My test data:
I have already tested with the following variables:
1. showTabsInTitlebar true or false
2. The initial position of the top left corner of the window
3. Whether to launch maximized
4. The DPI of the monitor
Test data combination:
Non-client island window (showTabsInTitlebar true)
1. Three monitors with the same DPI (100%), left, middle and right, with the
middle one as the primary, resolution: 1980 * 1200, 1920 * 1200, 1920 * 1080
launchMode: default
In-Screen test: (0, 0), (1000, 500), (2000, 300), (-1000, 400),
(-100, 200), (-2000, 100), (0, 1119)
out-of-screen:
(200, -200): initialize to (0, 0)
(200, 1500): initialize to (0, 0)
(2000, -200): initialize to (1920, 0)
(2500, 2000): initialize to (1920, 0)
(4000 100): initialize to (1920, 0)
(-1000, -100): initialize to (-1920, 0)
(-3000, 100): initialize to (-1920, 0)
(10000, -10000): initialize to (1920, 0)
(-10000, 10000): initialize to (-1920, 0)
(0, -10000): initialize to (0, 0)
(0, -1): initialize to (0, 0)
(0, 1200): initialize to (0, 0)
launch mode: maximize
(100, 100)
(-1000, 100): On the left monitor
(0, -2000): On the primary monitor
(10000, 10000): On the primary monitor
2. Left monitor 200% DPI, primary monitor 100% DPI
In screen: (-1900, 100), (-3000, 100), (-1000, 100)
our-of-screen: (-8000, 100): initialize at (-1920, 0)
launch Maximized: (-100, 100): launch maximized on the left monitor
correctly
3. Left monitor 100% DPI, primary monitor 200% DPI
In-screen: (-1900, 100), (300, 100), (-800, 100), (-200, 100)
out-of-screen: (-3000, 100): initialize at (-1920, 0)
launch maximized: (100, 100), (-1000, 100)
For client island window, the test data is the same as above.
Issues:
1. If we set the initial position on the monitor with a different DPI as the
primary monitor, and the window "lays" across two monitors, then the window
still renders as it is on the primary monitor. The size of the window is
correct.
Closes #1043
2019-10-17 06:51:50 +02:00
|
|
|
// - launchMode: A LaunchMode enum reference that indicates the launch mode
|
2019-05-03 00:29:04 +02:00
|
|
|
// Return Value:
|
Enable setting an initial position and maximized launch (#2817)
This PR includes the code changes that enable users to set an initial position
(top left corner) and launch maximized. There are some corner cases:
1. Multiple monitors. The user should be able to set the initial position to
any monitors attached. For the monitors on the left side of the major monitor,
the initial position values are negative.
2. If the initial position is larger than the screen resolution and the window
is off-screen, the current solution is to check if the top left corner of the
window intersect with any monitors. If it is not, we set the initial position
to the top left corner of the nearest monitor.
3. If the user wants to launch maximized and provides an initial position, we
launch the maximized window on the monitor where the position is located.
# Testing
To test:
1. Check-out this branch and build on VS2019
2. Launch Terminal, and open Settings. Then close the terminal.
3. Add the following setting into Json settings file as part of "globals", just
after "initialRows":
"initialPosition": "1000, 1000",
"launchMode": "default"
My test data:
I have already tested with the following variables:
1. showTabsInTitlebar true or false
2. The initial position of the top left corner of the window
3. Whether to launch maximized
4. The DPI of the monitor
Test data combination:
Non-client island window (showTabsInTitlebar true)
1. Three monitors with the same DPI (100%), left, middle and right, with the
middle one as the primary, resolution: 1980 * 1200, 1920 * 1200, 1920 * 1080
launchMode: default
In-Screen test: (0, 0), (1000, 500), (2000, 300), (-1000, 400),
(-100, 200), (-2000, 100), (0, 1119)
out-of-screen:
(200, -200): initialize to (0, 0)
(200, 1500): initialize to (0, 0)
(2000, -200): initialize to (1920, 0)
(2500, 2000): initialize to (1920, 0)
(4000 100): initialize to (1920, 0)
(-1000, -100): initialize to (-1920, 0)
(-3000, 100): initialize to (-1920, 0)
(10000, -10000): initialize to (1920, 0)
(-10000, 10000): initialize to (-1920, 0)
(0, -10000): initialize to (0, 0)
(0, -1): initialize to (0, 0)
(0, 1200): initialize to (0, 0)
launch mode: maximize
(100, 100)
(-1000, 100): On the left monitor
(0, -2000): On the primary monitor
(10000, 10000): On the primary monitor
2. Left monitor 200% DPI, primary monitor 100% DPI
In screen: (-1900, 100), (-3000, 100), (-1000, 100)
our-of-screen: (-8000, 100): initialize at (-1920, 0)
launch Maximized: (-100, 100): launch maximized on the left monitor
correctly
3. Left monitor 100% DPI, primary monitor 200% DPI
In-screen: (-1900, 100), (300, 100), (-800, 100), (-200, 100)
out-of-screen: (-3000, 100): initialize at (-1920, 0)
launch maximized: (100, 100), (-1000, 100)
For client island window, the test data is the same as above.
Issues:
1. If we set the initial position on the monitor with a different DPI as the
primary monitor, and the window "lays" across two monitors, then the window
still renders as it is on the primary monitor. The size of the window is
correct.
Closes #1043
2019-10-17 06:51:50 +02:00
|
|
|
// - None
|
2020-10-06 18:56:59 +02:00
|
|
|
void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode& launchMode)
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
2019-11-07 22:10:58 +01:00
|
|
|
launchMode = _logic.GetLaunchMode();
|
Enable setting an initial position and maximized launch (#2817)
This PR includes the code changes that enable users to set an initial position
(top left corner) and launch maximized. There are some corner cases:
1. Multiple monitors. The user should be able to set the initial position to
any monitors attached. For the monitors on the left side of the major monitor,
the initial position values are negative.
2. If the initial position is larger than the screen resolution and the window
is off-screen, the current solution is to check if the top left corner of the
window intersect with any monitors. If it is not, we set the initial position
to the top left corner of the nearest monitor.
3. If the user wants to launch maximized and provides an initial position, we
launch the maximized window on the monitor where the position is located.
# Testing
To test:
1. Check-out this branch and build on VS2019
2. Launch Terminal, and open Settings. Then close the terminal.
3. Add the following setting into Json settings file as part of "globals", just
after "initialRows":
"initialPosition": "1000, 1000",
"launchMode": "default"
My test data:
I have already tested with the following variables:
1. showTabsInTitlebar true or false
2. The initial position of the top left corner of the window
3. Whether to launch maximized
4. The DPI of the monitor
Test data combination:
Non-client island window (showTabsInTitlebar true)
1. Three monitors with the same DPI (100%), left, middle and right, with the
middle one as the primary, resolution: 1980 * 1200, 1920 * 1200, 1920 * 1080
launchMode: default
In-Screen test: (0, 0), (1000, 500), (2000, 300), (-1000, 400),
(-100, 200), (-2000, 100), (0, 1119)
out-of-screen:
(200, -200): initialize to (0, 0)
(200, 1500): initialize to (0, 0)
(2000, -200): initialize to (1920, 0)
(2500, 2000): initialize to (1920, 0)
(4000 100): initialize to (1920, 0)
(-1000, -100): initialize to (-1920, 0)
(-3000, 100): initialize to (-1920, 0)
(10000, -10000): initialize to (1920, 0)
(-10000, 10000): initialize to (-1920, 0)
(0, -10000): initialize to (0, 0)
(0, -1): initialize to (0, 0)
(0, 1200): initialize to (0, 0)
launch mode: maximize
(100, 100)
(-1000, 100): On the left monitor
(0, -2000): On the primary monitor
(10000, 10000): On the primary monitor
2. Left monitor 200% DPI, primary monitor 100% DPI
In screen: (-1900, 100), (-3000, 100), (-1000, 100)
our-of-screen: (-8000, 100): initialize at (-1920, 0)
launch Maximized: (-100, 100): launch maximized on the left monitor
correctly
3. Left monitor 100% DPI, primary monitor 200% DPI
In-screen: (-1900, 100), (300, 100), (-800, 100), (-200, 100)
out-of-screen: (-3000, 100): initialize at (-1920, 0)
launch maximized: (100, 100), (-1000, 100)
For client island window, the test data is the same as above.
Issues:
1. If we set the initial position on the monitor with a different DPI as the
primary monitor, and the window "lays" across two monitors, then the window
still renders as it is on the primary monitor. The size of the window is
correct.
Closes #1043
2019-10-17 06:51:50 +02:00
|
|
|
|
2020-02-10 21:40:01 +01:00
|
|
|
// Acquire the actual initial position
|
2020-08-28 05:49:16 +02:00
|
|
|
auto initialPos = _logic.GetInitialPosition(proposedRect.left, proposedRect.top);
|
Add `centerOnLaunch` setting (#9036)
This PR is a resurrection of #8414. @Hegunumo has apparently deleted
their account, but the contribution was still valuable. I'm just here to
get it across the finish line.
This PR adds new global setting `centerOnLaunch`. When set to `true`,
the Terminal window will be centered on the display it opens on.
So the interactions are like:
* `initialPos: x,y`, `centered: true`, `launchMode: default`
center on the monitor that x,y is on
* `initialPos: x,y`, `centered: true`, `launchMode: maximized`
maximized on the monitor that x,y is on (centered adds nothing)
* `initialPos: <omitted>`, `centered: true`, `launchMode: default`
center on the default monitor
* `initialPos: <omitted>`, `centered: true`, `launchMode: focus`
center, focus mode on the default monitor
* `initialPos: <omitted>`, `centered: true`, `launchMode: maximized`
maximized on the default monitor (centered adds nothing)
## Validation Steps Performed
I've played with it on multiple different monitors, and it seems to work
on all of them.
Closes #8414 (original PR)
Closes #7722
Co-authored-by: Kiminori Kaburagi <yukawa_hidenori@icloud.com>
2021-02-19 23:30:24 +01:00
|
|
|
const auto centerOnLaunch = _logic.CenterOnLaunch();
|
2020-08-28 05:49:16 +02:00
|
|
|
proposedRect.left = static_cast<long>(initialPos.X);
|
|
|
|
proposedRect.top = static_cast<long>(initialPos.Y);
|
Enable setting an initial position and maximized launch (#2817)
This PR includes the code changes that enable users to set an initial position
(top left corner) and launch maximized. There are some corner cases:
1. Multiple monitors. The user should be able to set the initial position to
any monitors attached. For the monitors on the left side of the major monitor,
the initial position values are negative.
2. If the initial position is larger than the screen resolution and the window
is off-screen, the current solution is to check if the top left corner of the
window intersect with any monitors. If it is not, we set the initial position
to the top left corner of the nearest monitor.
3. If the user wants to launch maximized and provides an initial position, we
launch the maximized window on the monitor where the position is located.
# Testing
To test:
1. Check-out this branch and build on VS2019
2. Launch Terminal, and open Settings. Then close the terminal.
3. Add the following setting into Json settings file as part of "globals", just
after "initialRows":
"initialPosition": "1000, 1000",
"launchMode": "default"
My test data:
I have already tested with the following variables:
1. showTabsInTitlebar true or false
2. The initial position of the top left corner of the window
3. Whether to launch maximized
4. The DPI of the monitor
Test data combination:
Non-client island window (showTabsInTitlebar true)
1. Three monitors with the same DPI (100%), left, middle and right, with the
middle one as the primary, resolution: 1980 * 1200, 1920 * 1200, 1920 * 1080
launchMode: default
In-Screen test: (0, 0), (1000, 500), (2000, 300), (-1000, 400),
(-100, 200), (-2000, 100), (0, 1119)
out-of-screen:
(200, -200): initialize to (0, 0)
(200, 1500): initialize to (0, 0)
(2000, -200): initialize to (1920, 0)
(2500, 2000): initialize to (1920, 0)
(4000 100): initialize to (1920, 0)
(-1000, -100): initialize to (-1920, 0)
(-3000, 100): initialize to (-1920, 0)
(10000, -10000): initialize to (1920, 0)
(-10000, 10000): initialize to (-1920, 0)
(0, -10000): initialize to (0, 0)
(0, -1): initialize to (0, 0)
(0, 1200): initialize to (0, 0)
launch mode: maximize
(100, 100)
(-1000, 100): On the left monitor
(0, -2000): On the primary monitor
(10000, 10000): On the primary monitor
2. Left monitor 200% DPI, primary monitor 100% DPI
In screen: (-1900, 100), (-3000, 100), (-1000, 100)
our-of-screen: (-8000, 100): initialize at (-1920, 0)
launch Maximized: (-100, 100): launch maximized on the left monitor
correctly
3. Left monitor 100% DPI, primary monitor 200% DPI
In-screen: (-1900, 100), (300, 100), (-800, 100), (-200, 100)
out-of-screen: (-3000, 100): initialize at (-1920, 0)
launch maximized: (100, 100), (-1000, 100)
For client island window, the test data is the same as above.
Issues:
1. If we set the initial position on the monitor with a different DPI as the
primary monitor, and the window "lays" across two monitors, then the window
still renders as it is on the primary monitor. The size of the window is
correct.
Closes #1043
2019-10-17 06:51:50 +02:00
|
|
|
|
|
|
|
long adjustedHeight = 0;
|
|
|
|
long adjustedWidth = 0;
|
2020-05-28 18:53:01 +02:00
|
|
|
|
|
|
|
// Find nearest monitor.
|
|
|
|
HMONITOR hmon = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST);
|
|
|
|
|
|
|
|
// Get nearest monitor information
|
|
|
|
MONITORINFO monitorInfo;
|
|
|
|
monitorInfo.cbSize = sizeof(MONITORINFO);
|
|
|
|
GetMonitorInfo(hmon, &monitorInfo);
|
|
|
|
|
|
|
|
// This API guarantees that dpix and dpiy will be equal, but neither is an
|
|
|
|
// optional parameter so give two UINTs.
|
|
|
|
UINT dpix = USER_DEFAULT_SCREEN_DPI;
|
|
|
|
UINT dpiy = USER_DEFAULT_SCREEN_DPI;
|
|
|
|
// If this fails, we'll use the default of 96.
|
|
|
|
GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
|
|
|
|
|
|
|
|
// We need to check if the top left point of the titlebar of the window is within any screen
|
|
|
|
RECT offScreenTestRect;
|
|
|
|
offScreenTestRect.left = proposedRect.left;
|
|
|
|
offScreenTestRect.top = proposedRect.top;
|
|
|
|
offScreenTestRect.right = offScreenTestRect.left + 1;
|
|
|
|
offScreenTestRect.bottom = offScreenTestRect.top + 1;
|
|
|
|
|
|
|
|
bool isTitlebarIntersectWithMonitors = false;
|
|
|
|
EnumDisplayMonitors(
|
|
|
|
nullptr, &offScreenTestRect, [](HMONITOR, HDC, LPRECT, LPARAM lParam) -> BOOL {
|
|
|
|
auto intersectWithMonitor = reinterpret_cast<bool*>(lParam);
|
|
|
|
*intersectWithMonitor = true;
|
|
|
|
// Continue the enumeration
|
|
|
|
return FALSE;
|
|
|
|
},
|
|
|
|
reinterpret_cast<LPARAM>(&isTitlebarIntersectWithMonitors));
|
|
|
|
|
|
|
|
if (!isTitlebarIntersectWithMonitors)
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
2020-05-28 18:53:01 +02:00
|
|
|
// If the title bar is out-of-screen, we set the initial position to
|
|
|
|
// the top left corner of the nearest monitor
|
|
|
|
proposedRect.left = monitorInfo.rcWork.left;
|
|
|
|
proposedRect.top = monitorInfo.rcWork.top;
|
|
|
|
}
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2020-05-28 18:53:01 +02:00
|
|
|
auto initialSize = _logic.GetLaunchDimensions(dpix);
|
Enable setting an initial position and maximized launch (#2817)
This PR includes the code changes that enable users to set an initial position
(top left corner) and launch maximized. There are some corner cases:
1. Multiple monitors. The user should be able to set the initial position to
any monitors attached. For the monitors on the left side of the major monitor,
the initial position values are negative.
2. If the initial position is larger than the screen resolution and the window
is off-screen, the current solution is to check if the top left corner of the
window intersect with any monitors. If it is not, we set the initial position
to the top left corner of the nearest monitor.
3. If the user wants to launch maximized and provides an initial position, we
launch the maximized window on the monitor where the position is located.
# Testing
To test:
1. Check-out this branch and build on VS2019
2. Launch Terminal, and open Settings. Then close the terminal.
3. Add the following setting into Json settings file as part of "globals", just
after "initialRows":
"initialPosition": "1000, 1000",
"launchMode": "default"
My test data:
I have already tested with the following variables:
1. showTabsInTitlebar true or false
2. The initial position of the top left corner of the window
3. Whether to launch maximized
4. The DPI of the monitor
Test data combination:
Non-client island window (showTabsInTitlebar true)
1. Three monitors with the same DPI (100%), left, middle and right, with the
middle one as the primary, resolution: 1980 * 1200, 1920 * 1200, 1920 * 1080
launchMode: default
In-Screen test: (0, 0), (1000, 500), (2000, 300), (-1000, 400),
(-100, 200), (-2000, 100), (0, 1119)
out-of-screen:
(200, -200): initialize to (0, 0)
(200, 1500): initialize to (0, 0)
(2000, -200): initialize to (1920, 0)
(2500, 2000): initialize to (1920, 0)
(4000 100): initialize to (1920, 0)
(-1000, -100): initialize to (-1920, 0)
(-3000, 100): initialize to (-1920, 0)
(10000, -10000): initialize to (1920, 0)
(-10000, 10000): initialize to (-1920, 0)
(0, -10000): initialize to (0, 0)
(0, -1): initialize to (0, 0)
(0, 1200): initialize to (0, 0)
launch mode: maximize
(100, 100)
(-1000, 100): On the left monitor
(0, -2000): On the primary monitor
(10000, 10000): On the primary monitor
2. Left monitor 200% DPI, primary monitor 100% DPI
In screen: (-1900, 100), (-3000, 100), (-1000, 100)
our-of-screen: (-8000, 100): initialize at (-1920, 0)
launch Maximized: (-100, 100): launch maximized on the left monitor
correctly
3. Left monitor 100% DPI, primary monitor 200% DPI
In-screen: (-1900, 100), (300, 100), (-800, 100), (-200, 100)
out-of-screen: (-3000, 100): initialize at (-1920, 0)
launch maximized: (100, 100), (-1000, 100)
For client island window, the test data is the same as above.
Issues:
1. If we set the initial position on the monitor with a different DPI as the
primary monitor, and the window "lays" across two monitors, then the window
still renders as it is on the primary monitor. The size of the window is
correct.
Closes #1043
2019-10-17 06:51:50 +02:00
|
|
|
|
2020-05-28 18:53:01 +02:00
|
|
|
const short islandWidth = Utils::ClampToShortMax(
|
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
|
|
|
static_cast<long>(ceil(initialSize.Width)), 1);
|
2020-05-28 18:53:01 +02:00
|
|
|
const short islandHeight = Utils::ClampToShortMax(
|
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
|
|
|
static_cast<long>(ceil(initialSize.Height)), 1);
|
Enable setting an initial position and maximized launch (#2817)
This PR includes the code changes that enable users to set an initial position
(top left corner) and launch maximized. There are some corner cases:
1. Multiple monitors. The user should be able to set the initial position to
any monitors attached. For the monitors on the left side of the major monitor,
the initial position values are negative.
2. If the initial position is larger than the screen resolution and the window
is off-screen, the current solution is to check if the top left corner of the
window intersect with any monitors. If it is not, we set the initial position
to the top left corner of the nearest monitor.
3. If the user wants to launch maximized and provides an initial position, we
launch the maximized window on the monitor where the position is located.
# Testing
To test:
1. Check-out this branch and build on VS2019
2. Launch Terminal, and open Settings. Then close the terminal.
3. Add the following setting into Json settings file as part of "globals", just
after "initialRows":
"initialPosition": "1000, 1000",
"launchMode": "default"
My test data:
I have already tested with the following variables:
1. showTabsInTitlebar true or false
2. The initial position of the top left corner of the window
3. Whether to launch maximized
4. The DPI of the monitor
Test data combination:
Non-client island window (showTabsInTitlebar true)
1. Three monitors with the same DPI (100%), left, middle and right, with the
middle one as the primary, resolution: 1980 * 1200, 1920 * 1200, 1920 * 1080
launchMode: default
In-Screen test: (0, 0), (1000, 500), (2000, 300), (-1000, 400),
(-100, 200), (-2000, 100), (0, 1119)
out-of-screen:
(200, -200): initialize to (0, 0)
(200, 1500): initialize to (0, 0)
(2000, -200): initialize to (1920, 0)
(2500, 2000): initialize to (1920, 0)
(4000 100): initialize to (1920, 0)
(-1000, -100): initialize to (-1920, 0)
(-3000, 100): initialize to (-1920, 0)
(10000, -10000): initialize to (1920, 0)
(-10000, 10000): initialize to (-1920, 0)
(0, -10000): initialize to (0, 0)
(0, -1): initialize to (0, 0)
(0, 1200): initialize to (0, 0)
launch mode: maximize
(100, 100)
(-1000, 100): On the left monitor
(0, -2000): On the primary monitor
(10000, 10000): On the primary monitor
2. Left monitor 200% DPI, primary monitor 100% DPI
In screen: (-1900, 100), (-3000, 100), (-1000, 100)
our-of-screen: (-8000, 100): initialize at (-1920, 0)
launch Maximized: (-100, 100): launch maximized on the left monitor
correctly
3. Left monitor 100% DPI, primary monitor 200% DPI
In-screen: (-1900, 100), (300, 100), (-800, 100), (-200, 100)
out-of-screen: (-3000, 100): initialize at (-1920, 0)
launch maximized: (100, 100), (-1000, 100)
For client island window, the test data is the same as above.
Issues:
1. If we set the initial position on the monitor with a different DPI as the
primary monitor, and the window "lays" across two monitors, then the window
still renders as it is on the primary monitor. The size of the window is
correct.
Closes #1043
2019-10-17 06:51:50 +02:00
|
|
|
|
2020-05-28 18:53:01 +02:00
|
|
|
// Get the size of a window we'd need to host that client rect. This will
|
|
|
|
// add the titlebar space.
|
2021-04-26 21:36:23 +02:00
|
|
|
const til::size nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix);
|
2021-08-09 20:27:20 +02:00
|
|
|
const til::rectangle nonClientFrame = _window->GetNonClientFrame(dpix);
|
2021-04-26 21:36:23 +02:00
|
|
|
adjustedWidth = islandWidth + nonClientSize.width<long>();
|
|
|
|
adjustedHeight = islandHeight + nonClientSize.height<long>();
|
|
|
|
|
|
|
|
til::size dimensions{ Utils::ClampToShortMax(adjustedWidth, 1),
|
|
|
|
Utils::ClampToShortMax(adjustedHeight, 1) };
|
|
|
|
|
|
|
|
// Find nearest monitor for the position that we've actually settled on
|
|
|
|
HMONITOR hMonNearest = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST);
|
|
|
|
MONITORINFO nearestMonitorInfo;
|
|
|
|
nearestMonitorInfo.cbSize = sizeof(MONITORINFO);
|
|
|
|
// Get monitor dimensions:
|
|
|
|
GetMonitorInfo(hMonNearest, &nearestMonitorInfo);
|
|
|
|
const til::size desktopDimensions{ gsl::narrow<short>(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left),
|
|
|
|
gsl::narrow<short>(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) };
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2021-08-09 20:27:20 +02:00
|
|
|
// GH#10583 - Adjust the position of the rectangle to account for the size
|
|
|
|
// of the invisible borders on the left/right. We DON'T want to adjust this
|
|
|
|
// for the top here - the IslandWindow includes the titlebar in
|
|
|
|
// nonClientFrame.top, so adjusting for that would actually place the
|
|
|
|
// titlebar _off_ the monitor.
|
|
|
|
til::point origin{ (proposedRect.left + nonClientFrame.left<LONG>()),
|
2021-04-26 21:36:23 +02:00
|
|
|
(proposedRect.top) };
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2021-04-26 21:36:23 +02:00
|
|
|
if (_logic.IsQuakeWindow())
|
|
|
|
{
|
|
|
|
// If we just use rcWork by itself, we'll fail to account for the invisible
|
|
|
|
// space reserved for the resize handles. So retrieve that size here.
|
|
|
|
const til::size availableSpace = desktopDimensions + nonClientSize;
|
|
|
|
|
|
|
|
origin = til::point{
|
|
|
|
::base::ClampSub<long>(nearestMonitorInfo.rcWork.left, (nonClientSize.width() / 2)),
|
|
|
|
(nearestMonitorInfo.rcWork.top)
|
|
|
|
};
|
|
|
|
dimensions = til::size{
|
|
|
|
availableSpace.width(),
|
|
|
|
availableSpace.height() / 2
|
|
|
|
};
|
|
|
|
launchMode = LaunchMode::FocusMode;
|
|
|
|
}
|
|
|
|
else if (centerOnLaunch)
|
Add `centerOnLaunch` setting (#9036)
This PR is a resurrection of #8414. @Hegunumo has apparently deleted
their account, but the contribution was still valuable. I'm just here to
get it across the finish line.
This PR adds new global setting `centerOnLaunch`. When set to `true`,
the Terminal window will be centered on the display it opens on.
So the interactions are like:
* `initialPos: x,y`, `centered: true`, `launchMode: default`
center on the monitor that x,y is on
* `initialPos: x,y`, `centered: true`, `launchMode: maximized`
maximized on the monitor that x,y is on (centered adds nothing)
* `initialPos: <omitted>`, `centered: true`, `launchMode: default`
center on the default monitor
* `initialPos: <omitted>`, `centered: true`, `launchMode: focus`
center, focus mode on the default monitor
* `initialPos: <omitted>`, `centered: true`, `launchMode: maximized`
maximized on the default monitor (centered adds nothing)
## Validation Steps Performed
I've played with it on multiple different monitors, and it seems to work
on all of them.
Closes #8414 (original PR)
Closes #7722
Co-authored-by: Kiminori Kaburagi <yukawa_hidenori@icloud.com>
2021-02-19 23:30:24 +01:00
|
|
|
{
|
|
|
|
// Move our proposed location into the center of that specific monitor.
|
2021-04-26 21:36:23 +02:00
|
|
|
origin = til::point{
|
|
|
|
(nearestMonitorInfo.rcWork.left + ((desktopDimensions.width() / 2) - (dimensions.width() / 2))),
|
|
|
|
(nearestMonitorInfo.rcWork.top + ((desktopDimensions.height() / 2) - (dimensions.height() / 2)))
|
|
|
|
};
|
Add `centerOnLaunch` setting (#9036)
This PR is a resurrection of #8414. @Hegunumo has apparently deleted
their account, but the contribution was still valuable. I'm just here to
get it across the finish line.
This PR adds new global setting `centerOnLaunch`. When set to `true`,
the Terminal window will be centered on the display it opens on.
So the interactions are like:
* `initialPos: x,y`, `centered: true`, `launchMode: default`
center on the monitor that x,y is on
* `initialPos: x,y`, `centered: true`, `launchMode: maximized`
maximized on the monitor that x,y is on (centered adds nothing)
* `initialPos: <omitted>`, `centered: true`, `launchMode: default`
center on the default monitor
* `initialPos: <omitted>`, `centered: true`, `launchMode: focus`
center, focus mode on the default monitor
* `initialPos: <omitted>`, `centered: true`, `launchMode: maximized`
maximized on the default monitor (centered adds nothing)
## Validation Steps Performed
I've played with it on multiple different monitors, and it seems to work
on all of them.
Closes #8414 (original PR)
Closes #7722
Co-authored-by: Kiminori Kaburagi <yukawa_hidenori@icloud.com>
2021-02-19 23:30:24 +01:00
|
|
|
}
|
|
|
|
|
2021-04-26 21:36:23 +02:00
|
|
|
const til::rectangle newRect{ origin, dimensions };
|
2019-06-11 22:27:09 +02:00
|
|
|
bool succeeded = SetWindowPos(hwnd,
|
|
|
|
nullptr,
|
2021-04-26 21:36:23 +02:00
|
|
|
newRect.left<int>(),
|
|
|
|
newRect.top<int>(),
|
|
|
|
newRect.width<int>(),
|
|
|
|
newRect.height<int>(),
|
2019-05-03 00:29:04 +02:00
|
|
|
SWP_NOACTIVATE | SWP_NOZORDER);
|
|
|
|
|
2020-02-10 21:40:01 +01:00
|
|
|
// Refresh the dpi of HWND because the dpi where the window will launch may be different
|
Enable setting an initial position and maximized launch (#2817)
This PR includes the code changes that enable users to set an initial position
(top left corner) and launch maximized. There are some corner cases:
1. Multiple monitors. The user should be able to set the initial position to
any monitors attached. For the monitors on the left side of the major monitor,
the initial position values are negative.
2. If the initial position is larger than the screen resolution and the window
is off-screen, the current solution is to check if the top left corner of the
window intersect with any monitors. If it is not, we set the initial position
to the top left corner of the nearest monitor.
3. If the user wants to launch maximized and provides an initial position, we
launch the maximized window on the monitor where the position is located.
# Testing
To test:
1. Check-out this branch and build on VS2019
2. Launch Terminal, and open Settings. Then close the terminal.
3. Add the following setting into Json settings file as part of "globals", just
after "initialRows":
"initialPosition": "1000, 1000",
"launchMode": "default"
My test data:
I have already tested with the following variables:
1. showTabsInTitlebar true or false
2. The initial position of the top left corner of the window
3. Whether to launch maximized
4. The DPI of the monitor
Test data combination:
Non-client island window (showTabsInTitlebar true)
1. Three monitors with the same DPI (100%), left, middle and right, with the
middle one as the primary, resolution: 1980 * 1200, 1920 * 1200, 1920 * 1080
launchMode: default
In-Screen test: (0, 0), (1000, 500), (2000, 300), (-1000, 400),
(-100, 200), (-2000, 100), (0, 1119)
out-of-screen:
(200, -200): initialize to (0, 0)
(200, 1500): initialize to (0, 0)
(2000, -200): initialize to (1920, 0)
(2500, 2000): initialize to (1920, 0)
(4000 100): initialize to (1920, 0)
(-1000, -100): initialize to (-1920, 0)
(-3000, 100): initialize to (-1920, 0)
(10000, -10000): initialize to (1920, 0)
(-10000, 10000): initialize to (-1920, 0)
(0, -10000): initialize to (0, 0)
(0, -1): initialize to (0, 0)
(0, 1200): initialize to (0, 0)
launch mode: maximize
(100, 100)
(-1000, 100): On the left monitor
(0, -2000): On the primary monitor
(10000, 10000): On the primary monitor
2. Left monitor 200% DPI, primary monitor 100% DPI
In screen: (-1900, 100), (-3000, 100), (-1000, 100)
our-of-screen: (-8000, 100): initialize at (-1920, 0)
launch Maximized: (-100, 100): launch maximized on the left monitor
correctly
3. Left monitor 100% DPI, primary monitor 200% DPI
In-screen: (-1900, 100), (300, 100), (-800, 100), (-200, 100)
out-of-screen: (-3000, 100): initialize at (-1920, 0)
launch maximized: (100, 100), (-1000, 100)
For client island window, the test data is the same as above.
Issues:
1. If we set the initial position on the monitor with a different DPI as the
primary monitor, and the window "lays" across two monitors, then the window
still renders as it is on the primary monitor. The size of the window is
correct.
Closes #1043
2019-10-17 06:51:50 +02:00
|
|
|
// at this time
|
|
|
|
_window->RefreshCurrentDPI();
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
// If we can't resize the window, that's really okay. We can just go on with
|
|
|
|
// the originally proposed window size.
|
|
|
|
LOG_LAST_ERROR_IF(!succeeded);
|
2019-09-05 22:38:42 +02:00
|
|
|
|
|
|
|
TraceLoggingWrite(
|
|
|
|
g_hWindowsTerminalProvider,
|
|
|
|
"WindowCreated",
|
|
|
|
TraceLoggingDescription("Event emitted upon creating the application window"),
|
|
|
|
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
|
|
|
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when the app wants to set its titlebar content. We'll take the
|
|
|
|
// UIElement and set the Content property of our Titlebar that element.
|
|
|
|
// Arguments:
|
|
|
|
// - sender: unused
|
|
|
|
// - arg: the UIElement to use as the new Titlebar content.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2019-09-04 23:34:06 +02:00
|
|
|
void AppHost::_UpdateTitleBarContent(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::UIElement& arg)
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
{
|
|
|
|
if (_useNonClientArea)
|
|
|
|
{
|
|
|
|
(static_cast<NonClientIslandWindow*>(_window.get()))->SetTitlebarContent(arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when the app wants to change its theme. We'll forward this to the
|
|
|
|
// IslandWindow, so it can update the root UI element of the entire XAML tree.
|
|
|
|
// Arguments:
|
|
|
|
// - sender: unused
|
|
|
|
// - arg: the ElementTheme to use as the new theme for the UI
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2019-11-07 22:10:58 +01:00
|
|
|
void AppHost::_UpdateTheme(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::ElementTheme& arg)
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
{
|
2019-11-05 00:45:40 +01:00
|
|
|
_window->OnApplicationThemeChanged(arg);
|
Enable dragging with the entire titlebar (#1948)
* This definitely works for getting shadow, pointy corners back
Don't do anything in NCPAINT. If you do, you have to do everything. But the
whole point of DwmExtendFrameIntoClientArea is to let you paint the NC area in
your normal paint. So just do that dummy.
* This doesn't transition across monitors.
* This has a window style change I think is wrong.
* I'm not sure the margins change is important.
* The window style was _not_ important
* Still getting a black xaml islands area (the HRGN) when we switch to high DPI
* I don't know if this affects anything.
* heyo this works.
I'm not entirely sure why. But if we only update the titlebar drag region when
that actually changes, it's a _lot_ smoother. I'm not super happy with the
duplicated work in _UpdateDragRegion and OnSize, but checking this in in case
I can't figure that out.
* Add more comments and cleanup
* Try making the button RightCustomContent
* * Make the MinMaxClose's drag bar's min size the same as a caption button
* Make the new tab button transparent, to see how that looks
* Make sure the TabView doesn't push the MMC off the window
* Create a TitlebarControl
* The TitlebarControl is owned by the NCIW. It consists of a Content, DragBar,
and MMCControl.
* The App instatntiates a TabRowControl at runtime, and either places it in
the UI (for tabs below titlebar) or hangs on to it, and gives it to the NCIW
when the NCIW creates its UI.
* When the NCIW is created, it creates a grid with two rows, one for the
titlebar and one for the app content.
* The MMCControl is only responsible for Min Max Close now, and is closer to
the window implementation.
* The drag bar takes up all the space from the right of the TabRow to the left
of the MMC
* Things that **DON'T** work:
- When you add tabs, the drag bar doesn't update it's size. It only updates
OnSize
- The MMCControl's Min and Max buttons don't seem to work anymore.
- They should probably just expose their OnMinimizeClick and
OnMaximizeClick events for the Titlebar to handle minimizing and
maximizing.
- The drag bar is Magenta (#ff00ff) currently.
- I'm not _sure_ we need a TabRowControl. We could probably get away with
removing it from the UI tree, I was just being dumb before.
* Fix the MMC buttons not working
I forgot to plumb the window handle through
* Make the titlebar less magenta
* Resize the drag region as we add/remove tabs
* Move the actual MMC handling to the TitlebarControl
* Some PR nits, fix the titlebar painting on maximize
* Put the TabRow in our XAML
* Remove dead code in preparation for review
* Horrifyingly try Gdi Plus as a solution, that is _wrong_ though
* Revert "Horrifyingly try Gdi Plus as a solution, that is _wrong_ though"
This reverts commit e038b5d9216c6710c2a7f81840d76f8130cd73b8.
* This fixes the bottom border but breaks the titlebar painting
* Fix the NC bottom border
* A bunch of the more minor PR nits
* Add a MinimizeClick event to the MMCControl
This works for Minimize. This is what I wanted to do originally.
* Add events for _all_ of the buttons, not just the Minimize btn
* Change hoe setting the titlebar content works
Now the app triggers a callcack on the host to set the content, instead of the host querying the app.
* Move the tab row to the bottom of it's available space
* Fix the theme reloading
* PR nits from @miniksa
* Update src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
* This needed to be fixed, was missed in other PR nits
* runformat
wait _what_
* Does this fix the CI build?
2019-07-19 00:21:33 +02:00
|
|
|
}
|
Enable fullscreen mode (#3408)
## Summary of the Pull Request
Enables the `toggleFullscreen` action to be able to enter fullscreen mode, bound by default to <kbd>alt+enter</kbd>.
The action is bubbled up to the WindowsTerminal (Win32) layer, where the window resizes itself to take the entire size of the monitor.
This largely reuses code from conhost. Conhost already had a fullscreen mode, so I figured I might as well re-use that.
## References
Unfortunately there are still very thin borders around the window when the NonClientIslandWindow is fullscreened. I think I know where the problem is. However, that area of code is about to get a massive overhaul with #3064, so I didn't want to necessarily make it worse right now.
A follow up should be filed to add support for "Always show / reveal / never show tabs in fullscreen mode". Currently, the only mode is "never show tabs".
Additionally, some of this code (particularily re:drawing the nonclient area) could be re-used for #2238.
## PR Checklist
* [x] Closes #531, #3411
* [x] I work here
* [n/a] Tests added/passed 😭
* [x] Requires documentation to be updated
## Validation Steps Performed
* Manually tested both the NonClientIslandWindow and the IslandWindow.
* Cherry-pick commit 8e56bfe
* Don't draw the tab strip when maximized
(cherry picked from commit bac4be7c0f3ed1cdcd4f9ae8980fc98103538613)
* Fix the vista window flash for the NCIW
(cherry picked from commit 7d3a18a893c02bd2ed75026f2aac52e20321a1cf)
* Some code cleanup for review
(cherry picked from commit 9e22b7730bba426adcbfd9e7025f192dbf8efb32)
* A tad bit more notes and cleanup
* Update schema, docs
* Most of the PR comments
* I'm not sure this actually works, so I'm committing it to revert it and check
* Update some comments that were lost.
* Fix a build break?
* oh no
2019-11-05 20:40:29 +01:00
|
|
|
|
2020-07-14 23:02:18 +02:00
|
|
|
void AppHost::_FocusModeChanged(const winrt::Windows::Foundation::IInspectable&,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
2020-07-13 19:40:20 +02:00
|
|
|
{
|
2020-07-14 23:02:18 +02:00
|
|
|
_window->FocusModeChanged(_logic.FocusMode());
|
2020-07-13 19:40:20 +02:00
|
|
|
}
|
|
|
|
|
2020-07-14 23:02:18 +02:00
|
|
|
void AppHost::_FullscreenChanged(const winrt::Windows::Foundation::IInspectable&,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
Enable fullscreen mode (#3408)
## Summary of the Pull Request
Enables the `toggleFullscreen` action to be able to enter fullscreen mode, bound by default to <kbd>alt+enter</kbd>.
The action is bubbled up to the WindowsTerminal (Win32) layer, where the window resizes itself to take the entire size of the monitor.
This largely reuses code from conhost. Conhost already had a fullscreen mode, so I figured I might as well re-use that.
## References
Unfortunately there are still very thin borders around the window when the NonClientIslandWindow is fullscreened. I think I know where the problem is. However, that area of code is about to get a massive overhaul with #3064, so I didn't want to necessarily make it worse right now.
A follow up should be filed to add support for "Always show / reveal / never show tabs in fullscreen mode". Currently, the only mode is "never show tabs".
Additionally, some of this code (particularily re:drawing the nonclient area) could be re-used for #2238.
## PR Checklist
* [x] Closes #531, #3411
* [x] I work here
* [n/a] Tests added/passed 😭
* [x] Requires documentation to be updated
## Validation Steps Performed
* Manually tested both the NonClientIslandWindow and the IslandWindow.
* Cherry-pick commit 8e56bfe
* Don't draw the tab strip when maximized
(cherry picked from commit bac4be7c0f3ed1cdcd4f9ae8980fc98103538613)
* Fix the vista window flash for the NCIW
(cherry picked from commit 7d3a18a893c02bd2ed75026f2aac52e20321a1cf)
* Some code cleanup for review
(cherry picked from commit 9e22b7730bba426adcbfd9e7025f192dbf8efb32)
* A tad bit more notes and cleanup
* Update schema, docs
* Most of the PR comments
* I'm not sure this actually works, so I'm committing it to revert it and check
* Update some comments that were lost.
* Fix a build break?
* oh no
2019-11-05 20:40:29 +01:00
|
|
|
{
|
2020-07-14 23:02:18 +02:00
|
|
|
_window->FullscreenChanged(_logic.Fullscreen());
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppHost::_AlwaysOnTopChanged(const winrt::Windows::Foundation::IInspectable&,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
|
|
|
{
|
|
|
|
_window->SetAlwaysOnTop(_logic.AlwaysOnTop());
|
Enable fullscreen mode (#3408)
## Summary of the Pull Request
Enables the `toggleFullscreen` action to be able to enter fullscreen mode, bound by default to <kbd>alt+enter</kbd>.
The action is bubbled up to the WindowsTerminal (Win32) layer, where the window resizes itself to take the entire size of the monitor.
This largely reuses code from conhost. Conhost already had a fullscreen mode, so I figured I might as well re-use that.
## References
Unfortunately there are still very thin borders around the window when the NonClientIslandWindow is fullscreened. I think I know where the problem is. However, that area of code is about to get a massive overhaul with #3064, so I didn't want to necessarily make it worse right now.
A follow up should be filed to add support for "Always show / reveal / never show tabs in fullscreen mode". Currently, the only mode is "never show tabs".
Additionally, some of this code (particularily re:drawing the nonclient area) could be re-used for #2238.
## PR Checklist
* [x] Closes #531, #3411
* [x] I work here
* [n/a] Tests added/passed 😭
* [x] Requires documentation to be updated
## Validation Steps Performed
* Manually tested both the NonClientIslandWindow and the IslandWindow.
* Cherry-pick commit 8e56bfe
* Don't draw the tab strip when maximized
(cherry picked from commit bac4be7c0f3ed1cdcd4f9ae8980fc98103538613)
* Fix the vista window flash for the NCIW
(cherry picked from commit 7d3a18a893c02bd2ed75026f2aac52e20321a1cf)
* Some code cleanup for review
(cherry picked from commit 9e22b7730bba426adcbfd9e7025f192dbf8efb32)
* A tad bit more notes and cleanup
* Update schema, docs
* Most of the PR comments
* I'm not sure this actually works, so I'm committing it to revert it and check
* Update some comments that were lost.
* Fix a build break?
* oh no
2019-11-05 20:40:29 +01:00
|
|
|
}
|
Manually pass mouse wheel messages to TermControls (#5131)
## Summary of the Pull Request
As we've learned in #979, not all touchpads are created equal. Some of them have bad drivers that makes scrolling inactive windows not work. For whatever reason, these devices think the Terminal is all one giant inactive window, so we don't get the mouse wheel events through the XAML stack. We do however get the event as a `WM_MOUSEWHEEL` on those devices (a message we don't get on devices with normally functioning trackpads).
This PR attempts to take that `WM_MOUSEWHEEL` and manually dispatch it to the `TermControl`, so we can at least scroll the terminal content.
Unfortunately, this solution is not very general purpose. This only works to scroll controls that manually implement our own `IMouseWheelListener` interface. As we add more controls, we'll need to continue manually implementing this interface, until the underlying XAML Islands bug is fixed. **I don't love this**. I'd rather have a better solution, but it seems that we can't synthesize a more general-purpose `PointerWheeled` event that could get routed through the XAML tree as normal.
## References
* #2606 and microsoft/microsoft-ui-xaml#2101 - these bugs are also tracking a similar "inactive windows" / "scaled mouse events" issue in XAML
## PR Checklist
* [x] Closes #979
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've also added a `til::point` conversion _to_ `winrt::Windows::Foundation::Point`, and some scaling operators for `point`
## Validation Steps Performed
* It works on my HP Spectre 2017 with a synaptics trackpad
- I also made sure to test that `tmux` works in panes on this laptop
* It works on my slaptop, and DOESN'T follow this hack codepath on this machine.
2020-04-01 18:58:16 +02:00
|
|
|
|
2020-11-18 23:55:10 +01:00
|
|
|
// Method Description
|
|
|
|
// - Called when the app wants to flash the taskbar, indicating to the user that
|
|
|
|
// something needs their attention
|
|
|
|
// Arguments
|
|
|
|
// - <unused>
|
|
|
|
void AppHost::_RaiseVisualBell(const winrt::Windows::Foundation::IInspectable&,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
|
|
|
{
|
|
|
|
_window->FlashTaskbar();
|
|
|
|
}
|
|
|
|
|
Manually pass mouse wheel messages to TermControls (#5131)
## Summary of the Pull Request
As we've learned in #979, not all touchpads are created equal. Some of them have bad drivers that makes scrolling inactive windows not work. For whatever reason, these devices think the Terminal is all one giant inactive window, so we don't get the mouse wheel events through the XAML stack. We do however get the event as a `WM_MOUSEWHEEL` on those devices (a message we don't get on devices with normally functioning trackpads).
This PR attempts to take that `WM_MOUSEWHEEL` and manually dispatch it to the `TermControl`, so we can at least scroll the terminal content.
Unfortunately, this solution is not very general purpose. This only works to scroll controls that manually implement our own `IMouseWheelListener` interface. As we add more controls, we'll need to continue manually implementing this interface, until the underlying XAML Islands bug is fixed. **I don't love this**. I'd rather have a better solution, but it seems that we can't synthesize a more general-purpose `PointerWheeled` event that could get routed through the XAML tree as normal.
## References
* #2606 and microsoft/microsoft-ui-xaml#2101 - these bugs are also tracking a similar "inactive windows" / "scaled mouse events" issue in XAML
## PR Checklist
* [x] Closes #979
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've also added a `til::point` conversion _to_ `winrt::Windows::Foundation::Point`, and some scaling operators for `point`
## Validation Steps Performed
* It works on my HP Spectre 2017 with a synaptics trackpad
- I also made sure to test that `tmux` works in panes on this laptop
* It works on my slaptop, and DOESN'T follow this hack codepath on this machine.
2020-04-01 18:58:16 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Called when the IslandWindow has received a WM_MOUSEWHEEL message. This can
|
|
|
|
// happen on some laptops, where their trackpads won't scroll inactive windows
|
|
|
|
// _ever_.
|
|
|
|
// - We're going to take that message and manually plumb it through to our
|
|
|
|
// TermControl's, or anything else that implements IMouseWheelListener.
|
|
|
|
// - See GH#979 for more details.
|
|
|
|
// Arguments:
|
|
|
|
// - coord: The Window-relative, logical coordinates location of the mouse during this event.
|
|
|
|
// - delta: the wheel delta that triggered this event.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta)
|
|
|
|
{
|
|
|
|
if (_logic)
|
|
|
|
{
|
|
|
|
// Find all the elements that are underneath the mouse
|
|
|
|
auto elems = winrt::Windows::UI::Xaml::Media::VisualTreeHelper::FindElementsInHostCoordinates(coord, _logic.GetRoot());
|
|
|
|
for (const auto& e : elems)
|
|
|
|
{
|
|
|
|
// If that element has implemented IMouseWheelListener, call OnMouseWheel on that element.
|
2021-03-17 21:47:24 +01:00
|
|
|
if (auto control{ e.try_as<winrt::Microsoft::Terminal::Control::IMouseWheelListener>() })
|
Manually pass mouse wheel messages to TermControls (#5131)
## Summary of the Pull Request
As we've learned in #979, not all touchpads are created equal. Some of them have bad drivers that makes scrolling inactive windows not work. For whatever reason, these devices think the Terminal is all one giant inactive window, so we don't get the mouse wheel events through the XAML stack. We do however get the event as a `WM_MOUSEWHEEL` on those devices (a message we don't get on devices with normally functioning trackpads).
This PR attempts to take that `WM_MOUSEWHEEL` and manually dispatch it to the `TermControl`, so we can at least scroll the terminal content.
Unfortunately, this solution is not very general purpose. This only works to scroll controls that manually implement our own `IMouseWheelListener` interface. As we add more controls, we'll need to continue manually implementing this interface, until the underlying XAML Islands bug is fixed. **I don't love this**. I'd rather have a better solution, but it seems that we can't synthesize a more general-purpose `PointerWheeled` event that could get routed through the XAML tree as normal.
## References
* #2606 and microsoft/microsoft-ui-xaml#2101 - these bugs are also tracking a similar "inactive windows" / "scaled mouse events" issue in XAML
## PR Checklist
* [x] Closes #979
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've also added a `til::point` conversion _to_ `winrt::Windows::Foundation::Point`, and some scaling operators for `point`
## Validation Steps Performed
* It works on my HP Spectre 2017 with a synaptics trackpad
- I also made sure to test that `tmux` works in panes on this laptop
* It works on my slaptop, and DOESN'T follow this hack codepath on this machine.
2020-04-01 18:58:16 +02:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Translate the event to the coordinate space of the control
|
|
|
|
// we're attempting to dispatch it to
|
|
|
|
const auto transform = e.TransformToVisual(nullptr);
|
|
|
|
const til::point controlOrigin{ til::math::flooring, transform.TransformPoint(til::point{ 0, 0 }) };
|
|
|
|
|
|
|
|
const til::point offsetPoint = coord - controlOrigin;
|
|
|
|
|
2020-08-08 01:21:09 +02:00
|
|
|
const auto lButtonDown = WI_IsFlagSet(GetKeyState(VK_LBUTTON), KeyPressed);
|
|
|
|
const auto mButtonDown = WI_IsFlagSet(GetKeyState(VK_MBUTTON), KeyPressed);
|
|
|
|
const auto rButtonDown = WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed);
|
|
|
|
|
|
|
|
if (control.OnMouseWheel(offsetPoint, delta, lButtonDown, mButtonDown, rButtonDown))
|
Manually pass mouse wheel messages to TermControls (#5131)
## Summary of the Pull Request
As we've learned in #979, not all touchpads are created equal. Some of them have bad drivers that makes scrolling inactive windows not work. For whatever reason, these devices think the Terminal is all one giant inactive window, so we don't get the mouse wheel events through the XAML stack. We do however get the event as a `WM_MOUSEWHEEL` on those devices (a message we don't get on devices with normally functioning trackpads).
This PR attempts to take that `WM_MOUSEWHEEL` and manually dispatch it to the `TermControl`, so we can at least scroll the terminal content.
Unfortunately, this solution is not very general purpose. This only works to scroll controls that manually implement our own `IMouseWheelListener` interface. As we add more controls, we'll need to continue manually implementing this interface, until the underlying XAML Islands bug is fixed. **I don't love this**. I'd rather have a better solution, but it seems that we can't synthesize a more general-purpose `PointerWheeled` event that could get routed through the XAML tree as normal.
## References
* #2606 and microsoft/microsoft-ui-xaml#2101 - these bugs are also tracking a similar "inactive windows" / "scaled mouse events" issue in XAML
## PR Checklist
* [x] Closes #979
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I've also added a `til::point` conversion _to_ `winrt::Windows::Foundation::Point`, and some scaling operators for `point`
## Validation Steps Performed
* It works on my HP Spectre 2017 with a synaptics trackpad
- I also made sure to test that `tmux` works in panes on this laptop
* It works on my slaptop, and DOESN'T follow this hack codepath on this machine.
2020-04-01 18:58:16 +02:00
|
|
|
{
|
|
|
|
// If the element handled the mouse wheel event, don't
|
|
|
|
// continue to iterate over the remaining controls.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CATCH_LOG();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
|
|
|
|
bool AppHost::HasWindow()
|
|
|
|
{
|
|
|
|
return _shouldCreateWindow;
|
|
|
|
}
|
|
|
|
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Event handler for the Peasant::ExecuteCommandlineRequested event. Take the
|
|
|
|
// provided commandline args, and attempt to parse them and perform the
|
|
|
|
// actions immediately. The parsing is performed by AppLogic.
|
|
|
|
// - This is invoked when another wt.exe instance runs something like `wt -w 1
|
|
|
|
// new-tab`, and the Monarch delegates the commandline to this instance.
|
|
|
|
// Arguments:
|
|
|
|
// - args: the bundle of a commandline and working directory to use for this invocation.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2021-05-27 19:14:12 +02:00
|
|
|
void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable sender,
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
Remoting::CommandlineArgs args)
|
|
|
|
{
|
Add `"monitor": "any"|"toCurrent"|"toMouse"` setting to globalSummon (#10092)
#### ⚠️ this pr targets #9977
## Summary of the Pull Request
This adds support for part of the `monitor` property for `globalSummon`. It also goes a little off-spec:
```json
"monitor": "any"|"toCurrent"|"toMouse"
```
* `monitor`: This controls the monitor that the window will be summoned from/to
- `"any"`: Summon the MRU window, regardless of which monitor it's currently on.
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor with the current **foreground** window.
- [**NEW**] `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse** cursor is.
When I was playing with this, It felt like `toMouse` was always what I wanted, not `toCurrent`. We can always just comment that out if we think that's contentious - I'm aware I didn't originally spec that.
## References
* Original thread: #653
* Spec: #9274
* megathread: #8888
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-60325291
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated 😢
## Detailed Description of the Pull Request / Additional comments
I made `toMouse` the default because it felt better. fite-me.jpg
## Validation Steps Performed
my ever evolving blob:
```jsonc
{ "keys": "ctrl+`", "command": { "action": "quakeMode" } },
{ "keys": "ctrl+1", "command": { "action": "globalSummon" } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "desktop": "toCurrent" } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "toggleVisibility": false } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "dropdownDuration": 2000 } },
{ "keys": "ctrl+2", "command": { "action": "globalSummon", "monitor": "any" } },
// { "keys": "ctrl+3", "command": { "action": "globalSummon", "desktop": "onCurrent" } },
{ "keys": "ctrl+3", "command": { "action": "globalSummon", "monitor": "toMouse" } },
// { "keys": "ctrl+4", "command": { "action": "globalSummon", "desktop": "any" } },
{ "keys": "ctrl+4", "command": { "action": "globalSummon", "monitor": "toMouse", "dropdownDuration": 500 } },
{ "keys": "ctrl+5", "command": { "action": "globalSummon", "dropdownDuration": 500 } },
```
2021-05-17 14:57:08 +02:00
|
|
|
const Remoting::SummonWindowBehavior summonArgs{};
|
|
|
|
summonArgs.MoveToCurrentDesktop(false);
|
|
|
|
summonArgs.DropdownDuration(0);
|
|
|
|
summonArgs.ToMonitor(Remoting::MonitorBehavior::InPlace);
|
2021-06-10 19:22:22 +02:00
|
|
|
summonArgs.ToggleVisibility(false); // Do not toggle, just make visible.
|
2021-04-29 00:13:28 +02:00
|
|
|
// Summon the window whenever we dispatch a commandline to it. This will
|
|
|
|
// make it obvious when a new tab/pane is created in a window.
|
2021-05-27 19:14:12 +02:00
|
|
|
_HandleSummon(sender, summonArgs);
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
_logic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory());
|
|
|
|
}
|
|
|
|
|
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
|
|
|
// Method Description:
|
|
|
|
// - Asynchronously get the window layout from the current page. This is
|
|
|
|
// done async because we need to switch between the ui thread and the calling
|
|
|
|
// thread.
|
|
|
|
// - NB: The peasant calling this must not be running on the UI thread, otherwise
|
|
|
|
// they will crash since they just call .get on the async operation.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - The window layout as a json string.
|
|
|
|
winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> AppHost::_GetWindowLayoutAsync()
|
|
|
|
{
|
|
|
|
winrt::apartment_context peasant_thread;
|
|
|
|
|
2021-10-20 02:12:18 +02:00
|
|
|
winrt::hstring layoutJson = L"";
|
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
|
|
|
// Use the main thread since we are accessing controls.
|
|
|
|
co_await winrt::resume_foreground(_logic.GetRoot().Dispatcher());
|
2021-10-20 02:12:18 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
const auto pos = _GetWindowLaunchPosition();
|
|
|
|
layoutJson = _logic.GetWindowLayoutJson(pos);
|
|
|
|
}
|
|
|
|
CATCH_LOG()
|
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
|
|
|
|
|
|
|
// go back to give the result to the peasant.
|
|
|
|
co_await peasant_thread;
|
|
|
|
|
|
|
|
co_return layoutJson;
|
|
|
|
}
|
|
|
|
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Event handler for the WindowManager::FindTargetWindowRequested event. The
|
|
|
|
// manager will ask us how to figure out what the target window is for a set
|
|
|
|
// of commandline arguments. We'll take those arguments, and ask AppLogic to
|
|
|
|
// parse them for us. We'll then set ResultTargetWindow in the given args, so
|
|
|
|
// the sender can use that result.
|
|
|
|
// Arguments:
|
|
|
|
// - args: the bundle of a commandline and working directory to find the correct target window for.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void AppHost::_FindTargetWindow(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
|
|
|
const Remoting::FindTargetWindowArgs& args)
|
|
|
|
{
|
|
|
|
const auto targetWindow = _logic.FindTargetWindow(args.Args().Commandline());
|
Add support for naming windows with the `-w` parameter (#9300)
This finishes the implementation of `--window` to also accept a string
as the "name" of the window. So you can say
```sh
wt -w foo new-tab
wt -w foo split-pane
```
and have both those commands execute in the same window, the one named
"foo". This is just slightly more ergonomic than manually using the IDs
of windows. In the future, I'll be working on renaming windows, and
displaying these names.
> #### `--window,-w <window-id>`
> Run these commands in the given Windows Terminal session. This enables opening
> new tabs, splits, etc. in already running Windows Terminal windows.
> * If `window-id` is `0`, run the given commands in _the current window_.
> * If `window-id` is a negative number, or the reserved name `new`, run the
> commands in a _new_ Terminal window.
> * If `window-id` is the ID or name of an existing window, then run the
> commandline in that window.
> * If `window-id` is _not_ the ID or name of an existing window, create a new
> window. That window will be assigned the ID or name provided in the
> commandline. The provided subcommands will be run in that new window.
> * If `window-id` is omitted, then obey the value of `windowingBehavior` when
> determining which window to run the command in.
Before this PR, I think we didn't actually properly support assigning
the id with `wt -w 12345`. If `12345` didn't exist, it would make a new
window, but just assign it the next id, not assign it 12345.
## References
* #4472, #8135
* https://github.com/microsoft/terminal/projects/5
## Validation Steps Performed
Ran tests
Messed with naming windows, working as expected.
Closes https://github.com/microsoft/terminal/projects/5#card-51431478
2021-03-17 20:28:01 +01:00
|
|
|
args.ResultTargetWindow(targetWindow.WindowId());
|
|
|
|
args.ResultTargetWindowName(targetWindow.WindowName());
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
winrt::fire_and_forget AppHost::_WindowActivated()
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
{
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
co_await winrt::resume_background();
|
|
|
|
|
|
|
|
if (auto peasant{ _windowManager.CurrentWindow() })
|
|
|
|
{
|
2021-02-19 22:09:17 +01:00
|
|
|
const auto currentDesktopGuid{ _CurrentDesktopGuid() };
|
|
|
|
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
// TODO: projects/5 - in the future, we'll want to actually get the
|
|
|
|
// desktop GUID in IslandWindow, and bubble that up here, then down to
|
|
|
|
// the Peasant. For now, we're just leaving space for it.
|
|
|
|
Remoting::WindowActivatedArgs args{ peasant.GetID(),
|
2021-02-19 22:09:17 +01:00
|
|
|
(uint64_t)_window->GetHandle(),
|
|
|
|
currentDesktopGuid,
|
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request
**If you're reading this PR and haven't signed off on #8135, go there first.**
![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)
This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
* If `window-id` is `0`, run the given commands in _the current window_.
* If `window-id` is a negative number, run the commands in a _new_ Terminal window.
* If `window-id` is the ID of an existing window, then run the commandline in that window.
* If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
* If `window-id` is omitted, then create a new window.
## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5
## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**
## Detailed Description of the Pull Request / Additional comments
Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change
There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.
I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in.
## Validation Steps Performed
I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.
# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬
- [x] `Monarch.cpp`
- [x] `Peasant.cpp`
- [x] `WindowManager.cpp`
- [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
- Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.
- Could we gracefully recover from such a state? maybe, probably not though.
- Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
- After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 12:28:09 +01:00
|
|
|
winrt::clock().now() };
|
|
|
|
peasant.ActivateWindow(args);
|
|
|
|
}
|
Add `Microsoft.Terminal.Remoting.dll` (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135.
This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.
This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".
Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
lib.
There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.
## References
* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)
## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 23:59:37 +01:00
|
|
|
}
|
2021-02-19 22:09:17 +01:00
|
|
|
|
2021-04-29 00:13:28 +02:00
|
|
|
void AppHost::_BecomeMonarch(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
|
|
|
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
|
|
|
{
|
|
|
|
_setupGlobalHotkeys();
|
2021-08-12 21:54:39 +02:00
|
|
|
|
|
|
|
if (_windowManager.DoesQuakeWindowExist() ||
|
|
|
|
_window->IsQuakeWindow() ||
|
2021-09-14 18:12:40 +02:00
|
|
|
(_logic.GetAlwaysShowNotificationIcon() || _logic.GetMinimizeToNotificationArea()))
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_CreateNotificationIcon();
|
2021-08-12 21:54:39 +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
|
|
|
// Set the number of open windows (so we know if we are the last window)
|
|
|
|
// and subscribe for updates if there are any changes to that number.
|
|
|
|
_logic.SetNumberOfOpenWindows(_windowManager.GetNumberOfPeasants());
|
|
|
|
|
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
|
|
|
_windowManager.WindowCreated([this](auto&&, auto&&) {
|
|
|
|
_getWindowLayoutThrottler.value()();
|
|
|
|
_logic.SetNumberOfOpenWindows(_windowManager.GetNumberOfPeasants()); });
|
|
|
|
_windowManager.WindowClosed([this](auto&&, auto&&) {
|
|
|
|
_getWindowLayoutThrottler.value()();
|
|
|
|
_logic.SetNumberOfOpenWindows(_windowManager.GetNumberOfPeasants());
|
|
|
|
});
|
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
|
|
|
|
2021-08-12 21:54:39 +02:00
|
|
|
// These events are coming from peasants that become or un-become quake windows.
|
2021-09-14 18:12:40 +02:00
|
|
|
_windowManager.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequested(); });
|
|
|
|
_windowManager.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequested(); });
|
2021-09-09 16:03:03 +02:00
|
|
|
// If the monarch receives a QuitAll event it will signal this event to be
|
|
|
|
// ran before each peasant is closed.
|
|
|
|
_windowManager.QuitAllRequested({ this, &AppHost::_QuitAllRequested });
|
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
|
|
|
|
|
|
|
// The monarch should be monitoring if it should save the window layout.
|
|
|
|
if (!_getWindowLayoutThrottler.has_value())
|
|
|
|
{
|
|
|
|
// We want at least some delay to prevent the first save from overwriting
|
|
|
|
// the data as we try load windows initially.
|
|
|
|
_getWindowLayoutThrottler.emplace(std::move(std::chrono::seconds(10)), std::move([this]() { _SaveWindowLayoutsRepeat(); }));
|
|
|
|
_getWindowLayoutThrottler.value()();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
winrt::Windows::Foundation::IAsyncAction AppHost::_SaveWindowLayouts()
|
|
|
|
{
|
|
|
|
// Make sure we run on a background thread to not block anything.
|
|
|
|
co_await winrt::resume_background();
|
|
|
|
|
|
|
|
if (_logic.ShouldUsePersistedLayout())
|
|
|
|
{
|
|
|
|
const auto layoutJsons = _windowManager.GetAllWindowLayouts();
|
|
|
|
_logic.SaveWindowLayoutJsons(layoutJsons);
|
|
|
|
}
|
|
|
|
|
|
|
|
co_return;
|
|
|
|
}
|
|
|
|
|
|
|
|
winrt::fire_and_forget AppHost::_SaveWindowLayoutsRepeat()
|
|
|
|
{
|
|
|
|
// Make sure we run on a background thread to not block anything.
|
|
|
|
co_await winrt::resume_background();
|
|
|
|
|
|
|
|
co_await _SaveWindowLayouts();
|
|
|
|
|
|
|
|
// Don't need to save too frequently.
|
|
|
|
co_await 30s;
|
|
|
|
|
|
|
|
// As long as we are supposed to keep saving, request another save.
|
|
|
|
// This will be delayed by the throttler so that at most one save happens
|
|
|
|
// per 10 seconds, if a save is requested by another source simultaneously.
|
|
|
|
if (_getWindowLayoutThrottler.has_value())
|
|
|
|
{
|
|
|
|
_getWindowLayoutThrottler.value()();
|
|
|
|
}
|
2021-05-24 23:56:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppHost::_listenForInboundConnections()
|
|
|
|
{
|
|
|
|
_logic.SetInboundListener();
|
2021-04-29 00:13:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
winrt::fire_and_forget AppHost::_setupGlobalHotkeys()
|
|
|
|
{
|
|
|
|
// The hotkey MUST be registered on the main thread. It will fail otherwise!
|
2021-07-21 00:34:51 +02:00
|
|
|
co_await winrt::resume_foreground(_logic.GetRoot().Dispatcher());
|
2021-04-29 00:13:28 +02:00
|
|
|
|
2021-07-21 00:34:51 +02:00
|
|
|
// Unregister all previously registered hotkeys.
|
|
|
|
//
|
|
|
|
// RegisterHotKey(), will not unregister hotkeys automatically.
|
|
|
|
// If a hotkey with a given HWND and ID combination already exists
|
|
|
|
// then a duplicate one will be added, which we don't want.
|
|
|
|
// (Additionally we want to remove hotkeys that were removed from the settings.)
|
|
|
|
for (int i = 0, count = gsl::narrow_cast<int>(_hotkeys.size()); i < count; ++i)
|
|
|
|
{
|
|
|
|
_window->UnregisterHotKey(i);
|
|
|
|
}
|
2021-04-29 00:13:28 +02:00
|
|
|
|
|
|
|
_hotkeys.clear();
|
2021-07-21 00:34:51 +02:00
|
|
|
|
|
|
|
// Re-register all current hotkeys.
|
|
|
|
for (const auto& [keyChord, cmd] : _logic.GlobalHotkeys())
|
2021-04-29 00:13:28 +02:00
|
|
|
{
|
2021-07-21 00:34:51 +02:00
|
|
|
if (auto summonArgs = cmd.ActionAndArgs().Args().try_as<Settings::Model::GlobalSummonArgs>())
|
2021-04-29 00:13:28 +02:00
|
|
|
{
|
2021-08-11 17:20:15 +02:00
|
|
|
int index = gsl::narrow_cast<int>(_hotkeys.size());
|
|
|
|
const bool succeeded = _window->RegisterHotKey(index, keyChord);
|
|
|
|
|
|
|
|
TraceLoggingWrite(g_hWindowsTerminalProvider,
|
|
|
|
"AppHost_setupGlobalHotkey",
|
|
|
|
TraceLoggingDescription("Emitted when setting a single hotkey"),
|
|
|
|
TraceLoggingInt64(index, "index", "the index of the hotkey to add"),
|
|
|
|
TraceLoggingWideString(cmd.Name().c_str(), "name", "the name of the command"),
|
|
|
|
TraceLoggingBoolean(succeeded, "succeeded", "true if we succeeded"),
|
|
|
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
|
|
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
2021-07-21 00:34:51 +02:00
|
|
|
_hotkeys.emplace_back(summonArgs);
|
2021-04-29 00:13:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called whenever a registered hotkey is pressed. We'll look up the
|
|
|
|
// GlobalSummonArgs for the specified hotkey, then dispatch a call to the
|
|
|
|
// Monarch with the selection information.
|
|
|
|
// - If the monarch finds a match for the window name (or no name was provided),
|
|
|
|
// it'll set FoundMatch=true.
|
|
|
|
// - If FoundMatch is false, and a name was provided, then we should create a
|
|
|
|
// new window with the given name.
|
|
|
|
// Arguments:
|
|
|
|
// - hotkeyIndex: the index of the entry in _hotkeys that was pressed.
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void AppHost::_GlobalHotkeyPressed(const long hotkeyIndex)
|
|
|
|
{
|
|
|
|
if (hotkeyIndex < 0 || static_cast<size_t>(hotkeyIndex) > _hotkeys.size())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-21 00:34:51 +02:00
|
|
|
const auto& summonArgs = til::at(_hotkeys, hotkeyIndex);
|
|
|
|
Remoting::SummonWindowSelectionArgs args{ summonArgs.Name() };
|
2021-04-29 00:25:48 +02:00
|
|
|
|
2021-07-21 00:34:51 +02:00
|
|
|
// desktop:any - MoveToCurrentDesktop=false, OnCurrentDesktop=false
|
|
|
|
// desktop:toCurrent - MoveToCurrentDesktop=true, OnCurrentDesktop=false
|
|
|
|
// desktop:onCurrent - MoveToCurrentDesktop=false, OnCurrentDesktop=true
|
|
|
|
args.OnCurrentDesktop(summonArgs.Desktop() == Settings::Model::DesktopBehavior::OnCurrent);
|
|
|
|
args.SummonBehavior().MoveToCurrentDesktop(summonArgs.Desktop() == Settings::Model::DesktopBehavior::ToCurrent);
|
|
|
|
args.SummonBehavior().ToggleVisibility(summonArgs.ToggleVisibility());
|
|
|
|
args.SummonBehavior().DropdownDuration(summonArgs.DropdownDuration());
|
Add `"monitor": "any"|"toCurrent"|"toMouse"` setting to globalSummon (#10092)
#### ⚠️ this pr targets #9977
## Summary of the Pull Request
This adds support for part of the `monitor` property for `globalSummon`. It also goes a little off-spec:
```json
"monitor": "any"|"toCurrent"|"toMouse"
```
* `monitor`: This controls the monitor that the window will be summoned from/to
- `"any"`: Summon the MRU window, regardless of which monitor it's currently on.
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor with the current **foreground** window.
- [**NEW**] `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse** cursor is.
When I was playing with this, It felt like `toMouse` was always what I wanted, not `toCurrent`. We can always just comment that out if we think that's contentious - I'm aware I didn't originally spec that.
## References
* Original thread: #653
* Spec: #9274
* megathread: #8888
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-60325291
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated 😢
## Detailed Description of the Pull Request / Additional comments
I made `toMouse` the default because it felt better. fite-me.jpg
## Validation Steps Performed
my ever evolving blob:
```jsonc
{ "keys": "ctrl+`", "command": { "action": "quakeMode" } },
{ "keys": "ctrl+1", "command": { "action": "globalSummon" } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "desktop": "toCurrent" } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "toggleVisibility": false } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "dropdownDuration": 2000 } },
{ "keys": "ctrl+2", "command": { "action": "globalSummon", "monitor": "any" } },
// { "keys": "ctrl+3", "command": { "action": "globalSummon", "desktop": "onCurrent" } },
{ "keys": "ctrl+3", "command": { "action": "globalSummon", "monitor": "toMouse" } },
// { "keys": "ctrl+4", "command": { "action": "globalSummon", "desktop": "any" } },
{ "keys": "ctrl+4", "command": { "action": "globalSummon", "monitor": "toMouse", "dropdownDuration": 500 } },
{ "keys": "ctrl+5", "command": { "action": "globalSummon", "dropdownDuration": 500 } },
```
2021-05-17 14:57:08 +02:00
|
|
|
|
2021-07-21 00:34:51 +02:00
|
|
|
switch (summonArgs.Monitor())
|
|
|
|
{
|
|
|
|
case Settings::Model::MonitorBehavior::Any:
|
|
|
|
args.SummonBehavior().ToMonitor(Remoting::MonitorBehavior::InPlace);
|
|
|
|
break;
|
|
|
|
case Settings::Model::MonitorBehavior::ToCurrent:
|
|
|
|
args.SummonBehavior().ToMonitor(Remoting::MonitorBehavior::ToCurrent);
|
|
|
|
break;
|
|
|
|
case Settings::Model::MonitorBehavior::ToMouse:
|
|
|
|
args.SummonBehavior().ToMonitor(Remoting::MonitorBehavior::ToMouse);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_windowManager.SummonWindow(args);
|
|
|
|
if (args.FoundMatch())
|
|
|
|
{
|
|
|
|
// Excellent, the window was found. We have nothing else to do here.
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// We should make the window ourselves.
|
|
|
|
_createNewTerminalWindow(summonArgs);
|
2021-04-29 00:13:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when the monarch failed to summon a window for a given set of
|
|
|
|
// SummonWindowSelectionArgs. In this case, we should create the specified
|
|
|
|
// window ourselves.
|
|
|
|
// - This is to support the scenario like `globalSummon(Name="_quake")` being
|
|
|
|
// used to summon the window if it already exists, or create it if it doesn't.
|
|
|
|
// Arguments:
|
|
|
|
// - args: Contains information on how we should name the window
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
winrt::fire_and_forget AppHost::_createNewTerminalWindow(Settings::Model::GlobalSummonArgs args)
|
|
|
|
{
|
|
|
|
// Hop to the BG thread
|
|
|
|
co_await winrt::resume_background();
|
|
|
|
|
|
|
|
// This will get us the correct exe for dev/preview/release. If you
|
|
|
|
// don't stick this in a local, it'll get mangled by ShellExecute. I
|
|
|
|
// have no idea why.
|
|
|
|
const auto exePath{ GetWtExePath() };
|
|
|
|
|
|
|
|
// If we weren't given a name, then just use new to force the window to be
|
|
|
|
// unnamed.
|
|
|
|
winrt::hstring cmdline{
|
|
|
|
fmt::format(L"-w {}",
|
|
|
|
args.Name().empty() ? L"new" :
|
|
|
|
args.Name())
|
|
|
|
};
|
|
|
|
|
|
|
|
SHELLEXECUTEINFOW seInfo{ 0 };
|
|
|
|
seInfo.cbSize = sizeof(seInfo);
|
|
|
|
seInfo.fMask = SEE_MASK_NOASYNC;
|
|
|
|
seInfo.lpVerb = L"open";
|
|
|
|
seInfo.lpFile = exePath.c_str();
|
|
|
|
seInfo.lpParameters = cmdline.c_str();
|
|
|
|
seInfo.nShow = SW_SHOWNORMAL;
|
|
|
|
LOG_IF_WIN32_BOOL_FALSE(ShellExecuteExW(&seInfo));
|
|
|
|
|
|
|
|
co_return;
|
|
|
|
}
|
|
|
|
|
2021-04-29 00:25:48 +02:00
|
|
|
// Method Description:
|
|
|
|
// - Helper to initialize our instance of IVirtualDesktopManager. If we already
|
|
|
|
// got one, then this will just return true. Otherwise, we'll try and init a
|
|
|
|
// new instance of one, and store that.
|
|
|
|
// - This will return false if we weren't able to initialize one, which I'm not
|
|
|
|
// sure is actually possible.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - true iff _desktopManager points to a non-null instance of IVirtualDesktopManager
|
|
|
|
bool AppHost::_LazyLoadDesktopManager()
|
|
|
|
{
|
|
|
|
if (_desktopManager == nullptr)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
_desktopManager = winrt::create_instance<IVirtualDesktopManager>(__uuidof(VirtualDesktopManager));
|
|
|
|
}
|
|
|
|
CATCH_LOG();
|
|
|
|
}
|
|
|
|
|
|
|
|
return _desktopManager != nullptr;
|
|
|
|
}
|
|
|
|
|
2021-04-29 00:13:28 +02:00
|
|
|
void AppHost::_HandleSummon(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
2021-04-29 00:25:48 +02:00
|
|
|
const Remoting::SummonWindowBehavior& args)
|
2021-04-29 00:13:28 +02:00
|
|
|
{
|
Add `"monitor": "any"|"toCurrent"|"toMouse"` setting to globalSummon (#10092)
#### ⚠️ this pr targets #9977
## Summary of the Pull Request
This adds support for part of the `monitor` property for `globalSummon`. It also goes a little off-spec:
```json
"monitor": "any"|"toCurrent"|"toMouse"
```
* `monitor`: This controls the monitor that the window will be summoned from/to
- `"any"`: Summon the MRU window, regardless of which monitor it's currently on.
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor with the current **foreground** window.
- [**NEW**] `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse** cursor is.
When I was playing with this, It felt like `toMouse` was always what I wanted, not `toCurrent`. We can always just comment that out if we think that's contentious - I'm aware I didn't originally spec that.
## References
* Original thread: #653
* Spec: #9274
* megathread: #8888
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-60325291
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated 😢
## Detailed Description of the Pull Request / Additional comments
I made `toMouse` the default because it felt better. fite-me.jpg
## Validation Steps Performed
my ever evolving blob:
```jsonc
{ "keys": "ctrl+`", "command": { "action": "quakeMode" } },
{ "keys": "ctrl+1", "command": { "action": "globalSummon" } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "desktop": "toCurrent" } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "toggleVisibility": false } },
// { "keys": "ctrl+2", "command": { "action": "globalSummon", "dropdownDuration": 2000 } },
{ "keys": "ctrl+2", "command": { "action": "globalSummon", "monitor": "any" } },
// { "keys": "ctrl+3", "command": { "action": "globalSummon", "desktop": "onCurrent" } },
{ "keys": "ctrl+3", "command": { "action": "globalSummon", "monitor": "toMouse" } },
// { "keys": "ctrl+4", "command": { "action": "globalSummon", "desktop": "any" } },
{ "keys": "ctrl+4", "command": { "action": "globalSummon", "monitor": "toMouse", "dropdownDuration": 500 } },
{ "keys": "ctrl+5", "command": { "action": "globalSummon", "dropdownDuration": 500 } },
```
2021-05-17 14:57:08 +02:00
|
|
|
_window->SummonWindow(args);
|
2021-04-29 00:25:48 +02:00
|
|
|
|
|
|
|
if (args != nullptr && args.MoveToCurrentDesktop())
|
|
|
|
{
|
|
|
|
if (_LazyLoadDesktopManager())
|
|
|
|
{
|
2021-05-04 23:20:01 +02:00
|
|
|
// First thing - make sure that we're not on the current desktop. If
|
|
|
|
// we are, then don't call MoveWindowToDesktop. This is to mitigate
|
|
|
|
// MSFT:33035972
|
|
|
|
BOOL onCurrentDesktop{ false };
|
|
|
|
if (SUCCEEDED(_desktopManager->IsWindowOnCurrentVirtualDesktop(_window->GetHandle(), &onCurrentDesktop)) && onCurrentDesktop)
|
2021-04-29 00:25:48 +02:00
|
|
|
{
|
2021-05-04 23:20:01 +02:00
|
|
|
// If we succeeded, and the window was on the current desktop, then do nothing.
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Here, we either failed to check if the window is on the
|
|
|
|
// current desktop, or it wasn't on that desktop. In both those
|
|
|
|
// cases, just move the window.
|
|
|
|
|
|
|
|
GUID currentlyActiveDesktop{ 0 };
|
|
|
|
if (VirtualDesktopUtils::GetCurrentVirtualDesktopId(¤tlyActiveDesktop))
|
|
|
|
{
|
|
|
|
LOG_IF_FAILED(_desktopManager->MoveWindowToDesktop(_window->GetHandle(), currentlyActiveDesktop));
|
|
|
|
}
|
|
|
|
// If GetCurrentVirtualDesktopId failed, then just leave the window
|
|
|
|
// where it is. Nothing else to be done :/
|
2021-04-29 00:25:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-29 00:13:28 +02:00
|
|
|
}
|
|
|
|
|
2021-04-29 00:25:48 +02:00
|
|
|
// Method Description:
|
|
|
|
// - This gets the GUID of the desktop our window is currently on. It does NOT
|
|
|
|
// get the GUID of the desktop that's currently active.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - the GUID of the desktop our window is currently on
|
2021-02-19 22:09:17 +01:00
|
|
|
GUID AppHost::_CurrentDesktopGuid()
|
|
|
|
{
|
|
|
|
GUID currentDesktopGuid{ 0 };
|
2021-04-29 00:25:48 +02:00
|
|
|
if (_LazyLoadDesktopManager())
|
2021-02-19 22:09:17 +01:00
|
|
|
{
|
2021-04-29 00:25:48 +02:00
|
|
|
LOG_IF_FAILED(_desktopManager->GetWindowDesktopId(_window->GetHandle(), ¤tDesktopGuid));
|
2021-02-19 22:09:17 +01:00
|
|
|
}
|
|
|
|
return currentDesktopGuid;
|
|
|
|
}
|
2021-03-30 18:08:03 +02:00
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when this window wants _all_ windows to display their
|
|
|
|
// identification. We'll hop to the BG thread, and raise an event (eventually
|
|
|
|
// handled by the monarch) to bubble this request to all the Terminal windows.
|
|
|
|
// Arguments:
|
|
|
|
// - <unused>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
Add support for renaming windows (#9662)
## Summary of the Pull Request
This PR adds support for renaming windows.
![window-renaming-000](https://user-images.githubusercontent.com/18356694/113034344-9a30be00-9157-11eb-9443-975f3c294f56.gif)
![window-renaming-001](https://user-images.githubusercontent.com/18356694/113034452-b5033280-9157-11eb-9e35-e5ac80fef0bc.gif)
It does so through two new actions:
* `renameWindow` takes a `name` parameter, and attempts to set the window's name
to the provided name. This is useful if you always want to hit <kbd>F3</kbd>
and rename a window to "foo" (READ: probably not that useful)
* `openWindowRenamer` is more interesting: it opens a `TeachingTip` with a
`TextBox`. When the user hits Ok, it'll request a rename for the provided
value. This lets the user pick a new name for the window at runtime.
In both cases, if there's already a window with that name, then the monarch will
reject the rename, and pop a `Toast` in the window informing the user that the
rename failed. Nifty!
## References
* Builds on the toasts from #9523
* #5000 - process model megathread
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50771747
* [x] I work here
* [x] Tests addded (and pass with the help of #9660)
* [ ] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I'm sending this PR while finishing up the tests. I figured I'll have time to sneak them in before I get the necessary reviews.
> PAIN: We can't immediately focus the textbox in the TeachingTip. It's
> not technically focusable until it is opened. However, it doesn't
> provide an even tto tell us when it is opened. That's tracked in
> microsoft/microsoft-ui-xaml#1607. So for now, the user _needs_ to
> click on the text box manually.
> We're also not using a ContentDialog for this, because in Xaml
> Islands a text box in a ContentDialog won't recieve _any_ keypresses.
> Fun!
## Validation Steps Performed
I've been playing with
```json
{ "keys": "f1", "command": "identifyWindow" },
{ "keys": "f2", "command": "identifyWindows" },
{ "keys": "f3", "command": "openWindowRenamer" },
{ "keys": "f4", "command": { "action": "renameWindow", "name": "foo" } },
{ "keys": "f5", "command": { "action": "renameWindow", "name": "bar" } },
```
and they seem to work as expected
2021-04-02 18:00:04 +02:00
|
|
|
winrt::fire_and_forget AppHost::_IdentifyWindowsRequested(const winrt::Windows::Foundation::IInspectable /*sender*/,
|
|
|
|
const winrt::Windows::Foundation::IInspectable /*args*/)
|
2021-03-30 18:08:03 +02:00
|
|
|
{
|
|
|
|
// We'll be raising an event that may result in a RPC call to the monarch -
|
|
|
|
// make sure we're on the background thread, or this will silently fail
|
|
|
|
co_await winrt::resume_background();
|
|
|
|
|
|
|
|
if (auto peasant{ _windowManager.CurrentWindow() })
|
|
|
|
{
|
|
|
|
peasant.RequestIdentifyWindows();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Called when the monarch wants us to display our window ID. We'll call down
|
|
|
|
// to the app layer to display the toast.
|
|
|
|
// Arguments:
|
|
|
|
// - <unused>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void AppHost::_DisplayWindowId(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
|
|
|
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
|
|
|
{
|
|
|
|
_logic.IdentifyWindow();
|
|
|
|
}
|
Add support for renaming windows (#9662)
## Summary of the Pull Request
This PR adds support for renaming windows.
![window-renaming-000](https://user-images.githubusercontent.com/18356694/113034344-9a30be00-9157-11eb-9443-975f3c294f56.gif)
![window-renaming-001](https://user-images.githubusercontent.com/18356694/113034452-b5033280-9157-11eb-9e35-e5ac80fef0bc.gif)
It does so through two new actions:
* `renameWindow` takes a `name` parameter, and attempts to set the window's name
to the provided name. This is useful if you always want to hit <kbd>F3</kbd>
and rename a window to "foo" (READ: probably not that useful)
* `openWindowRenamer` is more interesting: it opens a `TeachingTip` with a
`TextBox`. When the user hits Ok, it'll request a rename for the provided
value. This lets the user pick a new name for the window at runtime.
In both cases, if there's already a window with that name, then the monarch will
reject the rename, and pop a `Toast` in the window informing the user that the
rename failed. Nifty!
## References
* Builds on the toasts from #9523
* #5000 - process model megathread
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50771747
* [x] I work here
* [x] Tests addded (and pass with the help of #9660)
* [ ] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
I'm sending this PR while finishing up the tests. I figured I'll have time to sneak them in before I get the necessary reviews.
> PAIN: We can't immediately focus the textbox in the TeachingTip. It's
> not technically focusable until it is opened. However, it doesn't
> provide an even tto tell us when it is opened. That's tracked in
> microsoft/microsoft-ui-xaml#1607. So for now, the user _needs_ to
> click on the text box manually.
> We're also not using a ContentDialog for this, because in Xaml
> Islands a text box in a ContentDialog won't recieve _any_ keypresses.
> Fun!
## Validation Steps Performed
I've been playing with
```json
{ "keys": "f1", "command": "identifyWindow" },
{ "keys": "f2", "command": "identifyWindows" },
{ "keys": "f3", "command": "openWindowRenamer" },
{ "keys": "f4", "command": { "action": "renameWindow", "name": "foo" } },
{ "keys": "f5", "command": { "action": "renameWindow", "name": "bar" } },
```
and they seem to work as expected
2021-04-02 18:00:04 +02:00
|
|
|
|
|
|
|
winrt::fire_and_forget AppHost::_RenameWindowRequested(const winrt::Windows::Foundation::IInspectable /*sender*/,
|
|
|
|
const winrt::TerminalApp::RenameWindowRequestedArgs args)
|
|
|
|
{
|
|
|
|
// Capture calling context.
|
|
|
|
winrt::apartment_context ui_thread;
|
|
|
|
|
|
|
|
// Switch to the BG thread - anything x-proc must happen on a BG thread
|
|
|
|
co_await winrt::resume_background();
|
|
|
|
|
|
|
|
if (auto peasant{ _windowManager.CurrentWindow() })
|
|
|
|
{
|
|
|
|
Remoting::RenameRequestArgs requestArgs{ args.ProposedName() };
|
|
|
|
|
|
|
|
peasant.RequestRename(requestArgs);
|
|
|
|
|
|
|
|
// Switch back to the UI thread. Setting the WindowName needs to happen
|
|
|
|
// on the UI thread, because it'll raise a PropertyChanged event
|
|
|
|
co_await ui_thread;
|
|
|
|
|
|
|
|
if (requestArgs.Succeeded())
|
|
|
|
{
|
|
|
|
_logic.WindowName(args.ProposedName());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_logic.RenameFailed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-26 21:36:23 +02:00
|
|
|
|
2021-04-29 00:13:28 +02:00
|
|
|
void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
|
|
|
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
|
|
|
{
|
|
|
|
_setupGlobalHotkeys();
|
2021-08-12 21:54:39 +02:00
|
|
|
|
2021-09-14 18:12:40 +02:00
|
|
|
// If we're monarch, we need to check some conditions to show the notification icon.
|
|
|
|
// If there's a Quake window somewhere, we'll want to keep the notification icon.
|
|
|
|
// There's two settings - MinimizeToNotificationArea and AlwaysShowNotificationIcon. If either
|
|
|
|
// one of them are true, we want to make sure there's a notification icon.
|
|
|
|
// If both are false, we want to remove our icon from the notification area.
|
|
|
|
// When we remove our icon from the notification area, we'll also want to re-summon
|
2021-08-12 21:54:39 +02:00
|
|
|
// any hidden windows, but right now we're not keeping track of who's hidden,
|
|
|
|
// so just summon them all. Tracking the work to do a "summon all minimized" in
|
|
|
|
// GH#10448
|
|
|
|
if (_windowManager.IsMonarch())
|
|
|
|
{
|
|
|
|
if (!_windowManager.DoesQuakeWindowExist())
|
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
if (!_notificationIcon && (_logic.GetMinimizeToNotificationArea() || _logic.GetAlwaysShowNotificationIcon()))
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_CreateNotificationIcon();
|
2021-08-12 21:54:39 +02:00
|
|
|
}
|
2021-09-14 18:12:40 +02:00
|
|
|
else if (_notificationIcon && !_logic.GetMinimizeToNotificationArea() && !_logic.GetAlwaysShowNotificationIcon())
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
|
|
|
_windowManager.SummonAllWindows();
|
2021-09-14 18:12:40 +02:00
|
|
|
_DestroyNotificationIcon();
|
2021-08-12 21:54:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-14 18:12:40 +02:00
|
|
|
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
|
2021-04-29 00:13:28 +02:00
|
|
|
}
|
|
|
|
|
2021-04-26 21:36:23 +02:00
|
|
|
void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable&,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
// We want the quake window to be accessible through the notification icon.
|
|
|
|
// This means if there's a quake window _somewhere_, we want the notification icon
|
|
|
|
// to show regardless of the notification icon settings.
|
|
|
|
// This also means we'll need to destroy the notification icon if it was created
|
2021-08-12 21:54:39 +02:00
|
|
|
// specifically for the quake window. If not, it should not be destroyed.
|
|
|
|
if (!_window->IsQuakeWindow() && _logic.IsQuakeWindow())
|
2021-07-08 17:25:43 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_ShowNotificationIconRequested();
|
2021-07-08 17:25:43 +02:00
|
|
|
}
|
2021-08-12 21:54:39 +02:00
|
|
|
else if (_window->IsQuakeWindow() && !_logic.IsQuakeWindow())
|
2021-07-08 17:25:43 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_HideNotificationIconRequested();
|
2021-07-08 17:25:43 +02:00
|
|
|
}
|
|
|
|
|
2021-04-26 21:36:23 +02:00
|
|
|
_window->IsQuakeWindow(_logic.IsQuakeWindow());
|
|
|
|
}
|
2021-05-27 19:14:12 +02:00
|
|
|
|
2021-09-09 16:03:03 +02:00
|
|
|
winrt::fire_and_forget AppHost::_QuitRequested(const winrt::Windows::Foundation::IInspectable&,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
|
|
|
{
|
|
|
|
// Need to be on the main thread to close out all of the tabs.
|
|
|
|
co_await winrt::resume_foreground(_logic.GetRoot().Dispatcher());
|
|
|
|
|
|
|
|
_logic.Quit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppHost::_RequestQuitAll(const winrt::Windows::Foundation::IInspectable&,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
|
|
|
{
|
|
|
|
_windowManager.RequestQuitAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppHost::_QuitAllRequested(const winrt::Windows::Foundation::IInspectable&,
|
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
|
|
|
const winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs& args)
|
2021-09-09 16:03:03 +02:00
|
|
|
{
|
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
|
|
|
// Make sure that the current timer is destroyed so that it doesn't attempt
|
|
|
|
// to run while we are in the middle of quitting.
|
|
|
|
if (_getWindowLayoutThrottler.has_value())
|
|
|
|
{
|
|
|
|
_getWindowLayoutThrottler.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tell the monarch to wait for the window layouts to save before
|
|
|
|
// everyone quits.
|
|
|
|
args.BeforeQuitAllAction(_SaveWindowLayouts());
|
2021-09-09 16:03:03 +02:00
|
|
|
}
|
|
|
|
|
2021-05-27 19:14:12 +02:00
|
|
|
void AppHost::_SummonWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
|
|
|
{
|
|
|
|
const Remoting::SummonWindowBehavior summonArgs{};
|
|
|
|
summonArgs.MoveToCurrentDesktop(false);
|
|
|
|
summonArgs.DropdownDuration(0);
|
|
|
|
summonArgs.ToMonitor(Remoting::MonitorBehavior::InPlace);
|
2021-06-10 08:42:11 +02:00
|
|
|
summonArgs.ToggleVisibility(false); // Do not toggle, just make visible.
|
2021-05-27 19:14:12 +02:00
|
|
|
_HandleSummon(sender, summonArgs);
|
|
|
|
}
|
2021-07-08 17:25:43 +02:00
|
|
|
|
2021-09-10 20:25:43 +02:00
|
|
|
void AppHost::_OpenSystemMenu(const winrt::Windows::Foundation::IInspectable&,
|
|
|
|
const winrt::Windows::Foundation::IInspectable&)
|
|
|
|
{
|
|
|
|
_window->OpenSystemMenu(std::nullopt, std::nullopt);
|
|
|
|
}
|
|
|
|
|
2021-08-12 21:54:39 +02:00
|
|
|
// Method Description:
|
2021-09-14 18:12:40 +02:00
|
|
|
// - Creates a Notification Icon and hooks up its handlers
|
2021-08-12 21:54:39 +02:00
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2021-09-14 18:12:40 +02:00
|
|
|
void AppHost::_CreateNotificationIcon()
|
2021-07-08 17:25:43 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
if constexpr (Feature_NotificationIcon::IsEnabled())
|
2021-07-08 17:25:43 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_notificationIcon = std::make_unique<NotificationIcon>(_window->GetHandle());
|
2021-08-12 21:54:39 +02:00
|
|
|
|
|
|
|
// Hookup the handlers, save the tokens for revoking if settings change.
|
2021-09-14 18:12:40 +02:00
|
|
|
_ReAddNotificationIconToken = _window->NotifyReAddNotificationIcon([this]() { _notificationIcon->ReAddNotificationIcon(); });
|
|
|
|
_NotificationIconPressedToken = _window->NotifyNotificationIconPressed([this]() { _notificationIcon->NotificationIconPressed(); });
|
|
|
|
_ShowNotificationIconContextMenuToken = _window->NotifyShowNotificationIconContextMenu([this](til::point coord) { _notificationIcon->ShowContextMenu(coord, _windowManager.GetPeasantInfos()); });
|
|
|
|
_NotificationIconMenuItemSelectedToken = _window->NotifyNotificationIconMenuItemSelected([this](HMENU hm, UINT idx) { _notificationIcon->MenuItemSelected(hm, idx); });
|
|
|
|
_notificationIcon->SummonWindowRequested([this](auto& args) { _windowManager.SummonWindow(args); });
|
2021-07-08 17:25:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2021-09-14 18:12:40 +02:00
|
|
|
// - Deletes our notification icon if we have one.
|
2021-07-08 17:25:43 +02:00
|
|
|
// Arguments:
|
2021-08-12 21:54:39 +02:00
|
|
|
// - <none>
|
2021-07-08 17:25:43 +02:00
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
2021-09-14 18:12:40 +02:00
|
|
|
void AppHost::_DestroyNotificationIcon()
|
2021-07-08 17:25:43 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
if constexpr (Feature_NotificationIcon::IsEnabled())
|
2021-07-08 17:25:43 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_window->NotifyReAddNotificationIcon(_ReAddNotificationIconToken);
|
|
|
|
_window->NotifyNotificationIconPressed(_NotificationIconPressedToken);
|
|
|
|
_window->NotifyShowNotificationIconContextMenu(_ShowNotificationIconContextMenuToken);
|
|
|
|
_window->NotifyNotificationIconMenuItemSelected(_NotificationIconMenuItemSelectedToken);
|
2021-07-08 17:25:43 +02:00
|
|
|
|
2021-09-14 18:12:40 +02:00
|
|
|
_notificationIcon->RemoveIconFromNotificationArea();
|
|
|
|
_notificationIcon = nullptr;
|
2021-08-12 21:54:39 +02:00
|
|
|
}
|
|
|
|
}
|
2021-07-08 17:25:43 +02:00
|
|
|
|
2021-09-14 18:12:40 +02:00
|
|
|
void AppHost::_ShowNotificationIconRequested()
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
if constexpr (Feature_NotificationIcon::IsEnabled())
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
|
|
|
if (_windowManager.IsMonarch())
|
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
if (!_notificationIcon)
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_CreateNotificationIcon();
|
2021-08-12 21:54:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_windowManager.RequestShowNotificationIcon();
|
2021-08-12 21:54:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-07-08 17:25:43 +02:00
|
|
|
|
2021-09-14 18:12:40 +02:00
|
|
|
void AppHost::_HideNotificationIconRequested()
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
if constexpr (Feature_NotificationIcon::IsEnabled())
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
|
|
|
if (_windowManager.IsMonarch())
|
|
|
|
{
|
|
|
|
// Destroy it only if our settings allow it
|
2021-09-14 18:12:40 +02:00
|
|
|
if (_notificationIcon &&
|
|
|
|
!_logic.GetAlwaysShowNotificationIcon() &&
|
|
|
|
!_logic.GetMinimizeToNotificationArea())
|
2021-08-12 21:54:39 +02:00
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_DestroyNotificationIcon();
|
2021-08-12 21:54:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-14 18:12:40 +02:00
|
|
|
_windowManager.RequestHideNotificationIcon();
|
2021-08-12 21:54:39 +02:00
|
|
|
}
|
2021-07-08 17:25:43 +02:00
|
|
|
}
|
|
|
|
}
|
Manually dismiss popups when the window moves, or the SUI scrolls (#10922)
## Summary of the Pull Request
BODGY!
This solution was suggested in https://github.com/microsoft/microsoft-ui-xaml/issues/4554#issuecomment-887815332.
When the window moves, or when a ScrollViewer scrolls, dismiss any popups that are visible. This happens automagically when an app is a real XAML app, but it doesn't work for XAML Islands.
## References
* upstream at https://github.com/microsoft/microsoft-ui-xaml/issues/4554
## PR Checklist
* [x] Closes #9320
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Unfortunately, we've got a bunch of scroll viewers in our SUI. So I did something bodgyx2 to make our life a little easier.
`DismissAllPopups` can be used to dismiss all popups for a particular UI element. However, we've got a bunch of pages with scroll viewers that may or may not have popups in them. Rather than define the same exact body for all their `ViewChanging` events, the `HasScrollViewer` struct will just do it for you!
Inside the `HasScrollViewer` stuct, we can't get at the `XamlRoot()` that our subclass implements. I mean, _we_ can, but when XAML does it's codegen, _XAML_ won't be able to figure it out.
Fortunately for us, we don't need to! The sender is a UIElement, so we can just get _their_ `XamlRoot()`.
So, you can fix this for any SUI page with just a simple
```diff
- <ScrollViewer>
+ <ScrollViewer ViewChanging="ViewChanging">
```
```diff
- struct AddProfile : AddProfileT<AddProfile>
+ struct AddProfile : public HasScrollViewer<AddProfile>, AddProfileT<AddProfile>
```
## Validation Steps Performed
* the window doesn't close when you move it
* the popups _do_ close when you move the window
* the popups close when you scroll any SUI page
2021-08-16 15:41:17 +02:00
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - BODGY workaround for GH#9320. When the window moves, dismiss all the popups
|
|
|
|
// in the UI tree. Xaml Islands unfortunately doesn't do this for us, see
|
|
|
|
// microsoft/microsoft-ui-xaml#4554
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void AppHost::_WindowMoved()
|
|
|
|
{
|
|
|
|
if (_logic)
|
|
|
|
{
|
2021-10-12 20:00:06 +02:00
|
|
|
// Ensure any open ContentDialog is dismissed.
|
|
|
|
// Closing the popup in the UI tree as done below is not sufficient because
|
|
|
|
// it does not terminate the dialog's async operation.
|
|
|
|
_logic.DismissDialog();
|
|
|
|
|
Manually dismiss popups when the window moves, or the SUI scrolls (#10922)
## Summary of the Pull Request
BODGY!
This solution was suggested in https://github.com/microsoft/microsoft-ui-xaml/issues/4554#issuecomment-887815332.
When the window moves, or when a ScrollViewer scrolls, dismiss any popups that are visible. This happens automagically when an app is a real XAML app, but it doesn't work for XAML Islands.
## References
* upstream at https://github.com/microsoft/microsoft-ui-xaml/issues/4554
## PR Checklist
* [x] Closes #9320
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Unfortunately, we've got a bunch of scroll viewers in our SUI. So I did something bodgyx2 to make our life a little easier.
`DismissAllPopups` can be used to dismiss all popups for a particular UI element. However, we've got a bunch of pages with scroll viewers that may or may not have popups in them. Rather than define the same exact body for all their `ViewChanging` events, the `HasScrollViewer` struct will just do it for you!
Inside the `HasScrollViewer` stuct, we can't get at the `XamlRoot()` that our subclass implements. I mean, _we_ can, but when XAML does it's codegen, _XAML_ won't be able to figure it out.
Fortunately for us, we don't need to! The sender is a UIElement, so we can just get _their_ `XamlRoot()`.
So, you can fix this for any SUI page with just a simple
```diff
- <ScrollViewer>
+ <ScrollViewer ViewChanging="ViewChanging">
```
```diff
- struct AddProfile : AddProfileT<AddProfile>
+ struct AddProfile : public HasScrollViewer<AddProfile>, AddProfileT<AddProfile>
```
## Validation Steps Performed
* the window doesn't close when you move it
* the popups _do_ close when you move the window
* the popups close when you scroll any SUI page
2021-08-16 15:41:17 +02:00
|
|
|
const auto root{ _logic.GetRoot() };
|
|
|
|
|
2021-10-19 22:29:18 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// This is basically DismissAllPopups which is also in
|
|
|
|
// TerminalSettingsEditor/Utils.h
|
|
|
|
// There isn't a good place that's shared between these two files, but
|
|
|
|
// it's only 5 LOC so whatever.
|
|
|
|
const auto popups{ Media::VisualTreeHelper::GetOpenPopupsForXamlRoot(root.XamlRoot()) };
|
|
|
|
for (const auto& p : popups)
|
|
|
|
{
|
|
|
|
p.IsOpen(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (...)
|
Manually dismiss popups when the window moves, or the SUI scrolls (#10922)
## Summary of the Pull Request
BODGY!
This solution was suggested in https://github.com/microsoft/microsoft-ui-xaml/issues/4554#issuecomment-887815332.
When the window moves, or when a ScrollViewer scrolls, dismiss any popups that are visible. This happens automagically when an app is a real XAML app, but it doesn't work for XAML Islands.
## References
* upstream at https://github.com/microsoft/microsoft-ui-xaml/issues/4554
## PR Checklist
* [x] Closes #9320
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Unfortunately, we've got a bunch of scroll viewers in our SUI. So I did something bodgyx2 to make our life a little easier.
`DismissAllPopups` can be used to dismiss all popups for a particular UI element. However, we've got a bunch of pages with scroll viewers that may or may not have popups in them. Rather than define the same exact body for all their `ViewChanging` events, the `HasScrollViewer` struct will just do it for you!
Inside the `HasScrollViewer` stuct, we can't get at the `XamlRoot()` that our subclass implements. I mean, _we_ can, but when XAML does it's codegen, _XAML_ won't be able to figure it out.
Fortunately for us, we don't need to! The sender is a UIElement, so we can just get _their_ `XamlRoot()`.
So, you can fix this for any SUI page with just a simple
```diff
- <ScrollViewer>
+ <ScrollViewer ViewChanging="ViewChanging">
```
```diff
- struct AddProfile : AddProfileT<AddProfile>
+ struct AddProfile : public HasScrollViewer<AddProfile>, AddProfileT<AddProfile>
```
## Validation Steps Performed
* the window doesn't close when you move it
* the popups _do_ close when you move the window
* the popups close when you scroll any SUI page
2021-08-16 15:41:17 +02:00
|
|
|
{
|
2021-10-19 22:29:18 +02:00
|
|
|
// We purposely don't log here, because this is exceptionally noisy,
|
|
|
|
// especially on startup, when we're moving the window into place
|
|
|
|
// but might not have a real xamlRoot yet.
|
Manually dismiss popups when the window moves, or the SUI scrolls (#10922)
## Summary of the Pull Request
BODGY!
This solution was suggested in https://github.com/microsoft/microsoft-ui-xaml/issues/4554#issuecomment-887815332.
When the window moves, or when a ScrollViewer scrolls, dismiss any popups that are visible. This happens automagically when an app is a real XAML app, but it doesn't work for XAML Islands.
## References
* upstream at https://github.com/microsoft/microsoft-ui-xaml/issues/4554
## PR Checklist
* [x] Closes #9320
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
Unfortunately, we've got a bunch of scroll viewers in our SUI. So I did something bodgyx2 to make our life a little easier.
`DismissAllPopups` can be used to dismiss all popups for a particular UI element. However, we've got a bunch of pages with scroll viewers that may or may not have popups in them. Rather than define the same exact body for all their `ViewChanging` events, the `HasScrollViewer` struct will just do it for you!
Inside the `HasScrollViewer` stuct, we can't get at the `XamlRoot()` that our subclass implements. I mean, _we_ can, but when XAML does it's codegen, _XAML_ won't be able to figure it out.
Fortunately for us, we don't need to! The sender is a UIElement, so we can just get _their_ `XamlRoot()`.
So, you can fix this for any SUI page with just a simple
```diff
- <ScrollViewer>
+ <ScrollViewer ViewChanging="ViewChanging">
```
```diff
- struct AddProfile : AddProfileT<AddProfile>
+ struct AddProfile : public HasScrollViewer<AddProfile>, AddProfileT<AddProfile>
```
## Validation Steps Performed
* the window doesn't close when you move it
* the popups _do_ close when you move the window
* the popups close when you scroll any SUI page
2021-08-16 15:41:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|