mirror of
https://github.com/glfw/glfw.git
synced 2025-12-15 11:43:13 +00:00
Merge 1940dbccfd into dbadda2683
This commit is contained in:
commit
da63f5ef52
@ -302,6 +302,9 @@ video tutorials.
|
||||
- Jonas Ådahl
|
||||
- Lasse Öörni
|
||||
- Leonard König
|
||||
- Felipe da Silva
|
||||
- Naveen Karuthedath
|
||||
- Seneral
|
||||
- All the unmentioned and anonymous contributors in the GLFW community, for bug
|
||||
reports, patches, feedback, testing and encouragement
|
||||
|
||||
|
||||
@ -120,6 +120,7 @@ information on what to include when reporting a bug.
|
||||
|
||||
## Changelog since 3.4
|
||||
|
||||
- Added `glfwDragWindow` function for starting a drag operation on a window
|
||||
- Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond
|
||||
the limit of the mouse button tokens to be reported (#2423)
|
||||
- Added `glfwGetEGLConfig` function to query the `EGLConfig` of a window (#2045)
|
||||
|
||||
@ -31,6 +31,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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 xpos, ypos, height;
|
||||
@ -78,6 +84,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
glfwSetInputMode(windows[i], GLFW_STICKY_KEYS, GLFW_TRUE);
|
||||
glfwSetMouseButtonCallback(windows[i], mouse_button_callback);
|
||||
|
||||
glfwMakeContextCurrent(windows[i]);
|
||||
gladLoadGL(glfwGetProcAddress);
|
||||
|
||||
@ -3969,6 +3969,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
|
||||
|
||||
@ -542,6 +542,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform)
|
||||
.hideWindow = _glfwHideWindowCocoa,
|
||||
.requestWindowAttention = _glfwRequestWindowAttentionCocoa,
|
||||
.focusWindow = _glfwFocusWindowCocoa,
|
||||
.dragWindow = _glfwDragWindowCocoa,
|
||||
.setWindowMonitor = _glfwSetWindowMonitorCocoa,
|
||||
.windowFocused = _glfwWindowFocusedCocoa,
|
||||
.windowIconified = _glfwWindowIconifiedCocoa,
|
||||
|
||||
@ -234,6 +234,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);
|
||||
|
||||
@ -1240,6 +1240,11 @@ void _glfwFocusWindowCocoa(_GLFWwindow* window)
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void _glfwDragWindowCocoa(_GLFWwindow* window)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
|
||||
@ -733,6 +733,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*);
|
||||
|
||||
@ -88,6 +88,7 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform)
|
||||
.hideWindow = _glfwHideWindowNull,
|
||||
.requestWindowAttention = _glfwRequestWindowAttentionNull,
|
||||
.focusWindow = _glfwFocusWindowNull,
|
||||
.dragWindow = _glfwDragWindowNull,
|
||||
.setWindowMonitor = _glfwSetWindowMonitorNull,
|
||||
.windowFocused = _glfwWindowFocusedNull,
|
||||
.windowIconified = _glfwWindowIconifiedNull,
|
||||
|
||||
@ -251,6 +251,7 @@ void _glfwShowWindowNull(_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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -648,6 +648,7 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform)
|
||||
.hideWindow = _glfwHideWindowWin32,
|
||||
.requestWindowAttention = _glfwRequestWindowAttentionWin32,
|
||||
.focusWindow = _glfwFocusWindowWin32,
|
||||
.dragWindow = _glfwDragWindowWin32,
|
||||
.setWindowMonitor = _glfwSetWindowMonitorWin32,
|
||||
.windowFocused = _glfwWindowFocusedWin32,
|
||||
.windowIconified = _glfwWindowIconifiedWin32,
|
||||
|
||||
@ -502,6 +502,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);
|
||||
|
||||
@ -1828,6 +1828,13 @@ void _glfwFocusWindowWin32(_GLFWwindow* window)
|
||||
SetFocus(window->win32.handle);
|
||||
}
|
||||
|
||||
void _glfwDragWindowWin32(_GLFWwindow* window)
|
||||
{
|
||||
ReleaseCapture();
|
||||
SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, getKeyMods());
|
||||
}
|
||||
|
||||
void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
|
||||
10
src/window.c
10
src/window.c
@ -876,6 +876,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)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
|
||||
@ -493,6 +493,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
|
||||
.hideWindow = _glfwHideWindowWayland,
|
||||
.requestWindowAttention = _glfwRequestWindowAttentionWayland,
|
||||
.focusWindow = _glfwFocusWindowWayland,
|
||||
.dragWindow = _glfwDragWindowWayland,
|
||||
.setWindowMonitor = _glfwSetWindowMonitorWayland,
|
||||
.windowFocused = _glfwWindowFocusedWayland,
|
||||
.windowIconified = _glfwWindowIconifiedWayland,
|
||||
|
||||
@ -640,6 +640,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);
|
||||
|
||||
@ -1578,6 +1578,13 @@ static void pointerHandleLeave(void* userData,
|
||||
{
|
||||
window->wl.hovered = GLFW_FALSE;
|
||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
||||
// Would like to silently set mouse button state to undefined without triggering a mouse button release event
|
||||
// See https://gitlab.freedesktop.org/wayland/wayland/-/issues/280
|
||||
// But many underlying systems will keep their own state and only use GLFW events to keep it up to date
|
||||
// So realistically, they NEED a mouse button event, even if wayland spec would like it to be implicitly undefined
|
||||
for (int btn = 0; btn < GLFW_MOUSE_BUTTON_LAST+1; btn++)
|
||||
if (window->mouseButtons[btn] != GLFW_RELEASE)
|
||||
_glfwInputMouseClick(window, btn, GLFW_RELEASE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1801,6 +1808,14 @@ static void keyboardHandleLeave(void* userData,
|
||||
_glfw.wl.serial = serial;
|
||||
_glfw.wl.keyboardFocus = NULL;
|
||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||
|
||||
// Would like to silently set key state to undefined without triggering a key release event
|
||||
// See https://gitlab.freedesktop.org/wayland/wayland/-/issues/280
|
||||
// But many underlying systems will keep their own state and only use GLFW events to keep it up to date
|
||||
// So realistically, they NEED a key event, even if wayland spec would like it to be implicitly undefined
|
||||
for (int key = 0; key < GLFW_KEY_LAST+1; key++)
|
||||
if (window->keys[key] != GLFW_RELEASE)
|
||||
_glfwInputKey(window, key, _glfwGetKeyScancodeWayland(key), GLFW_RELEASE, 0);
|
||||
}
|
||||
|
||||
static void keyboardHandleKey(void* userData,
|
||||
@ -2551,6 +2566,37 @@ void _glfwFocusWindowWayland(_GLFWwindow* window)
|
||||
xdg_activation_token_v1_commit(window->wl.activationToken);
|
||||
}
|
||||
|
||||
void _glfwDragWindowWayland(_GLFWwindow* window)
|
||||
{
|
||||
struct xdg_toplevel* toplevel =
|
||||
window->wl.libdecor.frame ?
|
||||
libdecor_frame_get_xdg_toplevel(window->wl.libdecor.frame) :
|
||||
window->wl.xdg.toplevel;
|
||||
|
||||
if (!toplevel)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Cannot drag window: xdg_toplevel not created yet");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_glfw.wl.seat)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Cannot drag window: no valid seat");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_glfw.wl.serial == 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Cannot drag window: no valid serial");
|
||||
return;
|
||||
}
|
||||
|
||||
xdg_toplevel_move(toplevel, _glfw.wl.seat, _glfw.wl.serial);
|
||||
}
|
||||
|
||||
void _glfwSetWindowMonitorWayland(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
|
||||
@ -1224,6 +1224,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
|
||||
.hideWindow = _glfwHideWindowX11,
|
||||
.requestWindowAttention = _glfwRequestWindowAttentionX11,
|
||||
.focusWindow = _glfwFocusWindowX11,
|
||||
.dragWindow = _glfwDragWindowX11,
|
||||
.setWindowMonitor = _glfwSetWindowMonitorX11,
|
||||
.windowFocused = _glfwWindowFocusedX11,
|
||||
.windowIconified = _glfwWindowIconifiedX11,
|
||||
|
||||
@ -922,6 +922,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);
|
||||
|
||||
@ -45,6 +45,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
|
||||
@ -2474,6 +2475,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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user