diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index e1032790546..a997eef0dbe 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1815,6 +1815,14 @@ [b]Warning:[/b] Advanced users only! Adding such a callback to a [Window] node will override its default implementation, which can introduce bugs. + + + + + 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 only on macOS. + + @@ -1895,6 +1903,9 @@ The display server supports all features of [constant FEATURE_NATIVE_DIALOG_FILE], with the added functionality of Options and native dialog file access to [code]res://[/code] and [code]user://[/code] paths. See [method file_dialog_show] and [method file_dialog_with_options_show]. [b]Windows, macOS, Linux (X11/Wayland)[/b] + + The display server supports initiating window drag operation on demand. See [method window_start_drag]. + Makes the mouse cursor visible if it is hidden. diff --git a/editor/gui/editor_title_bar.cpp b/editor/gui/editor_title_bar.cpp index c251c70c6de..ac6d991b5ca 100644 --- a/editor/gui/editor_title_bar.cpp +++ b/editor/gui/editor_title_bar.cpp @@ -54,8 +54,12 @@ void EditorTitleBar::gui_input(const Ref &p_event) { if (w) { if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { - click_pos = DisplayServer::get_singleton()->mouse_get_position() - w->get_position(); - moving = true; + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_WINDOW_DRAG)) { + DisplayServer::get_singleton()->window_start_drag(w->get_window_id()); + } else { + click_pos = DisplayServer::get_singleton()->mouse_get_position() - w->get_position(); + moving = true; + } } else { moving = false; } diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 2c621fc605c..5e2e1b81622 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -402,6 +402,8 @@ public: virtual bool window_maximize_on_title_dbl_click() const override; 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_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 c723537d3b6..4b873e02b4e 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -765,6 +765,7 @@ bool DisplayServerMacOS::has_feature(Feature p_feature) const { case FEATURE_SCREEN_CAPTURE: case FEATURE_STATUS_INDICATOR: case FEATURE_NATIVE_HELP: + case FEATURE_WINDOW_DRAG: return true; default: { } @@ -2342,6 +2343,16 @@ bool DisplayServerMacOS::window_minimize_on_title_dbl_click() const { return false; } +void DisplayServerMacOS::window_start_drag(WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + NSEvent *event = [NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:((NSWindow *)wd.window_object).mouseLocationOutsideOfEventStream modifierFlags:0 timestamp:[[NSProcessInfo processInfo] systemUptime] windowNumber:((NSWindow *)wd.window_object).windowNumber context:nil eventNumber:0 clickCount:1 pressure:1.0f]; + [wd.window_object performWindowDragWithEvent:event]; +} + void DisplayServerMacOS::window_set_window_buttons_offset(const Vector2i &p_offset, WindowID p_window) { _THREAD_SAFE_METHOD_ diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 82ac62bc9fa..0fcbfb02cf5 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -972,6 +972,8 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("window_maximize_on_title_dbl_click"), &DisplayServer::window_maximize_on_title_dbl_click); 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("ime_get_selection"), &DisplayServer::ime_get_selection); ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text); @@ -1057,6 +1059,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_INPUT); BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_FILE); BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_FILE_EXTRA); + BIND_ENUM_CONSTANT(FEATURE_WINDOW_DRAG); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); diff --git a/servers/display_server.h b/servers/display_server.h index 916c006f011..954093c5cb7 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -153,6 +153,7 @@ public: FEATURE_NATIVE_DIALOG_INPUT, FEATURE_NATIVE_DIALOG_FILE, FEATURE_NATIVE_DIALOG_FILE_EXTRA, + FEATURE_WINDOW_DRAG, }; virtual bool has_feature(Feature p_feature) const = 0; @@ -490,6 +491,8 @@ public: virtual bool window_maximize_on_title_dbl_click() const { return false; } virtual bool window_minimize_on_title_dbl_click() const { return false; } + virtual void window_start_drag(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);