From 073c0cceb5a626ebafbfcc72af3db0b2800c687b Mon Sep 17 00:00:00 2001 From: Robbin Marcus Date: Sat, 19 Jan 2019 20:35:42 +0100 Subject: [PATCH 01/10] Support for drag and resize operations --- README.md | 4 +++ include/GLFW/glfw3.h | 57 +++++++++++++++++++++++++++++++ src/cocoa_window.m | 9 +++++ src/internal.h | 2 ++ src/null_window.c | 8 +++++ src/win32_window.c | 43 +++++++++++++++++++++++ src/window.c | 23 +++++++++++++ src/wl_window.c | 43 +++++++++++++++++++++++ src/x11_window.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ tests/windows.c | 7 ++++ 10 files changed, 277 insertions(+) diff --git a/README.md b/README.md index d50e5ddb..742f8073 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,10 @@ information on what to include when reporting a bug. (#235,#439,#677,#845,#898) - Added `glfwRequestWindowAttention` function for requesting attention from the user (#732,#988) +- Added `glfwDragWindow` function for starting a drag operation on a window + (#987) +- Added `glfwResizeWindow` function for starting a resize operation on a window + (#923) - Added `glfwGetKeyScancode` function that allows retrieving platform dependent scancodes for keys (#830) - Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 8606edc1..d4491e5e 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1015,6 +1015,15 @@ extern "C" { #define GLFW_EGL_CONTEXT_API 0x00036002 #define GLFW_OSMESA_CONTEXT_API 0x00036003 +#define GLFW_WINDOW_LEFT 0 +#define GLFW_WINDOW_TOP 1 +#define GLFW_WINDOW_RIGHT 2 +#define GLFW_WINDOW_BOTTOM 3 +#define GLFW_WINDOW_TOPLEFT 4 +#define GLFW_WINDOW_TOPRIGHT 5 +#define GLFW_WINDOW_BOTTOMLEFT 6 +#define GLFW_WINDOW_BOTTOMRIGHT 7 + /*! @defgroup shapes Standard cursor shapes * @brief Standard system cursor shapes. * @@ -3192,6 +3201,54 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window); */ GLFWAPI void glfwFocusWindow(GLFWwindow* window); +/*! @brief Starts drag operation to the specified window. + * + * This function starts the drag operation of the specified window. + * + * @param[in] window The window to start the dragging operation. + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_drag + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwDragWindow(GLFWwindow* handle); + +/*! @brief Starts a resize operation with the specified window. + * + * This function starts a resize operation on one of the borders of the + * specified window. + * + * this function must be called from a pointer or touch event callback, + * otherwise it risks reacting to a different event. + * + * The borders are [GLFW_WINDOW_LEFT](@ref GLFW_GLFW_WINDOW_LEFT), + * [GLFW_WINDOW_TOP](@ref GLFW_WINDOW_TOP), + * [GLFW_WINDOW_RIGHT](@ref GLFW_WINDOW_RIGHT), + * [GLFW_WINDOW_BOTTOM](@ref GLFW_WINDOW_BOTTOM), + * [GLFW_WINDOW_TOPLEFT](@ref GLFW_WINDOW_TOPLEFT), + * [GLFW_WINDOW_TOPRIGHT](@ref GLFW_WINDOW_TOPRIGHT), + * [GLFW_WINDOW_BOTTOMLEFT](@ref GLFW_WINDOW_BOTTOMLEFT) and + * [GLFW_WINDOW_BOTTOMRIGHT](@ref GLFW_WINDOW_BOTTOMRIGHT). + * + * @param[in] window The window to start the resize operation. + * @param[in] border One of the window borders. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_resize + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwResizeWindow(GLFWwindow* window, int border); + /*! @brief Requests user attention to the specified window. * * This function requests user attention to the specified window. On diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 7011a797..098e6cf3 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1146,6 +1146,15 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) [window->ns.object makeKeyAndOrderFront:nil]; } +void _glfwPlatformDragWindow(_GLFWwindow* window) +{ + [window->ns.object performWindowDragWithEvent:[NSApp currentEvent]]; +} + +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ +} + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/internal.h b/src/internal.h index c7c5bf8f..2e27d4f3 100644 --- a/src/internal.h +++ b/src/internal.h @@ -655,6 +655,8 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window); void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); +void _glfwPlatformDragWindow(_GLFWwindow* window); +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border); int _glfwPlatformWindowFocused(_GLFWwindow* window); int _glfwPlatformWindowIconified(_GLFWwindow* window); int _glfwPlatformWindowVisible(_GLFWwindow* window); diff --git a/src/null_window.c b/src/null_window.c index 6a54cfe5..b9f168da 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -217,6 +217,14 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) { } +void _glfwPlatformDragWindow(_GLFWwindow* window) +{ +} + +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ +} + int _glfwPlatformWindowFocused(_GLFWwindow* window) { return GLFW_FALSE; diff --git a/src/win32_window.c b/src/win32_window.c index a0abca06..883afb2e 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -33,6 +33,7 @@ #include #include #include +#include #define _GLFW_KEY_INVALID -2 @@ -1656,6 +1657,48 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) SetFocus(window->win32.handle); } +void _glfwPlatformDragWindow(_GLFWwindow* window) +{ + ReleaseCapture(); + SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, HTCAPTION, 0); +} + +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ + WPARAM wBorder; + switch (border) + { + case GLFW_WINDOW_LEFT: + wBorder = HTLEFT; + break; + case GLFW_WINDOW_TOP: + wBorder = HTTOP; + break; + case GLFW_WINDOW_RIGHT: + wBorder = HTRIGHT; + break; + case GLFW_WINDOW_BOTTOM: + wBorder = HTBOTTOM; + break; + case GLFW_WINDOW_TOPLEFT: + wBorder = HTTOPLEFT; + break; + case GLFW_WINDOW_TOPRIGHT: + wBorder = HTTOPRIGHT; + break; + case GLFW_WINDOW_BOTTOMLEFT: + wBorder = HTBOTTOMLEFT; + break; + case GLFW_WINDOW_BOTTOMRIGHT: + wBorder = HTBOTTOMRIGHT; + break; + default: + assert(GLFW_FALSE); + } + ReleaseCapture(); + SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, wBorder, 0); +} + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/window.c b/src/window.c index 2c98d4cb..dd30e859 100644 --- a/src/window.c +++ b/src/window.c @@ -801,6 +801,29 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* handle) _glfwPlatformFocusWindow(window); } +GLFWAPI void glfwDragWindow(GLFWwindow* handle) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT(); + + _glfwPlatformDragWindow(window); +} + +GLFWAPI void glfwResizeWindow(GLFWwindow* handle, int border) +{ + _GLFWwindow* window = (_GLFWwindow*)handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT(); + + if (border < GLFW_WINDOW_LEFT || border > GLFW_WINDOW_BOTTOMRIGHT) + return; + + _glfwPlatformResizeWindow(window, border); +} + GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/src/wl_window.c b/src/wl_window.c index 98a64659..1a7fffbc 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1215,6 +1215,49 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) "Wayland: Focusing a window requires user interaction"); } +void _glfwPlatformDragWindow(_GLFWwindow* window) +{ + wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, _glfw.wl.pointerSerial); +} + +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ + int wlBorder; + switch (border) + { + case GLFW_WINDOW_LEFT: + wlBorder = WL_SHELL_SURFACE_RESIZE_LEFT; + break; + case GLFW_WINDOW_TOP: + wlBorder = WL_SHELL_SURFACE_RESIZE_TOP; + break; + case GLFW_WINDOW_RIGHT: + wlBorder = WL_SHELL_SURFACE_RESIZE_RIGHT; + break; + case GLFW_WINDOW_BOTTOM: + wlBorder = WL_SHELL_SURFACE_RESIZE_BOTTOM; + break; + case GLFW_WINDOW_TOPLEFT: + wlBorder = WL_SHELL_SURFACE_RESIZE_TOP_LEFT; + break; + case GLFW_WINDOW_TOPRIGHT: + wlBorder = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT; + break; + case GLFW_WINDOW_BOTTOMLEFT: + wlBorder = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT; + break; + case GLFW_WINDOW_BOTTOMRIGHT: + wlBorder = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT; + break; + default: + assert(GLFW_FALSE); + } + wl_shell_surface_resize(window->wl.shellSurface, + _glfw.wl.seat, + _glfw.wl.pointerSerial, + wlBorder); +} + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/x11_window.c b/src/x11_window.c index 19ed7372..1c573f83 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -43,6 +43,15 @@ #define _NET_WM_STATE_REMOVE 0 #define _NET_WM_STATE_ADD 1 #define _NET_WM_STATE_TOGGLE 2 +#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 +#define _NET_WM_MOVERESIZE_SIZE_TOP 1 +#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 +#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 +#define _NET_WM_MOVERESIZE_SIZE_LEFT 7 +#define _NET_WM_MOVERESIZE_MOVE 8 // Additional mouse button names for XButtonEvent #define Button6 6 @@ -2388,6 +2397,78 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) XFlush(_glfw.x11.display); } +void _glfwPlatformDragWindow(_GLFWwindow* window) +{ + int winXpos, winYpos; + double curXpos, curYpos; + XClientMessageEvent xclient; + memset(&xclient, 0, sizeof(XClientMessageEvent)); + XUngrabPointer(_glfw.x11.display, 0); + XFlush(_glfw.x11.display); + _glfwPlatformGetCursorPos(window, &curXpos, &curYpos); + _glfwPlatformGetWindowPos(window, &winXpos, &winYpos); + xclient.type = ClientMessage; + xclient.window = window->x11.handle; + xclient.message_type = XInternAtom(_glfw.x11.display, "_NET_WM_MOVERESIZE", False); + xclient.format = 32; + xclient.data.l[0] = winXpos + curXpos; + xclient.data.l[1] = winYpos + curYpos; + xclient.data.l[2] = _NET_WM_MOVERESIZE_MOVE; + xclient.data.l[3] = 0; + xclient.data.l[4] = 0; + XSendEvent(_glfw.x11.display, _glfw.x11.root, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xclient); +} + +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ + int winXpos, winYpos; + double curXpos, curYpos; + XClientMessageEvent xclient; + memset(&xclient, 0, sizeof(XClientMessageEvent)); + XUngrabPointer(_glfw.x11.display, 0); + XFlush(_glfw.x11.display); + _glfwPlatformGetCursorPos(window, &curXpos, &curYpos); + _glfwPlatformGetWindowPos(window, &winXpos, &winYpos); + xclient.type = ClientMessage; + xclient.window = window->x11.handle; + xclient.message_type = XInternAtom(_glfw.x11.display, "_NET_WM_MOVERESIZE", False); + xclient.format = 32; + xclient.data.l[0] = winXpos + curXpos; + xclient.data.l[1] = winYpos + curYpos; + switch (border) + { + case GLFW_WINDOW_LEFT: + xclient.data.l[2] = _NET_WM_MOVERESIZE_SIZE_LEFT; + break; + case GLFW_WINDOW_TOP: + xclient.data.l[2] = _NET_WM_MOVERESIZE_SIZE_TOP; + break; + case GLFW_WINDOW_RIGHT: + xclient.data.l[2] = _NET_WM_MOVERESIZE_SIZE_RIGHT; + break; + case GLFW_WINDOW_BOTTOM: + xclient.data.l[2] = _NET_WM_MOVERESIZE_SIZE_BOTTOM; + break; + case GLFW_WINDOW_TOPLEFT: + xclient.data.l[2] = _NET_WM_MOVERESIZE_SIZE_TOPLEFT; + break; + case GLFW_WINDOW_TOPRIGHT: + xclient.data.l[2] = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT; + break; + case GLFW_WINDOW_BOTTOMLEFT: + xclient.data.l[2] = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT; + break; + case GLFW_WINDOW_BOTTOMRIGHT: + xclient.data.l[2] = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT; + break; + default: + assert(GLFW_FALSE); + } + xclient.data.l[3] = 0; + xclient.data.l[4] = 0; + XSendEvent(_glfw.x11.display, _glfw.x11.root, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xclient); +} + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/tests/windows.c b/tests/windows.c index 5fed58f3..da67108b 100644 --- a/tests/windows.c +++ b/tests/windows.c @@ -89,6 +89,12 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, } } +void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) +{ + if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) + glfwDragWindow(window); +} + int main(int argc, char** argv) { int i, ch; @@ -138,6 +144,7 @@ int main(int argc, char** argv) } glfwSetKeyCallback(windows[i], key_callback); + glfwSetMouseButtonCallback(windows[i], mouse_button_callback); glfwMakeContextCurrent(windows[i]); gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); From 749639347a11e64fe176e1b339553dfc63adbca3 Mon Sep 17 00:00:00 2001 From: Robbin Marcus Date: Sat, 19 Jan 2019 20:53:15 +0100 Subject: [PATCH 02/10] Remove trailing whitespace (Travis CI build) --- include/GLFW/glfw3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index d4491e5e..79ea35dc 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3220,7 +3220,7 @@ GLFWAPI void glfwDragWindow(GLFWwindow* handle); * * This function starts a resize operation on one of the borders of the * specified window. - * + * * this function must be called from a pointer or touch event callback, * otherwise it risks reacting to a different event. * From f59f2fc968cfcd51c996cc280db7305221b17f40 Mon Sep 17 00:00:00 2001 From: Robbin Marcus Date: Sat, 19 Jan 2019 21:06:22 +0100 Subject: [PATCH 03/10] WL rename to serial (Travis CI build) --- src/wl_window.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 1a7fffbc..2aa6e25b 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -37,6 +37,7 @@ #include #include #include +#include static void shellSurfaceHandlePing(void* data, @@ -1217,7 +1218,7 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) void _glfwPlatformDragWindow(_GLFWwindow* window) { - wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, _glfw.wl.pointerSerial); + wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, _glfw.wl.serial); } void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) @@ -1254,7 +1255,7 @@ void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) } wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat, - _glfw.wl.pointerSerial, + _glfw.wl.serial, wlBorder); } From 350600ed8948e05ffd3cdf957cf229b39a486706 Mon Sep 17 00:00:00 2001 From: "robbin.marcus" Date: Sat, 24 Sep 2022 23:59:25 +0200 Subject: [PATCH 04/10] Add WS_THICKFRAME for resizing undecorated windows --- src/null_window.c | 8 -------- src/win32_window.c | 5 +++++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/null_window.c b/src/null_window.c index 1d4809bd..103bf4ee 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -470,14 +470,6 @@ void _glfwFocusWindowNull(_GLFWwindow* window) _glfwInputWindowFocus(window, GLFW_TRUE); } -void _glfwPlatformDragWindow(_GLFWwindow* window) -{ -} - -void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) -{ -} - int _glfwPlatformWindowFocused(_GLFWwindow* window) { return _glfw.null.focusedWindow == window; diff --git a/src/win32_window.c b/src/win32_window.c index 89422c4d..024a174e 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -58,7 +58,12 @@ static DWORD getWindowStyle(const _GLFWwindow* window) style |= WS_MAXIMIZEBOX | WS_THICKFRAME; } else + { style |= WS_POPUP; + + if (window->resizable) + style |= WS_THICKFRAME; + } } return style; From 56e8df2f9675654d398cf790e8be60890bef1378 Mon Sep 17 00:00:00 2001 From: "robbin.marcus" Date: Sun, 25 Sep 2022 00:22:17 +0200 Subject: [PATCH 05/10] Attempt to fix build errors Removed some changes that slipped past me during the latest merge. --- src/cocoa_window.m | 5 -- src/wl_window.c | 4 +- src/x11_window.c | 8 +- tests/windows.c | 180 --------------------------------------------- 4 files changed, 6 insertions(+), 191 deletions(-) delete mode 100644 tests/windows.c diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 047e1d9e..64e6a289 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1245,11 +1245,6 @@ void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) { } -void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, - _GLFWmonitor* monitor, - int xpos, int ypos, - int width, int height, - int refreshRate) void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/wl_window.c b/src/wl_window.c index 001c0fca..783061c9 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -2100,7 +2100,7 @@ void _glfwFocusWindowWayland(_GLFWwindow* window) void _glfwPlatformDragWindow(_GLFWwindow* window) { - wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, _glfw.wl.serial); + wl_shell_surface_move(window->wl.surface, _glfw.wl.seat, _glfw.wl.serial); } void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) @@ -2135,7 +2135,7 @@ void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) default: assert(GLFW_FALSE); } - wl_shell_surface_resize(window->wl.shellSurface, + wl_shell_surface_resize(window->wl.surface, _glfw.wl.seat, _glfw.wl.serial, wlBorder); diff --git a/src/x11_window.c b/src/x11_window.c index edeebe8f..834460ab 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2483,8 +2483,8 @@ void _glfwPlatformDragWindow(_GLFWwindow* window) memset(&xclient, 0, sizeof(XClientMessageEvent)); XUngrabPointer(_glfw.x11.display, 0); XFlush(_glfw.x11.display); - _glfwPlatformGetCursorPos(window, &curXpos, &curYpos); - _glfwPlatformGetWindowPos(window, &winXpos, &winYpos); + _glfwGetCursorPosX11(window, &curXpos, &curYpos); + _glfwGetWindowPosX11(window, &winXpos, &winYpos); xclient.type = ClientMessage; xclient.window = window->x11.handle; xclient.message_type = XInternAtom(_glfw.x11.display, "_NET_WM_MOVERESIZE", False); @@ -2505,8 +2505,8 @@ void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) memset(&xclient, 0, sizeof(XClientMessageEvent)); XUngrabPointer(_glfw.x11.display, 0); XFlush(_glfw.x11.display); - _glfwPlatformGetCursorPos(window, &curXpos, &curYpos); - _glfwPlatformGetWindowPos(window, &winXpos, &winYpos); + _glfwGetCursorPosX11(window, &curXpos, &curYpos); + _glfwGetWindowPosX11(window, &winXpos, &winYpos); xclient.type = ClientMessage; xclient.window = window->x11.handle; xclient.message_type = XInternAtom(_glfw.x11.display, "_NET_WM_MOVERESIZE", False); diff --git a/tests/windows.c b/tests/windows.c deleted file mode 100644 index c98d11fb..00000000 --- a/tests/windows.c +++ /dev/null @@ -1,180 +0,0 @@ -//======================================================================== -// Simple multi-window test -// Copyright (c) Camilla Löwy -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== -// -// This test creates four windows and clears each in a different color -// -//======================================================================== - -#include -#include - -#include -#include - -#include "getopt.h" - -static const char* titles[] = -{ - "Red", - "Green", - "Blue", - "Yellow" -}; - -static const struct -{ - float r, g, b; -} colors[] = -{ - { 0.95f, 0.32f, 0.11f }, - { 0.50f, 0.80f, 0.16f }, - { 0.f, 0.68f, 0.94f }, - { 0.98f, 0.74f, 0.04f } -}; - -static void usage(void) -{ - printf("Usage: windows [-h] [-b] [-f] \n"); - printf("Options:\n"); - printf(" -b create decorated windows\n"); - printf(" -f set focus on show off for all but first window\n"); - printf(" -h show this help\n"); -} - -static void error_callback(int error, const char* description) -{ - fprintf(stderr, "Error: %s\n", description); -} - -static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - if (action != GLFW_PRESS) - return; - - switch (key) - { - case GLFW_KEY_SPACE: - { - int xpos, ypos; - glfwGetWindowPos(window, &xpos, &ypos); - glfwSetWindowPos(window, xpos, ypos); - break; - } - - case GLFW_KEY_ESCAPE: - glfwSetWindowShouldClose(window, GLFW_TRUE); - break; - } -} - -void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) -{ - if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) - glfwDragWindow(window); -} - -int main(int argc, char** argv) -{ - int i, ch; - int decorated = GLFW_FALSE; - int focusOnShow = GLFW_TRUE; - int running = GLFW_TRUE; - GLFWwindow* windows[4]; - - while ((ch = getopt(argc, argv, "bfh")) != -1) - { - switch (ch) - { - case 'b': - decorated = GLFW_TRUE; - break; - case 'f': - focusOnShow = GLFW_FALSE; - break; - case 'h': - usage(); - exit(EXIT_SUCCESS); - default: - usage(); - exit(EXIT_FAILURE); - } - } - - glfwSetErrorCallback(error_callback); - - if (!glfwInit()) - exit(EXIT_FAILURE); - - glfwWindowHint(GLFW_DECORATED, decorated); - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - - for (i = 0; i < 4; i++) - { - int left, top, right, bottom; - if (i) - glfwWindowHint(GLFW_FOCUS_ON_SHOW, focusOnShow); - - windows[i] = glfwCreateWindow(200, 200, titles[i], NULL, NULL); - if (!windows[i]) - { - glfwTerminate(); - exit(EXIT_FAILURE); - } - - glfwSetKeyCallback(windows[i], key_callback); - glfwSetMouseButtonCallback(windows[i], mouse_button_callback); - - glfwMakeContextCurrent(windows[i]); - gladLoadGL(glfwGetProcAddress); - glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f); - - glfwGetWindowFrameSize(windows[i], &left, &top, &right, &bottom); - glfwSetWindowPos(windows[i], - 100 + (i & 1) * (200 + left + right), - 100 + (i >> 1) * (200 + top + bottom)); - } - - for (i = 0; i < 4; i++) - glfwShowWindow(windows[i]); - - while (running) - { - for (i = 0; i < 4; i++) - { - glfwMakeContextCurrent(windows[i]); - glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(windows[i]); - - if (glfwWindowShouldClose(windows[i])) - running = GLFW_FALSE; - } - - glfwWaitEvents(); - } - - glfwTerminate(); - exit(EXIT_SUCCESS); -} - From b21eed2ad43f6ca2b76e202d2e1b561054d339d7 Mon Sep 17 00:00:00 2001 From: "robbin.marcus" Date: Mon, 26 Sep 2022 17:28:38 +0200 Subject: [PATCH 06/10] Win32: set mouse button released after drag/resize When calling the drag/resize operation GLFW would keep the left mouse button pressed even after drag/resize was completed. The other changes will hopefully make the build compile for other platforms. --- README.md | 2 +- src/win32_window.c | 6 ++++++ src/wl_window.c | 10 +++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fe7a51d7..8b4a1546 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,6 @@ information on what to include when reporting a bug. ## Changelog -User-visible changes since the last release. - Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958) - Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to @@ -402,6 +401,7 @@ User-visible changes since the last release. - [GLX] Added loading of glvnd `libGLX.so.0` where available - [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library + ## Contact On [glfw.org](https://www.glfw.org/) you can find the latest version of GLFW, as diff --git a/src/win32_window.c b/src/win32_window.c index 024a174e..ca16f044 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1779,6 +1779,9 @@ void _glfwPlatformDragWindow(_GLFWwindow* window) { ReleaseCapture(); SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, HTCAPTION, 0); + + // Mouse button will be released after drag, so prepare released state here already + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_1, GLFW_RELEASE, 0); } void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) @@ -1815,6 +1818,9 @@ void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) } ReleaseCapture(); SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, wBorder, 0); + + // Mouse button will be released after drag, so prepare released state here already + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_1, GLFW_RELEASE, 0); } void _glfwSetWindowMonitorWin32(_GLFWwindow* window, diff --git a/src/wl_window.c b/src/wl_window.c index 783061c9..c18fc907 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -2100,7 +2100,7 @@ void _glfwFocusWindowWayland(_GLFWwindow* window) void _glfwPlatformDragWindow(_GLFWwindow* window) { - wl_shell_surface_move(window->wl.surface, _glfw.wl.seat, _glfw.wl.serial); + xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, _glfw.wl.serial); } void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) @@ -2135,10 +2135,10 @@ void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) default: assert(GLFW_FALSE); } - wl_shell_surface_resize(window->wl.surface, - _glfw.wl.seat, - _glfw.wl.serial, - wlBorder); + xdg_toplevel_resize(window->wl.xdg.toplevel, + _glfw.wl.seat, + _glfw.wl.serial, + wlBorder); } void _glfwSetWindowMonitorWayland(_GLFWwindow* window, From 2f55709f3b856178e2033a9d7af4ab36eb4e8d25 Mon Sep 17 00:00:00 2001 From: "robbin.marcus" Date: Mon, 26 Sep 2022 18:07:32 +0200 Subject: [PATCH 07/10] Update to platform function setup --- src/cocoa_init.m | 2 ++ src/cocoa_platform.h | 2 ++ src/cocoa_window.m | 4 +-- src/internal.h | 62 ++------------------------------------------ src/null_init.c | 2 ++ src/null_platform.h | 2 ++ src/null_window.c | 8 ++++++ src/win32_init.c | 2 ++ src/win32_platform.h | 2 ++ src/win32_window.c | 4 +-- src/window.c | 4 +-- src/wl_init.c | 2 ++ src/wl_platform.h | 2 ++ src/wl_window.c | 4 +-- src/x11_init.c | 2 ++ src/x11_platform.h | 2 ++ src/x11_window.c | 4 +-- 17 files changed, 40 insertions(+), 70 deletions(-) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index b3831df1..a1fdad78 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -544,6 +544,8 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform) _glfwHideWindowCocoa, _glfwRequestWindowAttentionCocoa, _glfwFocusWindowCocoa, + _glfwDragWindowCocoa, + _glfwResizeWindowCocoa, _glfwSetWindowMonitorCocoa, _glfwWindowFocusedCocoa, _glfwWindowIconifiedCocoa, diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 9f7d191d..2fc05278 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -234,6 +234,8 @@ void _glfwShowWindowCocoa(_GLFWwindow* window); void _glfwHideWindowCocoa(_GLFWwindow* window); void _glfwRequestWindowAttentionCocoa(_GLFWwindow* window); void _glfwFocusWindowCocoa(_GLFWwindow* window); +void _glfwDragWindowCocoa(_GLFWwindow* window); +void _glfwResizeWindowCocoa(_GLFWwindow* window, int border); void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); GLFWbool _glfwWindowFocusedCocoa(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedCocoa(_GLFWwindow* window); diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 64e6a289..56bd0ec9 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1236,12 +1236,12 @@ void _glfwFocusWindowCocoa(_GLFWwindow* window) } // autoreleasepool } -void _glfwPlatformDragWindow(_GLFWwindow* window) +void _glfwDragWindowCocoa(_GLFWwindow* window) { [window->ns.object performWindowDragWithEvent:[NSApp currentEvent]]; } -void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +void _glfwResizeWindowCocoa(_GLFWwindow* window, int border) { } diff --git a/src/internal.h b/src/internal.h index 6ad15e48..49c1d1fa 100644 --- a/src/internal.h +++ b/src/internal.h @@ -722,6 +722,8 @@ struct _GLFWplatform void (*hideWindow)(_GLFWwindow*); void (*requestWindowAttention)(_GLFWwindow*); void (*focusWindow)(_GLFWwindow*); + void (*dragWindow)(_GLFWwindow*); + void (*resizeWindow)(_GLFWwindow*,int); void (*setWindowMonitor)(_GLFWwindow*,_GLFWmonitor*,int,int,int,int,int); GLFWbool (*windowFocused)(_GLFWwindow*); GLFWbool (*windowIconified)(_GLFWwindow*); @@ -884,66 +886,6 @@ void _glfwPlatformInitTimer(void); uint64_t _glfwPlatformGetTimerValue(void); uint64_t _glfwPlatformGetTimerFrequency(void); -int _glfwPlatformCreateWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig); -void _glfwPlatformDestroyWindow(_GLFWwindow* window); -void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title); -void _glfwPlatformSetWindowIcon(_GLFWwindow* window, - int count, const GLFWimage* images); -void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos); -void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos); -void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height); -void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height); -void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, - int minwidth, int minheight, - int maxwidth, int maxheight); -void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom); -void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height); -void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, - int* left, int* top, - int* right, int* bottom); -void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, - float* xscale, float* yscale); -void _glfwPlatformIconifyWindow(_GLFWwindow* window); -void _glfwPlatformRestoreWindow(_GLFWwindow* window); -void _glfwPlatformMaximizeWindow(_GLFWwindow* window); -void _glfwPlatformShowWindow(_GLFWwindow* window); -void _glfwPlatformHideWindow(_GLFWwindow* window); -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window); -void _glfwPlatformFocusWindow(_GLFWwindow* window); -void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, - int xpos, int ypos, int width, int height, - int refreshRate); -void _glfwPlatformDragWindow(_GLFWwindow* window); -void _glfwPlatformResizeWindow(_GLFWwindow* window, int border); -int _glfwPlatformWindowFocused(_GLFWwindow* window); -int _glfwPlatformWindowIconified(_GLFWwindow* window); -int _glfwPlatformWindowVisible(_GLFWwindow* window); -int _glfwPlatformWindowMaximized(_GLFWwindow* window); -int _glfwPlatformWindowHovered(_GLFWwindow* window); -int _glfwPlatformFramebufferTransparent(_GLFWwindow* window); -float _glfwPlatformGetWindowOpacity(_GLFWwindow* window); -void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled); -void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); -void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); -void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity); - -void _glfwPlatformPollEvents(void); -void _glfwPlatformWaitEvents(void); -void _glfwPlatformWaitEventsTimeout(double timeout); -void _glfwPlatformPostEmptyEvent(void); - -void _glfwPlatformGetRequiredInstanceExtensions(char** extensions); -int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, - VkPhysicalDevice device, - uint32_t queuefamily); -VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, - _GLFWwindow* window, - const VkAllocationCallbacks* allocator, - VkSurfaceKHR* surface); - GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls); void _glfwPlatformDestroyTls(_GLFWtls* tls); void* _glfwPlatformGetTls(_GLFWtls* tls); diff --git a/src/null_init.c b/src/null_init.c index de4b28f3..904f5754 100644 --- a/src/null_init.c +++ b/src/null_init.c @@ -89,6 +89,8 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) _glfwHideWindowNull, _glfwRequestWindowAttentionNull, _glfwFocusWindowNull, + _glfwDragWindowNull, + _glfwResizeWindowNull, _glfwSetWindowMonitorNull, _glfwWindowFocusedNull, _glfwWindowIconifiedNull, diff --git a/src/null_platform.h b/src/null_platform.h index b646acb3..20523c55 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -118,6 +118,8 @@ void _glfwRequestWindowAttentionNull(_GLFWwindow* window); void _glfwRequestWindowAttentionNull(_GLFWwindow* window); void _glfwHideWindowNull(_GLFWwindow* window); void _glfwFocusWindowNull(_GLFWwindow* window); +void _glfwDragWindowNull(_GLFWwindow* window); +void _glfwResizeWindowNull(_GLFWwindow* window, int border); GLFWbool _glfwWindowFocusedNull(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedNull(_GLFWwindow* window); GLFWbool _glfwWindowVisibleNull(_GLFWwindow* window); diff --git a/src/null_window.c b/src/null_window.c index 103bf4ee..f0419c86 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -470,6 +470,14 @@ void _glfwFocusWindowNull(_GLFWwindow* window) _glfwInputWindowFocus(window, GLFW_TRUE); } +void _glfwDragWindowNull(_GLFWwindow* window) +{ +} + +void _glfwResizeWindowNull(_GLFWwindow* window, int border) +{ +} + int _glfwPlatformWindowFocused(_GLFWwindow* window) { return _glfw.null.focusedWindow == window; diff --git a/src/win32_init.c b/src/win32_init.c index 64393e77..1f343f07 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -654,6 +654,8 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) _glfwHideWindowWin32, _glfwRequestWindowAttentionWin32, _glfwFocusWindowWin32, + _glfwDragWindowWin32, + _glfwResizeWindowWin32, _glfwSetWindowMonitorWin32, _glfwWindowFocusedWin32, _glfwWindowIconifiedWin32, diff --git a/src/win32_platform.h b/src/win32_platform.h index 82b34bb9..dc3fe50d 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -559,6 +559,8 @@ void _glfwShowWindowWin32(_GLFWwindow* window); void _glfwHideWindowWin32(_GLFWwindow* window); void _glfwRequestWindowAttentionWin32(_GLFWwindow* window); void _glfwFocusWindowWin32(_GLFWwindow* window); +void _glfwDragWindowWin32(_GLFWwindow* window); +void _glfwResizeWindowWin32(_GLFWwindow* window, int border); void _glfwSetWindowMonitorWin32(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); GLFWbool _glfwWindowFocusedWin32(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedWin32(_GLFWwindow* window); diff --git a/src/win32_window.c b/src/win32_window.c index ca16f044..f46d0a33 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1775,7 +1775,7 @@ void _glfwFocusWindowWin32(_GLFWwindow* window) SetFocus(window->win32.handle); } -void _glfwPlatformDragWindow(_GLFWwindow* window) +void _glfwDragWindowWin32(_GLFWwindow* window) { ReleaseCapture(); SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, HTCAPTION, 0); @@ -1784,7 +1784,7 @@ void _glfwPlatformDragWindow(_GLFWwindow* window) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_1, GLFW_RELEASE, 0); } -void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +void _glfwResizeWindowWin32(_GLFWwindow* window, int border) { WPARAM wBorder; switch (border) diff --git a/src/window.c b/src/window.c index 64d89eb5..3caa6059 100644 --- a/src/window.c +++ b/src/window.c @@ -852,7 +852,7 @@ GLFWAPI void glfwDragWindow(GLFWwindow* handle) _GLFW_REQUIRE_INIT(); - _glfwPlatformDragWindow(window); + _glfw.platform.dragWindow(window); } GLFWAPI void glfwResizeWindow(GLFWwindow* handle, int border) @@ -865,7 +865,7 @@ GLFWAPI void glfwResizeWindow(GLFWwindow* handle, int border) if (border < GLFW_WINDOW_LEFT || border > GLFW_WINDOW_BOTTOMRIGHT) return; - _glfwPlatformResizeWindow(window, border); + _glfw.platform.resizeWindow(window, border); } GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) diff --git a/src/wl_init.c b/src/wl_init.c index 4e6b4294..a8969654 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -435,6 +435,8 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform) _glfwHideWindowWayland, _glfwRequestWindowAttentionWayland, _glfwFocusWindowWayland, + _glfwDragWindowWayland, + _glfwResizeWindowWayland, _glfwSetWindowMonitorWayland, _glfwWindowFocusedWayland, _glfwWindowIconifiedWayland, diff --git a/src/wl_platform.h b/src/wl_platform.h index 238e1ed4..4ae3fd00 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -462,6 +462,8 @@ void _glfwShowWindowWayland(_GLFWwindow* window); void _glfwHideWindowWayland(_GLFWwindow* window); void _glfwRequestWindowAttentionWayland(_GLFWwindow* window); void _glfwFocusWindowWayland(_GLFWwindow* window); +void _glfwDragWindowWayland(_GLFWwindow* window); +void _glfwResizeWindowWayland(_GLFWwindow* window, int border); void _glfwSetWindowMonitorWayland(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); GLFWbool _glfwWindowFocusedWayland(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedWayland(_GLFWwindow* window); diff --git a/src/wl_window.c b/src/wl_window.c index c18fc907..01e357eb 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -2098,12 +2098,12 @@ void _glfwFocusWindowWayland(_GLFWwindow* window) "Wayland: The platform does not support setting the input focus"); } -void _glfwPlatformDragWindow(_GLFWwindow* window) +void _glfwDragWindowWayland(_GLFWwindow* window) { xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, _glfw.wl.serial); } -void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +void _glfwResizeWindowWayland(_GLFWwindow* window, int border) { int wlBorder; switch (border) diff --git a/src/x11_init.c b/src/x11_init.c index 1c69c0f6..3f93574b 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -1225,6 +1225,8 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) _glfwHideWindowX11, _glfwRequestWindowAttentionX11, _glfwFocusWindowX11, + _glfwDragWindowX11, + _glfwResizeWindowX11, _glfwSetWindowMonitorX11, _glfwWindowFocusedX11, _glfwWindowIconifiedX11, diff --git a/src/x11_platform.h b/src/x11_platform.h index cdea3957..0ca53936 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -921,6 +921,8 @@ void _glfwShowWindowX11(_GLFWwindow* window); void _glfwHideWindowX11(_GLFWwindow* window); void _glfwRequestWindowAttentionX11(_GLFWwindow* window); void _glfwFocusWindowX11(_GLFWwindow* window); +void _glfwDragWindowX11(_GLFWwindow* window); +void _glfwResizeWindowX11(_GLFWwindow* window, int border); void _glfwSetWindowMonitorX11(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); GLFWbool _glfwWindowFocusedX11(_GLFWwindow* window); GLFWbool _glfwWindowIconifiedX11(_GLFWwindow* window); diff --git a/src/x11_window.c b/src/x11_window.c index 834460ab..bf569af0 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2475,7 +2475,7 @@ void _glfwFocusWindowX11(_GLFWwindow* window) XFlush(_glfw.x11.display); } -void _glfwPlatformDragWindow(_GLFWwindow* window) +void _glfwDragWindowX11(_GLFWwindow* window) { int winXpos, winYpos; double curXpos, curYpos; @@ -2497,7 +2497,7 @@ void _glfwPlatformDragWindow(_GLFWwindow* window) XSendEvent(_glfw.x11.display, _glfw.x11.root, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xclient); } -void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +void _glfwResizeWindowX11(_GLFWwindow* window, int border) { int winXpos, winYpos; double curXpos, curYpos; From 6b9f384c18b04b0c76df273d6c321432944a4311 Mon Sep 17 00:00:00 2001 From: "robbin.marcus" Date: Mon, 26 Sep 2022 23:46:16 +0200 Subject: [PATCH 08/10] Undecorated border fix + customizable caption/bordersize Added functions to set caption area and resize border size for undecorated windows. Implemented this functionality for win32 using WM_NCHITTEST and WM_NCCALCSIZE. --- include/GLFW/glfw3.h | 37 ++++++++++++++++++++- src/internal.h | 5 +++ src/win32_window.c | 76 +++++++++++++++++++++++++++++++++++++++++++- src/window.c | 36 +++++++++++++++++++++ 4 files changed, 152 insertions(+), 2 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index ac6e8f56..50c91501 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3884,7 +3884,7 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* window); * * @ingroup window */ -GLFWAPI void glfwDragWindow(GLFWwindow* handle); +GLFWAPI void glfwDragWindow(GLFWwindow* window); /*! @brief Starts a resize operation with the specified window. * @@ -3919,6 +3919,41 @@ GLFWAPI void glfwDragWindow(GLFWwindow* handle); */ GLFWAPI void glfwResizeWindow(GLFWwindow* window, int border); +/*! @brief Sets the caption area for the specified window. + * + * This function sets the rectangle for the caption to drag the undecorated window. + * + * @param[in] window The window to set the caption area for. + * @param[in] offsetX The x offset from the top left of the window. + * @param[in] offsetY The y offset from the top left of the window. + * @param[in] sizeX The x size of the caption area. + * @param[in] sizeY The y size of the caption area. + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_caption_area + * + * @since Added in version 3.4. + * + * @ingroup window + */ +GLFWAPI void glfwWindowSetCaptionArea(GLFWwindow* window, int offsetX, int offsetY, int sizeX, int sizeY); + +/*! @brief Sets the resize border size for the specified window. + * + * This function sets the size of border where to start the resize operation. + * + * @param[in] window The window to set the caption area for. + * @param[in] size The size of the border. + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_border_size + * + * @since Added in version 3.4. + * + * @ingroup window + */ +GLFWAPI void glfwWindowSetResizeBorderSize(GLFWwindow* window, int size); + /*! @brief Requests user attention to the specified window. * * This function requests user attention to the specified window. On diff --git a/src/internal.h b/src/internal.h index 49c1d1fa..c30374d4 100644 --- a/src/internal.h +++ b/src/internal.h @@ -539,6 +539,11 @@ struct _GLFWwindow int maxwidth, maxheight; int numer, denom; + // Caption for undecorated window dragging functionality + int captionOffsetX, captionOffsetY; + int captionSizeX, captionSizeY; + int resizeBorderSize; + GLFWbool stickyKeys; GLFWbool stickyMouseButtons; GLFWbool lockKeyMods; diff --git a/src/win32_window.c b/src/win32_window.c index f46d0a33..2c29ad9b 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -62,7 +62,7 @@ static DWORD getWindowStyle(const _GLFWwindow* window) style |= WS_POPUP; if (window->resizable) - style |= WS_THICKFRAME; + style |= WS_MAXIMIZEBOX | WS_THICKFRAME; } } @@ -1248,6 +1248,80 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l DragFinish(drop); return 0; } + + case WM_NCCALCSIZE: + { + if (wParam && !window->decorated) + return 0; + + break; + } + + case WM_NCHITTEST: + { + if (!window->decorated) + { + POINT cursor; + cursor.x = GET_X_LPARAM(lParam); + cursor.y = GET_Y_LPARAM(lParam); + + RECT rect; + if (!GetWindowRect(hWnd, &rect)) + return HTNOWHERE; + + POINT border = { 0, 0 }; + if (window->resizable) + { + border.x = window->resizeBorderSize; + border.y = window->resizeBorderSize; + } + + const int captionOffsetX = window->captionOffsetX != GLFW_DONT_CARE ? window->captionOffsetX : 0; + const int captionOffsetY = window->captionOffsetY != GLFW_DONT_CARE ? window->captionOffsetY : 0; + const int captionSizeX = window->captionSizeX != GLFW_DONT_CARE ? window->captionSizeX : rect.right - rect.left; + const int captionSizeY = window->captionSizeY; + + const int clientAreaLeft = rect.left + border.x; + const int clientAreaRight = rect.right - border.x; + const int clientAreaTop = rect.top + border.y; + const int clientAreaBottom = rect.bottom - border.y; + + const int cursorInCaption = + cursor.x > clientAreaLeft + captionOffsetX && + cursor.x < clientAreaLeft + captionOffsetX + captionSizeX && + cursor.y > clientAreaTop + captionOffsetY && + cursor.y < clientAreaTop + captionOffsetY + captionSizeY; + + enum region_mask { + client = 0b0000, + left = 0b0001, + right = 0b0010, + top = 0b0100, + bottom = 0b1000, + }; + + const int result = + left * (cursor.x < clientAreaLeft) | + right * (cursor.x >= clientAreaRight)| + top * (cursor.y < clientAreaTop) | + bottom * (cursor.y >= clientAreaBottom); + + switch (result) + { + case left: return HTLEFT; + case right: return HTRIGHT; + case top: return HTTOP; + case bottom: return HTBOTTOM; + case top | left: return HTTOPLEFT; + case top | right: return HTTOPRIGHT; + case bottom | left: return HTBOTTOMLEFT; + case bottom | right: return HTBOTTOMRIGHT; + case client: return cursorInCaption ? HTCAPTION : HTCLIENT; + default: return HTNOWHERE; + } + } + break; + } } return DefWindowProcW(hWnd, uMsg, wParam, lParam); diff --git a/src/window.c b/src/window.c index 3caa6059..74acd311 100644 --- a/src/window.c +++ b/src/window.c @@ -245,6 +245,13 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->numer = GLFW_DONT_CARE; window->denom = GLFW_DONT_CARE; + window->captionOffsetX = GLFW_DONT_CARE; + window->captionOffsetY = GLFW_DONT_CARE; + window->captionSizeX = GLFW_DONT_CARE; + window->captionSizeY = 16; + + window->resizeBorderSize = 4; + if (!_glfw.platform.createWindow(window, &wndconfig, &ctxconfig, &fbconfig)) { glfwDestroyWindow((GLFWwindow*) window); @@ -868,6 +875,35 @@ GLFWAPI void glfwResizeWindow(GLFWwindow* handle, int border) _glfw.platform.resizeWindow(window, border); } +GLFWAPI void glfwWindowSetCaptionArea(GLFWwindow* handle, int offsetX, int offsetY, int sizeX, int sizeY) +{ + _GLFWwindow* window = (_GLFWwindow*)handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT(); + + if (offsetX < 0 || offsetY < 0 || sizeX < 1 || sizeY < 1) + return; + + window->captionOffsetX = offsetX; + window->captionOffsetY = offsetY; + window->captionSizeX = sizeX; + window->captionSizeY = sizeY; +} + +GLFWAPI void glfwWindowSetResizeBorderSize(GLFWwindow* handle, int size) +{ + _GLFWwindow* window = (_GLFWwindow*)handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT(); + + if (size < 1) + return; + + window->resizeBorderSize = size; +} + GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) { _GLFWwindow* window = (_GLFWwindow*) handle; From 797db588ded25c89a844eaf8ba8c95c2261953cb Mon Sep 17 00:00:00 2001 From: "robbin.marcus" Date: Mon, 26 Sep 2022 23:53:42 +0200 Subject: [PATCH 09/10] Fix appveyor build --- src/win32_window.c | 112 ++++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/src/win32_window.c b/src/win32_window.c index 2c29ad9b..38e00a38 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -531,6 +531,54 @@ static void maximizeWindowManually(_GLFWwindow* window) SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); } +static int HitTest(_GLFWwindow* window, RECT windowRect, POINT cursor, POINT border) +{ + const int captionOffsetX = window->captionOffsetX != GLFW_DONT_CARE ? window->captionOffsetX : 0; + const int captionOffsetY = window->captionOffsetY != GLFW_DONT_CARE ? window->captionOffsetY : 0; + const int captionSizeX = window->captionSizeX != GLFW_DONT_CARE ? window->captionSizeX : windowRect.right - windowRect.left; + const int captionSizeY = window->captionSizeY; + + const int clientAreaLeft = windowRect.left + border.x; + const int clientAreaRight = windowRect.right - border.x; + const int clientAreaTop = windowRect.top + border.y; + const int clientAreaBottom = windowRect.bottom - border.y; + + const int cursorInCaption = + cursor.x > clientAreaLeft + captionOffsetX && + cursor.x < clientAreaLeft + captionOffsetX + captionSizeX && + cursor.y > clientAreaTop + captionOffsetY && + cursor.y < clientAreaTop + captionOffsetY + captionSizeY; + + enum region_mask + { + client = 0, + left = 1, + right = 2, + top = 4, + bottom = 8, + }; + + const int result = + left * (cursor.x < clientAreaLeft) | + right * (cursor.x >= clientAreaRight) | + top * (cursor.y < clientAreaTop) | + bottom * (cursor.y >= clientAreaBottom); + + switch (result) + { + case left: return HTLEFT; + case right: return HTRIGHT; + case top: return HTTOP; + case bottom: return HTBOTTOM; + case top | left: return HTTOPLEFT; + case top | right: return HTTOPRIGHT; + case bottom | left: return HTBOTTOMLEFT; + case bottom | right: return HTBOTTOMRIGHT; + case client: return cursorInCaption ? HTCAPTION : HTCLIENT; + default: return HTNOWHERE; + } +} + // Window procedure for user-created windows // static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -1261,64 +1309,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l { if (!window->decorated) { - POINT cursor; - cursor.x = GET_X_LPARAM(lParam); - cursor.y = GET_Y_LPARAM(lParam); + POINT cursor = + { + GET_X_LPARAM(lParam), + GET_Y_LPARAM(lParam) + }; + POINT border = + { + window->resizable ? window->resizeBorderSize : 0, + window->resizable ? window->resizeBorderSize : 0, + }; RECT rect; if (!GetWindowRect(hWnd, &rect)) return HTNOWHERE; - POINT border = { 0, 0 }; - if (window->resizable) - { - border.x = window->resizeBorderSize; - border.y = window->resizeBorderSize; - } - - const int captionOffsetX = window->captionOffsetX != GLFW_DONT_CARE ? window->captionOffsetX : 0; - const int captionOffsetY = window->captionOffsetY != GLFW_DONT_CARE ? window->captionOffsetY : 0; - const int captionSizeX = window->captionSizeX != GLFW_DONT_CARE ? window->captionSizeX : rect.right - rect.left; - const int captionSizeY = window->captionSizeY; - - const int clientAreaLeft = rect.left + border.x; - const int clientAreaRight = rect.right - border.x; - const int clientAreaTop = rect.top + border.y; - const int clientAreaBottom = rect.bottom - border.y; - - const int cursorInCaption = - cursor.x > clientAreaLeft + captionOffsetX && - cursor.x < clientAreaLeft + captionOffsetX + captionSizeX && - cursor.y > clientAreaTop + captionOffsetY && - cursor.y < clientAreaTop + captionOffsetY + captionSizeY; - - enum region_mask { - client = 0b0000, - left = 0b0001, - right = 0b0010, - top = 0b0100, - bottom = 0b1000, - }; - - const int result = - left * (cursor.x < clientAreaLeft) | - right * (cursor.x >= clientAreaRight)| - top * (cursor.y < clientAreaTop) | - bottom * (cursor.y >= clientAreaBottom); - - switch (result) - { - case left: return HTLEFT; - case right: return HTRIGHT; - case top: return HTTOP; - case bottom: return HTBOTTOM; - case top | left: return HTTOPLEFT; - case top | right: return HTTOPRIGHT; - case bottom | left: return HTBOTTOMLEFT; - case bottom | right: return HTBOTTOMRIGHT; - case client: return cursorInCaption ? HTCAPTION : HTCLIENT; - default: return HTNOWHERE; - } + return HitTest(window, rect, cursor, border); } break; } From a9bef610898cbe9762c7a982f5e84c00e5339b56 Mon Sep 17 00:00:00 2001 From: "robbin.marcus" Date: Wed, 19 Oct 2022 12:18:46 +0200 Subject: [PATCH 10/10] Early return for clang compile Changed functions names to be in line with other glfw functions --- CONTRIBUTORS.md | 1 + README.md | 3 +++ include/GLFW/glfw3.h | 4 ++-- src/win32_window.c | 3 ++- src/window.c | 4 ++-- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 110ed4cd..c0a46b3b 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -260,6 +260,7 @@ video tutorials. - Jonas Ådahl - Lasse Öörni - Leonard König + - Robbin Marcus - All the unmentioned and anonymous contributors in the GLFW community, for bug reports, patches, feedback, testing and encouragement diff --git a/README.md b/README.md index 8b4a1546..e8ceda43 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,9 @@ information on what to include when reporting a bug. ## Changelog + - Added `glfwSetWindowCaptionArea` to define caption for borderless windows (#1420) + - Added `glfwSetWindowResizeBorderSize` to set the resize area on borders for + resizing borderless windows (#1420) - Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958) - Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 50c91501..6f3de7c2 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3936,7 +3936,7 @@ GLFWAPI void glfwResizeWindow(GLFWwindow* window, int border); * * @ingroup window */ -GLFWAPI void glfwWindowSetCaptionArea(GLFWwindow* window, int offsetX, int offsetY, int sizeX, int sizeY); +GLFWAPI void glfwSetWindowCaptionArea(GLFWwindow* window, int offsetX, int offsetY, int sizeX, int sizeY); /*! @brief Sets the resize border size for the specified window. * @@ -3952,7 +3952,7 @@ GLFWAPI void glfwWindowSetCaptionArea(GLFWwindow* window, int offsetX, int offse * * @ingroup window */ -GLFWAPI void glfwWindowSetResizeBorderSize(GLFWwindow* window, int size); +GLFWAPI void glfwSetWindowResizeBorderSize(GLFWwindow* window, int size); /*! @brief Requests user attention to the specified window. * diff --git a/src/win32_window.c b/src/win32_window.c index 38e00a38..c64af5d1 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1894,7 +1894,8 @@ void _glfwResizeWindowWin32(_GLFWwindow* window, int border) wBorder = HTBOTTOMRIGHT; break; default: - assert(GLFW_FALSE); + assert(GLFW_FALSE); + return; } ReleaseCapture(); SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, wBorder, 0); diff --git a/src/window.c b/src/window.c index 74acd311..7fc2a42a 100644 --- a/src/window.c +++ b/src/window.c @@ -875,7 +875,7 @@ GLFWAPI void glfwResizeWindow(GLFWwindow* handle, int border) _glfw.platform.resizeWindow(window, border); } -GLFWAPI void glfwWindowSetCaptionArea(GLFWwindow* handle, int offsetX, int offsetY, int sizeX, int sizeY) +GLFWAPI void glfwSetWindowCaptionArea(GLFWwindow* handle, int offsetX, int offsetY, int sizeX, int sizeY) { _GLFWwindow* window = (_GLFWwindow*)handle; assert(window != NULL); @@ -891,7 +891,7 @@ GLFWAPI void glfwWindowSetCaptionArea(GLFWwindow* handle, int offsetX, int offse window->captionSizeY = sizeY; } -GLFWAPI void glfwWindowSetResizeBorderSize(GLFWwindow* handle, int size) +GLFWAPI void glfwSetWindowResizeBorderSize(GLFWwindow* handle, int size) { _GLFWwindow* window = (_GLFWwindow*)handle; assert(window != NULL);