diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp index e4fd744c7de..5eb5ad768e0 100644 --- a/editor/plugins/game_view_plugin.cpp +++ b/editor/plugins/game_view_plugin.cpp @@ -515,11 +515,9 @@ GameView::EmbedAvailability GameView::_get_embed_available() { if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_WINDOW_EMBEDDING)) { return EMBED_NOT_AVAILABLE_FEATURE_NOT_SUPPORTED; } -#ifndef MACOS_ENABLED if (get_tree()->get_root()->is_embedding_subwindows()) { return EMBED_NOT_AVAILABLE_SINGLE_WINDOW_MODE; } -#endif String display_driver = GLOBAL_GET("display/display_server/driver"); if (display_driver == "headless" || display_driver == "wayland") { return EMBED_NOT_AVAILABLE_PROJECT_DISPLAY_DRIVER; @@ -835,11 +833,16 @@ void GameView::_update_arguments_for_instance(int p_idx, List &r_argumen // Remove duplicates/unwanted parameters. List::Element *E = r_arguments.front(); List::Element *user_args_element = nullptr; + HashSet remove_args({ "--position", "--resolution", "--screen" }); +#ifdef MACOS_ENABLED + // macOS requires the embedded display driver. + remove_args.insert("--display-driver"); +#endif while (E) { List::Element *N = E->next(); - //For these parameters, we need to also renove the value. - if (E->get() == "--position" || E->get() == "--resolution" || E->get() == "--screen") { + // For these parameters, we need to also remove the value. + if (remove_args.has(E->get())) { r_arguments.erase(E); if (N) { List::Element *V = N->next(); @@ -861,8 +864,6 @@ void GameView::_update_arguments_for_instance(int p_idx, List &r_argumen N = r_arguments.insert_after(N, itos(DisplayServer::get_singleton()->window_get_native_handle(DisplayServer::WINDOW_HANDLE, get_window()->get_window_id()))); #if MACOS_ENABLED - r_arguments.push_back("--display-driver"); - r_arguments.push_back("embedded"); r_arguments.push_back("--embedded"); #endif diff --git a/main/main.cpp b/main/main.cpp index e27979dd1a2..1800b7edbcf 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -287,6 +287,7 @@ bool profile_gpu = false; // Constants. static const String NULL_DISPLAY_DRIVER("headless"); +static const String EMBEDDED_DISPLAY_DRIVER("embedded"); static const String NULL_AUDIO_DRIVER("Dummy"); // The length of the longest column in the command-line help we should align to @@ -1397,6 +1398,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph audio_driver = NULL_AUDIO_DRIVER; display_driver = NULL_DISPLAY_DRIVER; + } else if (arg == "--embedded") { // Enable embedded mode. + + display_driver = EMBEDDED_DISPLAY_DRIVER; + } else if (arg == "--log-file") { // write to log file if (N) { diff --git a/platform/macos/editor/embedded_process_macos.h b/platform/macos/editor/embedded_process_macos.h index 01d34842489..a81d5cec25e 100644 --- a/platform/macos/editor/embedded_process_macos.h +++ b/platform/macos/editor/embedded_process_macos.h @@ -33,11 +33,13 @@ #include "editor/plugins/embedded_process.h" class DisplayServerMacOS; +class EmbeddedProcessMacOS; -class LayerHost : public Control { +class LayerHost final : public Control { GDCLASS(LayerHost, Control); ScriptEditorDebugger *script_debugger = nullptr; + EmbeddedProcessMacOS *process = nullptr; virtual void gui_input(const Ref &p_event) override; @@ -48,6 +50,8 @@ public: void set_script_debugger(ScriptEditorDebugger *p_debugger) { script_debugger = p_debugger; } + + LayerHost(EmbeddedProcessMacOS *p_process); }; class EmbeddedProcessMacOS final : public EmbeddedProcessBase { @@ -69,9 +73,11 @@ class EmbeddedProcessMacOS final : public EmbeddedProcessBase { // Embedded process state. - /// @brief The current mouse mode of the embedded process. + // The last mouse mode sent by the embedded process. DisplayServer::MouseMode mouse_mode = DisplayServer::MOUSE_MODE_VISIBLE; + // Helper functions. + void _try_embed_process(); void update_embedded_process() const; void _joy_connection_changed(int p_index, bool p_connected) const; @@ -81,7 +87,9 @@ protected: public: // MARK: - Message Handlers + void set_context_id(uint32_t p_context_id); + void mouse_set_mode(DisplayServer::MouseMode p_mode); uint32_t get_context_id() const { return context_id; } void set_script_debugger(ScriptEditorDebugger *p_debugger) override; @@ -90,7 +98,7 @@ public: return embedding_state == EmbeddingState::IN_PROGRESS; } - bool is_embedding_completed() const override { + _FORCE_INLINE_ bool is_embedding_completed() const override { return embedding_state == EmbeddingState::COMPLETED; } @@ -103,8 +111,10 @@ public: Rect2i get_adjusted_embedded_window_rect(const Rect2i &p_rect) const override; - void mouse_set_mode(DisplayServer::MouseMode p_mode); _FORCE_INLINE_ LayerHost *get_layer_host() const { return layer_host; } + // MARK: - Embedded process state + _FORCE_INLINE_ DisplayServer::MouseMode get_mouse_mode() const { return mouse_mode; } + EmbeddedProcessMacOS(); }; diff --git a/platform/macos/editor/embedded_process_macos.mm b/platform/macos/editor/embedded_process_macos.mm index 82189b0d72d..cd0b6e07105 100644 --- a/platform/macos/editor/embedded_process_macos.mm +++ b/platform/macos/editor/embedded_process_macos.mm @@ -34,6 +34,8 @@ #include "core/input/input_event_codec.h" #include "editor/debugger/script_editor_debugger.h" +#include "editor/editor_main_screen.h" +#include "editor/editor_node.h" #include "editor/editor_settings.h" #include "scene/gui/control.h" #include "scene/main/window.h" @@ -182,12 +184,18 @@ Rect2i EmbeddedProcessMacOS::get_adjusted_embedded_window_rect(const Rect2i &p_r } void EmbeddedProcessMacOS::mouse_set_mode(DisplayServer::MouseMode p_mode) { + mouse_mode = p_mode; + // If the mouse is anything other than visible, we must ensure the Game view is active and the layer focused. + if (mouse_mode != DisplayServer::MOUSE_MODE_VISIBLE) { + EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_GAME); + layer_host->grab_focus(); + } DisplayServer::get_singleton()->mouse_set_mode(p_mode); } EmbeddedProcessMacOS::EmbeddedProcessMacOS() : EmbeddedProcessBase() { - layer_host = memnew(LayerHost); + layer_host = memnew(LayerHost(this)); add_child(layer_host); layer_host->set_focus_mode(FOCUS_ALL); layer_host->set_anchors_and_offsets_preset(PRESET_FULL_RECT); @@ -207,11 +215,22 @@ void LayerHost::_notification(int p_what) { if (script_debugger) { script_debugger->send_message("embed:win_event", { DisplayServer::WINDOW_EVENT_MOUSE_ENTER }); } + // Temporarily release mouse capture, so we can interact with the editor. + DisplayServer *ds = DisplayServer::get_singleton(); + if (process->get_mouse_mode() != ds->mouse_get_mode()) { + // Restore embedded process mouse mode. + ds->mouse_set_mode(process->get_mouse_mode()); + } } break; case NOTIFICATION_FOCUS_EXIT: { if (script_debugger) { script_debugger->send_message("embed:win_event", { DisplayServer::WINDOW_EVENT_MOUSE_EXIT }); } + // Temporarily set mouse state back to visible, so the user can interact with the editor. + DisplayServer *ds = DisplayServer::get_singleton(); + if (ds->mouse_get_mode() != DisplayServer::MOUSE_MODE_VISIBLE) { + ds->mouse_set_mode(DisplayServer::MOUSE_MODE_VISIBLE); + } } break; case MainLoop::NOTIFICATION_OS_IME_UPDATE: { if (script_debugger && has_focus()) { @@ -224,7 +243,7 @@ void LayerHost::_notification(int p_what) { } void LayerHost::gui_input(const Ref &p_event) { - if (!script_debugger) { + if (!process->is_embedding_completed()) { return; } @@ -246,3 +265,6 @@ void LayerHost::gui_input(const Ref &p_event) { accept_event(); } } + +LayerHost::LayerHost(EmbeddedProcessMacOS *p_process) : + process(p_process) {} diff --git a/platform/macos/godot_main_macos.mm b/platform/macos/godot_main_macos.mm index 7fdd9173fee..9362179d36c 100644 --- a/platform/macos/godot_main_macos.mm +++ b/platform/macos/godot_main_macos.mm @@ -74,7 +74,6 @@ int main(int argc, char **argv) { if (strcmp("--embedded", argv[i]) == 0) { is_embedded = true; - continue; } args.ptr()[argsc] = argv[i];