MacOS: Additional improvements and fixes for embedded window support

This commit is contained in:
Stuart Carnie 2025-05-07 06:11:05 +10:00
parent 6a6a1168a5
commit 9290adee38
5 changed files with 50 additions and 13 deletions

View file

@ -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<String> &r_argumen
// Remove duplicates/unwanted parameters.
List<String>::Element *E = r_arguments.front();
List<String>::Element *user_args_element = nullptr;
HashSet<String> remove_args({ "--position", "--resolution", "--screen" });
#ifdef MACOS_ENABLED
// macOS requires the embedded display driver.
remove_args.insert("--display-driver");
#endif
while (E) {
List<String>::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<String>::Element *V = N->next();
@ -861,8 +864,6 @@ void GameView::_update_arguments_for_instance(int p_idx, List<String> &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

View file

@ -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) {

View file

@ -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<InputEvent> &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();
};

View file

@ -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<InputEvent> &p_event) {
if (!script_debugger) {
if (!process->is_embedding_completed()) {
return;
}
@ -246,3 +265,6 @@ void LayerHost::gui_input(const Ref<InputEvent> &p_event) {
accept_event();
}
}
LayerHost::LayerHost(EmbeddedProcessMacOS *p_process) :
process(p_process) {}

View file

@ -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];