From 2ae3e0c8d7d237523cf7ec8c4ce95a7fdb40114f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 27 Mar 2022 19:40:35 +0200 Subject: [PATCH] Win32: Add separate window class for helper window The current window procedure needs to deal with messages both for user created windows and the hidden helper window. This commit separates out the device message handling of the helper window, allowing both window procedures to be less complicated. --- README.md | 1 + src/win32_init.c | 53 +++++++++++++++++++++++++++++++++++++++++++- src/win32_window.c | 55 ++++++++++------------------------------------ 3 files changed, 64 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index b805e787..fe5a2c76 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,7 @@ information on what to include when reporting a bug. - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access to the window menu - [Win32] Added a version info resource to the GLFW DLL + - [Win32] Made hidden helper window use its own window class - [Win32] Disabled framebuffer transparency on Windows 7 when DWM windows are opaque (#1512) - [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused diff --git a/src/win32_init.c b/src/win32_init.c index 1cdc5b98..c2dc1322 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -331,15 +331,63 @@ static void createKeyTables(void) } } +// Window procedure for the hidden helper window +// +static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_DISPLAYCHANGE: + _glfwPollMonitorsWin32(); + break; + + case WM_DEVICECHANGE: + { + if (!_glfw.joysticksInitialized) + break; + + if (wParam == DBT_DEVICEARRIVAL) + { + DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; + if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + _glfwDetectJoystickConnectionWin32(); + } + else if (wParam == DBT_DEVICEREMOVECOMPLETE) + { + DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; + if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + _glfwDetectJoystickDisconnectionWin32(); + } + + break; + } + } + + return DefWindowProcW(hWnd, uMsg, wParam, lParam); +} + // Creates a dummy window for behind-the-scenes work // static GLFWbool createHelperWindow(void) { MSG msg; + WNDCLASSEXW wc = { sizeof(wc) }; + + wc.style = CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) helperWindowProc; + wc.hInstance = _glfw.win32.instance; + wc.lpszClassName = L"GLFW3 Helper"; + + if (!RegisterClassExW(&wc)) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WIn32: Failed to register helper window class"); + return GLFW_FALSE; + } _glfw.win32.helperWindowHandle = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, - _GLFW_WNDCLASSNAME, + L"GLFW3 Helper", L"GLFW message window", WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 1, 1, @@ -663,7 +711,10 @@ void _glfwTerminateWin32(void) UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle); if (_glfw.win32.helperWindowHandle) + { DestroyWindow(_glfw.win32.helperWindowHandle); + UnregisterClassW(L"GLFW3 Helper", _glfw.win32.instance); + } _glfwUnregisterWindowClassWin32(); diff --git a/src/win32_window.c b/src/win32_window.c index 95174497..cefb2cf6 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -533,59 +533,26 @@ static void maximizeWindowManually(_GLFWwindow* window) SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); } -// Window callback function (handles window messages) +// Window procedure for user-created windows // static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { _GLFWwindow* window = GetPropW(hWnd, L"GLFW"); if (!window) { - // This is the message handling for the hidden helper window - // and for a regular window during its initial creation - - switch (uMsg) + if (uMsg == WM_NCCREATE) { - case WM_NCCREATE: + if (_glfwIsWindows10Version1607OrGreaterWin32()) { - if (_glfwIsWindows10Version1607OrGreaterWin32()) - { - const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam; - const _GLFWwndconfig* wndconfig = cs->lpCreateParams; + const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam; + const _GLFWwndconfig* wndconfig = cs->lpCreateParams; - // On per-monitor DPI aware V1 systems, only enable - // non-client scaling for windows that scale the client area - // We need WM_GETDPISCALEDSIZE from V2 to keep the client - // area static when the non-client area is scaled - if (wndconfig && wndconfig->scaleToMonitor) - EnableNonClientDpiScaling(hWnd); - } - - break; - } - - case WM_DISPLAYCHANGE: - _glfwPollMonitorsWin32(); - break; - - case WM_DEVICECHANGE: - { - if (!_glfw.joysticksInitialized) - break; - - if (wParam == DBT_DEVICEARRIVAL) - { - DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; - if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) - _glfwDetectJoystickConnectionWin32(); - } - else if (wParam == DBT_DEVICEREMOVECOMPLETE) - { - DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; - if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) - _glfwDetectJoystickDisconnectionWin32(); - } - - break; + // On per-monitor DPI aware V1 systems, only enable + // non-client scaling for windows that scale the client area + // We need WM_GETDPISCALEDSIZE from V2 to keep the client + // area static when the non-client area is scaled + if (wndconfig && wndconfig->scaleToMonitor) + EnableNonClientDpiScaling(hWnd); } }