diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 3e82f55c583..b8e1b16ef4e 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -93,7 +93,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, } RECT win_rect = {left, top, long(left + width), long(top + height)}; - adjustWindowRectForClosestMonitor(&win_rect, style, extended_style); + adjustWindowRectForDesktop(&win_rect, style, extended_style); wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); m_hWnd = ::CreateWindowExW(extended_style, /* window extended style */ @@ -298,24 +298,52 @@ GHOST_WindowWin32::~GHOST_WindowWin32() m_directManipulationHelper = NULL; } -void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect, - DWORD dwStyle, - DWORD dwExStyle) +void GHOST_WindowWin32::adjustWindowRectForDesktop(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle) { - /* Get Details of the closest monitor. */ - HMONITOR hmonitor = MonitorFromRect(win_rect, MONITOR_DEFAULTTONEAREST); + /* Windows can span multiple monitors, but must be usable. The desktop can have a larger + * surface than all monitors combined, for example when two monitors are aligned diagonally. + * Therefore we ensure that all the window's corners are within some monitor's Work area. */ + + POINT pt; + HMONITOR hmonitor; MONITORINFOEX monitor; monitor.cbSize = sizeof(MONITORINFOEX); monitor.dwFlags = 0; - GetMonitorInfo(hmonitor, &monitor); - /* Constrain requested size and position to fit within this monitor. */ - LONG width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect->right - win_rect->left); - LONG height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect->bottom - win_rect->top); - win_rect->left = min(max(monitor.rcWork.left, win_rect->left), monitor.rcWork.right - width); - win_rect->right = win_rect->left + width; - win_rect->top = min(max(monitor.rcWork.top, win_rect->top), monitor.rcWork.bottom - height); - win_rect->bottom = win_rect->top + height; + /* Note that with MonitorFromPoint using MONITOR_DEFAULTTONEAREST, it will return + * the exact monitor if there is one at the location or the nearest monitor if not. */ + + /* Top-left. */ + pt.x = win_rect->left; + pt.y = win_rect->top; + hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(hmonitor, &monitor); + win_rect->top = max(win_rect->top, monitor.rcWork.top); + win_rect->left = max(win_rect->left, monitor.rcWork.left); + + /* Top-right. */ + pt.x = win_rect->right; + pt.y = win_rect->top; + hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(hmonitor, &monitor); + win_rect->top = max(win_rect->top, monitor.rcWork.top); + win_rect->right = min(win_rect->right, monitor.rcWork.right); + + /* Bottom-left. */ + pt.x = win_rect->left; + pt.y = win_rect->bottom; + hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(hmonitor, &monitor); + win_rect->bottom = min(win_rect->bottom, monitor.rcWork.bottom); + win_rect->left = max(win_rect->left, monitor.rcWork.left); + + /* Bottom-right. */ + pt.x = win_rect->right; + pt.y = win_rect->bottom; + hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(hmonitor, &monitor); + win_rect->bottom = min(win_rect->bottom, monitor.rcWork.bottom); + win_rect->right = min(win_rect->right, monitor.rcWork.right); /* With Windows 10 and newer we can adjust for chrome that differs with DPI and scale. */ GHOST_WIN32_AdjustWindowRectExForDpi fpAdjustWindowRectExForDpi = nullptr; @@ -334,9 +362,6 @@ void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect, else { AdjustWindowRectEx(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle); } - - /* But never allow a top position that can hide part of the title bar. */ - win_rect->top = max(monitor.rcWork.top, win_rect->top); } bool GHOST_WindowWin32::getValid() const diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 44071f0915e..b6c4aa25c79 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -87,12 +87,12 @@ class GHOST_WindowWin32 : public GHOST_Window { ~GHOST_WindowWin32(); /** - * Adjusts a requested window rect to fit and position correctly in monitor. + * Adjusts a requested window rect to fit and position within the desktop. * \param win_rect: pointer to rectangle that will be modified. * \param dwStyle: The Window Style of the window whose required size is to be calculated. * \param dwExStyle: The Extended Window Style of the window. */ - void adjustWindowRectForClosestMonitor(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle); + void adjustWindowRectForDesktop(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle); /** * Returns indication as to whether the window is valid.