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
|
||||
created on: 2021-02-23
|
||||
last updated: 2021-04-21
|
||||
last updated: 2021-05-13
|
||||
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:
|
||||
|
||||
```json
|
||||
"monitor": "any"|"toCurrent"|"onCurrent"|int,
|
||||
"monitor": "any"|"toCurrent"|"toMouse"|"onCurrent"|int,
|
||||
"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
|
||||
- `"any"`: Summon the MRU window, regardless of which monitor it's currently
|
||||
on.
|
||||
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the current
|
||||
monitor.
|
||||
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the 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.
|
||||
- `int`: Summon the MRU window for the given monitor (as identified by the
|
||||
"Identify" displays feature in the OS settings)
|
||||
|
@ -193,16 +195,33 @@ Else:
|
|||
</tr>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
<tr>
|
||||
<td><code>"toCurrent"</code><br> Summon the MRU window TO the current monitor</td>
|
||||
<td>Go to the desktop the window is on, move to this monitor</td>
|
||||
<td>Move the window to this desktop, move to this 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 the monitor with the foreground window</td>
|
||||
<td>Move the window to this desktop, move to the monitor with the foreground window</td>
|
||||
<td>
|
||||
|
||||
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:
|
||||
* 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>
|
||||
</tr>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
|
@ -673,6 +692,8 @@ aren't already included in this spec.
|
|||
```
|
||||
That would allow the user some further customizations on the quake mode
|
||||
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. `{
|
||||
"monitor": "any", "desktop": "any" }` is a little long, and maybe not the most
|
||||
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,
|
||||
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
|
||||
[#766]: https://github.com/microsoft/terminal/issues/766
|
||||
[#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
|
||||
[Quake 3 sample]: https://youtu.be/ZmR6HQbuHPA?t=27
|
||||
|
|
|
@ -30,13 +30,21 @@ namespace Microsoft.Terminal.Remoting
|
|||
Windows.Foundation.DateTime ActivatedTime { get; };
|
||||
};
|
||||
|
||||
|
||||
enum MonitorBehavior
|
||||
{
|
||||
InPlace,
|
||||
ToCurrent,
|
||||
ToMouse,
|
||||
};
|
||||
|
||||
|
||||
[default_interface] runtimeclass SummonWindowBehavior {
|
||||
SummonWindowBehavior();
|
||||
Boolean MoveToCurrentDesktop;
|
||||
Boolean ToggleVisibility;
|
||||
UInt32 DropdownDuration;
|
||||
// Other options:
|
||||
// * CurrentMonitor
|
||||
MonitorBehavior ToMonitor;
|
||||
}
|
||||
|
||||
interface IPeasant
|
||||
|
|
|
@ -24,10 +24,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
WINRT_PROPERTY(bool, MoveToCurrentDesktop, true);
|
||||
WINRT_PROPERTY(bool, ToggleVisibility, true);
|
||||
WINRT_PROPERTY(uint32_t, DropdownDuration, 0);
|
||||
WINRT_PROPERTY(Remoting::MonitorBehavior, ToMonitor, Remoting::MonitorBehavior::ToCurrent);
|
||||
|
||||
public:
|
||||
SummonWindowBehavior(const Remoting::SummonWindowBehavior& other) :
|
||||
_MoveToCurrentDesktop{ other.MoveToCurrentDesktop() },
|
||||
_ToMonitor{ other.ToMonitor() },
|
||||
_DropdownDuration{ other.DropdownDuration() },
|
||||
_ToggleVisibility{ other.ToggleVisibility() } {};
|
||||
};
|
||||
|
|
|
@ -1158,11 +1158,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
GlobalSummonArgs() = default;
|
||||
WINRT_PROPERTY(winrt::hstring, Name, L"");
|
||||
WINRT_PROPERTY(Model::DesktopBehavior, Desktop, Model::DesktopBehavior::ToCurrent);
|
||||
WINRT_PROPERTY(Model::MonitorBehavior, Monitor, Model::MonitorBehavior::ToMouse);
|
||||
WINRT_PROPERTY(bool, ToggleVisibility, true);
|
||||
WINRT_PROPERTY(uint32_t, DropdownDuration, 0);
|
||||
|
||||
static constexpr std::string_view NameKey{ "name" };
|
||||
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 DropdownDurationKey{ "dropdownDuration" };
|
||||
|
||||
|
@ -1175,6 +1177,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
{
|
||||
return otherAsUs->_Name == _Name &&
|
||||
otherAsUs->_Desktop == _Desktop &&
|
||||
otherAsUs->_Monitor == _Monitor &&
|
||||
otherAsUs->_DropdownDuration == _DropdownDuration &&
|
||||
otherAsUs->_ToggleVisibility == _ToggleVisibility;
|
||||
}
|
||||
|
@ -1186,6 +1189,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
auto args = winrt::make_self<GlobalSummonArgs>();
|
||||
JsonUtils::GetValueForKey(json, NameKey, args->_Name);
|
||||
JsonUtils::GetValueForKey(json, DesktopKey, args->_Desktop);
|
||||
JsonUtils::GetValueForKey(json, MonitorKey, args->_Monitor);
|
||||
JsonUtils::GetValueForKey(json, DropdownDurationKey, args->_DropdownDuration);
|
||||
JsonUtils::GetValueForKey(json, ToggleVisibilityKey, args->_ToggleVisibility);
|
||||
return { *args, {} };
|
||||
|
@ -1195,6 +1199,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
auto copy{ winrt::make_self<GlobalSummonArgs>() };
|
||||
copy->_Name = _Name;
|
||||
copy->_Desktop = _Desktop;
|
||||
copy->_Monitor = _Monitor;
|
||||
copy->_DropdownDuration = _DropdownDuration;
|
||||
copy->_ToggleVisibility = _ToggleVisibility;
|
||||
return *copy;
|
||||
|
@ -1213,7 +1218,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
}
|
||||
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,
|
||||
};
|
||||
|
||||
enum MonitorBehavior
|
||||
{
|
||||
Any,
|
||||
ToCurrent,
|
||||
ToMouse,
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass NewTerminalArgs {
|
||||
NewTerminalArgs();
|
||||
NewTerminalArgs(Int32 profileIndex);
|
||||
|
@ -266,6 +273,7 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
{
|
||||
String Name { get; };
|
||||
DesktopBehavior Desktop { get; };
|
||||
MonitorBehavior Monitor { get; };
|
||||
Boolean ToggleVisibility { get; };
|
||||
UInt32 DropdownDuration { get; };
|
||||
};
|
||||
|
|
|
@ -457,3 +457,12 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::DesktopBehavior)
|
|||
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*/,
|
||||
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
|
||||
// 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());
|
||||
}
|
||||
|
||||
|
@ -695,6 +699,19 @@ void AppHost::_GlobalHotkeyPressed(const long hotkeyIndex)
|
|||
args.SummonBehavior().ToggleVisibility(summonArgs.ToggleVisibility());
|
||||
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);
|
||||
if (args.FoundMatch())
|
||||
{
|
||||
|
@ -776,7 +793,7 @@ bool AppHost::_LazyLoadDesktopManager()
|
|||
void AppHost::_HandleSummon(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const Remoting::SummonWindowBehavior& args)
|
||||
{
|
||||
_window->SummonWindow(args.ToggleVisibility(), args.DropdownDuration());
|
||||
_window->SummonWindow(args);
|
||||
|
||||
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::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace ::Microsoft::Console::Types;
|
||||
|
||||
#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.
|
||||
// Return Value:
|
||||
// - <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:
|
||||
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 (dropdownDuration > 0)
|
||||
if (args.DropdownDuration() > 0)
|
||||
{
|
||||
BOOL animationsEnabled = TRUE;
|
||||
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
|
||||
// activate.
|
||||
// * If the user does want to toggleVisibility, then dismiss the window if
|
||||
// we're the current foreground window.
|
||||
if (toggleVisibility && GetForegroundWindow() == _window.get())
|
||||
// * If the user does want to toggleVisibility,
|
||||
// - If we're the foreground window, ToMonitor == ToMouse, and the mouse is on the monitor we are
|
||||
// - 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
|
||||
{
|
||||
_globalActivateWindow(actualDropdownDuration);
|
||||
_globalActivateWindow(actualDropdownDuration, args.ToMonitor());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1105,8 +1129,15 @@ void IslandWindow::_doSlideAnimation(const uint32_t dropdownDuration, const bool
|
|||
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
|
||||
// piece of functionality where it will restore the window position
|
||||
// _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;
|
||||
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.
|
||||
_doSlideAnimation(dropdownDuration, true);
|
||||
}
|
||||
|
@ -1145,8 +1179,15 @@ void IslandWindow::_slideUpWindow(const uint32_t dropdownDuration)
|
|||
// milliseconds. If 0, we won't perform a dropdown animation.
|
||||
// Return Value:
|
||||
// - <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
|
||||
// > The trick is to make windows ‘think’ that our process and the target
|
||||
// > window (hwnd) are related by attaching the threads (using
|
||||
|
@ -1158,16 +1199,19 @@ void IslandWindow::_globalActivateWindow(const uint32_t dropdownDuration)
|
|||
{
|
||||
if (dropdownDuration > 0)
|
||||
{
|
||||
_dropdownWindow(dropdownDuration);
|
||||
_dropdownWindow(dropdownDuration, toMonitor);
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
{
|
||||
const DWORD windowThreadProcessId = GetWindowThreadProcessId(GetForegroundWindow(), nullptr);
|
||||
const DWORD windowThreadProcessId = GetWindowThreadProcessId(oldForegroundWindow, nullptr);
|
||||
const DWORD currentThreadId = GetCurrentThreadId();
|
||||
|
||||
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
|
||||
// window is on, if it's on another virtual desktop.
|
||||
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
|
||||
{
|
||||
return _isQuakeWindow;
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
void UnsetHotkeys(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;
|
||||
void IsQuakeWindow(bool isQuakeWindow) noexcept;
|
||||
|
@ -93,12 +93,21 @@ protected:
|
|||
void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam);
|
||||
long _calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize);
|
||||
|
||||
void _globalActivateWindow(const uint32_t dropdownDuration);
|
||||
void _dropdownWindow(const uint32_t dropdownDuration);
|
||||
void _globalActivateWindow(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 _doSlideAnimation(const uint32_t dropdownDuration, const bool down);
|
||||
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 };
|
||||
void _enterQuakeMode();
|
||||
|
||||
|
|
Loading…
Reference in New Issue