From 8247e90eea461d21fa43d0512d202efbf2392f8c Mon Sep 17 00:00:00 2001 From: bilsaboob Date: Mon, 19 Sep 2022 22:45:02 +0200 Subject: [PATCH] add custom window resize handling --- include/GLFW/glfw3.h | 10 ++++++++- make.ps1 | 7 +++++-- src/internal.h | 4 +++- src/win32_window.c | 43 ++++++++++++++++++++++++++++++++------- src/window.c | 48 ++++++++++++++++++++++++++++++++++++++++++-- tests/events.c | 25 +++++++++++++++++++++++ 6 files changed, 124 insertions(+), 13 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index f98b6f71..20389423 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1588,7 +1588,11 @@ typedef void (* GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos); * * @ingroup window */ -typedef void (* GLFWwindowsizefun)(GLFWwindow* window, int width, int height); +typedef int (* GLFWwindowsizefun)(GLFWwindow* window, int width, int height); + +typedef void (* GLFWwindowsizebeginfun)(GLFWwindow* window); + +typedef void (* GLFWwindowsizeendfun)(GLFWwindow* window); /*! @brief The function pointer type for window close callbacks. * @@ -4159,6 +4163,10 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindow */ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun callback); +GLFWAPI GLFWwindowsizebeginfun glfwSetWindowSizeBeginCallback(GLFWwindow* window, GLFWwindowsizebeginfun callback); + +GLFWAPI GLFWwindowsizeendfun glfwSetWindowSizeEndCallback(GLFWwindow* window, GLFWwindowsizeendfun callback); + /*! @brief Sets the close callback for the specified window. * * This function sets the close callback of the specified window, which is diff --git a/make.ps1 b/make.ps1 index 8d7a3c44..26e0e2e5 100644 --- a/make.ps1 +++ b/make.ps1 @@ -63,5 +63,8 @@ cd ..\.. Write-Host "" Write-Host "-----------------------------" - - +$libOutputDir = "$buildPath/src/Release/*" +$examplesOutputDir = "$buildPath/examples/Release" +$testsOutputDir = "$buildPath/tests/Release" +Copy-item -Force -Recurse -Verbose $libOutputDir -Destination $examplesOutputDir +Copy-item -Force -Recurse -Verbose $libOutputDir -Destination $testsOutputDir diff --git a/src/internal.h b/src/internal.h index 781c8cdc..76cf2c33 100644 --- a/src/internal.h +++ b/src/internal.h @@ -554,6 +554,8 @@ struct _GLFWwindow struct { GLFWwindowposfun pos; GLFWwindowsizefun size; + GLFWwindowsizebeginfun sizeBegin; + GLFWwindowsizeendfun sizeEnd; GLFWwindowclosefun close; GLFWwindowrefreshfun refresh; GLFWwindowfocusfun focus; @@ -905,7 +907,7 @@ GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name); void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused); void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos); -void _glfwInputWindowSize(_GLFWwindow* window, int width, int height); +int _glfwInputWindowSize(_GLFWwindow* window, int width, int height); void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height); void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale); diff --git a/src/win32_window.c b/src/win32_window.c index 1a9a468a..e09fb664 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -986,6 +986,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } case WM_ENTERSIZEMOVE: + _glfwInputWindowSizeBegin(window); case WM_ENTERMENULOOP: { if (window->win32.frameAction) @@ -1002,6 +1003,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } case WM_EXITSIZEMOVE: + _glfwInputWindowSizeEnd(window); case WM_EXITMENULOOP: { if (window->win32.frameAction) @@ -1040,6 +1042,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l window->win32.width = width; window->win32.height = height; + //printf("window resize: (%i,%i)\n", width, height); + _glfwInputFramebufferSize(window, width, height); _glfwInputWindowSize(window, width, height); } @@ -1065,24 +1069,49 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l if (_glfw.win32.capturedCursorWindow == window) captureCursor(window); + //printf("window move: (%i,%i)\n", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as // those macros do not handle negative window positions correctly _glfwInputWindowPos(window, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + return 0; } case WM_SIZING: { - if (window->numer == GLFW_DONT_CARE || - window->denom == GLFW_DONT_CARE) - { - break; - } + RECT* rc = (RECT*)lParam; + + RECT clientArea; + GetClientRect(window->win32.handle, &clientArea); - applyAspectRatio(window, (int) wParam, (RECT*) lParam); - return TRUE; + RECT windowArea; + GetWindowRect(window->win32.handle, &windowArea); + + //printf("window sizing: (%i,%i,%i,%i) / (%i,%i,%i,%i) / (%i,%i,%i,%i)\n", rc->left, rc->top, rc->right, rc->bottom, windowArea.left, windowArea.top, windowArea.right, windowArea.bottom, clientArea.left, clientArea.top, clientArea.right, clientArea.bottom); + + // notify of desired size change + int windowWidth = windowArea.right - windowArea.left; + int windowHeight = windowArea.bottom - windowArea.top; + int newWidth = rc->right - rc->left - (windowWidth - clientArea.right); + int newHeight = rc->bottom - rc->top - (windowHeight - clientArea.bottom); + int handled = _glfwInputWindowSize(window, newWidth, newHeight); + + if (handled > 0) + { + *rc = windowArea; + return 0; + } else { + if (window->numer == GLFW_DONT_CARE || window->denom == GLFW_DONT_CARE) + { + break; + } + + applyAspectRatio(window, (int) wParam, (RECT*) lParam); + return TRUE; + } } case WM_GETMINMAXINFO: diff --git a/src/window.c b/src/window.c index 1c8519ff..38a60205 100644 --- a/src/window.c +++ b/src/window.c @@ -85,14 +85,36 @@ void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) // Notifies shared code that a window has been resized // The size is specified in screen coordinates // -void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) +int _glfwInputWindowSize(_GLFWwindow* window, int width, int height) { assert(window != NULL); assert(width >= 0); assert(height >= 0); if (window->callbacks.size) - window->callbacks.size((GLFWwindow*) window, width, height); + return window->callbacks.size((GLFWwindow*) window, width, height); + + return 0; +} + +// Notifies shared code that a window resizing has started +// +void _glfwInputWindowSizeBegin(_GLFWwindow* window) +{ + assert(window != NULL); + + if (window->callbacks.sizeBegin) + window->callbacks.sizeBegin((GLFWwindow*) window); +} + +// Notifies shared code that a window resizing has finished +// +void _glfwInputWindowSizeEnd(_GLFWwindow* window) +{ + assert(window != NULL); + + if (window->callbacks.sizeEnd) + window->callbacks.sizeEnd((GLFWwindow*) window); } // Notifies shared code that a window has been iconified or restored @@ -1042,6 +1064,28 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, return cbfun; } +GLFWAPI GLFWwindowsizebeginfun glfwSetWindowSizeBeginCallback(GLFWwindow* handle, + GLFWwindowsizebeginfun cbfun) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP(GLFWwindowsizebeginfun, window->callbacks.sizeBegin, cbfun); + return cbfun; +} + +GLFWAPI GLFWwindowsizeendfun glfwSetWindowSizeEndCallback(GLFWwindow* handle, + GLFWwindowsizeendfun cbfun) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP(GLFWwindowsizeendfun, window->callbacks.sizeEnd, cbfun); + return cbfun; +} + GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, GLFWwindowclosefun cbfun) { diff --git a/tests/events.c b/tests/events.c index d61e374d..26e8d7b9 100644 --- a/tests/events.c +++ b/tests/events.c @@ -294,11 +294,24 @@ static void window_pos_callback(GLFWwindow* window, int x, int y) counter++, slot->number, glfwGetTime(), x, y);*/ } +int desiredWidth = 0; +int desiredHeight = 0; + static void window_size_callback(GLFWwindow* window, int width, int height) { Slot* slot = glfwGetWindowUserPointer(window); /*printf("%08x to %i at %0.3f: Window size: %i %i\n", counter++, slot->number, glfwGetTime(), width, height);*/ + + desiredWidth = width; + desiredHeight = height; + + int currentWidth = 0; + int currentHeight = 0; + glfwGetWindowSize(window, ¤tWidth, ¤tHeight); + if (currentWidth != desiredWidth || currentHeight != desiredHeight) { + glfwSetWindowSize(window, desiredWidth, desiredHeight); + } } static void framebuffer_size_callback(GLFWwindow* window, int width, int height) @@ -588,6 +601,9 @@ int main(int argc, char** argv) height = 480; } + desiredWidth = width; + desiredHeight = height; + slots = calloc(count, sizeof(Slot)); for (i = 0; i < count; i++) @@ -660,6 +676,15 @@ int main(int argc, char** argv) glfwWaitEvents(); + int currentWidth = 0; + int currentHeight = 0; + glfwGetWindowSize(slots[0].window, ¤tWidth, ¤tHeight); + + if (currentWidth != desiredWidth || currentHeight != desiredHeight) { + printf("will resize to: (%i, %i)", desiredWidth, desiredHeight); + glfwSetWindowSize(slots[0].window, desiredWidth, desiredHeight); + } + // Workaround for an issue with msvcrt and mintty fflush(stdout); }