Wayland: Implement game embedding

This patch introduces a new protocol proxy, which multiplxes Wayland
clients into a single connection, allowing us to redirect calls (e.g.
create toplevel -> create subsurface). Mixed with some state tracking
and emulation, we can embed a full-featured client into the editor.
This commit is contained in:
Dery Almas 2025-11-15 23:38:41 +01:00
parent ef34c3d534
commit bbf65ae72f
25 changed files with 6053 additions and 23 deletions

View file

@ -668,7 +668,7 @@ GameView::EmbedAvailability GameView::_get_embed_available() {
return EMBED_NOT_AVAILABLE_SINGLE_WINDOW_MODE;
}
String display_driver = GLOBAL_GET("display/display_server/driver");
if (display_driver == "headless" || display_driver == "wayland") {
if (display_driver == "headless") {
return EMBED_NOT_AVAILABLE_PROJECT_DISPLAY_DRIVER;
}
@ -714,11 +714,7 @@ void GameView::_update_ui() {
}
break;
case EMBED_NOT_AVAILABLE_FEATURE_NOT_SUPPORTED:
if (DisplayServer::get_singleton()->get_name() == "Wayland") {
state_label->set_text(TTRC("Game embedding not available on Wayland.\nWayland can be disabled in the Editor Settings (Run > Platforms > Linux/*BSD > Prefer Wayland)."));
} else {
state_label->set_text(TTRC("Game embedding not available on your OS."));
}
state_label->set_text(TTRC("Game embedding not available on your OS."));
break;
case EMBED_NOT_AVAILABLE_PROJECT_DISPLAY_DRIVER:
state_label->set_text(vformat(TTR("Game embedding not available for the Display Server: '%s'.\nDisplay Server can be modified in the Project Settings (Display > Display Server > Driver)."), GLOBAL_GET("display/display_server/driver")));
@ -991,6 +987,21 @@ void GameView::_update_arguments_for_instance(int p_idx, List<String> &r_argumen
// macOS requires the embedded display driver.
remove_args.insert("--display-driver");
#endif
#ifdef WAYLAND_ENABLED
// Wayland requires its display driver.
if (DisplayServer::get_singleton()->get_name() == "Wayland") {
remove_args.insert("--display-driver");
}
#endif
#ifdef X11_ENABLED
// X11 requires its display driver.
if (DisplayServer::get_singleton()->get_name() == "X11") {
remove_args.insert("--display-driver");
}
#endif
while (E) {
List<String>::Element *N = E->next();
@ -1020,6 +1031,20 @@ void GameView::_update_arguments_for_instance(int p_idx, List<String> &r_argumen
N = r_arguments.insert_after(N, "--embedded");
#endif
#ifdef WAYLAND_ENABLED
if (DisplayServer::get_singleton()->get_name() == "Wayland") {
N = r_arguments.insert_after(N, "--display-driver");
N = r_arguments.insert_after(N, "wayland");
}
#endif
#ifdef X11_ENABLED
if (DisplayServer::get_singleton()->get_name() == "X11") {
N = r_arguments.insert_after(N, "--display-driver");
N = r_arguments.insert_after(N, "x11");
}
#endif
// Be sure to have the correct window size in the embedded_process control.
_update_embed_window_size();
Rect2i rect = embedded_process->get_screen_embedded_window_rect();