Add glfwDragWindow

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.
This commit is contained in:
Felipe Ferreira da Silva 2017-04-05 22:14:09 -03:00 committed by Camilla Löwy
parent 5b7281bd41
commit a4c76fbeed
11 changed files with 80 additions and 0 deletions

View File

@ -138,6 +138,7 @@ information on what to include when reporting a bug.
for retrieving gamepad input state (#900) for retrieving gamepad input state (#900)
- Added `glfwRequestWindowAttention` function for requesting attention from the - Added `glfwRequestWindowAttention` function for requesting attention from the
user (#732,#988) user (#732,#988)
- Added `glfwDragWindow` function for starting a drag operation on a window
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent - Added `glfwGetKeyScancode` function that allows retrieving platform dependent
scancodes for keys (#830) scancodes for keys (#830)
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for - Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for

View File

@ -68,6 +68,12 @@ static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", 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) static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{ {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
@ -96,6 +102,7 @@ int main(void)
} }
glfwSetKeyCallback(window, key_callback); glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);

View File

@ -2929,6 +2929,21 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
*/ */
GLFWAPI void glfwFocusWindow(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.2.
*
* @ingroup window
*/
GLFWAPI void glfwDragWindow(GLFWwindow* handle);
/*! @brief Requests user attention to the specified window. /*! @brief Requests user attention to the specified window.
* *
* This function requests user attention to the specified window. On * This function requests user attention to the specified window. On

View File

@ -1298,6 +1298,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
[window->ns.object makeKeyAndOrderFront:nil]; [window->ns.object makeKeyAndOrderFront:nil];
} }
void _glfwPlatformDragWindow(_GLFWwindow* window)
{
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor, _GLFWmonitor* monitor,
int xpos, int ypos, int xpos, int ypos,

View File

@ -674,6 +674,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window);
void _glfwPlatformHideWindow(_GLFWwindow* window); void _glfwPlatformHideWindow(_GLFWwindow* window);
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window); void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
void _glfwPlatformFocusWindow(_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); void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
int _glfwPlatformWindowFocused(_GLFWwindow* window); int _glfwPlatformWindowFocused(_GLFWwindow* window);
int _glfwPlatformWindowIconified(_GLFWwindow* window); int _glfwPlatformWindowIconified(_GLFWwindow* window);

View File

@ -582,6 +582,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
"Mir: Unsupported function %s", __PRETTY_FUNCTION__); "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
} }
void _glfwPlatformDragWindow(_GLFWwindow* window)
{
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor, _GLFWmonitor* monitor,
int xpos, int ypos, int xpos, int ypos,

View File

@ -189,6 +189,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
{ {
} }
void _glfwPlatformDragWindow(_GLFWwindow* window)
{
}
int _glfwPlatformWindowFocused(_GLFWwindow* window) int _glfwPlatformWindowFocused(_GLFWwindow* window)
{ {
return GLFW_FALSE; return GLFW_FALSE;

View File

@ -1328,6 +1328,12 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
SetFocus(window->win32.handle); SetFocus(window->win32.handle);
} }
void _glfwPlatformDragWindow(_GLFWwindow* window)
{
ReleaseCapture();
SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor, _GLFWmonitor* monitor,
int xpos, int ypos, int xpos, int ypos,

View File

@ -708,6 +708,16 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
_glfwPlatformFocusWindow(window); _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) GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;

View File

@ -612,6 +612,11 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
"Wayland: Focusing a window requires user interaction"); "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 _glfwPlatformSetWindowMonitor(_GLFWwindow* window, void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor, _GLFWmonitor* monitor,
int xpos, int ypos, int xpos, int ypos,

View File

@ -43,6 +43,7 @@
#define _NET_WM_STATE_REMOVE 0 #define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1 #define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2 #define _NET_WM_STATE_TOGGLE 2
#define _NET_WM_MOVERESIZE_MOVE 8
// Additional mouse button names for XButtonEvent // Additional mouse button names for XButtonEvent
#define Button6 6 #define Button6 6
@ -2143,6 +2144,28 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
XFlush(_glfw.x11.display); 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 _glfwPlatformSetWindowMonitor(_GLFWwindow* window, void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor, _GLFWmonitor* monitor,
int xpos, int ypos, int xpos, int ypos,