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 } }, ```
This commit is contained in:
parent
6e11780ca6
commit
3866771b1b
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
author: Mike Griese @zadjii-msft
|
author: Mike Griese @zadjii-msft
|
||||||
created on: 2021-02-23
|
created on: 2021-02-23
|
||||||
last updated: 2021-04-21
|
last updated: 2021-05-13
|
||||||
issue id: #653
|
issue id: #653
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ the window. To try and satisfy all these scenarios, I'm proposing the following
|
||||||
two arguments to the `globalSummon` action:
|
two arguments to the `globalSummon` action:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"monitor": "any"|"toCurrent"|"onCurrent"|int,
|
"monitor": "any"|"toCurrent"|"toMouse"|"onCurrent"|int,
|
||||||
"desktop": "any"|"toCurrent"|"onCurrent"
|
"desktop": "any"|"toCurrent"|"onCurrent"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -141,8 +141,10 @@ The way these settings can be combined is in a table below. As an overview:
|
||||||
* `monitor`: This controls the monitor that the window will be summoned from/to
|
* `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
|
- `"any"`: Summon the MRU window, regardless of which monitor it's currently
|
||||||
on.
|
on.
|
||||||
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the current
|
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor
|
||||||
monitor.
|
with the current **foreground** window.
|
||||||
|
- `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse**
|
||||||
|
cursor is.
|
||||||
- `"onCurrent"`: Summon the MRU window **ALREADY ON** the current monitor.
|
- `"onCurrent"`: Summon the MRU window **ALREADY ON** the current monitor.
|
||||||
- `int`: Summon the MRU window for the given monitor (as identified by the
|
- `int`: Summon the MRU window for the given monitor (as identified by the
|
||||||
"Identify" displays feature in the OS settings)
|
"Identify" displays feature in the OS settings)
|
||||||
|
@ -193,16 +195,33 @@ Else:
|
||||||
</tr>
|
</tr>
|
||||||
<!-- ----------------------------------------------------------------------- -->
|
<!-- ----------------------------------------------------------------------- -->
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>"toCurrent"</code><br> Summon the MRU window TO the current monitor</td>
|
<td><code>"toCurrent"</code><br> Summon the MRU window TO the monitor with the foreground window</td>
|
||||||
<td>Go to the desktop the window is on, move to this monitor</td>
|
<td>Go to the desktop the window is on, move to the monitor with the foreground window</td>
|
||||||
<td>Move the window to this desktop, move to this monitor</td>
|
<td>Move the window to this desktop, move to the monitor with the foreground window</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
If there isn't one on this desktop:
|
If there isn't one on this desktop:
|
||||||
* create a new one (on this monitor)
|
* create a new one (on the monitor with the foreground window)
|
||||||
|
|
||||||
Else:
|
Else:
|
||||||
* activate the one on this desktop, move to this window
|
* activate the one on this desktop, move to the monitor with the foreground window
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- ----------------------------------------------------------------------- -->
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>"toMouse"</code>
|
||||||
|
<sup><a href="#footnote-2">[2]</a></sup> <br>
|
||||||
|
Summon the MRU window TO the monitor with the mouse</td>
|
||||||
|
<td>Go to the desktop the window is on, move to the monitor with the mouse</td>
|
||||||
|
<td>Move the window to this desktop, move to the monitor with the mouse</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
If there isn't one on this desktop:
|
||||||
|
* create a new one (on the monitor with the mouse)
|
||||||
|
|
||||||
|
Else:
|
||||||
|
* activate the one on this desktop, move to the monitor with the mouse
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- ----------------------------------------------------------------------- -->
|
<!-- ----------------------------------------------------------------------- -->
|
||||||
|
@ -673,6 +692,8 @@ aren't already included in this spec.
|
||||||
```
|
```
|
||||||
That would allow the user some further customizations on the quake mode
|
That would allow the user some further customizations on the quake mode
|
||||||
behaviors.
|
behaviors.
|
||||||
|
- This was later converted to the idea in [#9992] - Add per-window-name global
|
||||||
|
settings
|
||||||
* Another proposed idea was a simplification of some of the summoning modes. `{
|
* Another proposed idea was a simplification of some of the summoning modes. `{
|
||||||
"monitor": "any", "desktop": "any" }` is a little long, and maybe not the most
|
"monitor": "any", "desktop": "any" }` is a little long, and maybe not the most
|
||||||
apparent naming. Perhaps we could add another property like `summonMode` that
|
apparent naming. Perhaps we could add another property like `summonMode` that
|
||||||
|
@ -698,9 +719,16 @@ windows. Once [#766] lands, this will give us a chance to persist the state of
|
||||||
_all_ open windows. This will allow us to re-open with all the user's windows,
|
_all_ open windows. This will allow us to re-open with all the user's windows,
|
||||||
not just the one that happened to be closed last.
|
not just the one that happened to be closed last.
|
||||||
|
|
||||||
|
<a name="footnote-2"><a>[2]: **Addenda, May 2021**: In the course of
|
||||||
|
implementation, it became apparent that there's an important UX difference
|
||||||
|
between summoning _to the monitor with the cursor_ vs _to the monitor with the
|
||||||
|
foreground window_. `"monitor": "toMouse"` was added as an option, to allow the
|
||||||
|
user to differentiate between the two behaviors.
|
||||||
|
|
||||||
[#653]: https://github.com/microsoft/terminal/issues/653
|
[#653]: https://github.com/microsoft/terminal/issues/653
|
||||||
[#766]: https://github.com/microsoft/terminal/issues/766
|
[#766]: https://github.com/microsoft/terminal/issues/766
|
||||||
[#5727]: https://github.com/microsoft/terminal/issues/5727
|
[#5727]: https://github.com/microsoft/terminal/issues/5727
|
||||||
|
[#9992]: https://github.com/microsoft/terminal/issues/9992
|
||||||
|
|
||||||
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md
|
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md
|
||||||
[Quake 3 sample]: https://youtu.be/ZmR6HQbuHPA?t=27
|
[Quake 3 sample]: https://youtu.be/ZmR6HQbuHPA?t=27
|
||||||
|
|
|
@ -30,13 +30,21 @@ namespace Microsoft.Terminal.Remoting
|
||||||
Windows.Foundation.DateTime ActivatedTime { get; };
|
Windows.Foundation.DateTime ActivatedTime { get; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum MonitorBehavior
|
||||||
|
{
|
||||||
|
InPlace,
|
||||||
|
ToCurrent,
|
||||||
|
ToMouse,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
[default_interface] runtimeclass SummonWindowBehavior {
|
[default_interface] runtimeclass SummonWindowBehavior {
|
||||||
SummonWindowBehavior();
|
SummonWindowBehavior();
|
||||||
Boolean MoveToCurrentDesktop;
|
Boolean MoveToCurrentDesktop;
|
||||||
Boolean ToggleVisibility;
|
Boolean ToggleVisibility;
|
||||||
UInt32 DropdownDuration;
|
UInt32 DropdownDuration;
|
||||||
// Other options:
|
MonitorBehavior ToMonitor;
|
||||||
// * CurrentMonitor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPeasant
|
interface IPeasant
|
||||||
|
|
|
@ -24,10 +24,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
WINRT_PROPERTY(bool, MoveToCurrentDesktop, true);
|
WINRT_PROPERTY(bool, MoveToCurrentDesktop, true);
|
||||||
WINRT_PROPERTY(bool, ToggleVisibility, true);
|
WINRT_PROPERTY(bool, ToggleVisibility, true);
|
||||||
WINRT_PROPERTY(uint32_t, DropdownDuration, 0);
|
WINRT_PROPERTY(uint32_t, DropdownDuration, 0);
|
||||||
|
WINRT_PROPERTY(Remoting::MonitorBehavior, ToMonitor, Remoting::MonitorBehavior::ToCurrent);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SummonWindowBehavior(const Remoting::SummonWindowBehavior& other) :
|
SummonWindowBehavior(const Remoting::SummonWindowBehavior& other) :
|
||||||
_MoveToCurrentDesktop{ other.MoveToCurrentDesktop() },
|
_MoveToCurrentDesktop{ other.MoveToCurrentDesktop() },
|
||||||
|
_ToMonitor{ other.ToMonitor() },
|
||||||
_DropdownDuration{ other.DropdownDuration() },
|
_DropdownDuration{ other.DropdownDuration() },
|
||||||
_ToggleVisibility{ other.ToggleVisibility() } {};
|
_ToggleVisibility{ other.ToggleVisibility() } {};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1158,11 +1158,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
GlobalSummonArgs() = default;
|
GlobalSummonArgs() = default;
|
||||||
WINRT_PROPERTY(winrt::hstring, Name, L"");
|
WINRT_PROPERTY(winrt::hstring, Name, L"");
|
||||||
WINRT_PROPERTY(Model::DesktopBehavior, Desktop, Model::DesktopBehavior::ToCurrent);
|
WINRT_PROPERTY(Model::DesktopBehavior, Desktop, Model::DesktopBehavior::ToCurrent);
|
||||||
|
WINRT_PROPERTY(Model::MonitorBehavior, Monitor, Model::MonitorBehavior::ToMouse);
|
||||||
WINRT_PROPERTY(bool, ToggleVisibility, true);
|
WINRT_PROPERTY(bool, ToggleVisibility, true);
|
||||||
WINRT_PROPERTY(uint32_t, DropdownDuration, 0);
|
WINRT_PROPERTY(uint32_t, DropdownDuration, 0);
|
||||||
|
|
||||||
static constexpr std::string_view NameKey{ "name" };
|
static constexpr std::string_view NameKey{ "name" };
|
||||||
static constexpr std::string_view DesktopKey{ "desktop" };
|
static constexpr std::string_view DesktopKey{ "desktop" };
|
||||||
|
static constexpr std::string_view MonitorKey{ "monitor" };
|
||||||
static constexpr std::string_view ToggleVisibilityKey{ "toggleVisibility" };
|
static constexpr std::string_view ToggleVisibilityKey{ "toggleVisibility" };
|
||||||
static constexpr std::string_view DropdownDurationKey{ "dropdownDuration" };
|
static constexpr std::string_view DropdownDurationKey{ "dropdownDuration" };
|
||||||
|
|
||||||
|
@ -1175,6 +1177,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
{
|
{
|
||||||
return otherAsUs->_Name == _Name &&
|
return otherAsUs->_Name == _Name &&
|
||||||
otherAsUs->_Desktop == _Desktop &&
|
otherAsUs->_Desktop == _Desktop &&
|
||||||
|
otherAsUs->_Monitor == _Monitor &&
|
||||||
otherAsUs->_DropdownDuration == _DropdownDuration &&
|
otherAsUs->_DropdownDuration == _DropdownDuration &&
|
||||||
otherAsUs->_ToggleVisibility == _ToggleVisibility;
|
otherAsUs->_ToggleVisibility == _ToggleVisibility;
|
||||||
}
|
}
|
||||||
|
@ -1186,6 +1189,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
auto args = winrt::make_self<GlobalSummonArgs>();
|
auto args = winrt::make_self<GlobalSummonArgs>();
|
||||||
JsonUtils::GetValueForKey(json, NameKey, args->_Name);
|
JsonUtils::GetValueForKey(json, NameKey, args->_Name);
|
||||||
JsonUtils::GetValueForKey(json, DesktopKey, args->_Desktop);
|
JsonUtils::GetValueForKey(json, DesktopKey, args->_Desktop);
|
||||||
|
JsonUtils::GetValueForKey(json, MonitorKey, args->_Monitor);
|
||||||
JsonUtils::GetValueForKey(json, DropdownDurationKey, args->_DropdownDuration);
|
JsonUtils::GetValueForKey(json, DropdownDurationKey, args->_DropdownDuration);
|
||||||
JsonUtils::GetValueForKey(json, ToggleVisibilityKey, args->_ToggleVisibility);
|
JsonUtils::GetValueForKey(json, ToggleVisibilityKey, args->_ToggleVisibility);
|
||||||
return { *args, {} };
|
return { *args, {} };
|
||||||
|
@ -1195,6 +1199,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
auto copy{ winrt::make_self<GlobalSummonArgs>() };
|
auto copy{ winrt::make_self<GlobalSummonArgs>() };
|
||||||
copy->_Name = _Name;
|
copy->_Name = _Name;
|
||||||
copy->_Desktop = _Desktop;
|
copy->_Desktop = _Desktop;
|
||||||
|
copy->_Monitor = _Monitor;
|
||||||
copy->_DropdownDuration = _DropdownDuration;
|
copy->_DropdownDuration = _DropdownDuration;
|
||||||
copy->_ToggleVisibility = _ToggleVisibility;
|
copy->_ToggleVisibility = _ToggleVisibility;
|
||||||
return *copy;
|
return *copy;
|
||||||
|
@ -1213,7 +1218,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
}
|
}
|
||||||
size_t Hash() const
|
size_t Hash() const
|
||||||
{
|
{
|
||||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Name, _Desktop, _ToggleVisibility);
|
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Name, _Desktop, _Monitor, _DropdownDuration, _ToggleVisibility);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,13 @@ namespace Microsoft.Terminal.Settings.Model
|
||||||
OnCurrent,
|
OnCurrent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MonitorBehavior
|
||||||
|
{
|
||||||
|
Any,
|
||||||
|
ToCurrent,
|
||||||
|
ToMouse,
|
||||||
|
};
|
||||||
|
|
||||||
[default_interface] runtimeclass NewTerminalArgs {
|
[default_interface] runtimeclass NewTerminalArgs {
|
||||||
NewTerminalArgs();
|
NewTerminalArgs();
|
||||||
NewTerminalArgs(Int32 profileIndex);
|
NewTerminalArgs(Int32 profileIndex);
|
||||||
|
@ -266,6 +273,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||||
{
|
{
|
||||||
String Name { get; };
|
String Name { get; };
|
||||||
DesktopBehavior Desktop { get; };
|
DesktopBehavior Desktop { get; };
|
||||||
|
MonitorBehavior Monitor { get; };
|
||||||
Boolean ToggleVisibility { get; };
|
Boolean ToggleVisibility { get; };
|
||||||
UInt32 DropdownDuration { get; };
|
UInt32 DropdownDuration { get; };
|
||||||
};
|
};
|
||||||
|
|
|
@ -457,3 +457,12 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::DesktopBehavior)
|
||||||
pair_type{ "onCurrent", ValueType::OnCurrent },
|
pair_type{ "onCurrent", ValueType::OnCurrent },
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::MonitorBehavior)
|
||||||
|
{
|
||||||
|
JSON_MAPPINGS(3) = {
|
||||||
|
pair_type{ "any", ValueType::Any },
|
||||||
|
pair_type{ "toCurrent", ValueType::ToCurrent },
|
||||||
|
pair_type{ "toMouse", ValueType::ToMouse },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -589,9 +589,13 @@ bool AppHost::HasWindow()
|
||||||
void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable /*sender*/,
|
void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable /*sender*/,
|
||||||
Remoting::CommandlineArgs args)
|
Remoting::CommandlineArgs args)
|
||||||
{
|
{
|
||||||
|
const Remoting::SummonWindowBehavior summonArgs{};
|
||||||
|
summonArgs.MoveToCurrentDesktop(false);
|
||||||
|
summonArgs.DropdownDuration(0);
|
||||||
|
summonArgs.ToMonitor(Remoting::MonitorBehavior::InPlace);
|
||||||
// Summon the window whenever we dispatch a commandline to it. This will
|
// 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.
|
// make it obvious when a new tab/pane is created in a window.
|
||||||
_window->SummonWindow(false, 0);
|
_window->SummonWindow(summonArgs);
|
||||||
_logic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory());
|
_logic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,6 +699,19 @@ void AppHost::_GlobalHotkeyPressed(const long hotkeyIndex)
|
||||||
args.SummonBehavior().ToggleVisibility(summonArgs.ToggleVisibility());
|
args.SummonBehavior().ToggleVisibility(summonArgs.ToggleVisibility());
|
||||||
args.SummonBehavior().DropdownDuration(summonArgs.DropdownDuration());
|
args.SummonBehavior().DropdownDuration(summonArgs.DropdownDuration());
|
||||||
|
|
||||||
|
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);
|
_windowManager.SummonWindow(args);
|
||||||
if (args.FoundMatch())
|
if (args.FoundMatch())
|
||||||
{
|
{
|
||||||
|
@ -776,7 +793,7 @@ bool AppHost::_LazyLoadDesktopManager()
|
||||||
void AppHost::_HandleSummon(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
void AppHost::_HandleSummon(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||||
const Remoting::SummonWindowBehavior& args)
|
const Remoting::SummonWindowBehavior& args)
|
||||||
{
|
{
|
||||||
_window->SummonWindow(args.ToggleVisibility(), args.DropdownDuration());
|
_window->SummonWindow(args);
|
||||||
|
|
||||||
if (args != nullptr && args.MoveToCurrentDesktop())
|
if (args != nullptr && args.MoveToCurrentDesktop())
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@ using namespace winrt::Windows::UI::Xaml::Hosting;
|
||||||
using namespace winrt::Windows::Foundation::Numerics;
|
using namespace winrt::Windows::Foundation::Numerics;
|
||||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||||
using namespace winrt::Microsoft::Terminal::Control;
|
using namespace winrt::Microsoft::Terminal::Control;
|
||||||
|
using namespace winrt::Microsoft::Terminal;
|
||||||
using namespace ::Microsoft::Console::Types;
|
using namespace ::Microsoft::Console::Types;
|
||||||
|
|
||||||
#define XAML_HOSTING_WINDOW_CLASS_NAME L"CASCADIA_HOSTING_WINDOW_CLASS"
|
#define XAML_HOSTING_WINDOW_CLASS_NAME L"CASCADIA_HOSTING_WINDOW_CLASS"
|
||||||
|
@ -1009,14 +1010,14 @@ void IslandWindow::SetGlobalHotkeys(const std::vector<winrt::Microsoft::Terminal
|
||||||
// - toggleVisibility: controls how we should behave when already in the foreground.
|
// - toggleVisibility: controls how we should behave when already in the foreground.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
winrt::fire_and_forget IslandWindow::SummonWindow(const bool toggleVisibility, const uint32_t dropdownDuration)
|
winrt::fire_and_forget IslandWindow::SummonWindow(Remoting::SummonWindowBehavior args)
|
||||||
{
|
{
|
||||||
// On the foreground thread:
|
// On the foreground thread:
|
||||||
co_await winrt::resume_foreground(_rootGrid.Dispatcher());
|
co_await winrt::resume_foreground(_rootGrid.Dispatcher());
|
||||||
|
|
||||||
uint32_t actualDropdownDuration = dropdownDuration;
|
uint32_t actualDropdownDuration = args.DropdownDuration();
|
||||||
// If the user requested an animation, let's check if animations are enabled in the OS.
|
// If the user requested an animation, let's check if animations are enabled in the OS.
|
||||||
if (dropdownDuration > 0)
|
if (args.DropdownDuration() > 0)
|
||||||
{
|
{
|
||||||
BOOL animationsEnabled = TRUE;
|
BOOL animationsEnabled = TRUE;
|
||||||
SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION, 0, &animationsEnabled, 0);
|
SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION, 0, &animationsEnabled, 0);
|
||||||
|
@ -1036,15 +1037,38 @@ winrt::fire_and_forget IslandWindow::SummonWindow(const bool toggleVisibility, c
|
||||||
|
|
||||||
// * If the user doesn't want to toggleVisibility, then just always try to
|
// * If the user doesn't want to toggleVisibility, then just always try to
|
||||||
// activate.
|
// activate.
|
||||||
// * If the user does want to toggleVisibility, then dismiss the window if
|
// * If the user does want to toggleVisibility,
|
||||||
// we're the current foreground window.
|
// - If we're the foreground window, ToMonitor == ToMouse, and the mouse is on the monitor we are
|
||||||
if (toggleVisibility && GetForegroundWindow() == _window.get())
|
// - activate the window
|
||||||
|
// - else
|
||||||
|
// - dismiss the window
|
||||||
|
if (args.ToggleVisibility() && GetForegroundWindow() == _window.get())
|
||||||
{
|
{
|
||||||
_globalDismissWindow(actualDropdownDuration);
|
bool handled = false;
|
||||||
|
|
||||||
|
// They want to toggle the window when it is the FG window, and we are
|
||||||
|
// the FG window. However, if we're on a different monitor than the
|
||||||
|
// mouse, then we should move to that monitor instead of dismissing.
|
||||||
|
if (args.ToMonitor() == Remoting::MonitorBehavior::ToMouse)
|
||||||
|
{
|
||||||
|
const til::rectangle cursorMonitorRect{ _getMonitorForCursor().rcMonitor };
|
||||||
|
const til::rectangle currentMonitorRect{ _getMonitorForWindow(GetHandle()).rcMonitor };
|
||||||
|
if (cursorMonitorRect != currentMonitorRect)
|
||||||
|
{
|
||||||
|
// We're not on the same monitor as the mouse. Go to that monitor.
|
||||||
|
_globalActivateWindow(actualDropdownDuration, args.ToMonitor());
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
{
|
||||||
|
_globalDismissWindow(actualDropdownDuration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_globalActivateWindow(actualDropdownDuration);
|
_globalActivateWindow(actualDropdownDuration, args.ToMonitor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1105,8 +1129,15 @@ void IslandWindow::_doSlideAnimation(const uint32_t dropdownDuration, const bool
|
||||||
SetWindowRgn(_interopWindowHandle, nullptr, true);
|
SetWindowRgn(_interopWindowHandle, nullptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IslandWindow::_dropdownWindow(const uint32_t dropdownDuration)
|
void IslandWindow::_dropdownWindow(const uint32_t dropdownDuration,
|
||||||
|
const Remoting::MonitorBehavior toMonitor)
|
||||||
{
|
{
|
||||||
|
// First, get the window that's currently in the foreground. We'll need
|
||||||
|
// _this_ window to be able to appear on top of. If we just use
|
||||||
|
// GetForegroundWindow afer the SetWindowPlacement call, _we_ will be the
|
||||||
|
// foreground window.
|
||||||
|
const auto oldForegroundWindow = GetForegroundWindow();
|
||||||
|
|
||||||
// First, restore the window. SetWindowPlacement has a fun undocumented
|
// First, restore the window. SetWindowPlacement has a fun undocumented
|
||||||
// piece of functionality where it will restore the window position
|
// piece of functionality where it will restore the window position
|
||||||
// _without_ the animation, so use that instead of ShowWindow(SW_RESTORE).
|
// _without_ the animation, so use that instead of ShowWindow(SW_RESTORE).
|
||||||
|
@ -1116,6 +1147,9 @@ void IslandWindow::_dropdownWindow(const uint32_t dropdownDuration)
|
||||||
wpc.showCmd = SW_RESTORE;
|
wpc.showCmd = SW_RESTORE;
|
||||||
SetWindowPlacement(_window.get(), &wpc);
|
SetWindowPlacement(_window.get(), &wpc);
|
||||||
|
|
||||||
|
// Possibly go to the monitor of the mouse / old foreground window.
|
||||||
|
_moveToMonitor(oldForegroundWindow, toMonitor);
|
||||||
|
|
||||||
// Now that we're visible, animate the dropdown.
|
// Now that we're visible, animate the dropdown.
|
||||||
_doSlideAnimation(dropdownDuration, true);
|
_doSlideAnimation(dropdownDuration, true);
|
||||||
}
|
}
|
||||||
|
@ -1145,8 +1179,15 @@ void IslandWindow::_slideUpWindow(const uint32_t dropdownDuration)
|
||||||
// milliseconds. If 0, we won't perform a dropdown animation.
|
// milliseconds. If 0, we won't perform a dropdown animation.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
void IslandWindow::_globalActivateWindow(const uint32_t dropdownDuration)
|
void IslandWindow::_globalActivateWindow(const uint32_t dropdownDuration,
|
||||||
|
const Remoting::MonitorBehavior toMonitor)
|
||||||
{
|
{
|
||||||
|
// First, get the window that's currently in the foreground. We'll need
|
||||||
|
// _this_ window to be able to appear on top of. If we just use
|
||||||
|
// GetForegroundWindow afer the SetWindowPlacement/ShowWindow call, _we_
|
||||||
|
// will be the foreground window.
|
||||||
|
const auto oldForegroundWindow = GetForegroundWindow();
|
||||||
|
|
||||||
// From: https://stackoverflow.com/a/59659421
|
// From: https://stackoverflow.com/a/59659421
|
||||||
// > The trick is to make windows ‘think’ that our process and the target
|
// > The trick is to make windows ‘think’ that our process and the target
|
||||||
// > window (hwnd) are related by attaching the threads (using
|
// > window (hwnd) are related by attaching the threads (using
|
||||||
|
@ -1158,16 +1199,19 @@ void IslandWindow::_globalActivateWindow(const uint32_t dropdownDuration)
|
||||||
{
|
{
|
||||||
if (dropdownDuration > 0)
|
if (dropdownDuration > 0)
|
||||||
{
|
{
|
||||||
_dropdownWindow(dropdownDuration);
|
_dropdownWindow(dropdownDuration, toMonitor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_IF_WIN32_BOOL_FALSE(ShowWindow(_window.get(), SW_RESTORE));
|
LOG_IF_WIN32_BOOL_FALSE(ShowWindow(_window.get(), SW_RESTORE));
|
||||||
|
|
||||||
|
// Once we've been restored, throw us on the active monitor.
|
||||||
|
_moveToMonitor(oldForegroundWindow, toMonitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const DWORD windowThreadProcessId = GetWindowThreadProcessId(GetForegroundWindow(), nullptr);
|
const DWORD windowThreadProcessId = GetWindowThreadProcessId(oldForegroundWindow, nullptr);
|
||||||
const DWORD currentThreadId = GetCurrentThreadId();
|
const DWORD currentThreadId = GetCurrentThreadId();
|
||||||
|
|
||||||
LOG_IF_WIN32_BOOL_FALSE(AttachThreadInput(windowThreadProcessId, currentThreadId, true));
|
LOG_IF_WIN32_BOOL_FALSE(AttachThreadInput(windowThreadProcessId, currentThreadId, true));
|
||||||
|
@ -1181,6 +1225,9 @@ void IslandWindow::_globalActivateWindow(const uint32_t dropdownDuration)
|
||||||
// Activate the window too. This will force us to the virtual desktop this
|
// Activate the window too. This will force us to the virtual desktop this
|
||||||
// window is on, if it's on another virtual desktop.
|
// window is on, if it's on another virtual desktop.
|
||||||
LOG_LAST_ERROR_IF_NULL(SetActiveWindow(_window.get()));
|
LOG_LAST_ERROR_IF_NULL(SetActiveWindow(_window.get()));
|
||||||
|
|
||||||
|
// Throw us on the active monitor.
|
||||||
|
_moveToMonitor(oldForegroundWindow, toMonitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1206,6 +1253,115 @@ void IslandWindow::_globalDismissWindow(const uint32_t dropdownDuration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Get the monitor the mouse cursor is currently on
|
||||||
|
// Arguments:
|
||||||
|
// - dropdownDuration: The duration to play the slide-up animation, in
|
||||||
|
// milliseconds. If 0, we won't perform a slide-up animation.
|
||||||
|
// Return Value:
|
||||||
|
// - The MONITORINFO for the monitor the mouse cursor is on
|
||||||
|
MONITORINFO IslandWindow::_getMonitorForCursor()
|
||||||
|
{
|
||||||
|
POINT p{};
|
||||||
|
GetCursorPos(&p);
|
||||||
|
|
||||||
|
// Get the monitor info for the window's current monitor.
|
||||||
|
MONITORINFO activeMonitor{};
|
||||||
|
activeMonitor.cbSize = sizeof(activeMonitor);
|
||||||
|
GetMonitorInfo(MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST), &activeMonitor);
|
||||||
|
return activeMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Get the monitor for a given HWND
|
||||||
|
// Arguments:
|
||||||
|
// - <none>
|
||||||
|
// Return Value:
|
||||||
|
// - The MONITORINFO for the given HWND
|
||||||
|
MONITORINFO IslandWindow::_getMonitorForWindow(HWND foregroundWindow)
|
||||||
|
{
|
||||||
|
// Get the monitor info for the window's current monitor.
|
||||||
|
MONITORINFO activeMonitor{};
|
||||||
|
activeMonitor.cbSize = sizeof(activeMonitor);
|
||||||
|
GetMonitorInfo(MonitorFromWindow(foregroundWindow, MONITOR_DEFAULTTONEAREST), &activeMonitor);
|
||||||
|
return activeMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Based on the value in toMonitor, move the window to the monitor of the
|
||||||
|
// given HWND, the monitor of the mouse pointer, or just leave it where it is.
|
||||||
|
// Arguments:
|
||||||
|
// - oldForegroundWindow: when toMonitor is ToCurrent, we'll move to the monitor
|
||||||
|
// of this HWND. Otherwise, this param is ignored.
|
||||||
|
// - toMonitor: Controls which monitor we should move to.
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void IslandWindow::_moveToMonitor(HWND oldForegroundWindow, Remoting::MonitorBehavior toMonitor)
|
||||||
|
{
|
||||||
|
if (toMonitor == Remoting::MonitorBehavior::ToCurrent)
|
||||||
|
{
|
||||||
|
_moveToMonitorOf(oldForegroundWindow);
|
||||||
|
}
|
||||||
|
else if (toMonitor == Remoting::MonitorBehavior::ToMouse)
|
||||||
|
{
|
||||||
|
_moveToMonitorOfMouse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Move our window to the monitor the mouse is on.
|
||||||
|
// Arguments:
|
||||||
|
// - <none>
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void IslandWindow::_moveToMonitorOfMouse()
|
||||||
|
{
|
||||||
|
_moveToMonitor(_getMonitorForCursor());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Move our window to the monitor that the given HWND is on.
|
||||||
|
// Arguments:
|
||||||
|
// - <none>
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void IslandWindow::_moveToMonitorOf(HWND foregroundWindow)
|
||||||
|
{
|
||||||
|
_moveToMonitor(_getMonitorForWindow(foregroundWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Move our window to the given monitor. This will do nothing if we're already
|
||||||
|
// on that monitor.
|
||||||
|
// - We'll retain the same relative position on the new monitor as we had on the
|
||||||
|
// old monitor.
|
||||||
|
// Arguments:
|
||||||
|
// - activeMonitor: the monitor to move to.
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void IslandWindow::_moveToMonitor(const MONITORINFO activeMonitor)
|
||||||
|
{
|
||||||
|
// Get the monitor info for the window's current monitor.
|
||||||
|
const auto currentMonitor = _getMonitorForWindow(GetHandle());
|
||||||
|
|
||||||
|
const til::rectangle currentRect{ currentMonitor.rcMonitor };
|
||||||
|
const til::rectangle activeRect{ activeMonitor.rcMonitor };
|
||||||
|
if (currentRect != activeRect)
|
||||||
|
{
|
||||||
|
const til::rectangle currentWindowRect{ GetWindowRect() };
|
||||||
|
const til::point offset{ currentWindowRect.origin() - currentRect.origin() };
|
||||||
|
const til::point newOrigin{ activeRect.origin() + offset };
|
||||||
|
|
||||||
|
SetWindowPos(GetHandle(),
|
||||||
|
0,
|
||||||
|
newOrigin.x<int>(),
|
||||||
|
newOrigin.y<int>(),
|
||||||
|
currentWindowRect.width<int>(),
|
||||||
|
currentWindowRect.height<int>(),
|
||||||
|
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IslandWindow::IsQuakeWindow() const noexcept
|
bool IslandWindow::IsQuakeWindow() const noexcept
|
||||||
{
|
{
|
||||||
return _isQuakeWindow;
|
return _isQuakeWindow;
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
void UnsetHotkeys(const std::vector<winrt::Microsoft::Terminal::Control::KeyChord>& hotkeyList);
|
void UnsetHotkeys(const std::vector<winrt::Microsoft::Terminal::Control::KeyChord>& hotkeyList);
|
||||||
void SetGlobalHotkeys(const std::vector<winrt::Microsoft::Terminal::Control::KeyChord>& hotkeyList);
|
void SetGlobalHotkeys(const std::vector<winrt::Microsoft::Terminal::Control::KeyChord>& hotkeyList);
|
||||||
|
|
||||||
winrt::fire_and_forget SummonWindow(const bool toggleVisibility, const uint32_t dropdownDuration);
|
winrt::fire_and_forget SummonWindow(winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior args);
|
||||||
|
|
||||||
bool IsQuakeWindow() const noexcept;
|
bool IsQuakeWindow() const noexcept;
|
||||||
void IsQuakeWindow(bool isQuakeWindow) noexcept;
|
void IsQuakeWindow(bool isQuakeWindow) noexcept;
|
||||||
|
@ -93,12 +93,21 @@ protected:
|
||||||
void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam);
|
void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam);
|
||||||
long _calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize);
|
long _calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize);
|
||||||
|
|
||||||
void _globalActivateWindow(const uint32_t dropdownDuration);
|
void _globalActivateWindow(const uint32_t dropdownDuration,
|
||||||
void _dropdownWindow(const uint32_t dropdownDuration);
|
const winrt::Microsoft::Terminal::Remoting::MonitorBehavior toMonitor);
|
||||||
|
void _dropdownWindow(const uint32_t dropdownDuration,
|
||||||
|
const winrt::Microsoft::Terminal::Remoting::MonitorBehavior toMonitor);
|
||||||
void _slideUpWindow(const uint32_t dropdownDuration);
|
void _slideUpWindow(const uint32_t dropdownDuration);
|
||||||
void _doSlideAnimation(const uint32_t dropdownDuration, const bool down);
|
void _doSlideAnimation(const uint32_t dropdownDuration, const bool down);
|
||||||
void _globalDismissWindow(const uint32_t dropdownDuration);
|
void _globalDismissWindow(const uint32_t dropdownDuration);
|
||||||
|
|
||||||
|
static MONITORINFO _getMonitorForCursor();
|
||||||
|
static MONITORINFO _getMonitorForWindow(HWND foregroundWindow);
|
||||||
|
void _moveToMonitor(HWND foregroundWindow, const winrt::Microsoft::Terminal::Remoting::MonitorBehavior toMonitor);
|
||||||
|
void _moveToMonitorOfMouse();
|
||||||
|
void _moveToMonitorOf(HWND foregroundWindow);
|
||||||
|
void _moveToMonitor(const MONITORINFO activeMonitor);
|
||||||
|
|
||||||
bool _isQuakeWindow{ false };
|
bool _isQuakeWindow{ false };
|
||||||
void _enterQuakeMode();
|
void _enterQuakeMode();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue