From 7f0b4e58b003d87877e3d53fbc0c7dc9e07f4f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Tue, 17 Dec 2024 20:01:56 +0200 Subject: [PATCH] Implement `DisplayServer.window_start_resize`. --- doc/classes/DisplayServer.xml | 40 +++++++++- .../wayland/display_server_wayland.cpp | 7 ++ .../linuxbsd/wayland/display_server_wayland.h | 1 + platform/linuxbsd/wayland/wayland_thread.cpp | 74 +++++++++++++++++++ platform/linuxbsd/wayland/wayland_thread.h | 2 + platform/linuxbsd/x11/display_server_x11.cpp | 72 ++++++++++++++++++ platform/linuxbsd/x11/display_server_x11.h | 1 + platform/macos/display_server_macos.h | 2 + platform/macos/display_server_macos.mm | 10 +++ platform/macos/godot_content_view.mm | 60 +++++++++++++++ platform/windows/display_server_windows.cpp | 46 ++++++++++++ platform/windows/display_server_windows.h | 1 + servers/display_server.cpp | 11 +++ servers/display_server.h | 15 ++++ 14 files changed, 340 insertions(+), 2 deletions(-) diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 35edebeb4a9..1f98e3f4867 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1836,8 +1836,17 @@ - Starts a drag operation on the window with the given [param window_id], using the current mouse position. Call this method when handling a mouse button being pressed to simulate a pressed event on the window's title bar. Using this method allows the window to participate in space switching, tiling, and other system features. - [b]Note:[/b] This method is implemented on Linux(X11/Wayland), macOS, and Windows. + Starts an interactive drag operation on the window with the given [param window_id], using the current mouse position. Call this method when handling a mouse button being pressed to simulate a pressed event on the window's title bar. Using this method allows the window to participate in space switching, tiling, and other system features. + [b]Note:[/b] This method is implemented on Linux (X11/Wayland), macOS, and Windows. + + + + + + + + Starts an interactive resize operation on the window with the given [param window_id], using the current mouse position. Call this method when handling a mouse button being pressed to simulate a pressed event on the window's edge. + [b]Note:[/b] This method is implemented on Linux (X11/Wayland), macOS, and Windows. @@ -2183,6 +2192,33 @@ Sent when the window title bar decoration is changed (e.g. [constant WINDOW_FLAG_EXTEND_TO_TITLE] is set or window entered/exited full screen mode). [b]Note:[/b] This flag is implemented only on macOS. + + Top-left edge of a window. + + + Top edge of a window. + + + Top-right edge of a window. + + + Left edge of a window. + + + Right edge of a window. + + + Bottom-left edge of a window. + + + Bottom edge of a window. + + + Bottom-right edge of a window. + + + Represents the size of the [enum WindowResizeEdge] enum. + No vertical synchronization, which means the engine will display frames as fast as possible (tearing may be visible). Framerate is unlimited (regardless of [member Engine.max_fps]). diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 320f4109028..697cd8388c7 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -993,6 +993,13 @@ void DisplayServerWayland::window_start_drag(WindowID p_window) { wayland_thread.window_start_drag(p_window); } +void DisplayServerWayland::window_start_resize(WindowResizeEdge p_edge, WindowID p_window) { + MutexLock mutex_lock(wayland_thread.mutex); + + ERR_FAIL_INDEX(int(p_edge), WINDOW_EDGE_MAX); + wayland_thread.window_start_resize(p_edge, p_window); +} + void DisplayServerWayland::cursor_set_shape(CursorShape p_shape) { ERR_FAIL_INDEX(p_shape, CURSOR_MAX); diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h index 4c3ecc09052..beab5a83128 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.h +++ b/platform/linuxbsd/wayland/display_server_wayland.h @@ -273,6 +273,7 @@ public: virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_window_id) const override; virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window) override; virtual void cursor_set_shape(CursorShape p_shape) override; virtual CursorShape cursor_get_shape() const override; diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp index f571f70936c..e1a0739a95c 100644 --- a/platform/linuxbsd/wayland/wayland_thread.cpp +++ b/platform/linuxbsd/wayland/wayland_thread.cpp @@ -3354,6 +3354,80 @@ void WaylandThread::window_start_drag(DisplayServer::WindowID p_window_id) { #endif } +void WaylandThread::window_start_resize(DisplayServer::WindowResizeEdge p_edge, DisplayServer::WindowID p_window) { + // TODO: Use window IDs for multiwindow support. + WindowState &ws = main_window; + SeatState *ss = wl_seat_get_seat_state(wl_seat_current); + + if (ss && ws.xdg_toplevel) { + xdg_toplevel_resize_edge edge = XDG_TOPLEVEL_RESIZE_EDGE_NONE; + switch (p_edge) { + case DisplayServer::WINDOW_EDGE_TOP_LEFT: { + edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + } break; + case DisplayServer::WINDOW_EDGE_TOP: { + edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP; + } break; + case DisplayServer::WINDOW_EDGE_TOP_RIGHT: { + edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + } break; + case DisplayServer::WINDOW_EDGE_LEFT: { + edge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + } break; + case DisplayServer::WINDOW_EDGE_RIGHT: { + edge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_LEFT: { + edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM: { + edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_RIGHT: { + edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + } break; + default: + break; + } + xdg_toplevel_resize(ws.xdg_toplevel, ss->wl_seat, ss->pointer_data.button_serial, edge); + } + +#ifdef LIBDECOR_ENABLED + if (ws.libdecor_frame) { + libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE; + switch (p_edge) { + case DisplayServer::WINDOW_EDGE_TOP_LEFT: { + edge = LIBDECOR_RESIZE_EDGE_TOP_LEFT; + } break; + case DisplayServer::WINDOW_EDGE_TOP: { + edge = LIBDECOR_RESIZE_EDGE_TOP; + } break; + case DisplayServer::WINDOW_EDGE_TOP_RIGHT: { + edge = LIBDECOR_RESIZE_EDGE_TOP_RIGHT; + } break; + case DisplayServer::WINDOW_EDGE_LEFT: { + edge = LIBDECOR_RESIZE_EDGE_LEFT; + } break; + case DisplayServer::WINDOW_EDGE_RIGHT: { + edge = LIBDECOR_RESIZE_EDGE_RIGHT; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_LEFT: { + edge = LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM: { + edge = LIBDECOR_RESIZE_EDGE_BOTTOM; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_RIGHT: { + edge = LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT; + } break; + default: + break; + } + libdecor_frame_resize(ws.libdecor_frame, ss->wl_seat, ss->pointer_data.button_serial, edge); + } +#endif +} + void WaylandThread::window_set_max_size(DisplayServer::WindowID p_window_id, const Size2i &p_size) { // TODO: Use window IDs for multiwindow support. WindowState &ws = main_window; diff --git a/platform/linuxbsd/wayland/wayland_thread.h b/platform/linuxbsd/wayland/wayland_thread.h index 1996e0e359d..5172bf4087b 100644 --- a/platform/linuxbsd/wayland/wayland_thread.h +++ b/platform/linuxbsd/wayland/wayland_thread.h @@ -955,6 +955,8 @@ public: struct wl_surface *window_get_wl_surface(DisplayServer::WindowID p_window_id) const; + void window_start_resize(DisplayServer::WindowResizeEdge p_edge, DisplayServer::WindowID p_window); + void window_set_max_size(DisplayServer::WindowID p_window_id, const Size2i &p_size); void window_set_min_size(DisplayServer::WindowID p_window_id, const Size2i &p_size); diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 60a27cc8343..8a33e10cbe2 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -69,6 +69,14 @@ #define _NET_WM_STATE_REMOVE 0L // remove/unset property #define _NET_WM_STATE_ADD 1L // add/set property +#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0L +#define _NET_WM_MOVERESIZE_SIZE_TOP 1L +#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2L +#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3L +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4L +#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5L +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6L +#define _NET_WM_MOVERESIZE_SIZE_LEFT 7L #define _NET_WM_MOVERESIZE_MOVE 8L // 2.2 is the first release with multitouch @@ -5516,6 +5524,70 @@ void DisplayServerX11::window_start_drag(WindowID p_window) { XSync(x11_display, 0); } +void DisplayServerX11::window_start_resize(WindowResizeEdge p_edge, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_INDEX(int(p_edge), WINDOW_EDGE_MAX); + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + XClientMessageEvent m; + memset(&m, 0, sizeof(m)); + + XUngrabPointer(x11_display, CurrentTime); + + Window root_return, child_return; + int root_x, root_y, win_x, win_y; + unsigned int mask_return; + + Bool xquerypointer_result = XQueryPointer(x11_display, wd.x11_window, &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &mask_return); + + m.type = ClientMessage; + m.window = wd.x11_window; + m.message_type = XInternAtom(x11_display, "_NET_WM_MOVERESIZE", True); + m.format = 32; + if (xquerypointer_result) { + m.data.l[0] = root_x; + m.data.l[1] = root_y; + m.data.l[3] = Button1; + } + + switch (p_edge) { + case DisplayServer::WINDOW_EDGE_TOP_LEFT: { + m.data.l[2] = _NET_WM_MOVERESIZE_SIZE_TOPLEFT; + } break; + case DisplayServer::WINDOW_EDGE_TOP: { + m.data.l[2] = _NET_WM_MOVERESIZE_SIZE_TOP; + } break; + case DisplayServer::WINDOW_EDGE_TOP_RIGHT: { + m.data.l[2] = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT; + } break; + case DisplayServer::WINDOW_EDGE_LEFT: { + m.data.l[2] = _NET_WM_MOVERESIZE_SIZE_LEFT; + } break; + case DisplayServer::WINDOW_EDGE_RIGHT: { + m.data.l[2] = _NET_WM_MOVERESIZE_SIZE_RIGHT; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_LEFT: { + m.data.l[2] = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM: { + m.data.l[2] = _NET_WM_MOVERESIZE_SIZE_BOTTOM; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_RIGHT: { + m.data.l[2] = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT; + } break; + default: + break; + } + m.data.l[4] = 1; // Source - normal application. + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&m); + + XSync(x11_display, 0); +} + pid_t get_window_pid(Display *p_display, Window p_window) { Atom atom = XInternAtom(p_display, "_NET_WM_PID", False); Atom actualType; diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index cc57f5a41b3..e0a84db4b62 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -527,6 +527,7 @@ public: virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override; virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window) override; virtual Error embed_process(WindowID p_window, OS::ProcessID p_pid, const Rect2i &p_rect, bool p_visible, bool p_grab_focus) override; virtual Error remove_embedded_process(OS::ProcessID p_pid) override; diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 7004ff2e5a1..cc7ef3507e7 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -92,6 +92,7 @@ public: Vector mpath; Point2i mouse_pos; + WindowResizeEdge edge = WINDOW_EDGE_MAX; Size2i min_size; Size2i max_size; @@ -409,6 +410,7 @@ public: virtual bool window_minimize_on_title_dbl_click() const override; virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window = MAIN_WINDOW_ID) override; virtual void window_set_window_buttons_offset(const Vector2i &p_offset, WindowID p_window = MAIN_WINDOW_ID) override; virtual Vector3i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 253b4b0a9fe..f4935437552 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -2440,6 +2440,16 @@ void DisplayServerMacOS::window_start_drag(WindowID p_window) { [wd.window_object performWindowDragWithEvent:event]; } +void DisplayServerMacOS::window_start_resize(WindowResizeEdge p_edge, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_INDEX(int(p_edge), WINDOW_EDGE_MAX); + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + wd.edge = p_edge; +} + void DisplayServerMacOS::window_set_window_buttons_offset(const Vector2i &p_offset, WindowID p_window) { _THREAD_SAFE_METHOD_ diff --git a/platform/macos/godot_content_view.mm b/platform/macos/godot_content_view.mm index 7d43ac9fe61..eff33208db4 100644 --- a/platform/macos/godot_content_view.mm +++ b/platform/macos/godot_content_view.mm @@ -394,6 +394,11 @@ } - (void)mouseDown:(NSEvent *)event { + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); + if (ds && ds->has_window(window_id)) { + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); + wd.edge = DisplayServer::WINDOW_EDGE_MAX; + } if (([event modifierFlags] & NSEventModifierFlagControl)) { mouse_down_control = true; [self processMouseEvent:event index:MouseButton::RIGHT pressed:true outofstream:false]; @@ -404,10 +409,65 @@ } - (void)mouseDragged:(NSEvent *)event { + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); + if (ds && ds->has_window(window_id)) { + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); + if (wd.edge != DisplayServer::WINDOW_EDGE_MAX) { + Size2i max_size = wd.max_size / ds->screen_get_max_scale(); + Size2i min_size = wd.min_size / ds->screen_get_max_scale(); + NSRect frame = [wd.window_object frame]; + switch (wd.edge) { + case DisplayServer::WINDOW_EDGE_TOP_LEFT: { + int clamped_dx = CLAMP(frame.size.width - event.deltaX, min_size.x, max_size.x) - frame.size.width; + int clamped_dy = CLAMP(frame.size.height - event.deltaY, min_size.y, max_size.y) - frame.size.height; + [wd.window_object setFrame:NSMakeRect(frame.origin.x - clamped_dx, frame.origin.y, frame.size.width + clamped_dx, frame.size.height + clamped_dy) display:YES]; + } break; + case DisplayServer::WINDOW_EDGE_TOP: { + int clamped_dy = CLAMP(frame.size.height - event.deltaY, min_size.y, max_size.y) - frame.size.height; + [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height + clamped_dy) display:YES]; + } break; + case DisplayServer::WINDOW_EDGE_TOP_RIGHT: { + int clamped_dx = CLAMP(frame.size.width + event.deltaX, min_size.x, max_size.x) - frame.size.width; + int clamped_dy = CLAMP(frame.size.height - event.deltaY, min_size.y, max_size.y) - frame.size.height; + [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width + clamped_dx, frame.size.height + clamped_dy) display:YES]; + } break; + case DisplayServer::WINDOW_EDGE_LEFT: { + int clamped_dx = CLAMP(frame.size.width - event.deltaX, min_size.x, max_size.x) - frame.size.width; + [wd.window_object setFrame:NSMakeRect(frame.origin.x - clamped_dx, frame.origin.y, frame.size.width + clamped_dx, frame.size.height) display:YES]; + } break; + case DisplayServer::WINDOW_EDGE_RIGHT: { + int clamped_dx = CLAMP(frame.size.width + event.deltaX, min_size.x, max_size.x) - frame.size.width; + [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width + clamped_dx, frame.size.height) display:YES]; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_LEFT: { + int clamped_dx = CLAMP(frame.size.width - event.deltaX, min_size.x, max_size.x) - frame.size.width; + int clamped_dy = CLAMP(frame.size.height + event.deltaY, min_size.y, max_size.y) - frame.size.height; + [wd.window_object setFrame:NSMakeRect(frame.origin.x - clamped_dx, frame.origin.y - clamped_dy, frame.size.width + clamped_dx, frame.size.height + clamped_dy) display:YES]; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM: { + int clamped_dy = CLAMP(frame.size.height + event.deltaY, min_size.y, max_size.y) - frame.size.height; + [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y - clamped_dy, frame.size.width, frame.size.height + clamped_dy) display:YES]; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_RIGHT: { + int clamped_dx = CLAMP(frame.size.width + event.deltaX, min_size.x, max_size.x) - frame.size.width; + int clamped_dy = CLAMP(frame.size.height + event.deltaY, min_size.y, max_size.y) - frame.size.height; + [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y - clamped_dy, frame.size.width + clamped_dx, frame.size.height + clamped_dy) display:YES]; + } break; + default: + break; + } + return; + } + } [self mouseMoved:event]; } - (void)mouseUp:(NSEvent *)event { + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); + if (ds && ds->has_window(window_id)) { + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); + wd.edge = DisplayServer::WINDOW_EDGE_MAX; + } if (mouse_down_control) { [self processMouseEvent:event index:MouseButton::RIGHT pressed:false outofstream:false]; } else { diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 34596022655..c053408ed4c 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -3999,6 +3999,52 @@ void DisplayServerWindows::window_start_drag(WindowID p_window) { SendMessage(wd.hWnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(coords.x, coords.y)); } +void DisplayServerWindows::window_start_resize(WindowResizeEdge p_edge, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_INDEX(int(p_edge), WINDOW_EDGE_MAX); + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + ReleaseCapture(); + + POINT coords; + GetCursorPos(&coords); + ScreenToClient(wd.hWnd, &coords); + + DWORD op = 0; + switch (p_edge) { + case DisplayServer::WINDOW_EDGE_TOP_LEFT: { + op = WMSZ_TOPLEFT; + } break; + case DisplayServer::WINDOW_EDGE_TOP: { + op = WMSZ_TOP; + } break; + case DisplayServer::WINDOW_EDGE_TOP_RIGHT: { + op = WMSZ_TOPRIGHT; + } break; + case DisplayServer::WINDOW_EDGE_LEFT: { + op = WMSZ_LEFT; + } break; + case DisplayServer::WINDOW_EDGE_RIGHT: { + op = WMSZ_RIGHT; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_LEFT: { + op = WMSZ_BOTTOMLEFT; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM: { + op = WMSZ_BOTTOM; + } break; + case DisplayServer::WINDOW_EDGE_BOTTOM_RIGHT: { + op = WMSZ_BOTTOMRIGHT; + } break; + default: + break; + } + + SendMessage(wd.hWnd, WM_SYSCOMMAND, SC_SIZE | op, MAKELPARAM(coords.x, coords.y)); +} + void DisplayServerWindows::set_context(Context p_context) { } diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 891f82890a1..5d69e1490d6 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -819,6 +819,7 @@ public: virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override; virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window = MAIN_WINDOW_ID) override; virtual void cursor_set_shape(CursorShape p_shape) override; virtual CursorShape cursor_get_shape() const override; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index ad3e57f302d..ce1e75d3093 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -993,6 +993,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("window_minimize_on_title_dbl_click"), &DisplayServer::window_minimize_on_title_dbl_click); ClassDB::bind_method(D_METHOD("window_start_drag", "window_id"), &DisplayServer::window_start_drag, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_start_resize", "edge", "window_id"), &DisplayServer::window_start_resize, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection); ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text); @@ -1170,6 +1171,16 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(WINDOW_EVENT_DPI_CHANGE); BIND_ENUM_CONSTANT(WINDOW_EVENT_TITLEBAR_CHANGE); + BIND_ENUM_CONSTANT(WINDOW_EDGE_TOP_LEFT); + BIND_ENUM_CONSTANT(WINDOW_EDGE_TOP); + BIND_ENUM_CONSTANT(WINDOW_EDGE_TOP_RIGHT); + BIND_ENUM_CONSTANT(WINDOW_EDGE_LEFT); + BIND_ENUM_CONSTANT(WINDOW_EDGE_RIGHT); + BIND_ENUM_CONSTANT(WINDOW_EDGE_BOTTOM_LEFT); + BIND_ENUM_CONSTANT(WINDOW_EDGE_BOTTOM); + BIND_ENUM_CONSTANT(WINDOW_EDGE_BOTTOM_RIGHT); + BIND_ENUM_CONSTANT(WINDOW_EDGE_MAX); + BIND_ENUM_CONSTANT(VSYNC_DISABLED); BIND_ENUM_CONSTANT(VSYNC_ENABLED); BIND_ENUM_CONSTANT(VSYNC_ADAPTIVE); diff --git a/servers/display_server.h b/servers/display_server.h index f804c22d088..39bdc80b862 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -499,6 +499,20 @@ public: virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) {} + enum WindowResizeEdge { + WINDOW_EDGE_TOP_LEFT, + WINDOW_EDGE_TOP, + WINDOW_EDGE_TOP_RIGHT, + WINDOW_EDGE_LEFT, + WINDOW_EDGE_RIGHT, + WINDOW_EDGE_BOTTOM_LEFT, + WINDOW_EDGE_BOTTOM, + WINDOW_EDGE_BOTTOM_RIGHT, + WINDOW_EDGE_MAX, + }; + + virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window = MAIN_WINDOW_ID) {} + // necessary for GL focus, may be able to use one of the existing functions for this, not sure yet virtual void gl_window_make_current(DisplayServer::WindowID p_window_id); @@ -639,6 +653,7 @@ VARIANT_ENUM_CAST(DisplayServer::MouseMode) VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation) VARIANT_ENUM_CAST(DisplayServer::WindowMode) VARIANT_ENUM_CAST(DisplayServer::WindowFlags) +VARIANT_ENUM_CAST(DisplayServer::WindowResizeEdge) VARIANT_ENUM_CAST(DisplayServer::HandleType) VARIANT_ENUM_CAST(DisplayServer::VirtualKeyboardType); VARIANT_ENUM_CAST(DisplayServer::CursorShape)