From b9d2ea9fa6d58ee06ee49483c6831ddf36564736 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Wed, 5 Apr 2017 22:14:09 -0300 Subject: [PATCH] Implementation of glfwDragWindow for X11 This is the initial implementation of glfwDragWindow, with support for X11. The function glfwDragWindow requires only the target window to be dragged. To make the function easier and more portable, the position of the window and of the cursor are grabbed internally, so the end-user do not need to pass them manually. The example 'simple.c' was updated to include this functionality when clicking on the client area of the window. --- examples/simple.c | 7 +++++++ include/GLFW/glfw3.h | 19 +++++++++++++++++++ src/internal.h | 1 + src/window.c | 10 ++++++++++ src/x11_window.c | 19 +++++++++++++++++++ 5 files changed, 56 insertions(+) diff --git a/examples/simple.c b/examples/simple.c index 7752a3655..692fa5b35 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -68,6 +68,12 @@ static void error_callback(int error, const char* description) fprintf(stderr, "Error: %s\n", description); } +void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) +{ + if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) + glfwDragWindow(window); +} + static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) @@ -96,6 +102,7 @@ int main(void) } glfwSetKeyCallback(window, key_callback); + glfwSetMouseButtonCallback(window, mouse_button_callback); glfwMakeContextCurrent(window); gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 5436b9b48..0c0bc4147 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -2751,6 +2751,25 @@ 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. + * + * @sa @ref window_drag + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwDragWindow(GLFWwindow* handle); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is diff --git a/src/internal.h b/src/internal.h index be9ced898..3a52d2b02 100644 --- a/src/internal.h +++ b/src/internal.h @@ -631,6 +631,7 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window); void _glfwPlatformShowWindow(_GLFWwindow* window); void _glfwPlatformHideWindow(_GLFWwindow* window); void _glfwPlatformFocusWindow(_GLFWwindow* window); +void _glfwPlatformDragWindow(_GLFWwindow* window); void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); int _glfwPlatformWindowFocused(_GLFWwindow* window); int _glfwPlatformWindowIconified(_GLFWwindow* window); diff --git a/src/window.c b/src/window.c index bf98723ea..622d4908c 100644 --- a/src/window.c +++ b/src/window.c @@ -698,6 +698,16 @@ 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 int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/src/x11_window.c b/src/x11_window.c index e1c2a3e3e..80f9f46c5 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -43,6 +43,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 @@ -2091,6 +2092,24 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) XFlush(_glfw.x11.display); } +void _glfwPlatformDragWindow(_GLFWwindow* window) +{ + XClientMessageEvent xclient; + memset(&xclient, 0, sizeof(XClientMessageEvent)); + XUngrabPointer(_glfw.x11.display, 0); + XFlush(_glfw.x11.display); + 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] = window->x11.xpos + window->x11.lastCursorPosX; + xclient.data.l[1] = window->x11.ypos + window->x11.lastCursorPosY; + 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 _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos,