From cd02f4ac30cc22e7f4ce2f488bfa10c325873ee2 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Fri, 7 Apr 2017 21:35:58 -0300 Subject: [PATCH 1/4] Support for resize operation on X11 This adds the function ```glfwResizeWindow```, that allows to resize windows without borders. --- include/GLFW/glfw3.h | 39 ++++++++++++++++++++++++++++++ src/internal.h | 1 + src/window.c | 13 ++++++++++ src/x11_window.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 5436b9b48..292c91db9 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -900,6 +900,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. * @@ -2751,6 +2760,36 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window); */ GLFWAPI void glfwFocusWindow(GLFWwindow* window); +/*! @brief Starts a resize operation with the specified window. + * + * This function starts a resize operation on one of the borders of the + * specified window. + * + * 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 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..72314cb1b 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 _glfwPlatformResizeWindow(_GLFWwindow* window, int border); 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..36d6d6b84 100644 --- a/src/window.c +++ b/src/window.c @@ -698,6 +698,19 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* handle) _glfwPlatformFocusWindow(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; diff --git a/src/x11_window.c b/src/x11_window.c index e1c2a3e3e..d7e852fa8 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -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 + // Additional mouse button names for XButtonEvent #define Button6 6 @@ -2091,6 +2100,53 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) XFlush(_glfw.x11.display); } +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; + } + 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, From 6451897a98f8923f298ad04dc73fb79cd63e4261 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Fri, 7 Apr 2017 21:48:20 -0300 Subject: [PATCH 2/4] Add stub functions for each platform --- src/cocoa_window.m | 4 ++++ src/mir_window.c | 4 ++++ src/win32_window.c | 4 ++++ src/wl_window.c | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index d2aab85f9..f15e206e9 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1288,6 +1288,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) [window->ns.object makeKeyAndOrderFront:nil]; } +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ +} + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/mir_window.c b/src/mir_window.c index e380f4070..ae332eafd 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -576,6 +576,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ +} + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/win32_window.c b/src/win32_window.c index 363ef0f32..810ec048c 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1323,6 +1323,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) SetFocus(window->win32.handle); } +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ +} + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, diff --git a/src/wl_window.c b/src/wl_window.c index e6c554527..7c672d7fb 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -605,6 +605,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) "Wayland: Focusing a window requires user interaction"); } +void _glfwPlatformResizeWindow(_GLFWwindow* window, int border) +{ +} + void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, From f7d8de651b0706cec8b33e5e77890d2b79a4c74e Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Fri, 7 Apr 2017 23:30:09 -0300 Subject: [PATCH 3/4] Support for resize operation on Windows The function ```glfwResizeWindow``` now supports the Windows platform. --- src/win32_window.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/win32_window.c b/src/win32_window.c index 810ec048c..f1fe20bf9 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1325,6 +1325,35 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) 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; + } + ReleaseCapture(); + SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, wBorder, 0); } void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, From 71bb507172a2b9667e0e91d22ab08d36c0224313 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Fri, 7 Apr 2017 23:57:24 -0300 Subject: [PATCH 4/4] Support for resize operation on Wayland This is an initial implementation and still isn't working. --- src/wl_window.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/wl_window.c b/src/wl_window.c index 7c672d7fb..d31586024 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -607,6 +607,37 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) 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; + } + wl_shell_surface_resize(window->wl.shellSurface, + _glfw.wl.seat, + _glfw.wl.pointerSerial, + wlBorder); } void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,