From 541b151cff6b5c243e0c6fa3ed64b3daaf89615f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 8 Mar 2022 23:00:47 +0100 Subject: [PATCH] Win32: Fix maximization showing a hidden window The normal way of maximizing a window also makes it visible. This implements window maximization manually for when the window passed to glfwMaximizeWindow is hidden. This will very likely not be forward-compatible and should be replaced. (cherry picked from commit 723f3eb40db27a26c846f0d38ee24af3365ffa96) --- README.md | 1 + src/win32_init.c | 2 ++ src/win32_platform.h | 3 +++ src/win32_window.c | 58 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d0f46849..2bd4b63a 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ information on what to include when reporting a bug. monitor (#1806) - [Win32] Bugfix: The default restored window position was lost when creating a maximized window + - [Win32] Bugfix: `glfwMaximizeWindow` would make a hidden window visible - [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003) - [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences - [X11] Bugfix: Waiting for events would fail if file descriptor was too large diff --git a/src/win32_init.c b/src/win32_init.c index 40eb795f..cb6e8222 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -92,6 +92,8 @@ static GLFWbool loadLibraries(void) GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow"); _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi) GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi"); + _glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi) + GetProcAddress(_glfw.win32.user32.instance, "GetSystemMetricsForDpi"); _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll"); if (_glfw.win32.dinput8.instance) diff --git a/src/win32_platform.h b/src/win32_platform.h index b964e135..2e947ecf 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -235,12 +235,14 @@ typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND); typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE); typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND); typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT); +typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT); #define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_ #define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_ #define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_ #define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_ #define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_ #define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_ +#define GetSystemMetricsForDpi _glfw.win32.user32.GetSystemMetricsForDpi_ // dwmapi.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); @@ -366,6 +368,7 @@ typedef struct _GLFWlibraryWin32 PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_; PFN_GetDpiForWindow GetDpiForWindow_; PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_; + PFN_GetSystemMetricsForDpi GetSystemMetricsForDpi_; } user32; struct { diff --git a/src/win32_window.c b/src/win32_window.c index a68b3c8b..c124ab23 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -489,6 +489,59 @@ static void releaseMonitor(_GLFWwindow* window) _glfwRestoreVideoModeWin32(window->monitor); } +// Manually maximize the window, for when SW_MAXIMIZE cannot be used +// +static void maximizeWindowManually(_GLFWwindow* window) +{ + RECT rect; + DWORD style; + MONITORINFO mi = { sizeof(mi) }; + + GetMonitorInfo(MonitorFromWindow(window->win32.handle, + MONITOR_DEFAULTTONEAREST), &mi); + + rect = mi.rcWork; + + if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE) + { + if (rect.right - rect.left > window->maxwidth) + rect.right = rect.left + window->maxwidth; + if (rect.bottom - rect.top > window->maxheight) + rect.bottom = rect.top + window->maxheight; + } + + style = GetWindowLongW(window->win32.handle, GWL_STYLE); + style |= WS_MAXIMIZE; + SetWindowLongW(window->win32.handle, GWL_STYLE, style); + + if (window->decorated) + { + const DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); + + if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) + { + const UINT dpi = GetDpiForWindow(window->win32.handle); + AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi); + OffsetRect(&rect, 0, GetSystemMetricsForDpi(SM_CYCAPTION, dpi)); + } + else + { + AdjustWindowRectEx(&rect, style, FALSE, exStyle); + OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION)); + } + + if (rect.bottom > mi.rcWork.bottom) + rect.bottom = mi.rcWork.bottom; + } + + SetWindowPos(window->win32.handle, HWND_TOP, + rect.left, + rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); +} + // Window callback function (handles window messages) // static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, @@ -1692,7 +1745,10 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) void _glfwPlatformMaximizeWindow(_GLFWwindow* window) { - ShowWindow(window->win32.handle, SW_MAXIMIZE); + if (IsWindowVisible(window->win32.handle)) + ShowWindow(window->win32.handle, SW_MAXIMIZE); + else + maximizeWindowManually(window); } void _glfwPlatformShowWindow(_GLFWwindow* window)