diff --git a/doc/specs/#653 - Quake Mode/#653 - Quake Mode.md b/doc/specs/#653 - Quake Mode/#653 - Quake Mode.md index a7a2eeb45..fee697f9c 100644 --- a/doc/specs/#653 - Quake Mode/#653 - Quake Mode.md +++ b/doc/specs/#653 - Quake Mode/#653 - Quake Mode.md @@ -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: -"toCurrent"
Summon the MRU window TO the current monitor -Go to the desktop the window is on, move to this monitor -Move the window to this desktop, move to this monitor +"toCurrent"
Summon the MRU window TO the monitor with the foreground window +Go to the desktop the window is on, move to the monitor with the foreground window +Move the window to this desktop, move to the monitor with the foreground window 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 + + + + + + "toMouse" + [2]
+ Summon the MRU window TO the monitor with the mouse +Go to the desktop the window is on, move to the monitor with the mouse +Move the window to this desktop, move to the monitor with the mouse + + +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 @@ -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. +[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 diff --git a/src/cascadia/Remoting/Peasant.idl b/src/cascadia/Remoting/Peasant.idl index 33064bc9d..bc36e3f30 100644 --- a/src/cascadia/Remoting/Peasant.idl +++ b/src/cascadia/Remoting/Peasant.idl @@ -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 diff --git a/src/cascadia/Remoting/SummonWindowBehavior.h b/src/cascadia/Remoting/SummonWindowBehavior.h index caa11ee3b..e9cc18371 100644 --- a/src/cascadia/Remoting/SummonWindowBehavior.h +++ b/src/cascadia/Remoting/SummonWindowBehavior.h @@ -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() } {}; }; diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index 520639880..7d89207e8 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -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(); 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() }; 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); } }; diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index 71c16a55e..a7a7fd079 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -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; }; }; diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index 57607607e..12938e4ca 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -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 }, + }; +}; diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index eebbc2920..6e4e24bda 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -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()) { diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index f74de76ed..33f24feab 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -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::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: // - -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: +// - +// 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: +// - +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: +// - +// Return Value: +// - +void IslandWindow::_moveToMonitorOfMouse() +{ + _moveToMonitor(_getMonitorForCursor()); +} + +// Method Description: +// - Move our window to the monitor that the given HWND is on. +// Arguments: +// - +// Return Value: +// - +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: +// - +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(), + newOrigin.y(), + currentWindowRect.width(), + currentWindowRect.height(), + SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + } +} + bool IslandWindow::IsQuakeWindow() const noexcept { return _isQuakeWindow; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 09c27ffba..470e8ecac 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -41,7 +41,7 @@ public: void UnsetHotkeys(const std::vector& hotkeyList); void SetGlobalHotkeys(const std::vector& 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();