Recalculate quake window size when snapping across monitors (#10744)
## Summary of the Pull Request <kbd>win+shift+arrows</kbd> can be used to move windows to adjacent monitors. When that happens, we'll new re-calculate the size of the window for the new monitor. ## References * megathread: #8888 ## PR Checklist * [x] Closes #10274 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments In `WM_WINDOWPOSCHANGING`, the OS says "hey, I'm about to do {something} to your window. You cool with that?". We handle that message by: 1. checking if the window was _moved_ as a part of this message 2. getting the monitor that the window will be moved onto 3. If that monitor is different than the monitor the window is currently on, then * calculate how big the quake window should be on that monitor * tell the OS that's where we'd like to be. ## Validation Steps Performed * <kbd>win+shift+arrows</kbd> works right now * normal quake summoning still works right
This commit is contained in:
parent
fc64ff3029
commit
a151607c79
|
@ -274,7 +274,9 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam)
|
|||
LRESULT IslandWindow::_OnMoving(const WPARAM /*wParam*/, const LPARAM lParam)
|
||||
{
|
||||
LPRECT winRect = reinterpret_cast<LPRECT>(lParam);
|
||||
// If we're the quake window, prevent moving the window
|
||||
|
||||
// If we're the quake window, prevent moving the window. If we don't do
|
||||
// this, then Alt+Space...Move will still be able to move the window.
|
||||
if (IsQuakeWindow())
|
||||
{
|
||||
// Stuff our current window into the lParam, and return true. This
|
||||
|
@ -506,6 +508,61 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
|
|||
case WM_THEMECHANGED:
|
||||
UpdateWindowIconForActiveMetrics(_window.get());
|
||||
return 0;
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
{
|
||||
// GH#10274 - if the quake window gets moved to another monitor via aero
|
||||
// snap (win+shift+arrows), then re-adjust the size for the new monitor.
|
||||
if (IsQuakeWindow())
|
||||
{
|
||||
// Retrieve the suggested dimensions and make a rect and size.
|
||||
LPWINDOWPOS lpwpos = (LPWINDOWPOS)lparam;
|
||||
|
||||
// We only need to apply restrictions if the position is changing.
|
||||
// The SWP_ flags are confusing to read. This is
|
||||
// "if we're not moving the window, do nothing."
|
||||
if (WI_IsFlagSet(lpwpos->flags, SWP_NOMOVE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Figure out the suggested dimensions and position.
|
||||
RECT rcSuggested;
|
||||
rcSuggested.left = lpwpos->x;
|
||||
rcSuggested.top = lpwpos->y;
|
||||
rcSuggested.right = rcSuggested.left + lpwpos->cx;
|
||||
rcSuggested.bottom = rcSuggested.top + lpwpos->cy;
|
||||
|
||||
// Find the bounds of the current monitor, and the monitor that
|
||||
// we're suggested to be on.
|
||||
|
||||
HMONITOR current = MonitorFromWindow(_window.get(), MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO currentInfo;
|
||||
currentInfo.cbSize = sizeof(MONITORINFO);
|
||||
GetMonitorInfo(current, ¤tInfo);
|
||||
|
||||
HMONITOR proposed = MonitorFromRect(&rcSuggested, MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO proposedInfo;
|
||||
proposedInfo.cbSize = sizeof(MONITORINFO);
|
||||
GetMonitorInfo(proposed, &proposedInfo);
|
||||
|
||||
// If the monitor changed...
|
||||
if (til::rectangle{ proposedInfo.rcMonitor } !=
|
||||
til::rectangle{ currentInfo.rcMonitor })
|
||||
{
|
||||
const auto newWindowRect{ _getQuakeModeSize(proposed) };
|
||||
|
||||
// Inform User32 that we want to be placed at the position
|
||||
// and dimensions that _getQuakeModeSize returned. When we
|
||||
// snap across monitor boundaries, this will re-evaluate our
|
||||
// size for the new monitor.
|
||||
lpwpos->x = newWindowRect.left<int>();
|
||||
lpwpos->y = newWindowRect.top<int>();
|
||||
lpwpos->cx = newWindowRect.width<int>();
|
||||
lpwpos->cy = newWindowRect.height<int>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
case CM_NOTIFY_FROM_TRAY:
|
||||
{
|
||||
switch (LOWORD(lparam))
|
||||
|
@ -1448,6 +1505,13 @@ void IslandWindow::IsQuakeWindow(bool isQuakeWindow) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Enter quake mode for the monitor this window is currently on. This involves
|
||||
// resizing it to the top half of the monitor.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void IslandWindow::_enterQuakeMode()
|
||||
{
|
||||
if (!_window)
|
||||
|
@ -1457,6 +1521,29 @@ void IslandWindow::_enterQuakeMode()
|
|||
|
||||
RECT windowRect = GetWindowRect();
|
||||
HMONITOR hmon = MonitorFromRect(&windowRect, MONITOR_DEFAULTTONEAREST);
|
||||
|
||||
// Get the size and position of the window that we should occupy
|
||||
const auto newRect{ _getQuakeModeSize(hmon) };
|
||||
|
||||
SetWindowPos(GetHandle(),
|
||||
HWND_TOP,
|
||||
newRect.left<int>(),
|
||||
newRect.top<int>(),
|
||||
newRect.width<int>(),
|
||||
newRect.height<int>(),
|
||||
SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the size and position of the window that a "quake mode" should occupy
|
||||
// on the given monitor.
|
||||
// - The window will occupy the top half of the monitor.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
til::rectangle IslandWindow::_getQuakeModeSize(HMONITOR hmon)
|
||||
{
|
||||
MONITORINFO nearestMonitorInfo;
|
||||
|
||||
UINT dpix = USER_DEFAULT_SCREEN_DPI;
|
||||
|
@ -1488,14 +1575,7 @@ void IslandWindow::_enterQuakeMode()
|
|||
availableSpace.height() / 2
|
||||
};
|
||||
|
||||
const til::rectangle newRect{ origin, dimensions };
|
||||
SetWindowPos(GetHandle(),
|
||||
HWND_TOP,
|
||||
newRect.left<int>(),
|
||||
newRect.top<int>(),
|
||||
newRect.width<int>(),
|
||||
newRect.height<int>(),
|
||||
SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE);
|
||||
return til::rectangle{ origin, dimensions };
|
||||
}
|
||||
|
||||
DEFINE_EVENT(IslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
|
||||
|
|
|
@ -109,7 +109,9 @@ protected:
|
|||
void _moveToMonitor(const MONITORINFO activeMonitor);
|
||||
|
||||
bool _isQuakeWindow{ false };
|
||||
|
||||
void _enterQuakeMode();
|
||||
til::rectangle _getQuakeModeSize(HMONITOR hmon);
|
||||
|
||||
void _summonWindowRoutineBody(winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior args);
|
||||
|
||||
|
|
Loading…
Reference in a new issue