diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 9d194f1c..79919781 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3943,6 +3943,23 @@ 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. + * + * @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. + * + * @since Added in version 3.4. + * + * @ingroup window + */ +GLFWAPI void glfwDragWindow(GLFWwindow* handle); + /*! @brief Requests user attention to the specified window. * * This function requests user attention to the specified window. On diff --git a/src/cocoa_init.m b/src/cocoa_init.m index b0191503..f43ad413 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -608,6 +608,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform) _glfwHideWindowCocoa, _glfwRequestWindowAttentionCocoa, _glfwFocusWindowCocoa, + _glfwDragWindowCocoa, _glfwSetWindowMonitorCocoa, _glfwWindowFocusedCocoa, _glfwWindowIconifiedCocoa, diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index a452643e..36a0e50a 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -264,6 +264,7 @@ void _glfwShowWindowCocoa(_GLFWwindow* window); void _glfwHideWindowCocoa(_GLFWwindow* window); void _glfwRequestWindowAttentionCocoa(_GLFWwindow* window); void _glfwFocusWindowCocoa(_GLFWwindow* window); +void _glfwDragWindowCocoa(_GLFWwindow* window); 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 da346bcc..9400203e 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1347,6 +1347,11 @@ void _glfwFocusWindowCocoa(_GLFWwindow* window) } // autoreleasepool } +void _glfwDragWindowCocoa(_GLFWwindow* window) +{ + // TODO +} + void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/internal.h b/src/internal.h index dfdb4827..a8937c53 100644 --- a/src/internal.h +++ b/src/internal.h @@ -781,6 +781,7 @@ struct _GLFWplatform void (*hideWindow)(_GLFWwindow*); void (*requestWindowAttention)(_GLFWwindow*); void (*focusWindow)(_GLFWwindow*); + void (*dragWindow)(_GLFWwindow*); void (*setWindowMonitor)(_GLFWwindow*,_GLFWmonitor*,int,int,int,int,int); GLFWbool (*windowFocused)(_GLFWwindow*); GLFWbool (*windowIconified)(_GLFWwindow*); diff --git a/src/null_init.c b/src/null_init.c index a0383384..11f542e4 100644 --- a/src/null_init.c +++ b/src/null_init.c @@ -94,6 +94,7 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) _glfwHideWindowNull, _glfwRequestWindowAttentionNull, _glfwFocusWindowNull, + _glfwDragWindowNull, _glfwSetWindowMonitorNull, _glfwWindowFocusedNull, _glfwWindowIconifiedNull, diff --git a/src/null_platform.h b/src/null_platform.h index dbfa7c75..d906f35e 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -242,6 +242,7 @@ void _glfwRequestWindowAttentionNull(_GLFWwindow* window); void _glfwRequestWindowAttentionNull(_GLFWwindow* window); void _glfwHideWindowNull(_GLFWwindow* window); void _glfwFocusWindowNull(_GLFWwindow* window); +void _glfwDragWindowNull(_GLFWwindow* window); 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 a60519a5..e42f1ded 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -470,6 +470,11 @@ void _glfwFocusWindowNull(_GLFWwindow* window) _glfwInputWindowFocus(window, GLFW_TRUE); } +void _glfwDragWindowNull(_GLFWwindow* window) +{ + // TODO +} + GLFWbool _glfwWindowFocusedNull(_GLFWwindow* window) { return _glfw.null.focusedWindow == window; diff --git a/src/win32_init.c b/src/win32_init.c index 59e6245c..4d7a75a2 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -710,6 +710,7 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) _glfwHideWindowWin32, _glfwRequestWindowAttentionWin32, _glfwFocusWindowWin32, + _glfwDragWindowWin32, _glfwSetWindowMonitorWin32, _glfwWindowFocusedWin32, _glfwWindowIconifiedWin32, diff --git a/src/win32_platform.h b/src/win32_platform.h index 2493250e..b4de5ff2 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -874,6 +874,7 @@ void _glfwShowWindowWin32(_GLFWwindow* window); void _glfwHideWindowWin32(_GLFWwindow* window); void _glfwRequestWindowAttentionWin32(_GLFWwindow* window); void _glfwFocusWindowWin32(_GLFWwindow* window); +void _glfwDragWindowWin32(_GLFWwindow* window); 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 264d35c7..f8973c30 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2141,6 +2141,12 @@ void _glfwFocusWindowWin32(_GLFWwindow* window) SetFocus(window->win32.handle); } +void _glfwDragWindowWin32(_GLFWwindow* window) +{ + ReleaseCapture(); + SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, HTCAPTION, 0); +} + void _glfwSetWindowMonitorWin32(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/window.c b/src/window.c index 8e6d01aa..1b66a69d 100644 --- a/src/window.c +++ b/src/window.c @@ -853,6 +853,16 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* handle) _glfw.platform.focusWindow(window); } +GLFWAPI void glfwDragWindow(GLFWwindow* handle) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT(); + + _glfw.platform.dragWindow(window); +} + GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/src/wl_init.c b/src/wl_init.c index f6395439..a62770be 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -475,6 +475,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform) _glfwHideWindowWayland, _glfwRequestWindowAttentionWayland, _glfwFocusWindowWayland, + _glfwDragWindowWayland, _glfwSetWindowMonitorWayland, _glfwWindowFocusedWayland, _glfwWindowIconifiedWayland, diff --git a/src/wl_platform.h b/src/wl_platform.h index 104cf4d0..4d527ba0 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -638,6 +638,7 @@ void _glfwShowWindowWayland(_GLFWwindow* window); void _glfwHideWindowWayland(_GLFWwindow* window); void _glfwRequestWindowAttentionWayland(_GLFWwindow* window); void _glfwFocusWindowWayland(_GLFWwindow* window); +void _glfwDragWindowWayland(_GLFWwindow* window); 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 134ae099..fea265b6 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -2763,6 +2763,11 @@ void _glfwFocusWindowWayland(_GLFWwindow* window) "Wayland: The platform does not support setting the input focus"); } +void _glfwDragWindowWayland(_GLFWwindow* window) +{ + xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, _glfw.wl.pointerEnterSerial); +} + void _glfwSetWindowMonitorWayland(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/x11_init.c b/src/x11_init.c index 791cea73..724eb1e7 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -1234,6 +1234,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) _glfwHideWindowX11, _glfwRequestWindowAttentionX11, _glfwFocusWindowX11, + _glfwDragWindowX11, _glfwSetWindowMonitorX11, _glfwWindowFocusedX11, _glfwWindowIconifiedX11, diff --git a/src/x11_platform.h b/src/x11_platform.h index 579b9b3e..f7c70fdf 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -947,6 +947,7 @@ void _glfwShowWindowX11(_GLFWwindow* window); void _glfwHideWindowX11(_GLFWwindow* window); void _glfwRequestWindowAttentionX11(_GLFWwindow* window); void _glfwFocusWindowX11(_GLFWwindow* window); +void _glfwDragWindowX11(_GLFWwindow* window); 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 7d77ff00..5ae8488d 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -47,6 +47,7 @@ #define _NET_WM_STATE_REMOVE 0 #define _NET_WM_STATE_ADD 1 #define _NET_WM_STATE_TOGGLE 2 +#define _NET_WM_MOVERESIZE_MOVE 8 // Additional mouse button names for XButtonEvent #define Button6 6 @@ -2678,6 +2679,28 @@ void _glfwFocusWindowX11(_GLFWwindow* window) XFlush(_glfw.x11.display); } +void _glfwDragWindowX11(_GLFWwindow* window) +{ + int winXpos, winYpos; + double curXpos, curYpos; + XClientMessageEvent xclient; + memset(&xclient, 0, sizeof(XClientMessageEvent)); + XUngrabPointer(_glfw.x11.display, 0); + XFlush(_glfw.x11.display); + _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); + 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 _glfwSetWindowMonitorX11(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos,