mirror of
https://github.com/glfw/glfw.git
synced 2024-11-27 04:22:00 +00:00
Support for drag and resize operations
This commit is contained in:
parent
29d8ca4ce4
commit
073c0cceb5
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <string.h>
|
||||
#include <windowsx.h>
|
||||
#include <shellapi.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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,
|
||||
|
23
src/window.c
23
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;
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user