summaryrefslogtreecommitdiffstats
path: root/platform/linuxbsd
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/SCsub3
-rw-r--r--platform/linuxbsd/crash_handler_linuxbsd.cpp4
-rw-r--r--platform/linuxbsd/detect.py74
-rw-r--r--platform/linuxbsd/export/export_plugin.cpp19
-rw-r--r--platform/linuxbsd/freedesktop_portal_desktop.cpp190
-rw-r--r--platform/linuxbsd/freedesktop_portal_desktop.h17
-rw-r--r--platform/linuxbsd/godot_linuxbsd.cpp13
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp26
-rw-r--r--platform/linuxbsd/platform_linuxbsd_builders.py18
-rw-r--r--platform/linuxbsd/wayland/SCsub1
-rw-r--r--platform/linuxbsd/wayland/detect_prime_egl.cpp2
-rw-r--r--platform/linuxbsd/wayland/display_server_wayland.cpp107
-rw-r--r--platform/linuxbsd/wayland/display_server_wayland.h6
-rw-r--r--platform/linuxbsd/wayland/egl_manager_wayland_gles.cpp64
-rw-r--r--platform/linuxbsd/wayland/egl_manager_wayland_gles.h53
-rw-r--r--platform/linuxbsd/wayland/wayland_thread.cpp257
-rw-r--r--platform/linuxbsd/wayland/wayland_thread.h64
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp63
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h2
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp14
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.h1
21 files changed, 604 insertions, 394 deletions
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index a3ce773ac2..0802b528f4 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -2,7 +2,6 @@
Import("env")
-from platform_methods import run_in_subprocess
import platform_linuxbsd_builders
common_linuxbsd = [
@@ -42,4 +41,4 @@ if env["dbus"]:
prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_linuxbsd)
if env["debug_symbols"] and env["separate_debug_symbols"]:
- env.AddPostAction(prog, run_in_subprocess(platform_linuxbsd_builders.make_debug_linuxbsd))
+ env.AddPostAction(prog, env.Run(platform_linuxbsd_builders.make_debug_linuxbsd))
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp
index fd4bcf92be..446fe5c7a1 100644
--- a/platform/linuxbsd/crash_handler_linuxbsd.cpp
+++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp
@@ -36,8 +36,8 @@
#include "core/version.h"
#include "main/main.h"
-#ifdef DEBUG_ENABLED
-#define CRASH_HANDLER_ENABLED 1
+#ifndef DEBUG_ENABLED
+#undef CRASH_HANDLER_ENABLED
#endif
#ifdef CRASH_HANDLER_ENABLED
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 4856076436..afc9d25a80 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -1,7 +1,7 @@
import os
import platform
import sys
-from methods import get_compiler_version, using_gcc
+from methods import print_warning, print_error, get_compiler_version, using_gcc
from platform_methods import detect_arch
from typing import TYPE_CHECKING
@@ -20,7 +20,7 @@ def can_build():
pkgconf_error = os.system("pkg-config --version > /dev/null")
if pkgconf_error:
- print("Error: pkg-config not found. Aborting.")
+ print_error("pkg-config not found. Aborting.")
return False
return True
@@ -50,7 +50,7 @@ def get_opts():
BoolVariable("wayland", "Enable Wayland display", True),
BoolVariable("libdecor", "Enable libdecor support", True),
BoolVariable("touch", "Enable touch events", True),
- BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", False),
+ BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", None),
]
@@ -75,7 +75,7 @@ def configure(env: "SConsEnvironment"):
# Validate arch.
supported_arches = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64"]
if env["arch"] not in supported_arches:
- print(
+ print_error(
'Unsupported CPU architecture "%s" for Linux / *BSD. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches))
)
@@ -128,7 +128,9 @@ def configure(env: "SConsEnvironment"):
found_wrapper = True
break
if not found_wrapper:
- print("Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local.")
+ print_error(
+ "Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local."
+ )
sys.exit(255)
else:
env.Append(LINKFLAGS=["-fuse-ld=mold"])
@@ -185,7 +187,7 @@ def configure(env: "SConsEnvironment"):
if env["lto"] != "none":
if env["lto"] == "thin":
if not env["use_llvm"]:
- print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
+ print_error("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
sys.exit(255)
env.Append(CCFLAGS=["-flto=thin"])
env.Append(LINKFLAGS=["-flto=thin"])
@@ -209,7 +211,7 @@ def configure(env: "SConsEnvironment"):
if env["wayland"]:
if os.system("wayland-scanner -v 2>/dev/null") != 0:
- print("wayland-scanner not found. Disabling Wayland support.")
+ print_warning("wayland-scanner not found. Disabling Wayland support.")
env["wayland"] = False
if env["touch"]:
@@ -227,7 +229,7 @@ def configure(env: "SConsEnvironment"):
env["builtin_harfbuzz"],
]
if (not all(ft_linked_deps)) and any(ft_linked_deps): # All or nothing.
- print(
+ print_error(
"These libraries should be either all builtin, or all system provided:\n"
"freetype, libpng, zlib, graphite, harfbuzz.\n"
"Please specify `builtin_<name>=no` for all of them, or none."
@@ -318,7 +320,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config fontconfig --cflags --libs")
env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
else:
- print("Warning: fontconfig development libraries not found. Disabling the system fonts support.")
+ print_warning("fontconfig development libraries not found. Disabling the system fonts support.")
env["fontconfig"] = False
else:
env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
@@ -329,7 +331,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config alsa --cflags --libs")
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
else:
- print("Warning: ALSA development libraries not found. Disabling the ALSA audio driver.")
+ print_warning("ALSA development libraries not found. Disabling the ALSA audio driver.")
env["alsa"] = False
else:
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
@@ -340,7 +342,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config libpulse --cflags --libs")
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"])
else:
- print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.")
+ print_warning("PulseAudio development libraries not found. Disabling the PulseAudio audio driver.")
env["pulseaudio"] = False
else:
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"])
@@ -351,7 +353,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config dbus-1 --cflags --libs")
env.Append(CPPDEFINES=["DBUS_ENABLED"])
else:
- print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.")
+ print_warning("D-Bus development libraries not found. Disabling screensaver prevention.")
env["dbus"] = False
else:
env.Append(CPPDEFINES=["DBUS_ENABLED"])
@@ -362,7 +364,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config speech-dispatcher --cflags --libs")
env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
else:
- print("Warning: speech-dispatcher development libraries not found. Disabling text to speech support.")
+ print_warning("speech-dispatcher development libraries not found. Disabling text to speech support.")
env["speechd"] = False
else:
env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
@@ -373,11 +375,11 @@ def configure(env: "SConsEnvironment"):
env.Append(CPPDEFINES=["XKB_ENABLED"])
else:
if env["wayland"]:
- print("Error: libxkbcommon development libraries required by Wayland not found. Aborting.")
+ print_error("libxkbcommon development libraries required by Wayland not found. Aborting.")
sys.exit(255)
else:
- print(
- "Warning: libxkbcommon development libraries not found. Disabling dead key composition and key label support."
+ print_warning(
+ "libxkbcommon development libraries not found. Disabling dead key composition and key label support."
)
else:
env.Append(CPPDEFINES=["XKB_ENABLED"])
@@ -390,7 +392,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config libudev --cflags --libs")
env.Append(CPPDEFINES=["UDEV_ENABLED"])
else:
- print("Warning: libudev development libraries not found. Disabling controller hotplugging support.")
+ print_warning("libudev development libraries not found. Disabling controller hotplugging support.")
env["udev"] = False
else:
env.Append(CPPDEFINES=["UDEV_ENABLED"])
@@ -416,31 +418,31 @@ def configure(env: "SConsEnvironment"):
if env["x11"]:
if not env["use_sowrap"]:
if os.system("pkg-config --exists x11"):
- print("Error: X11 libraries not found. Aborting.")
+ print_error("X11 libraries not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config x11 --cflags --libs")
if os.system("pkg-config --exists xcursor"):
- print("Error: Xcursor library not found. Aborting.")
+ print_error("Xcursor library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config xcursor --cflags --libs")
if os.system("pkg-config --exists xinerama"):
- print("Error: Xinerama library not found. Aborting.")
+ print_error("Xinerama library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config xinerama --cflags --libs")
if os.system("pkg-config --exists xext"):
- print("Error: Xext library not found. Aborting.")
+ print_error("Xext library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config xext --cflags --libs")
if os.system("pkg-config --exists xrandr"):
- print("Error: XrandR library not found. Aborting.")
+ print_error("XrandR library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config xrandr --cflags --libs")
if os.system("pkg-config --exists xrender"):
- print("Error: XRender library not found. Aborting.")
+ print_error("XRender library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config xrender --cflags --libs")
if os.system("pkg-config --exists xi"):
- print("Error: Xi library not found. Aborting.")
+ print_error("Xi library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config xi --cflags --libs")
env.Append(CPPDEFINES=["X11_ENABLED"])
@@ -448,20 +450,20 @@ def configure(env: "SConsEnvironment"):
if env["wayland"]:
if not env["use_sowrap"]:
if os.system("pkg-config --exists libdecor-0"):
- print("Warning: libdecor development libraries not found. Disabling client-side decorations.")
+ print_warning("libdecor development libraries not found. Disabling client-side decorations.")
env["libdecor"] = False
else:
env.ParseConfig("pkg-config libdecor-0 --cflags --libs")
if os.system("pkg-config --exists wayland-client"):
- print("Error: Wayland client library not found. Aborting.")
+ print_error("Wayland client library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config wayland-client --cflags --libs")
if os.system("pkg-config --exists wayland-cursor"):
- print("Error: Wayland cursor library not found. Aborting.")
+ print_error("Wayland cursor library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config wayland-cursor --cflags --libs")
if os.system("pkg-config --exists wayland-egl"):
- print("Error: Wayland EGL library not found. Aborting.")
+ print_error("Wayland EGL library not found. Aborting.")
sys.exit(255)
env.ParseConfig("pkg-config wayland-egl --cflags --libs")
@@ -488,14 +490,20 @@ def configure(env: "SConsEnvironment"):
if platform.system() == "Linux":
env.Append(LIBS=["dl"])
- if not env["execinfo"] and platform.libc_ver()[0] != "glibc":
+ if platform.libc_ver()[0] != "glibc":
# The default crash handler depends on glibc, so if the host uses
# a different libc (BSD libc, musl), fall back to libexecinfo.
- print("Note: Using `execinfo=yes` for the crash handler as required on platforms where glibc is missing.")
- env["execinfo"] = True
+ if not "execinfo" in env:
+ print("Note: Using `execinfo=yes` for the crash handler as required on platforms where glibc is missing.")
+ env["execinfo"] = True
- if env["execinfo"]:
- env.Append(LIBS=["execinfo"])
+ if env["execinfo"]:
+ env.Append(LIBS=["execinfo"])
+ env.Append(CPPDEFINES=["CRASH_HANDLER_ENABLED"])
+ else:
+ print("Note: Using `execinfo=no` disables the crash handler on platforms where glibc is missing.")
+ else:
+ env.Append(CPPDEFINES=["CRASH_HANDLER_ENABLED"])
if platform.system() == "FreeBSD":
env.Append(LINKFLAGS=["-lkvm"])
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp
index 773b124c6a..936adddda3 100644
--- a/platform/linuxbsd/export/export_plugin.cpp
+++ b/platform/linuxbsd/export/export_plugin.cpp
@@ -146,12 +146,19 @@ List<String> EditorExportPlatformLinuxBSD::get_binary_extensions(const Ref<Edito
}
bool EditorExportPlatformLinuxBSD::get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const {
- if (p_preset) {
- // Hide SSH options.
- bool ssh = p_preset->get("ssh_remote_deploy/enabled");
- if (!ssh && p_option != "ssh_remote_deploy/enabled" && p_option.begins_with("ssh_remote_deploy/")) {
- return false;
- }
+ if (p_preset == nullptr) {
+ return true;
+ }
+
+ bool advanced_options_enabled = p_preset->are_advanced_options_enabled();
+
+ // Hide SSH options.
+ bool ssh = p_preset->get("ssh_remote_deploy/enabled");
+ if (!ssh && p_option != "ssh_remote_deploy/enabled" && p_option.begins_with("ssh_remote_deploy/")) {
+ return false;
+ }
+ if (p_option == "dotnet/embed_build_outputs") {
+ return advanced_options_enabled;
}
return true;
}
diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp
index cdebed58b2..e65404a531 100644
--- a/platform/linuxbsd/freedesktop_portal_desktop.cpp
+++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp
@@ -367,6 +367,7 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo
}
ERR_FAIL_INDEX_V(int(p_mode), DisplayServer::FILE_DIALOG_MODE_SAVE_MAX, FAILED);
+ ERR_FAIL_NULL_V(monitor_connection, FAILED);
Vector<String> filter_names;
Vector<String> filter_exts;
@@ -406,24 +407,16 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo
Error rng_err = rng.get_random_bytes(uuid, 64);
ERR_FAIL_COND_V_MSG(rng_err, rng_err, "Failed to generate unique token.");
- fd.connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
- if (dbus_error_is_set(&err)) {
- ERR_PRINT(vformat("Failed to open DBus connection: %s", err.message));
- dbus_error_free(&err);
- unsupported = true;
- return FAILED;
- }
-
- String dbus_unique_name = String::utf8(dbus_bus_get_unique_name(fd.connection));
+ String dbus_unique_name = String::utf8(dbus_bus_get_unique_name(monitor_connection));
String token = String::hex_encode_buffer(uuid, 64);
String path = vformat("/org/freedesktop/portal/desktop/request/%s/%s", dbus_unique_name.replace(".", "_").replace(":", ""), token);
- fd.path = vformat("type='signal',sender='org.freedesktop.portal.Desktop',path='%s',interface='org.freedesktop.portal.Request',member='Response',destination='%s'", path, dbus_unique_name);
- dbus_bus_add_match(fd.connection, fd.path.utf8().get_data(), &err);
+ fd.path = path;
+ fd.filter = vformat("type='signal',sender='org.freedesktop.portal.Desktop',path='%s',interface='org.freedesktop.portal.Request',member='Response',destination='%s'", path, dbus_unique_name);
+ dbus_bus_add_match(monitor_connection, fd.filter.utf8().get_data(), &err);
if (dbus_error_is_set(&err)) {
ERR_PRINT(vformat("Failed to add DBus match: %s", err.message));
dbus_error_free(&err);
- dbus_connection_unref(fd.connection);
return FAILED;
}
@@ -460,14 +453,13 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo
dbus_message_iter_close_container(&iter, &arr_iter);
}
- DBusMessage *reply = dbus_connection_send_with_reply_and_block(fd.connection, message, DBUS_TIMEOUT_INFINITE, &err);
+ DBusMessage *reply = dbus_connection_send_with_reply_and_block(monitor_connection, message, DBUS_TIMEOUT_INFINITE, &err);
dbus_message_unref(message);
if (!reply || dbus_error_is_set(&err)) {
ERR_PRINT(vformat("Failed to send DBus message: %s", err.message));
dbus_error_free(&err);
- dbus_bus_remove_match(fd.connection, fd.path.utf8().get_data(), &err);
- dbus_connection_unref(fd.connection);
+ dbus_bus_remove_match(monitor_connection, fd.filter.utf8().get_data(), &err);
return FAILED;
}
@@ -479,19 +471,17 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo
const char *new_path = nullptr;
dbus_message_iter_get_basic(&iter, &new_path);
if (String::utf8(new_path) != path) {
- dbus_bus_remove_match(fd.connection, fd.path.utf8().get_data(), &err);
+ dbus_bus_remove_match(monitor_connection, fd.filter.utf8().get_data(), &err);
if (dbus_error_is_set(&err)) {
ERR_PRINT(vformat("Failed to remove DBus match: %s", err.message));
dbus_error_free(&err);
- dbus_connection_unref(fd.connection);
return FAILED;
}
- fd.path = String::utf8(new_path);
- dbus_bus_add_match(fd.connection, fd.path.utf8().get_data(), &err);
+ fd.filter = String::utf8(new_path);
+ dbus_bus_add_match(monitor_connection, fd.filter.utf8().get_data(), &err);
if (dbus_error_is_set(&err)) {
ERR_PRINT(vformat("Failed to add DBus match: %s", err.message));
dbus_error_free(&err);
- dbus_connection_unref(fd.connection);
return FAILED;
}
}
@@ -506,24 +496,30 @@ Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_windo
return OK;
}
-void FreeDesktopPortalDesktop::_file_dialog_callback(const Callable &p_callable, const Variant &p_status, const Variant &p_list, const Variant &p_index, const Variant &p_options, bool p_opt_in_cb) {
- if (p_opt_in_cb) {
- Variant ret;
- Callable::CallError ce;
- const Variant *args[4] = { &p_status, &p_list, &p_index, &p_options };
-
- p_callable.callp(args, 4, ret, ce);
- if (ce.error != Callable::CallError::CALL_OK) {
- ERR_PRINT(vformat("Failed to execute file dialogs callback: %s.", Variant::get_callable_error_text(p_callable, args, 4, ce)));
- }
- } else {
- Variant ret;
- Callable::CallError ce;
- const Variant *args[3] = { &p_status, &p_list, &p_index };
+void FreeDesktopPortalDesktop::process_file_dialog_callbacks() {
+ MutexLock lock(file_dialog_mutex);
+ while (!pending_cbs.is_empty()) {
+ FileDialogCallback cb = pending_cbs.front()->get();
+ pending_cbs.pop_front();
+
+ if (cb.opt_in_cb) {
+ Variant ret;
+ Callable::CallError ce;
+ const Variant *args[4] = { &cb.status, &cb.files, &cb.index, &cb.options };
+
+ cb.callback.callp(args, 4, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(cb.callback, args, 4, ce)));
+ }
+ } else {
+ Variant ret;
+ Callable::CallError ce;
+ const Variant *args[3] = { &cb.status, &cb.files, &cb.index };
- p_callable.callp(args, 3, ret, ce);
- if (ce.error != Callable::CallError::CALL_OK) {
- ERR_PRINT(vformat("Failed to execute file dialogs callback: %s.", Variant::get_callable_error_text(p_callable, args, 3, ce)));
+ cb.callback.callp(args, 3, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(cb.callback, args, 3, ce)));
+ }
}
}
}
@@ -532,57 +528,9 @@ void FreeDesktopPortalDesktop::_thread_monitor(void *p_ud) {
FreeDesktopPortalDesktop *portal = (FreeDesktopPortalDesktop *)p_ud;
while (!portal->monitor_thread_abort.is_set()) {
- {
- MutexLock lock(portal->file_dialog_mutex);
- for (int i = portal->file_dialogs.size() - 1; i >= 0; i--) {
- bool remove = false;
- {
- FreeDesktopPortalDesktop::FileDialogData &fd = portal->file_dialogs.write[i];
- if (fd.connection) {
- while (true) {
- DBusMessage *msg = dbus_connection_pop_message(fd.connection);
- if (!msg) {
- break;
- } else if (dbus_message_is_signal(msg, "org.freedesktop.portal.Request", "Response")) {
- DBusMessageIter iter;
- if (dbus_message_iter_init(msg, &iter)) {
- bool cancel = false;
- Vector<String> uris;
- Dictionary options;
- int index = 0;
- file_chooser_parse_response(&iter, fd.filter_names, cancel, uris, index, options);
-
- if (fd.callback.is_valid()) {
- callable_mp(portal, &FreeDesktopPortalDesktop::_file_dialog_callback).call_deferred(fd.callback, !cancel, uris, index, options, fd.opt_in_cb);
- }
- if (fd.prev_focus != DisplayServer::INVALID_WINDOW_ID) {
- callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(fd.prev_focus);
- }
- }
- dbus_message_unref(msg);
-
- DBusError err;
- dbus_error_init(&err);
- dbus_bus_remove_match(fd.connection, fd.path.utf8().get_data(), &err);
- dbus_error_free(&err);
- dbus_connection_unref(fd.connection);
- remove = true;
- break;
- }
- dbus_message_unref(msg);
- }
- dbus_connection_read_write(fd.connection, 0);
- }
- }
- if (remove) {
- portal->file_dialogs.remove_at(i);
- }
- }
- }
-
- if (portal->theme_connection) {
+ if (portal->monitor_connection) {
while (true) {
- DBusMessage *msg = dbus_connection_pop_message(portal->theme_connection);
+ DBusMessage *msg = dbus_connection_pop_message(portal->monitor_connection);
if (!msg) {
break;
} else if (dbus_message_is_signal(msg, "org.freedesktop.portal.Settings", "SettingChanged")) {
@@ -599,12 +547,48 @@ void FreeDesktopPortalDesktop::_thread_monitor(void *p_ud) {
callable_mp(portal, &FreeDesktopPortalDesktop::_system_theme_changed_callback).call_deferred();
}
}
- dbus_message_unref(msg);
- break;
+ } else if (dbus_message_is_signal(msg, "org.freedesktop.portal.Request", "Response")) {
+ String path = String::utf8(dbus_message_get_path(msg));
+ MutexLock lock(portal->file_dialog_mutex);
+ for (int i = 0; i < portal->file_dialogs.size(); i++) {
+ FreeDesktopPortalDesktop::FileDialogData &fd = portal->file_dialogs.write[i];
+ if (fd.path == path) {
+ DBusMessageIter iter;
+ if (dbus_message_iter_init(msg, &iter)) {
+ bool cancel = false;
+ Vector<String> uris;
+ Dictionary options;
+ int index = 0;
+ file_chooser_parse_response(&iter, fd.filter_names, cancel, uris, index, options);
+
+ if (fd.callback.is_valid()) {
+ FileDialogCallback cb;
+ cb.callback = fd.callback;
+ cb.status = !cancel;
+ cb.files = uris;
+ cb.index = index;
+ cb.options = options;
+ cb.opt_in_cb = fd.opt_in_cb;
+ portal->pending_cbs.push_back(cb);
+ }
+ if (fd.prev_focus != DisplayServer::INVALID_WINDOW_ID) {
+ callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(fd.prev_focus);
+ }
+ }
+
+ DBusError err;
+ dbus_error_init(&err);
+ dbus_bus_remove_match(portal->monitor_connection, fd.filter.utf8().get_data(), &err);
+ dbus_error_free(&err);
+
+ portal->file_dialogs.remove_at(i);
+ break;
+ }
+ }
}
dbus_message_unref(msg);
}
- dbus_connection_read_write(portal->theme_connection, 0);
+ dbus_connection_read_write(portal->monitor_connection, 0);
}
usleep(50000);
@@ -647,18 +631,18 @@ FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
DBusError err;
dbus_error_init(&err);
- theme_connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
+ monitor_connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err)) {
dbus_error_free(&err);
} else {
theme_path = "type='signal',sender='org.freedesktop.portal.Desktop',interface='org.freedesktop.portal.Settings',member='SettingChanged'";
- dbus_bus_add_match(theme_connection, theme_path.utf8().get_data(), &err);
+ dbus_bus_add_match(monitor_connection, theme_path.utf8().get_data(), &err);
if (dbus_error_is_set(&err)) {
dbus_error_free(&err);
- dbus_connection_unref(theme_connection);
- theme_connection = nullptr;
+ dbus_connection_unref(monitor_connection);
+ monitor_connection = nullptr;
}
- dbus_connection_read_write(theme_connection, 0);
+ dbus_connection_read_write(monitor_connection, 0);
}
if (!unsupported) {
@@ -673,21 +657,17 @@ FreeDesktopPortalDesktop::~FreeDesktopPortalDesktop() {
monitor_thread.wait_to_finish();
}
- for (FreeDesktopPortalDesktop::FileDialogData &fd : file_dialogs) {
- if (fd.connection) {
- DBusError err;
+ if (monitor_connection) {
+ DBusError err;
+ for (FreeDesktopPortalDesktop::FileDialogData &fd : file_dialogs) {
dbus_error_init(&err);
- dbus_bus_remove_match(fd.connection, fd.path.utf8().get_data(), &err);
+ dbus_bus_remove_match(monitor_connection, fd.filter.utf8().get_data(), &err);
dbus_error_free(&err);
- dbus_connection_unref(fd.connection);
}
- }
- if (theme_connection) {
- DBusError err;
dbus_error_init(&err);
- dbus_bus_remove_match(theme_connection, theme_path.utf8().get_data(), &err);
+ dbus_bus_remove_match(monitor_connection, theme_path.utf8().get_data(), &err);
dbus_error_free(&err);
- dbus_connection_unref(theme_connection);
+ dbus_connection_unref(monitor_connection);
}
}
diff --git a/platform/linuxbsd/freedesktop_portal_desktop.h b/platform/linuxbsd/freedesktop_portal_desktop.h
index 75afe02a26..96c38de2c2 100644
--- a/platform/linuxbsd/freedesktop_portal_desktop.h
+++ b/platform/linuxbsd/freedesktop_portal_desktop.h
@@ -56,23 +56,31 @@ private:
static void append_dbus_dict_bool(DBusMessageIter *p_iter, const String &p_key, bool p_value);
static bool file_chooser_parse_response(DBusMessageIter *p_iter, const Vector<String> &p_names, bool &r_cancel, Vector<String> &r_urls, int &r_index, Dictionary &r_options);
- void _file_dialog_callback(const Callable &p_callable, const Variant &p_status, const Variant &p_list, const Variant &p_index, const Variant &p_options, bool p_opt_in_cb);
-
struct FileDialogData {
Vector<String> filter_names;
- DBusConnection *connection = nullptr;
DisplayServer::WindowID prev_focus = DisplayServer::INVALID_WINDOW_ID;
Callable callback;
+ String filter;
String path;
bool opt_in_cb = false;
};
+ struct FileDialogCallback {
+ Callable callback;
+ Variant status;
+ Variant files;
+ Variant index;
+ Variant options;
+ bool opt_in_cb = false;
+ };
+ List<FileDialogCallback> pending_cbs;
+
Mutex file_dialog_mutex;
Vector<FileDialogData> file_dialogs;
Thread monitor_thread;
SafeFlag monitor_thread_abort;
+ DBusConnection *monitor_connection = nullptr;
- DBusConnection *theme_connection = nullptr;
String theme_path;
Callable system_theme_changed;
void _system_theme_changed_callback();
@@ -86,6 +94,7 @@ public:
bool is_supported() { return !unsupported; }
Error file_dialog_show(DisplayServer::WindowID p_window_id, const String &p_xid, const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, DisplayServer::FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb);
+ void process_file_dialog_callbacks();
// Retrieve the system's preferred color scheme.
// 0: No preference or unknown.
diff --git a/platform/linuxbsd/godot_linuxbsd.cpp b/platform/linuxbsd/godot_linuxbsd.cpp
index a2b6fbeb25..b0880c86b8 100644
--- a/platform/linuxbsd/godot_linuxbsd.cpp
+++ b/platform/linuxbsd/godot_linuxbsd.cpp
@@ -72,18 +72,19 @@ int main(int argc, char *argv[]) {
char *ret = getcwd(cwd, PATH_MAX);
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
+
if (err != OK) {
free(cwd);
-
if (err == ERR_HELP) { // Returned by --help and --version, so success.
- return 0;
+ return EXIT_SUCCESS;
}
- return 255;
+ return EXIT_FAILURE;
}
- if (Main::start()) {
- os.set_exit_code(EXIT_SUCCESS);
- os.run(); // it is actually the OS that decides how to run
+ if (Main::start() == EXIT_SUCCESS) {
+ os.run();
+ } else {
+ os.set_exit_code(EXIT_FAILURE);
}
Main::cleanup();
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index f29275c910..68b4cd7f5a 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -62,6 +62,10 @@
#include <mntent.h>
#endif
+#if defined(__FreeBSD__)
+#include <sys/sysctl.h>
+#endif
+
void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
@@ -145,17 +149,36 @@ void OS_LinuxBSD::initialize_joypads() {
String OS_LinuxBSD::get_unique_id() const {
static String machine_id;
if (machine_id.is_empty()) {
+#if defined(__FreeBSD__)
+ const int mib[2] = { CTL_KERN, KERN_HOSTUUID };
+ char buf[4096];
+ memset(buf, 0, sizeof(buf));
+ size_t len = sizeof(buf) - 1;
+ if (sysctl(mib, 2, buf, &len, 0x0, 0) != -1) {
+ machine_id = String::utf8(buf).replace("-", "");
+ }
+#else
Ref<FileAccess> f = FileAccess::open("/etc/machine-id", FileAccess::READ);
if (f.is_valid()) {
while (machine_id.is_empty() && !f->eof_reached()) {
machine_id = f->get_line().strip_edges();
}
}
+#endif
}
return machine_id;
}
String OS_LinuxBSD::get_processor_name() const {
+#if defined(__FreeBSD__)
+ const int mib[2] = { CTL_HW, HW_MODEL };
+ char buf[4096];
+ memset(buf, 0, sizeof(buf));
+ size_t len = sizeof(buf) - 1;
+ if (sysctl(mib, 2, buf, &len, 0x0, 0) != -1) {
+ return String::utf8(buf);
+ }
+#else
Ref<FileAccess> f = FileAccess::open("/proc/cpuinfo", FileAccess::READ);
ERR_FAIL_COND_V_MSG(f.is_null(), "", String("Couldn't open `/proc/cpuinfo` to get the CPU model name. Returning an empty string."));
@@ -165,8 +188,9 @@ String OS_LinuxBSD::get_processor_name() const {
return line.split(":")[1].strip_edges();
}
}
+#endif
- ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name from `/proc/cpuinfo`. Returning an empty string."));
+ ERR_FAIL_V_MSG("", String("Couldn't get the CPU model. Returning an empty string."));
}
bool OS_LinuxBSD::is_sandboxed() const {
diff --git a/platform/linuxbsd/platform_linuxbsd_builders.py b/platform/linuxbsd/platform_linuxbsd_builders.py
index 85d55f0ac6..46fa1947e8 100644
--- a/platform/linuxbsd/platform_linuxbsd_builders.py
+++ b/platform/linuxbsd/platform_linuxbsd_builders.py
@@ -1,18 +1,10 @@
-"""Functions used to generate source files during build time
-
-All such functions are invoked in a subprocess on Windows to prevent build flakiness.
-
-"""
+"""Functions used to generate source files during build time"""
import os
-from platform_methods import subprocess_main
def make_debug_linuxbsd(target, source, env):
- os.system("objcopy --only-keep-debug {0} {0}.debugsymbols".format(target[0]))
- os.system("strip --strip-debug --strip-unneeded {0}".format(target[0]))
- os.system("objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(target[0]))
-
-
-if __name__ == "__main__":
- subprocess_main(globals())
+ dst = str(target[0])
+ os.system("objcopy --only-keep-debug {0} {0}.debugsymbols".format(dst))
+ os.system("strip --strip-debug --strip-unneeded {0}".format(dst))
+ os.system("objcopy --add-gnu-debuglink={0}.debugsymbols {0}".format(dst))
diff --git a/platform/linuxbsd/wayland/SCsub b/platform/linuxbsd/wayland/SCsub
index cab45b7672..add5bdb504 100644
--- a/platform/linuxbsd/wayland/SCsub
+++ b/platform/linuxbsd/wayland/SCsub
@@ -199,6 +199,7 @@ if env["vulkan"]:
if env["opengl3"]:
source_files.append("egl_manager_wayland.cpp")
+ source_files.append("egl_manager_wayland_gles.cpp")
objects = []
diff --git a/platform/linuxbsd/wayland/detect_prime_egl.cpp b/platform/linuxbsd/wayland/detect_prime_egl.cpp
index 4bee32ae3a..4c97a80039 100644
--- a/platform/linuxbsd/wayland/detect_prime_egl.cpp
+++ b/platform/linuxbsd/wayland/detect_prime_egl.cpp
@@ -69,7 +69,7 @@ void DetectPrimeEGL::create_context() {
EGLConfig egl_config;
EGLContext egl_context = EGL_NO_CONTEXT;
- eglInitialize(egl_display, NULL, NULL);
+ eglInitialize(egl_display, nullptr, nullptr);
#if defined(GLAD_ENABLED)
if (!gladLoaderLoadEGL(egl_display)) {
diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp
index 528c688a9c..1c3cae0435 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.cpp
+++ b/platform/linuxbsd/wayland/display_server_wayland.cpp
@@ -46,6 +46,8 @@
#ifdef GLES3_ENABLED
#include "detect_prime_egl.h"
#include "drivers/gles3/rasterizer_gles3.h"
+#include "wayland/egl_manager_wayland.h"
+#include "wayland/egl_manager_wayland_gles.h"
#endif
String DisplayServerWayland::_get_app_id_from_context(Context p_context) {
@@ -192,19 +194,37 @@ void DisplayServerWayland::_show_window() {
bool DisplayServerWayland::has_feature(Feature p_feature) const {
switch (p_feature) {
+#ifndef DISABLE_DEPRECATED
+ case FEATURE_GLOBAL_MENU: {
+ return (native_menu && native_menu->has_feature(NativeMenu::FEATURE_GLOBAL_MENU));
+ } break;
+#endif
case FEATURE_MOUSE:
+ case FEATURE_MOUSE_WARP:
case FEATURE_CLIPBOARD:
case FEATURE_CURSOR_SHAPE:
+ case FEATURE_CUSTOM_CURSOR_SHAPE:
case FEATURE_WINDOW_TRANSPARENCY:
+ case FEATURE_HIDPI:
case FEATURE_SWAP_BUFFERS:
case FEATURE_KEEP_SCREEN_ON:
- case FEATURE_CLIPBOARD_PRIMARY:
+ case FEATURE_CLIPBOARD_PRIMARY: {
+ return true;
+ } break;
+
+ //case FEATURE_NATIVE_DIALOG:
+ //case FEATURE_NATIVE_DIALOG_INPUT:
#ifdef DBUS_ENABLED
- case FEATURE_NATIVE_DIALOG:
+ case FEATURE_NATIVE_DIALOG_FILE: {
+ return true;
+ } break;
#endif
- case FEATURE_HIDPI: {
+
+#ifdef SPEECHD_ENABLED
+ case FEATURE_TEXT_TO_SPEECH: {
return true;
} break;
+#endif
default: {
return false;
@@ -569,9 +589,9 @@ void DisplayServerWayland::screen_set_keep_on(bool p_enable) {
bool DisplayServerWayland::screen_is_kept_on() const {
#ifdef DBUS_ENABLED
return wayland_thread.window_get_idle_inhibition(MAIN_WINDOW_ID) || screensaver_inhibited;
-#endif
-
+#else
return wayland_thread.window_get_idle_inhibition(MAIN_WINDOW_ID);
+#endif
}
Vector<DisplayServer::WindowID> DisplayServerWayland::get_window_list() const {
@@ -1143,6 +1163,12 @@ void DisplayServerWayland::process_events() {
}
}
+#ifdef DBUS_ENABLED
+ if (portal_desktop) {
+ portal_desktop->process_file_dialog_callbacks();
+ }
+#endif
+
wayland_thread.mutex.unlock();
Input::get_singleton()->flush_buffered_events();
@@ -1156,14 +1182,6 @@ void DisplayServerWayland::release_rendering_thread() {
#endif
}
-void DisplayServerWayland::make_rendering_thread() {
-#ifdef GLES3_ENABLED
- if (egl_manager) {
- egl_manager->make_current();
- }
-#endif
-}
-
void DisplayServerWayland::swap_buffers() {
#ifdef GLES3_ENABLED
if (egl_manager) {
@@ -1192,6 +1210,7 @@ Vector<String> DisplayServerWayland::get_rendering_drivers_func() {
#ifdef GLES3_ENABLED
drivers.push_back("opengl3");
+ drivers.push_back("opengl3_es");
#endif
return drivers;
@@ -1231,6 +1250,8 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
// Input.
Input::get_singleton()->set_event_dispatch_function(dispatch_input_events);
+ native_menu = memnew(NativeMenu);
+
#ifdef SPEECHD_ENABLED
// Init TTS
tts = memnew(TTS_Linux);
@@ -1240,14 +1261,14 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
#ifdef RD_ENABLED
#ifdef VULKAN_ENABLED
- if (p_rendering_driver == "vulkan") {
+ if (rendering_driver == "vulkan") {
rendering_context = memnew(RenderingContextDriverVulkanWayland);
}
#endif
if (rendering_context) {
if (rendering_context->initialize() != OK) {
- ERR_PRINT(vformat("Could not initialize %s", p_rendering_driver));
+ ERR_PRINT(vformat("Could not initialize %s", rendering_driver));
memdelete(rendering_context);
rendering_context = nullptr;
r_error = ERR_CANT_CREATE;
@@ -1257,7 +1278,14 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
#endif
#ifdef GLES3_ENABLED
- if (p_rendering_driver == "opengl3") {
+ if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") {
+#ifdef SOWRAP_ENABLED
+ if (initialize_wayland_egl(dylibloader_verbose) != 0) {
+ WARN_PRINT("Can't load the Wayland EGL library.");
+ return;
+ }
+#endif // SOWRAP_ENABLED
+
if (getenv("DRI_PRIME") == nullptr) {
int prime_idx = -1;
@@ -1300,23 +1328,38 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
}
}
- egl_manager = memnew(EGLManagerWayland);
+ if (rendering_driver == "opengl3") {
+ egl_manager = memnew(EGLManagerWayland);
-#ifdef SOWRAP_ENABLED
- if (initialize_wayland_egl(dylibloader_verbose) != 0) {
- WARN_PRINT("Can't load the Wayland EGL library.");
- return;
- }
-#endif // SOWRAP_ENABLED
+ if (egl_manager->initialize() != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) {
+ memdelete(egl_manager);
+ egl_manager = nullptr;
- if (egl_manager->initialize() != OK) {
- memdelete(egl_manager);
- egl_manager = nullptr;
- r_error = ERR_CANT_CREATE;
- ERR_FAIL_MSG("Could not initialize GLES3.");
+ bool fallback = GLOBAL_GET("rendering/gl_compatibility/fallback_to_gles");
+ if (fallback) {
+ WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES.");
+ rendering_driver = "opengl3_es";
+ } else {
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Could not initialize OpenGL.");
+ }
+ } else {
+ RasterizerGLES3::make_current(true);
+ }
}
- RasterizerGLES3::make_current(true);
+ if (rendering_driver == "opengl3_es") {
+ egl_manager = memnew(EGLManagerWaylandGLES);
+
+ if (egl_manager->initialize() != OK) {
+ memdelete(egl_manager);
+ egl_manager = nullptr;
+ r_error = ERR_CANT_CREATE;
+ ERR_FAIL_MSG("Could not initialize GLES3.");
+ }
+
+ RasterizerGLES3::make_current(false);
+ }
}
#endif // GLES3_ENABLED
@@ -1355,6 +1398,12 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
DisplayServerWayland::~DisplayServerWayland() {
// TODO: Multiwindow support.
+
+ if (native_menu) {
+ memdelete(native_menu);
+ native_menu = nullptr;
+ }
+
if (main_window.visible) {
#ifdef VULKAN_ENABLED
if (rendering_device) {
diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h
index 5b8db1be47..1bad358462 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.h
+++ b/platform/linuxbsd/wayland/display_server_wayland.h
@@ -45,7 +45,7 @@
#endif //RD_ENABLED
#ifdef GLES3_ENABLED
-#include "wayland/egl_manager_wayland.h"
+#include "drivers/egl/egl_manager.h"
#endif
#if defined(SPEECHD_ENABLED)
@@ -126,12 +126,13 @@ class DisplayServerWayland : public DisplayServer {
#endif
#ifdef GLES3_ENABLED
- EGLManagerWayland *egl_manager = nullptr;
+ EGLManager *egl_manager = nullptr;
#endif
#ifdef SPEECHD_ENABLED
TTS_Linux *tts = nullptr;
#endif
+ NativeMenu *native_menu = nullptr;
#if DBUS_ENABLED
FreeDesktopPortalDesktop *portal_desktop = nullptr;
@@ -275,7 +276,6 @@ public:
virtual void process_events() override;
virtual void release_rendering_thread() override;
- virtual void make_rendering_thread() override;
virtual void swap_buffers() override;
virtual void set_context(Context p_context) override;
diff --git a/platform/linuxbsd/wayland/egl_manager_wayland_gles.cpp b/platform/linuxbsd/wayland/egl_manager_wayland_gles.cpp
new file mode 100644
index 0000000000..9431b18f05
--- /dev/null
+++ b/platform/linuxbsd/wayland/egl_manager_wayland_gles.cpp
@@ -0,0 +1,64 @@
+/**************************************************************************/
+/* egl_manager_wayland_gles.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "egl_manager_wayland_gles.h"
+
+#ifdef WAYLAND_ENABLED
+#ifdef EGL_ENABLED
+#ifdef GLES3_ENABLED
+
+const char *EGLManagerWaylandGLES::_get_platform_extension_name() const {
+ return "EGL_KHR_platform_wayland";
+}
+
+EGLenum EGLManagerWaylandGLES::_get_platform_extension_enum() const {
+ return EGL_PLATFORM_WAYLAND_KHR;
+}
+
+EGLenum EGLManagerWaylandGLES::_get_platform_api_enum() const {
+ return EGL_OPENGL_ES_API;
+}
+
+Vector<EGLAttrib> EGLManagerWaylandGLES::_get_platform_display_attributes() const {
+ return Vector<EGLAttrib>();
+}
+
+Vector<EGLint> EGLManagerWaylandGLES::_get_platform_context_attribs() const {
+ Vector<EGLint> ret;
+ ret.push_back(EGL_CONTEXT_MAJOR_VERSION);
+ ret.push_back(3);
+ ret.push_back(EGL_NONE);
+
+ return ret;
+}
+
+#endif // GLES3_ENABLED
+#endif // EGL_ENABLED
+#endif // WAYLAND_ENABLED
diff --git a/platform/linuxbsd/wayland/egl_manager_wayland_gles.h b/platform/linuxbsd/wayland/egl_manager_wayland_gles.h
new file mode 100644
index 0000000000..f526f18277
--- /dev/null
+++ b/platform/linuxbsd/wayland/egl_manager_wayland_gles.h
@@ -0,0 +1,53 @@
+/**************************************************************************/
+/* egl_manager_wayland_gles.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef EGL_MANAGER_WAYLAND_GLES_H
+#define EGL_MANAGER_WAYLAND_GLES_H
+
+#ifdef WAYLAND_ENABLED
+#ifdef EGL_ENABLED
+#ifdef GLES3_ENABLED
+
+#include "drivers/egl/egl_manager.h"
+
+class EGLManagerWaylandGLES : public EGLManager {
+public:
+ virtual const char *_get_platform_extension_name() const override;
+ virtual EGLenum _get_platform_extension_enum() const override;
+ virtual EGLenum _get_platform_api_enum() const override;
+ virtual Vector<EGLAttrib> _get_platform_display_attributes() const override;
+ virtual Vector<EGLint> _get_platform_context_attribs() const override;
+};
+
+#endif // GLES3_ENABLED
+#endif // EGL_ENABLED
+#endif // WAYLAND_ENABLED
+
+#endif // EGL_MANAGER_WAYLAND_GLES_H
diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp
index 7fa69a3bed..aabf1abdda 100644
--- a/platform/linuxbsd/wayland/wayland_thread.cpp
+++ b/platform/linuxbsd/wayland/wayland_thread.cpp
@@ -371,28 +371,22 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re
}
if (strcmp(interface, zxdg_exporter_v1_interface.name) == 0) {
- registry->wl_exporter = (struct zxdg_exporter_v1 *)wl_registry_bind(wl_registry, name, &zxdg_exporter_v1_interface, 1);
- registry->wl_exporter_name = name;
+ registry->xdg_exporter = (struct zxdg_exporter_v1 *)wl_registry_bind(wl_registry, name, &zxdg_exporter_v1_interface, 1);
+ registry->xdg_exporter_name = name;
return;
}
if (strcmp(interface, wl_compositor_interface.name) == 0) {
- registry->wl_compositor = (struct wl_compositor *)wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4);
+ registry->wl_compositor = (struct wl_compositor *)wl_registry_bind(wl_registry, name, &wl_compositor_interface, CLAMP((int)version, 1, 6));
registry->wl_compositor_name = name;
return;
}
- if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
- registry->wl_subcompositor = (struct wl_subcompositor *)wl_registry_bind(wl_registry, name, &wl_subcompositor_interface, 1);
- registry->wl_subcompositor_name = name;
- return;
- }
-
if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
- registry->wl_data_device_manager = (struct wl_data_device_manager *)wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3);
+ registry->wl_data_device_manager = (struct wl_data_device_manager *)wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, CLAMP((int)version, 1, 3));
registry->wl_data_device_manager_name = name;
- // This global creates some seats data. Let's do that for the ones already available.
+ // This global creates some seat data. Let's do that for the ones already available.
for (struct wl_seat *wl_seat : registry->wl_seats) {
SeatState *ss = wl_seat_get_seat_state(wl_seat);
ERR_FAIL_NULL(ss);
@@ -406,7 +400,7 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re
}
if (strcmp(interface, wl_output_interface.name) == 0) {
- struct wl_output *wl_output = (struct wl_output *)wl_registry_bind(wl_registry, name, &wl_output_interface, 2);
+ struct wl_output *wl_output = (struct wl_output *)wl_registry_bind(wl_registry, name, &wl_output_interface, CLAMP((int)version, 1, 4));
wl_proxy_tag_godot((struct wl_proxy *)wl_output);
registry->wl_outputs.push_back(wl_output);
@@ -421,7 +415,7 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re
}
if (strcmp(interface, wl_seat_interface.name) == 0) {
- struct wl_seat *wl_seat = (struct wl_seat *)wl_registry_bind(wl_registry, name, &wl_seat_interface, 5);
+ struct wl_seat *wl_seat = (struct wl_seat *)wl_registry_bind(wl_registry, name, &wl_seat_interface, CLAMP((int)version, 1, 9));
wl_proxy_tag_godot((struct wl_proxy *)wl_seat);
SeatState *ss = memnew(SeatState);
@@ -466,7 +460,7 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re
}
if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
- registry->xdg_wm_base = (struct xdg_wm_base *)wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, MAX(2, MIN(6, (int)version)));
+ registry->xdg_wm_base = (struct xdg_wm_base *)wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, CLAMP((int)version, 1, 6));
registry->xdg_wm_base_name = name;
xdg_wm_base_add_listener(registry->xdg_wm_base, &xdg_wm_base_listener, nullptr);
@@ -502,7 +496,7 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re
if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) {
registry->wp_primary_selection_device_manager = (struct zwp_primary_selection_device_manager_v1 *)wl_registry_bind(wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
- // This global creates some seats data. Let's do that for the ones already available.
+ // This global creates some seat data. Let's do that for the ones already available.
for (struct wl_seat *wl_seat : registry->wl_seats) {
SeatState *ss = wl_seat_get_seat_state(wl_seat);
ERR_FAIL_NULL(ss);
@@ -570,13 +564,13 @@ void WaylandThread::_wl_registry_on_global_remove(void *data, struct wl_registry
return;
}
- if (name == registry->wl_exporter_name) {
- if (registry->wl_exporter) {
- zxdg_exporter_v1_destroy(registry->wl_exporter);
- registry->wl_exporter = nullptr;
+ if (name == registry->xdg_exporter_name) {
+ if (registry->xdg_exporter) {
+ zxdg_exporter_v1_destroy(registry->xdg_exporter);
+ registry->xdg_exporter = nullptr;
}
- registry->wl_exporter_name = 0;
+ registry->xdg_exporter_name = 0;
return;
}
@@ -592,17 +586,6 @@ void WaylandThread::_wl_registry_on_global_remove(void *data, struct wl_registry
return;
}
- if (name == registry->wl_subcompositor_name) {
- if (registry->wl_subcompositor) {
- wl_subcompositor_destroy(registry->wl_subcompositor);
- registry->wl_subcompositor = nullptr;
- }
-
- registry->wl_subcompositor_name = 0;
-
- return;
- }
-
if (name == registry->wl_data_device_manager_name) {
if (registry->wl_data_device_manager) {
wl_data_device_manager_destroy(registry->wl_data_device_manager);
@@ -1000,6 +983,12 @@ void WaylandThread::_wl_output_on_geometry(void *data, struct wl_output *wl_outp
ss->pending_data.make.parse_utf8(make);
ss->pending_data.model.parse_utf8(model);
+
+ // `wl_output::done` is a version 2 addition. We'll directly update the data
+ // for compatibility.
+ if (wl_output_get_version(wl_output) == 1) {
+ ss->data = ss->pending_data;
+ }
}
void WaylandThread::_wl_output_on_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
@@ -1010,8 +999,17 @@ void WaylandThread::_wl_output_on_mode(void *data, struct wl_output *wl_output,
ss->pending_data.size.height = height;
ss->pending_data.refresh_rate = refresh ? refresh / 1000.0f : -1;
+
+ // `wl_output::done` is a version 2 addition. We'll directly update the data
+ // for compatibility.
+ if (wl_output_get_version(wl_output) == 1) {
+ ss->data = ss->pending_data;
+ }
}
+// NOTE: The following `wl_output` events are only for version 2 onwards, so we
+// can assume that they're "atomic" (i.e. rely on the `wl_output::done` event).
+
void WaylandThread::_wl_output_on_done(void *data, struct wl_output *wl_output) {
ScreenState *ss = (ScreenState *)data;
ERR_FAIL_NULL(ss);
@@ -1231,8 +1229,6 @@ void WaylandThread::_wl_seat_on_capabilities(void *data, struct wl_seat *wl_seat
// Pointer handling.
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
ss->cursor_surface = wl_compositor_create_surface(ss->registry->wl_compositor);
- ss->cursor_frame_callback = wl_surface_frame(ss->cursor_surface);
- wl_callback_add_listener(ss->cursor_frame_callback, &cursor_frame_callback_listener, ss);
wl_surface_commit(ss->cursor_surface);
ss->wl_pointer = wl_seat_get_pointer(wl_seat);
@@ -1313,11 +1309,9 @@ void WaylandThread::_cursor_frame_callback_on_done(void *data, struct wl_callbac
SeatState *ss = (SeatState *)data;
ERR_FAIL_NULL(ss);
- ss->cursor_time_ms = time_ms;
+ ss->cursor_frame_callback = nullptr;
- ss->cursor_frame_callback = wl_surface_frame(ss->cursor_surface);
- wl_callback_add_listener(ss->cursor_frame_callback, &cursor_frame_callback_listener, ss);
- wl_surface_commit(ss->cursor_surface);
+ ss->cursor_time_ms = time_ms;
seat_state_update_cursor(ss);
}
@@ -1527,7 +1521,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
wayland_thread->push_message(msg);
}
- if (pd.discrete_scroll_vector - old_pd.discrete_scroll_vector != Vector2i()) {
+ if (pd.discrete_scroll_vector_120 - old_pd.discrete_scroll_vector_120 != Vector2i()) {
// This is a discrete scroll (eg. from a scroll wheel), so we'll just emit
// scroll wheel buttons.
if (pd.scroll_vector.y != 0) {
@@ -1567,7 +1561,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
}
if (old_pd.pressed_button_mask != pd.pressed_button_mask) {
- BitField<MouseButtonMask> pressed_mask_delta = BitField<MouseButtonMask>((uint32_t)old_pd.pressed_button_mask ^ (uint32_t)pd.pressed_button_mask);
+ BitField<MouseButtonMask> pressed_mask_delta = old_pd.pressed_button_mask ^ pd.pressed_button_mask;
const MouseButton buttons_to_test[] = {
MouseButton::LEFT,
@@ -1600,13 +1594,13 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
if (test_button == MouseButton::WHEEL_UP || test_button == MouseButton::WHEEL_DOWN) {
// If this is a discrete scroll, specify how many "clicks" it did for this
// pointer frame.
- mb->set_factor(abs(pd.discrete_scroll_vector.y));
+ mb->set_factor(Math::abs(pd.discrete_scroll_vector_120.y / (float)120));
}
if (test_button == MouseButton::WHEEL_RIGHT || test_button == MouseButton::WHEEL_LEFT) {
// If this is a discrete scroll, specify how many "clicks" it did for this
// pointer frame.
- mb->set_factor(abs(pd.discrete_scroll_vector.x));
+ mb->set_factor(fabs(pd.discrete_scroll_vector_120.x / (float)120));
}
mb->set_button_mask(pd.pressed_button_mask);
@@ -1665,7 +1659,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
// Reset the scroll vectors as we already handled them.
pd.scroll_vector = Vector2();
- pd.discrete_scroll_vector = Vector2();
+ pd.discrete_scroll_vector_120 = Vector2i();
// Update the data all getters read. Wayland's specification requires us to do
// this, since all pointer actions are sent in individual events.
@@ -1687,6 +1681,9 @@ void WaylandThread::_wl_pointer_on_axis_source(void *data, struct wl_pointer *wl
void WaylandThread::_wl_pointer_on_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) {
}
+// NOTE: This event is deprecated since version 8 and superseded by
+// `wl_pointer::axis_value120`. This thus converts the data to its
+// fraction-of-120 format.
void WaylandThread::_wl_pointer_on_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) {
SeatState *ss = (SeatState *)data;
ERR_FAIL_NULL(ss);
@@ -1698,17 +1695,37 @@ void WaylandThread::_wl_pointer_on_axis_discrete(void *data, struct wl_pointer *
PointerData &pd = ss->pointer_data_buffer;
+ // NOTE: We can allow ourselves to not accumulate this data (and thus just
+ // assign it) as the spec guarantees only one event per axis type.
+
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
- pd.discrete_scroll_vector.y = discrete;
+ pd.discrete_scroll_vector_120.y = discrete * 120;
}
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
- pd.discrete_scroll_vector.x = discrete;
+ pd.discrete_scroll_vector_120.x = discrete * 120;
}
}
-// TODO: Add support to this event.
+// Supersedes `wl_pointer::axis_discrete` Since version 8.
void WaylandThread::_wl_pointer_on_axis_value120(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120) {
+ SeatState *ss = (SeatState *)data;
+ ERR_FAIL_NULL(ss);
+
+ if (!ss->pointed_surface) {
+ // We're probably on a decoration or some other third-party thing.
+ return;
+ }
+
+ PointerData &pd = ss->pointer_data_buffer;
+
+ if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
+ pd.discrete_scroll_vector_120.y += value120;
+ }
+
+ if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
+ pd.discrete_scroll_vector_120.x += value120;
+ }
}
// TODO: Add support to this event.
@@ -1728,7 +1745,7 @@ void WaylandThread::_wl_keyboard_on_keymap(void *data, struct wl_keyboard *wl_ke
ss->keymap_buffer = nullptr;
}
- ss->keymap_buffer = (const char *)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ ss->keymap_buffer = (const char *)mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
ss->keymap_buffer_size = size;
xkb_keymap_unref(ss->xkb_keymap);
@@ -2003,7 +2020,7 @@ void WaylandThread::_wp_relative_pointer_on_relative_motion(void *data, struct z
pd.relative_motion_time = uptime_lo;
}
-void WaylandThread::_wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers) {
+void WaylandThread::_wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers) {
SeatState *ss = (SeatState *)data;
ERR_FAIL_NULL(ss);
@@ -2013,7 +2030,7 @@ void WaylandThread::_wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_po
}
}
-void WaylandThread::_wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation) {
+void WaylandThread::_wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation) {
SeatState *ss = (SeatState *)data;
ERR_FAIL_NULL(ss);
@@ -2072,7 +2089,7 @@ void WaylandThread::_wp_pointer_gesture_pinch_on_update(void *data, struct zwp_p
}
}
-void WaylandThread::_wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled) {
+void WaylandThread::_wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled) {
SeatState *ss = (SeatState *)data;
ERR_FAIL_NULL(ss);
@@ -2097,7 +2114,7 @@ void WaylandThread::_wp_primary_selection_device_on_selection(void *data, struct
ss->wp_primary_selection_offer = id;
}
-void WaylandThread::_wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *zwp_primary_selection_offer_v1, const char *mime_type) {
+void WaylandThread::_wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *wp_primary_selection_offer_v1, const char *mime_type) {
OfferState *os = (OfferState *)data;
ERR_FAIL_NULL(os);
@@ -2151,10 +2168,10 @@ void WaylandThread::_wp_primary_selection_source_on_cancelled(void *data, struct
}
}
-void WaylandThread::_wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_v2 *id) {
+void WaylandThread::_wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_v2 *id) {
}
-void WaylandThread::_wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id) {
+void WaylandThread::_wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id) {
SeatState *ss = (SeatState *)data;
ERR_FAIL_NULL(ss);
@@ -2167,38 +2184,43 @@ void WaylandThread::_wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_
ss->tablet_tools.push_back(id);
}
-void WaylandThread::_wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id) {
+void WaylandThread::_wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id) {
}
-void WaylandThread::_wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t tool_type) {
- TabletToolState *state = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t tool_type) {
+ TabletToolState *state = wp_tablet_tool_get_state(wp_tablet_tool_v2);
if (state && tool_type == ZWP_TABLET_TOOL_V2_TYPE_ERASER) {
state->is_eraser = true;
}
}
-void WaylandThread::_wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo) {
+void WaylandThread::_wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo) {
}
-void WaylandThread::_wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo) {
+void WaylandThread::_wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo) {
}
-void WaylandThread::_wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t capability) {
+void WaylandThread::_wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t capability) {
}
-void WaylandThread::_wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) {
+void WaylandThread::_wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2) {
}
-void WaylandThread::_wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
+
+ if (!ts) {
+ return;
+ }
+
SeatState *ss = wl_seat_get_seat_state(ts->wl_seat);
- if (!ts || !ss) {
+ if (!ss) {
return;
}
- List<struct zwp_tablet_tool_v2 *>::Element *E = ss->tablet_tools.find(zwp_tablet_tool_v2);
+ List<struct zwp_tablet_tool_v2 *>::Element *E = ss->tablet_tools.find(wp_tablet_tool_v2);
if (E && E->get()) {
struct zwp_tablet_tool_v2 *tool = E->get();
@@ -2212,11 +2234,16 @@ void WaylandThread::_wp_tablet_tool_on_removed(void *data, struct zwp_tablet_too
}
}
-void WaylandThread::_wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
+
+ if (!ts) {
+ return;
+ }
+
SeatState *ss = wl_seat_get_seat_state(ts->wl_seat);
- if (!ts || !ss) {
+ if (!ss) {
return;
}
@@ -2235,11 +2262,16 @@ void WaylandThread::_wp_tablet_tool_on_proximity_in(void *data, struct zwp_table
DEBUG_LOG_WAYLAND_THREAD("Tablet tool entered window.");
}
-void WaylandThread::_wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
+
+ if (!ts) {
+ return;
+ }
+
SeatState *ss = wl_seat_get_seat_state(ts->wl_seat);
- if (!ts || !ss) {
+ if (!ss) {
return;
}
@@ -2257,8 +2289,8 @@ void WaylandThread::_wp_tablet_tool_on_proximity_out(void *data, struct zwp_tabl
DEBUG_LOG_WAYLAND_THREAD("Tablet tool left window.");
}
-void WaylandThread::_wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
if (!ts) {
return;
@@ -2275,8 +2307,8 @@ void WaylandThread::_wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v
td.button_time = OS::get_singleton()->get_ticks_msec();
}
-void WaylandThread::_wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
if (!ts) {
return;
@@ -2291,8 +2323,8 @@ void WaylandThread::_wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2
td.button_time = OS::get_singleton()->get_ticks_msec();
}
-void WaylandThread::_wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
if (!ts) {
return;
@@ -2312,8 +2344,8 @@ void WaylandThread::_wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool
td.motion_time = OS::get_singleton()->get_ticks_msec();
}
-void WaylandThread::_wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t pressure) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t pressure) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
if (!ts) {
return;
@@ -2322,12 +2354,12 @@ void WaylandThread::_wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_to
ts->data_pending.pressure = pressure;
}
-void WaylandThread::_wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t distance) {
+void WaylandThread::_wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t distance) {
// Unsupported
}
-void WaylandThread::_wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
if (!ts) {
return;
@@ -2339,20 +2371,20 @@ void WaylandThread::_wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v
td.tilt.y = wl_fixed_to_double(tilt_y);
}
-void WaylandThread::_wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t degrees) {
+void WaylandThread::_wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees) {
// Unsupported.
}
-void WaylandThread::_wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, int32_t position) {
+void WaylandThread::_wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, int32_t position) {
// Unsupported.
}
-void WaylandThread::_wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks) {
+void WaylandThread::_wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks) {
// TODO
}
-void WaylandThread::_wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
if (!ts) {
return;
@@ -2387,11 +2419,16 @@ void WaylandThread::_wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool
}
}
-void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t time) {
- TabletToolState *ts = wp_tablet_tool_get_state(zwp_tablet_tool_v2);
+void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t time) {
+ TabletToolState *ts = wp_tablet_tool_get_state(wp_tablet_tool_v2);
+
+ if (!ts) {
+ return;
+ }
+
SeatState *ss = wl_seat_get_seat_state(ts->wl_seat);
- if (!ts || !ss) {
+ if (!ss) {
return;
}
@@ -2424,8 +2461,7 @@ void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_
// According to the tablet proto spec, tilt is expressed in degrees relative
// to the Z axis of the tablet, so it shouldn't go over 90 degrees either way,
// I think. We'll clamp it just in case.
- td.tilt.x = CLAMP(td.tilt.x, -90, 90);
- td.tilt.y = CLAMP(td.tilt.x, -90, 90);
+ td.tilt = td.tilt.clampf(-90, 90);
mm->set_tilt(td.tilt / 90);
@@ -2439,7 +2475,7 @@ void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_
mm->set_relative_screen_position(mm->get_relative());
Vector2i pos_delta = td.position - old_td.position;
- uint32_t time_delta = td.motion_time - td.motion_time;
+ uint32_t time_delta = td.motion_time - old_td.motion_time;
mm->set_velocity((Vector2)pos_delta / time_delta);
Ref<InputEventMessage> inputev_msg;
@@ -2839,7 +2875,7 @@ void WaylandThread::seat_state_lock_pointer(SeatState *p_ss) {
ERR_FAIL_NULL(locked_surface);
- p_ss->wp_locked_pointer = zwp_pointer_constraints_v1_lock_pointer(registry.wp_pointer_constraints, locked_surface, p_ss->wl_pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
+ p_ss->wp_locked_pointer = zwp_pointer_constraints_v1_lock_pointer(registry.wp_pointer_constraints, locked_surface, p_ss->wl_pointer, nullptr, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
}
}
@@ -2871,7 +2907,7 @@ void WaylandThread::seat_state_confine_pointer(SeatState *p_ss) {
ERR_FAIL_NULL(confined_surface);
- p_ss->wp_confined_pointer = zwp_pointer_constraints_v1_confine_pointer(registry.wp_pointer_constraints, confined_surface, p_ss->wl_pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
+ p_ss->wp_confined_pointer = zwp_pointer_constraints_v1_confine_pointer(registry.wp_pointer_constraints, confined_surface, p_ss->wl_pointer, nullptr, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
}
}
@@ -2900,7 +2936,18 @@ void WaylandThread::seat_state_update_cursor(SeatState *p_ss) {
// compositor do it for us (badly).
scale = 1;
} else if (wl_cursor) {
- int frame_idx = wl_cursor_frame(wl_cursor, p_ss->cursor_time_ms);
+ int frame_idx = 0;
+
+ if (wl_cursor->image_count > 1) {
+ // The cursor is animated.
+ frame_idx = wl_cursor_frame(wl_cursor, p_ss->cursor_time_ms);
+
+ if (!p_ss->cursor_frame_callback) {
+ // Since it's animated, we'll re-update it the next frame.
+ p_ss->cursor_frame_callback = wl_surface_frame(p_ss->cursor_surface);
+ wl_callback_add_listener(p_ss->cursor_frame_callback, &cursor_frame_callback_listener, p_ss);
+ }
+ }
struct wl_cursor_image *wl_cursor_image = wl_cursor->images[frame_idx];
@@ -3045,8 +3092,8 @@ void WaylandThread::window_create(DisplayServer::WindowID p_window_id, int p_wid
// "loop".
wl_surface_commit(ws.wl_surface);
- if (registry.wl_exporter) {
- ws.xdg_exported = zxdg_exporter_v1_export(registry.wl_exporter, ws.wl_surface);
+ if (registry.xdg_exporter) {
+ ws.xdg_exported = zxdg_exporter_v1_export(registry.xdg_exporter, ws.wl_surface);
zxdg_exported_v1_add_listener(ws.xdg_exported, &xdg_exported_listener, &ws);
}
@@ -3380,7 +3427,7 @@ bool WaylandThread::window_get_idle_inhibition(DisplayServer::WindowID p_window_
WaylandThread::ScreenData WaylandThread::screen_get_data(int p_screen) const {
ERR_FAIL_INDEX_V(p_screen, registry.wl_outputs.size(), ScreenData());
- return wl_output_get_screen_state(registry.wl_outputs[p_screen])->data;
+ return wl_output_get_screen_state(registry.wl_outputs.get(p_screen))->data;
}
int WaylandThread::get_screen_count() const {
@@ -3503,9 +3550,6 @@ Error WaylandThread::init() {
ERR_FAIL_NULL_V_MSG(registry.wl_shm, ERR_UNAVAILABLE, "Can't obtain the Wayland shared memory global.");
ERR_FAIL_NULL_V_MSG(registry.wl_compositor, ERR_UNAVAILABLE, "Can't obtain the Wayland compositor global.");
- ERR_FAIL_NULL_V_MSG(registry.wl_subcompositor, ERR_UNAVAILABLE, "Can't obtain the Wayland subcompositor global.");
- ERR_FAIL_NULL_V_MSG(registry.wl_data_device_manager, ERR_UNAVAILABLE, "Can't obtain the Wayland data device manager global.");
- ERR_FAIL_NULL_V_MSG(registry.wp_pointer_constraints, ERR_UNAVAILABLE, "Can't obtain the Wayland pointer constraints global.");
ERR_FAIL_NULL_V_MSG(registry.xdg_wm_base, ERR_UNAVAILABLE, "Can't obtain the Wayland XDG shell global.");
if (!registry.xdg_decoration_manager) {
@@ -3634,7 +3678,10 @@ void WaylandThread::cursor_shape_set_custom_image(DisplayServer::CursorShape p_c
munmap(cursor.buffer_data, cursor.buffer_data_size);
}
- cursor.buffer_data = (uint32_t *)mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ // NOTE: From `wl_keyboard`s of version 7 or later, the spec requires the mmap
+ // operation to be done with MAP_PRIVATE, as "MAP_SHARED may fail". We'll do it
+ // regardless of global version.
+ cursor.buffer_data = (uint32_t *)mmap(nullptr, data_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (cursor.wl_buffer) {
// Clean up the old Wayland buffer.
@@ -4153,18 +4200,14 @@ void WaylandThread::destroy() {
xdg_wm_base_destroy(registry.xdg_wm_base);
}
- if (registry.wl_exporter) {
- zxdg_exporter_v1_destroy(registry.wl_exporter);
+ if (registry.xdg_exporter) {
+ zxdg_exporter_v1_destroy(registry.xdg_exporter);
}
if (registry.wl_shm) {
wl_shm_destroy(registry.wl_shm);
}
- if (registry.wl_subcompositor) {
- wl_subcompositor_destroy(registry.wl_subcompositor);
- }
-
if (registry.wl_compositor) {
wl_compositor_destroy(registry.wl_compositor);
}
diff --git a/platform/linuxbsd/wayland/wayland_thread.h b/platform/linuxbsd/wayland/wayland_thread.h
index b9e7e0437a..d35a5b7139 100644
--- a/platform/linuxbsd/wayland/wayland_thread.h
+++ b/platform/linuxbsd/wayland/wayland_thread.h
@@ -133,8 +133,8 @@ public:
struct xdg_wm_base *xdg_wm_base = nullptr;
uint32_t xdg_wm_base_name = 0;
- struct zxdg_exporter_v1 *wl_exporter = nullptr;
- uint32_t wl_exporter_name = 0;
+ struct zxdg_exporter_v1 *xdg_exporter = nullptr;
+ uint32_t xdg_exporter_name = 0;
// wayland-protocols globals.
@@ -300,15 +300,15 @@ public:
// The amount "scrolled" in pixels, in each direction.
Vector2 scroll_vector;
- // The amount of scroll "clicks" in each direction.
- Vector2i discrete_scroll_vector;
+ // The amount of scroll "clicks" in each direction, in fractions of 120.
+ Vector2i discrete_scroll_vector_120;
uint32_t pinch_scale = 1;
};
struct TabletToolData {
Point2i position;
- Vector2i tilt;
+ Vector2 tilt;
uint32_t pressure = 0;
BitField<MouseButtonMask> pressed_button_mask;
@@ -579,41 +579,41 @@ private:
static void _wp_relative_pointer_on_relative_motion(void *data, struct zwp_relative_pointer_v1 *wp_relative_pointer_v1, uint32_t uptime_hi, uint32_t uptime_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel, wl_fixed_t dy_unaccel);
- static void _wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers);
- static void _wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation);
- static void _wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled);
+ static void _wp_pointer_gesture_pinch_on_begin(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, struct wl_surface *surface, uint32_t fingers);
+ static void _wp_pointer_gesture_pinch_on_update(void *data, struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch_v1, uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation);
+ static void _wp_pointer_gesture_pinch_on_end(void *data, struct zwp_pointer_gesture_pinch_v1 *zp_pointer_gesture_pinch_v1, uint32_t serial, uint32_t time, int32_t cancelled);
static void _wp_primary_selection_device_on_data_offer(void *data, struct zwp_primary_selection_device_v1 *wp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *offer);
static void _wp_primary_selection_device_on_selection(void *data, struct zwp_primary_selection_device_v1 *wp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *id);
- static void _wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *zwp_primary_selection_offer_v1, const char *mime_type);
+ static void _wp_primary_selection_offer_on_offer(void *data, struct zwp_primary_selection_offer_v1 *wp_primary_selection_offer_v1, const char *mime_type);
static void _wp_primary_selection_source_on_send(void *data, struct zwp_primary_selection_source_v1 *wp_primary_selection_source_v1, const char *mime_type, int32_t fd);
static void _wp_primary_selection_source_on_cancelled(void *data, struct zwp_primary_selection_source_v1 *wp_primary_selection_source_v1);
- static void _wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_v2 *id);
- static void _wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id);
- static void _wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id);
-
- static void _wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t tool_type);
- static void _wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo);
- static void _wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo);
- static void _wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t capability);
- static void _wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2);
- static void _wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2);
- static void _wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface);
- static void _wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2);
- static void _wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial);
- static void _wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2);
- static void _wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y);
- static void _wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t pressure);
- static void _wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t distance);
- static void _wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y);
- static void _wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t degrees);
- static void _wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, int32_t position);
- static void _wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks);
- static void _wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state);
- static void _wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t time);
+ static void _wp_tablet_seat_on_tablet_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_v2 *id);
+ static void _wp_tablet_seat_on_tool_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_tool_v2 *id);
+ static void _wp_tablet_seat_on_pad_added(void *data, struct zwp_tablet_seat_v2 *wp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id);
+
+ static void _wp_tablet_tool_on_type(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t tool_type);
+ static void _wp_tablet_tool_on_hardware_serial(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_serial_hi, uint32_t hardware_serial_lo);
+ static void _wp_tablet_tool_on_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t hardware_id_hi, uint32_t hardware_id_lo);
+ static void _wp_tablet_tool_on_capability(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t capability);
+ static void _wp_tablet_tool_on_done(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2);
+ static void _wp_tablet_tool_on_removed(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2);
+ static void _wp_tablet_tool_on_proximity_in(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, struct zwp_tablet_v2 *tablet, struct wl_surface *surface);
+ static void _wp_tablet_tool_on_proximity_out(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2);
+ static void _wp_tablet_tool_on_down(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial);
+ static void _wp_tablet_tool_on_up(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2);
+ static void _wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t x, wl_fixed_t y);
+ static void _wp_tablet_tool_on_pressure(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t pressure);
+ static void _wp_tablet_tool_on_distance(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t distance);
+ static void _wp_tablet_tool_on_tilt(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t tilt_x, wl_fixed_t tilt_y);
+ static void _wp_tablet_tool_on_rotation(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees);
+ static void _wp_tablet_tool_on_slider(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, int32_t position);
+ static void _wp_tablet_tool_on_wheel(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, wl_fixed_t degrees, int32_t clicks);
+ static void _wp_tablet_tool_on_button(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t serial, uint32_t button, uint32_t state);
+ static void _wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_v2 *wp_tablet_tool_v2, uint32_t time);
static void _xdg_toplevel_decoration_on_configure(void *data, struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration, uint32_t mode);
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index d58b5b93d7..b76cbc126f 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -109,6 +109,11 @@ static String get_atom_name(Display *p_disp, Atom p_atom) {
bool DisplayServerX11::has_feature(Feature p_feature) const {
switch (p_feature) {
+#ifndef DISABLE_DEPRECATED
+ case FEATURE_GLOBAL_MENU: {
+ return (native_menu && native_menu->has_feature(NativeMenu::FEATURE_GLOBAL_MENU));
+ } break;
+#endif
case FEATURE_SUBWINDOWS:
#ifdef TOUCH_ENABLED
case FEATURE_TOUCHSCREEN:
@@ -123,8 +128,10 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
//case FEATURE_HIDPI:
case FEATURE_ICON:
#ifdef DBUS_ENABLED
- case FEATURE_NATIVE_DIALOG:
+ case FEATURE_NATIVE_DIALOG_FILE:
#endif
+ //case FEATURE_NATIVE_DIALOG:
+ //case FEATURE_NATIVE_DIALOG_INPUT:
//case FEATURE_NATIVE_ICON:
case FEATURE_SWAP_BUFFERS:
#ifdef DBUS_ENABLED
@@ -1990,8 +1997,7 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
Size2i wsize = window_get_size(p_window);
wpos += srect.position;
if (srect != Rect2i()) {
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - wsize.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
+ wpos = wpos.clamp(srect.position, srect.position + srect.size - wsize / 3);
}
window_set_position(wpos, p_window);
}
@@ -2219,8 +2225,7 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
Size2i size = p_size;
- size.x = MAX(1, size.x);
- size.y = MAX(1, size.y);
+ size = size.maxi(1);
WindowData &wd = windows[p_window];
@@ -4263,7 +4268,7 @@ bool DisplayServerX11::_window_focus_check() {
}
void DisplayServerX11::process_events() {
- _THREAD_SAFE_METHOD_
+ _THREAD_SAFE_LOCK_
#ifdef DISPLAY_SERVER_X11_DEBUG_LOGS_ENABLED
static int frame = 0;
@@ -4701,19 +4706,6 @@ void DisplayServerX11::process_events() {
break;
}
- const WindowData &wd = windows[window_id];
-
- XWindowAttributes xwa;
- XSync(x11_display, False);
- XGetWindowAttributes(x11_display, wd.x11_window, &xwa);
-
- // Set focus when menu window is re-used.
- // RevertToPointerRoot is used to make sure we don't lose all focus in case
- // a subwindow and its parent are both destroyed.
- if ((xwa.map_state == IsViewable) && !wd.no_focus && !wd.is_popup && _window_focus_check()) {
- _set_input_focus(wd.x11_window, RevertToPointerRoot);
- }
-
_window_changed(&event);
} break;
@@ -5000,7 +4992,7 @@ void DisplayServerX11::process_events() {
files.write[i] = files[i].replace("file://", "").uri_decode();
}
- if (!windows[window_id].drop_files_callback.is_null()) {
+ if (windows[window_id].drop_files_callback.is_valid()) {
windows[window_id].drop_files_callback.call(files);
}
@@ -5105,6 +5097,14 @@ void DisplayServerX11::process_events() {
*/
}
+#ifdef DBUS_ENABLED
+ if (portal_desktop) {
+ portal_desktop->process_file_dialog_callbacks();
+ }
+#endif
+
+ _THREAD_SAFE_UNLOCK_
+
Input::get_singleton()->flush_buffered_events();
}
@@ -5119,17 +5119,6 @@ void DisplayServerX11::release_rendering_thread() {
#endif
}
-void DisplayServerX11::make_rendering_thread() {
-#if defined(GLES3_ENABLED)
- if (gl_manager) {
- gl_manager->make_current();
- }
- if (gl_manager_egl) {
- gl_manager_egl->make_current();
- }
-#endif
-}
-
void DisplayServerX11::swap_buffers() {
#if defined(GLES3_ENABLED)
if (gl_manager) {
@@ -5220,7 +5209,7 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) {
if (g_set_icon_error) {
g_set_icon_error = false;
- WARN_PRINT("Icon too large, attempting to resize icon.");
+ WARN_PRINT(vformat("Icon too large (%dx%d), attempting to downscale icon.", w, h));
int new_width, new_height;
if (w > h) {
@@ -5459,8 +5448,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
} else {
Rect2i srect = screen_get_usable_rect(rq_screen);
Point2i wpos = p_rect.position;
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
+ wpos = wpos.clamp(srect.position, srect.position + srect.size - p_rect.size / 3);
win_rect.position = wpos;
}
@@ -5765,6 +5753,8 @@ static ::XIMStyle _get_best_xim_style(const ::XIMStyle &p_style_a, const ::XIMSt
DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
KeyMappingX11::initialize();
+ native_menu = memnew(NativeMenu);
+
#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
@@ -6357,6 +6347,11 @@ DisplayServerX11::~DisplayServerX11() {
events_thread_done.set();
events_thread.wait_to_finish();
+ if (native_menu) {
+ memdelete(native_menu);
+ native_menu = nullptr;
+ }
+
//destroy all windows
for (KeyValue<WindowID, WindowData> &E : windows) {
#if defined(RD_ENABLED)
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index a5cbe34d26..8a7062857c 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -156,6 +156,7 @@ class DisplayServerX11 : public DisplayServer {
#ifdef SPEECHD_ENABLED
TTS_Linux *tts = nullptr;
#endif
+ NativeMenu *native_menu = nullptr;
#if defined(DBUS_ENABLED)
FreeDesktopPortalDesktop *portal_desktop = nullptr;
@@ -525,7 +526,6 @@ public:
virtual void process_events() override;
virtual void release_rendering_thread() override;
- virtual void make_rendering_thread() override;
virtual void swap_buffers() override;
virtual void set_context(Context p_context) override;
diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index 602dd784e0..febb7ae584 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -311,20 +311,6 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) {
_internal_set_current_window(&win);
}
-void GLManager_X11::make_current() {
- if (!_current_window) {
- return;
- }
- if (!_current_window->in_use) {
- WARN_PRINT("current window not in use!");
- return;
- }
- const GLDisplay &disp = get_current_display();
- if (!glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context)) {
- ERR_PRINT("glXMakeCurrent failed");
- }
-}
-
void GLManager_X11::swap_buffers() {
if (!_current_window) {
return;
diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h
index 235c7d22f9..06e147e39f 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.h
+++ b/platform/linuxbsd/x11/gl_manager_x11.h
@@ -117,7 +117,6 @@ public:
void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
void release_current();
- void make_current();
void swap_buffers();
void window_make_current(DisplayServer::WindowID p_window_id);