Skip to content

Commit 293be04

Browse files
committed
Implement window_start_drag on Windows and Linux.
1 parent 4364ed6 commit 293be04

9 files changed

+82
-1
lines changed

doc/classes/DisplayServer.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1836,7 +1836,7 @@
18361836
<param index="0" name="window_id" type="int" default="0" />
18371837
<description>
18381838
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.
1839-
[b]Note:[/b] This method is implemented only on macOS.
1839+
[b]Note:[/b] This method is implemented on Linux(X11/Wayland), macOS, and Windows.
18401840
</description>
18411841
</method>
18421842
</methods>

platform/linuxbsd/wayland/display_server_wayland.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,12 @@ DisplayServer::VSyncMode DisplayServerWayland::window_get_vsync_mode(DisplayServ
986986
return DisplayServer::VSYNC_ENABLED;
987987
}
988988

989+
void DisplayServerWayland::window_start_drag(WindowID p_window) {
990+
MutexLock mutex_lock(wayland_thread.mutex);
991+
992+
wayland_thread.window_start_drag(p_window);
993+
}
994+
989995
void DisplayServerWayland::cursor_set_shape(CursorShape p_shape) {
990996
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
991997

platform/linuxbsd/wayland/display_server_wayland.h

+2
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ class DisplayServerWayland : public DisplayServer {
272272
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window_id = MAIN_WINDOW_ID) override;
273273
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_window_id) const override;
274274

275+
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
276+
275277
virtual void cursor_set_shape(CursorShape p_shape) override;
276278
virtual CursorShape cursor_get_shape() const override;
277279
virtual void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) override;

platform/linuxbsd/wayland/wayland_thread.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -3338,6 +3338,22 @@ void WaylandThread::beep() const {
33383338
}
33393339
}
33403340

3341+
void WaylandThread::window_start_drag(DisplayServer::WindowID p_window_id) {
3342+
// TODO: Use window IDs for multiwindow support.
3343+
WindowState &ws = main_window;
3344+
SeatState *ss = wl_seat_get_seat_state(wl_seat_current);
3345+
3346+
if (ss && ws.xdg_toplevel) {
3347+
xdg_toplevel_move(ws.xdg_toplevel, ss->wl_seat, ss->pointer_data.button_serial);
3348+
}
3349+
3350+
#ifdef LIBDECOR_ENABLED
3351+
if (ws.libdecor_frame) {
3352+
libdecor_frame_move(ws.libdecor_frame, ss->wl_seat, ss->pointer_data.button_serial);
3353+
}
3354+
#endif
3355+
}
3356+
33413357
void WaylandThread::window_set_max_size(DisplayServer::WindowID p_window_id, const Size2i &p_size) {
33423358
// TODO: Use window IDs for multiwindow support.
33433359
WindowState &ws = main_window;

platform/linuxbsd/wayland/wayland_thread.h

+2
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,8 @@ class WaylandThread {
971971
// Optional - requires xdg_activation_v1
972972
void window_request_attention(DisplayServer::WindowID p_window_id);
973973

974+
void window_start_drag(DisplayServer::WindowID p_window_id);
975+
974976
// Optional - require idle_inhibit_unstable_v1
975977
void window_set_idle_inhibition(DisplayServer::WindowID p_window_id, bool p_enable);
976978
bool window_get_idle_inhibition(DisplayServer::WindowID p_window_id) const;

platform/linuxbsd/x11/display_server_x11.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969
#define _NET_WM_STATE_REMOVE 0L // remove/unset property
7070
#define _NET_WM_STATE_ADD 1L // add/set property
7171

72+
#define _NET_WM_MOVERESIZE_MOVE 8L
73+
7274
// 2.2 is the first release with multitouch
7375
#define XINPUT_CLIENT_VERSION_MAJOR 2
7476
#define XINPUT_CLIENT_VERSION_MINOR 2
@@ -5422,6 +5424,40 @@ DisplayServer::VSyncMode DisplayServerX11::window_get_vsync_mode(WindowID p_wind
54225424
return DisplayServer::VSYNC_ENABLED;
54235425
}
54245426

5427+
void DisplayServerX11::window_start_drag(WindowID p_window) {
5428+
_THREAD_SAFE_METHOD_
5429+
5430+
ERR_FAIL_COND(!windows.has(p_window));
5431+
WindowData &wd = windows[p_window];
5432+
5433+
XClientMessageEvent m;
5434+
memset(&m, 0, sizeof(m));
5435+
5436+
XUngrabPointer(x11_display, CurrentTime);
5437+
5438+
Window root_return, child_return;
5439+
int root_x, root_y, win_x, win_y;
5440+
unsigned int mask_return;
5441+
5442+
Bool xquerypointer_result = XQueryPointer(x11_display, wd.x11_window, &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &mask_return);
5443+
5444+
m.type = ClientMessage;
5445+
m.window = wd.x11_window;
5446+
m.message_type = XInternAtom(x11_display, "_NET_WM_MOVERESIZE", True);
5447+
m.format = 32;
5448+
if (xquerypointer_result) {
5449+
m.data.l[0] = root_x;
5450+
m.data.l[1] = root_y;
5451+
m.data.l[3] = Button1;
5452+
}
5453+
m.data.l[2] = _NET_WM_MOVERESIZE_MOVE;
5454+
m.data.l[4] = 1; // Source - normal application.
5455+
5456+
XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&m);
5457+
5458+
XSync(x11_display, 0);
5459+
}
5460+
54255461
Vector<String> DisplayServerX11::get_rendering_drivers_func() {
54265462
Vector<String> drivers;
54275463

platform/linuxbsd/x11/display_server_x11.h

+2
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ class DisplayServerX11 : public DisplayServer {
512512
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
513513
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
514514

515+
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
516+
515517
virtual void cursor_set_shape(CursorShape p_shape) override;
516518
virtual CursorShape cursor_get_shape() const override;
517519
virtual void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) override;

platform/windows/display_server_windows.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -3803,6 +3803,21 @@ DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_
38033803
return DisplayServer::VSYNC_ENABLED;
38043804
}
38053805

3806+
void DisplayServerWindows::window_start_drag(WindowID p_window) {
3807+
_THREAD_SAFE_METHOD_
3808+
3809+
ERR_FAIL_COND(!windows.has(p_window));
3810+
WindowData &wd = windows[p_window];
3811+
3812+
ReleaseCapture();
3813+
3814+
POINT coords;
3815+
GetCursorPos(&coords);
3816+
ScreenToClient(wd.hWnd, &coords);
3817+
3818+
SendMessage(wd.hWnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(coords.x, coords.y));
3819+
}
3820+
38063821
void DisplayServerWindows::set_context(Context p_context) {
38073822
}
38083823

platform/windows/display_server_windows.h

+2
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,8 @@ class DisplayServerWindows : public DisplayServer {
805805
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
806806
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
807807

808+
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
809+
808810
virtual void cursor_set_shape(CursorShape p_shape) override;
809811
virtual CursorShape cursor_get_shape() const override;
810812
virtual void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;

0 commit comments

Comments
 (0)