From ea2bd12045fcb013b662b764962b336fa337572c Mon Sep 17 00:00:00 2001 From: Jonathna Cline Date: Wed, 27 Mar 2024 04:39:23 -0700 Subject: [PATCH] works fine but resizing the window causes things to scale in very very strange ways --- src/win32_init.c | 53 +++++++++++++++++++++++++++++++---- src/win32_platform.h | 7 +++++ src/win32_window.c | 67 +++++++++++++++++++++++++++++--------------- 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/src/win32_init.c b/src/win32_init.c index 77ab56ba..ad0b3c4d 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -370,7 +370,6 @@ static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP // static GLFWbool createHelperWindow(void) { - MSG msg; WNDCLASSEXW wc = { sizeof(wc) }; wc.style = CS_OWNDC; @@ -421,11 +420,7 @@ static GLFWbool createHelperWindow(void) DEVICE_NOTIFY_WINDOW_HANDLE); } - while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } + SwitchToFiber(_glfw.win32.messageFiber); return GLFW_TRUE; } @@ -583,6 +578,41 @@ BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp) return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; } +// Windows message dispatch fiber +void CALLBACK messageFiberProc(LPVOID lpFiberParameter) +{ + MSG msg; + _GLFWwindow* window; + (void)lpFiberParameter; + + for (;;) + { + while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_QUIT) + { + // NOTE: While GLFW does not itself post WM_QUIT, other processes + // may post it to this one, for example Task Manager + // HACK: Treat WM_QUIT as a close on all windows + + window = _glfw.windowListHead; + while (window) + { + _glfwInputWindowCloseRequest(window); + window = window->next; + } + } + else + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + + SwitchToFiber(_glfw.win32.mainFiber); + } +} + // Checks whether we are on at least the specified build of Windows 10 // BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build) @@ -695,6 +725,14 @@ int _glfwInitWin32(void) else if (IsWindowsVistaOrGreater()) SetProcessDPIAware(); + _glfw.win32.mainFiber = ConvertThreadToFiber(NULL); + if (!_glfw.win32.mainFiber) + return GLFW_FALSE; + + _glfw.win32.messageFiber = CreateFiber(0, &messageFiberProc, NULL); + if (!_glfw.win32.messageFiber) + return GLFW_FALSE; + if (!createHelperWindow()) return GLFW_FALSE; @@ -716,6 +754,9 @@ void _glfwTerminateWin32(void) UnregisterClassW(MAKEINTATOM(_glfw.win32.helperWindowClass), _glfw.win32.instance); if (_glfw.win32.mainWindowClass) UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance); + + DeleteFiber(_glfw.win32.messageFiber); + ConvertFiberToThread(); _glfw_free(_glfw.win32.clipboardString); _glfw_free(_glfw.win32.rawInput); diff --git a/src/win32_platform.h b/src/win32_platform.h index a2f86852..6e45e81e 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -433,6 +433,11 @@ typedef struct _GLFWwindowWin32 int lastCursorPosX, lastCursorPosY; // The last received high surrogate when decoding pairs of UTF-16 messages WCHAR highSurrogate; + + // If user pressed mouse button on window title bar + UINT ncMouseButton; + LPARAM ncMousePos; + } _GLFWwindowWin32; // Win32-specific global data @@ -458,6 +463,8 @@ typedef struct _GLFWlibraryWin32 RAWINPUT* rawInput; int rawInputSize; UINT mouseTrailSize; + LPVOID messageFiber; + LPVOID mainFiber; // The cursor handle to use to hide the cursor (NULL or a transparent cursor) HCURSOR blankCursor; diff --git a/src/win32_window.c b/src/win32_window.c index 7d26f0b1..e3a29c1a 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -854,12 +854,46 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l return 0; } + case WM_NCLBUTTONDOWN: + { + if (wParam == HTCAPTION) + { + window->win32.ncMouseButton = uMsg; + window->win32.ncMousePos = lParam; + return 0; + } + break; + } + + case WM_NCMOUSEMOVE: + { + if (window->win32.ncMouseButton) + { + if (GET_X_LPARAM(window->win32.ncMousePos) != GET_X_LPARAM(lParam) || + GET_Y_LPARAM(window->win32.ncMousePos) != GET_Y_LPARAM(lParam)) + { + DefWindowProcW(hWnd, window->win32.ncMouseButton, HTCAPTION, window->win32.ncMousePos); + window->win32.ncMouseButton = 0; + } + } + break; + } case WM_MOUSEMOVE: { const int x = GET_X_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam); + if (window->win32.ncMouseButton) + { + if (GET_X_LPARAM(window->win32.ncMousePos) != x || + GET_Y_LPARAM(window->win32.ncMousePos) != y) + { + DefWindowProcW(hWnd, window->win32.ncMouseButton, HTCAPTION, window->win32.ncMousePos); + window->win32.ncMouseButton = 0; + } + } + if (!window->win32.cursorTracked) { TRACKMOUSEEVENT tme; @@ -1000,7 +1034,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l enableCursor(window); else if (window->cursorMode == GLFW_CURSOR_CAPTURED) releaseCursor(); - + SetTimer(hWnd, 1, 1, NULL); break; } @@ -1016,9 +1050,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l disableCursor(window); else if (window->cursorMode == GLFW_CURSOR_CAPTURED) captureCursor(window); + KillTimer(hWnd, 1); break; } + case WM_TIMER: + { + if (wParam == 1) + { + SwitchToFiber(_glfw.win32.mainFiber); + } + break; + } case WM_SIZE: { @@ -2104,27 +2147,7 @@ void _glfwPollEventsWin32(void) HWND handle; _GLFWwindow* window; - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - { - // NOTE: While GLFW does not itself post WM_QUIT, other processes - // may post it to this one, for example Task Manager - // HACK: Treat WM_QUIT as a close on all windows - - window = _glfw.windowListHead; - while (window) - { - _glfwInputWindowCloseRequest(window); - window = window->next; - } - } - else - { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - } + SwitchToFiber(_glfw.win32.messageFiber); // HACK: Release modifier keys that the system did not emit KEYUP for // NOTE: Shift keys on Windows tend to "stick" when both are pressed as