summaryrefslogtreecommitdiff
path: root/platform/linuxbsd
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/SCsub10
-rw-r--r--platform/linuxbsd/crash_handler_linuxbsd.cpp2
-rw-r--r--platform/linuxbsd/detect.py60
-rw-r--r--platform/linuxbsd/export/export_plugin.cpp4
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.cpp2
-rw-r--r--platform/linuxbsd/godot_linuxbsd.cpp1
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp292
-rw-r--r--platform/linuxbsd/os_linuxbsd.h11
-rw-r--r--platform/linuxbsd/platform_config.h2
-rw-r--r--platform/linuxbsd/x11/SCsub21
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.cpp (renamed from platform/linuxbsd/detect_prime_x11.cpp)28
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.h (renamed from platform/linuxbsd/detect_prime_x11.h)8
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp (renamed from platform/linuxbsd/display_server_x11.cpp)139
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h (renamed from platform/linuxbsd/display_server_x11.h)16
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp (renamed from platform/linuxbsd/gl_manager_x11.cpp)65
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.h (renamed from platform/linuxbsd/gl_manager_x11.h)2
-rw-r--r--platform/linuxbsd/x11/key_mapping_x11.cpp (renamed from platform/linuxbsd/key_mapping_x11.cpp)26
-rw-r--r--platform/linuxbsd/x11/key_mapping_x11.h (renamed from platform/linuxbsd/key_mapping_x11.h)0
-rw-r--r--platform/linuxbsd/x11/vulkan_context_x11.cpp (renamed from platform/linuxbsd/vulkan_context_x11.cpp)4
-rw-r--r--platform/linuxbsd/x11/vulkan_context_x11.h (renamed from platform/linuxbsd/vulkan_context_x11.h)4
20 files changed, 524 insertions, 173 deletions
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index 91d45627b9..fcd739cdc9 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -14,15 +14,7 @@ common_linuxbsd = [
]
if env["x11"]:
- common_linuxbsd += [
- "gl_manager_x11.cpp",
- "detect_prime_x11.cpp",
- "display_server_x11.cpp",
- "key_mapping_x11.cpp",
- ]
-
- if env["vulkan"]:
- common_linuxbsd.append("vulkan_context_x11.cpp")
+ common_linuxbsd += SConscript("x11/SCsub")
if env["speechd"]:
common_linuxbsd.append(["speechd-so_wrap.c", "tts_linux.cpp"])
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp
index 33da094860..8c8c8588b8 100644
--- a/platform/linuxbsd/crash_handler_linuxbsd.cpp
+++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp
@@ -89,7 +89,7 @@ static void handle_crash(int sig) {
// Try to demangle the function name to provide a more readable one
if (dladdr(bt_buffer[i], &info) && info.dli_sname) {
if (info.dli_sname[0] == '_') {
- int status;
+ int status = 0;
char *demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
if (status == 0 && demangled) {
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index f5f7e65417..004bcb8674 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -4,6 +4,11 @@ import sys
from methods import get_compiler_version, using_gcc
from platform_methods import detect_arch
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from SCons import Environment
+
def is_active():
return True
@@ -31,7 +36,6 @@ def get_opts():
return [
EnumVariable("linker", "Linker program", "default", ("default", "bfd", "gold", "lld", "mold")),
BoolVariable("use_llvm", "Use the LLVM compiler", False),
- BoolVariable("use_thinlto", "Use ThinLTO (LLVM only, requires linker=lld, implies use_lto=yes)", False),
BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True),
BoolVariable("use_coverage", "Test Godot coverage", False),
BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False),
@@ -45,8 +49,6 @@ def get_opts():
BoolVariable("fontconfig", "Detect and use fontconfig for system fonts support", True),
BoolVariable("udev", "Use udev for gamepad connection callbacks", True),
BoolVariable("x11", "Enable X11 display", True),
- BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
- BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
BoolVariable("touch", "Enable touch events", True),
BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", False),
]
@@ -58,7 +60,7 @@ def get_flags():
]
-def configure(env):
+def configure(env: "Environment"):
# Validate arch.
supported_arches = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64"]
if env["arch"] not in supported_arches:
@@ -70,26 +72,9 @@ def configure(env):
## Build type
- if env["target"] == "release":
- if env["optimize"] == "speed": # optimize for speed (default)
- env.Prepend(CCFLAGS=["-O3"])
- elif env["optimize"] == "size": # optimize for size
- env.Prepend(CCFLAGS=["-Os"])
-
- if env["debug_symbols"]:
- env.Prepend(CCFLAGS=["-g2"])
-
- elif env["target"] == "release_debug":
- if env["optimize"] == "speed": # optimize for speed (default)
- env.Prepend(CCFLAGS=["-O2"])
- elif env["optimize"] == "size": # optimize for size
- env.Prepend(CCFLAGS=["-Os"])
-
- if env["debug_symbols"]:
- env.Prepend(CCFLAGS=["-g2"])
-
- elif env["target"] == "debug":
- env.Prepend(CCFLAGS=["-g3"])
+ if env.dev_build:
+ # This is needed for our crash handler to work properly.
+ # gdb works fine without it though, so maybe our crash handler could too.
env.Append(LINKFLAGS=["-rdynamic"])
# CPU architecture flags.
@@ -129,13 +114,6 @@ def configure(env):
else:
env.Append(LINKFLAGS=["-fuse-ld=%s" % env["linker"]])
- if env["use_thinlto"]:
- if not env["use_llvm"] or env["linker"] != "lld":
- print("ThinLTO is only compatible with LLVM and the LLD linker, use `use_llvm=yes linker=lld`.")
- sys.exit(255)
- else:
- env["use_lto"] = True # ThinLTO implies LTO
-
if env["use_coverage"]:
env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
env.Append(LINKFLAGS=["-ftest-coverage", "-fprofile-arcs"])
@@ -178,8 +156,16 @@ def configure(env):
env.Append(CCFLAGS=["-fsanitize-recover=memory"])
env.Append(LINKFLAGS=["-fsanitize=memory"])
- if env["use_lto"]:
- if env["use_thinlto"]:
+ # LTO
+
+ if env["lto"] == "auto": # Full LTO for production.
+ env["lto"] = "full"
+
+ 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`.")
+ sys.exit(255)
env.Append(CCFLAGS=["-flto=thin"])
env.Append(LINKFLAGS=["-flto=thin"])
elif not env["use_llvm"] and env.GetOption("num_jobs") > 1:
@@ -370,20 +356,22 @@ def configure(env):
if env["opengl3"]:
env.Append(CPPDEFINES=["GLES3_ENABLED"])
- env.ParseConfig("pkg-config gl --cflags --libs")
env.Append(LIBS=["pthread"])
if platform.system() == "Linux":
env.Append(LIBS=["dl"])
- if platform.system().find("BSD") >= 0:
+ if not env["execinfo"] and 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 env["execinfo"]:
env.Append(LIBS=["execinfo"])
- if not env["tools"]:
+ if not env.editor_build:
import subprocess
import re
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp
index 4d45d3ba12..8277bb1505 100644
--- a/platform/linuxbsd/export/export_plugin.cpp
+++ b/platform/linuxbsd/export/export_plugin.cpp
@@ -56,8 +56,8 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset>
}
String app_name;
- if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
- app_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
+ if (String(GLOBAL_GET("application/config/name")) != "") {
+ app_name = String(GLOBAL_GET("application/config/name"));
} else {
app_name = "Unnamed";
}
diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp
index fa3f7fbfea..88ec37c456 100644
--- a/platform/linuxbsd/freedesktop_screensaver.cpp
+++ b/platform/linuxbsd/freedesktop_screensaver.cpp
@@ -55,7 +55,7 @@ void FreeDesktopScreenSaver::inhibit() {
return;
}
- String app_name_string = ProjectSettings::get_singleton()->get("application/config/name");
+ String app_name_string = GLOBAL_GET("application/config/name");
CharString app_name_utf8 = app_name_string.utf8();
const char *app_name = app_name_string.is_empty() ? "Godot Engine" : app_name_utf8.get_data();
diff --git a/platform/linuxbsd/godot_linuxbsd.cpp b/platform/linuxbsd/godot_linuxbsd.cpp
index 91a260182e..fa5e20891c 100644
--- a/platform/linuxbsd/godot_linuxbsd.cpp
+++ b/platform/linuxbsd/godot_linuxbsd.cpp
@@ -69,6 +69,7 @@ int main(int argc, char *argv[]) {
}
if (Main::start()) {
+ os.set_exit_code(EXIT_SUCCESS);
os.run(); // it is actually the OS that decides how to run
}
Main::cleanup();
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 61faf3061c..e14e4fb52d 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -34,22 +34,26 @@
#include "main/main.h"
#include "servers/display_server.h"
+#include "modules/modules_enabled.gen.h" // For regex.
+#ifdef MODULE_REGEX_ENABLED
+#include "modules/regex/regex.h"
+#endif
+
#ifdef X11_ENABLED
-#include "display_server_x11.h"
+#include "x11/display_server_x11.h"
#endif
#ifdef HAVE_MNTENT
#include <mntent.h>
#endif
+#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#include <dlfcn.h>
-#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <unistd.h>
#ifdef FONTCONFIG_ENABLED
@@ -124,6 +128,8 @@ void OS_LinuxBSD::initialize() {
crash_handler.initialize();
OS_Unix::initialize_core();
+
+ system_dir_desktop_cache = get_system_dir(SYSTEM_DIR_DESKTOP);
}
void OS_LinuxBSD::initialize_joypads() {
@@ -205,6 +211,240 @@ String OS_LinuxBSD::get_name() const {
#endif
}
+String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const {
+ static String info;
+ if (info.is_empty()) {
+ Ref<FileAccess> f = FileAccess::open("/etc/os-release", FileAccess::READ);
+ if (f.is_valid()) {
+ while (!f->eof_reached()) {
+ const String line = f->get_line();
+ if (line.find(key) != -1) {
+ return line.split("=")[1].strip_edges();
+ }
+ }
+ }
+ }
+ return info;
+}
+
+String OS_LinuxBSD::get_distribution_name() const {
+ static String systemd_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string.
+ if (!systemd_name.is_empty()) {
+ return systemd_name;
+ }
+ struct utsname uts; // returns a decent value for BSD family.
+ uname(&uts);
+ return uts.sysname;
+}
+
+String OS_LinuxBSD::get_version() const {
+ static String systemd_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string.
+ if (!systemd_version.is_empty()) {
+ return systemd_version;
+ }
+ struct utsname uts; // returns a decent value for BSD family.
+ uname(&uts);
+ return uts.version;
+}
+
+Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const {
+ if (RenderingServer::get_singleton()->get_rendering_device() == nullptr) {
+ return Vector<String>();
+ }
+
+ const String rendering_device_name = RenderingServer::get_singleton()->get_rendering_device()->get_device_name(); // e.g. `NVIDIA GeForce GTX 970`
+ const String rendering_device_vendor = RenderingServer::get_singleton()->get_rendering_device()->get_device_vendor_name(); // e.g. `NVIDIA`
+ const String card_name = rendering_device_name.trim_prefix(rendering_device_vendor).strip_edges(); // -> `GeForce GTX 970`
+
+ String vendor_device_id_mappings;
+ List<String> lspci_args;
+ lspci_args.push_back("-n");
+ Error err = const_cast<OS_LinuxBSD *>(this)->execute("lspci", lspci_args, &vendor_device_id_mappings);
+ if (err != OK || vendor_device_id_mappings.is_empty()) {
+ return Vector<String>();
+ }
+
+ // Usually found under "VGA", but for example NVIDIA mobile/laptop adapters are often listed under "3D" and some AMD adapters are under "Display".
+ const String dc_vga = "0300"; // VGA compatible controller
+ const String dc_display = "0302"; // Display controller
+ const String dc_3d = "0380"; // 3D controller
+
+ // splitting results by device class allows prioritizing, if multiple devices are found.
+ Vector<String> class_vga_device_candidates;
+ Vector<String> class_display_device_candidates;
+ Vector<String> class_3d_device_candidates;
+
+#ifdef MODULE_REGEX_ENABLED
+ RegEx regex_id_format = RegEx();
+ regex_id_format.compile("^[a-f0-9]{4}:[a-f0-9]{4}$"); // e.g. `10de:13c2`; IDs are always in hexadecimal
+#endif
+
+ Vector<String> value_lines = vendor_device_id_mappings.split("\n", false); // example: `02:00.0 0300: 10de:13c2 (rev a1)`
+ for (const String &line : value_lines) {
+ Vector<String> columns = line.split(" ", false);
+ if (columns.size() < 3) {
+ continue;
+ }
+ String device_class = columns[1].trim_suffix(":");
+ String vendor_device_id_mapping = columns[2];
+
+#ifdef MODULE_REGEX_ENABLED
+ if (regex_id_format.search(vendor_device_id_mapping).is_null()) {
+ continue;
+ }
+#endif
+
+ if (device_class == dc_vga) {
+ class_vga_device_candidates.push_back(vendor_device_id_mapping);
+ } else if (device_class == dc_display) {
+ class_display_device_candidates.push_back(vendor_device_id_mapping);
+ } else if (device_class == dc_3d) {
+ class_3d_device_candidates.push_back(vendor_device_id_mapping);
+ }
+ }
+
+ // Check results against currently used device (`card_name`), in case the user has multiple graphics cards.
+ const String device_lit = "Device"; // line of interest
+ class_vga_device_candidates = OS_LinuxBSD::lspci_device_filter(class_vga_device_candidates, dc_vga, device_lit, card_name);
+ class_display_device_candidates = OS_LinuxBSD::lspci_device_filter(class_display_device_candidates, dc_display, device_lit, card_name);
+ class_3d_device_candidates = OS_LinuxBSD::lspci_device_filter(class_3d_device_candidates, dc_3d, device_lit, card_name);
+
+ // Get driver names and filter out invalid ones, because some adapters are dummys used only for passthrough.
+ // And they have no indicator besides certain driver names.
+ const String kernel_lit = "Kernel driver in use"; // line of interest
+ const String dummys = "vfio"; // for e.g. pci passthrough dummy kernel driver `vfio-pci`
+ Vector<String> class_vga_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_vga_device_candidates, kernel_lit, dummys);
+ Vector<String> class_display_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_display_device_candidates, kernel_lit, dummys);
+ Vector<String> class_3d_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_3d_device_candidates, kernel_lit, dummys);
+
+ static String driver_name;
+ static String driver_version;
+
+ // Use first valid value:
+ for (const String &driver : class_3d_device_drivers) {
+ driver_name = driver;
+ break;
+ }
+ if (driver_name.is_empty()) {
+ for (const String &driver : class_display_device_drivers) {
+ driver_name = driver;
+ break;
+ }
+ }
+ if (driver_name.is_empty()) {
+ for (const String &driver : class_vga_device_drivers) {
+ driver_name = driver;
+ break;
+ }
+ }
+
+ Vector<String> info;
+ info.push_back(driver_name);
+
+ String modinfo;
+ List<String> modinfo_args;
+ modinfo_args.push_back(driver_name);
+ err = const_cast<OS_LinuxBSD *>(this)->execute("modinfo", modinfo_args, &modinfo);
+ if (err != OK || modinfo.is_empty()) {
+ info.push_back(""); // So that this method always either returns an empty array, or an array of length 2.
+ return info;
+ }
+ Vector<String> lines = modinfo.split("\n", false);
+ for (const String &line : lines) {
+ Vector<String> columns = line.split(":", false, 1);
+ if (columns.size() < 2) {
+ continue;
+ }
+ if (columns[0].strip_edges() == "version") {
+ driver_version = columns[1].strip_edges(); // example value: `510.85.02` on Linux/BSD
+ break;
+ }
+ }
+
+ info.push_back(driver_version);
+
+ return info;
+}
+
+Vector<String> OS_LinuxBSD::lspci_device_filter(Vector<String> vendor_device_id_mapping, String class_suffix, String check_column, String whitelist) const {
+ // NOTE: whitelist can be changed to `Vector<String>`, if the need arises.
+ const String sep = ":";
+ Vector<String> devices;
+ for (const String &mapping : vendor_device_id_mapping) {
+ String device;
+ List<String> d_args;
+ d_args.push_back("-d");
+ d_args.push_back(mapping + sep + class_suffix);
+ d_args.push_back("-vmm");
+ Error err = const_cast<OS_LinuxBSD *>(this)->execute("lspci", d_args, &device); // e.g. `lspci -d 10de:13c2:0300 -vmm`
+ if (err != OK) {
+ return Vector<String>();
+ } else if (device.is_empty()) {
+ continue;
+ }
+
+ Vector<String> device_lines = device.split("\n", false);
+ for (const String &line : device_lines) {
+ Vector<String> columns = line.split(":", false, 1);
+ if (columns.size() < 2) {
+ continue;
+ }
+ if (columns[0].strip_edges() == check_column) {
+ // for `column[0] == "Device"` this may contain `GM204 [GeForce GTX 970]`
+ bool is_valid = true;
+ if (!whitelist.is_empty()) {
+ is_valid = columns[1].strip_edges().contains(whitelist);
+ }
+ if (is_valid) {
+ devices.push_back(mapping);
+ }
+ break;
+ }
+ }
+ }
+ return devices;
+}
+
+Vector<String> OS_LinuxBSD::lspci_get_device_value(Vector<String> vendor_device_id_mapping, String check_column, String blacklist) const {
+ // NOTE: blacklist can be changed to `Vector<String>`, if the need arises.
+ const String sep = ":";
+ Vector<String> values;
+ for (const String &mapping : vendor_device_id_mapping) {
+ String device;
+ List<String> d_args;
+ d_args.push_back("-d");
+ d_args.push_back(mapping);
+ d_args.push_back("-k");
+ Error err = const_cast<OS_LinuxBSD *>(this)->execute("lspci", d_args, &device); // e.g. `lspci -d 10de:13c2 -k`
+ if (err != OK) {
+ return Vector<String>();
+ } else if (device.is_empty()) {
+ continue;
+ }
+
+ Vector<String> device_lines = device.split("\n", false);
+ for (const String &line : device_lines) {
+ Vector<String> columns = line.split(":", false, 1);
+ if (columns.size() < 2) {
+ continue;
+ }
+ if (columns[0].strip_edges() == check_column) {
+ // for `column[0] == "Kernel driver in use"` this may contain `nvidia`
+ bool is_valid = true;
+ const String value = columns[1].strip_edges();
+ if (!blacklist.is_empty()) {
+ is_valid = !value.contains(blacklist);
+ }
+ if (is_valid) {
+ values.push_back(value);
+ }
+ break;
+ }
+ }
+ }
+ return values;
+}
+
Error OS_LinuxBSD::shell_open(String p_uri) {
Error ok;
int err_code;
@@ -243,7 +483,16 @@ Error OS_LinuxBSD::shell_open(String p_uri) {
}
bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
- return p_feature == "pc";
+#ifdef FONTCONFIG_ENABLED
+ if (p_feature == "system_fonts") {
+ return font_config_initialized;
+ }
+#endif
+ if (p_feature == "pc") {
+ return true;
+ }
+
+ return false;
}
uint64_t OS_LinuxBSD::get_embedded_pck_offset() const {
@@ -385,6 +634,8 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold,
ERR_FAIL_V_MSG(String(), "Unable to load fontconfig, system font support is disabled.");
}
+ bool allow_substitutes = (p_font_name.to_lower() == "sans-serif") || (p_font_name.to_lower() == "serif") || (p_font_name.to_lower() == "monospace") || (p_font_name.to_lower() == "cursive") || (p_font_name.to_lower() == "fantasy");
+
String ret;
FcConfig *config = FcInitLoadConfigAndFonts();
@@ -406,6 +657,19 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, bool p_bold,
FcResult result;
FcPattern *match = FcFontMatch(0, pattern, &result);
if (match) {
+ if (!allow_substitutes) {
+ char *family_name = nullptr;
+ if (FcPatternGetString(match, FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
+ if (family_name && String::utf8(family_name).to_lower() != p_font_name.to_lower()) {
+ FcPatternDestroy(match);
+ FcPatternDestroy(pattern);
+ FcObjectSetDestroy(object_set);
+ FcConfigDestroy(config);
+
+ return String();
+ }
+ }
+ }
char *file_name = nullptr;
if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
if (file_name) {
@@ -472,6 +736,10 @@ String OS_LinuxBSD::get_cache_path() const {
}
String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
+ if (p_dir == SYSTEM_DIR_DESKTOP && !system_dir_desktop_cache.is_empty()) {
+ return system_dir_desktop_cache;
+ }
+
String xdgparam;
switch (p_dir) {
@@ -480,31 +748,24 @@ String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const
} break;
case SYSTEM_DIR_DCIM: {
xdgparam = "PICTURES";
-
} break;
case SYSTEM_DIR_DOCUMENTS: {
xdgparam = "DOCUMENTS";
-
} break;
case SYSTEM_DIR_DOWNLOADS: {
xdgparam = "DOWNLOAD";
-
} break;
case SYSTEM_DIR_MOVIES: {
xdgparam = "VIDEOS";
-
} break;
case SYSTEM_DIR_MUSIC: {
xdgparam = "MUSIC";
-
} break;
case SYSTEM_DIR_PICTURES: {
xdgparam = "PICTURES";
-
} break;
case SYSTEM_DIR_RINGTONES: {
xdgparam = "MUSIC";
-
} break;
}
@@ -686,10 +947,9 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
String renamed_path = path.get_base_dir() + "/" + file_name;
// Generates the .trashinfo file
- OS::Date date = OS::get_singleton()->get_date(false);
- OS::Time time = OS::get_singleton()->get_time(false);
- String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.minute);
- timestamp = vformat("%s%02d", timestamp, time.second); // vformat only supports up to 6 arguments.
+ OS::DateTime dt = OS::get_singleton()->get_datetime(false);
+ String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", dt.year, (int)dt.month, dt.day, dt.hour, dt.minute);
+ timestamp = vformat("%s%02d", timestamp, dt.second); // vformat only supports up to 6 arguments.
String trash_info = "[Trash Info]\nPath=" + path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index d5b2321316..aa7af92aa1 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -67,6 +67,13 @@ class OS_LinuxBSD : public OS_Unix {
MainLoop *main_loop = nullptr;
+ String get_systemd_os_release_info_value(const String &key) const;
+
+ Vector<String> lspci_device_filter(Vector<String> vendor_device_id_mapping, String class_suffix, String check_column, String whitelist) const;
+ Vector<String> lspci_get_device_value(Vector<String> vendor_device_id_mapping, String check_column, String blacklist) const;
+
+ String system_dir_desktop_cache;
+
protected:
virtual void initialize() override;
virtual void finalize() override;
@@ -77,6 +84,10 @@ protected:
public:
virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
+
+ virtual Vector<String> get_video_adapter_driver_info() const override;
virtual MainLoop *get_main_loop() const override;
diff --git a/platform/linuxbsd/platform_config.h b/platform/linuxbsd/platform_config.h
index 3c05c67444..79e15e2512 100644
--- a/platform/linuxbsd/platform_config.h
+++ b/platform/linuxbsd/platform_config.h
@@ -44,4 +44,4 @@
#endif
#endif
-#define OPENGL_INCLUDE_H "thirdparty/glad/glad/glad.h"
+#define OPENGL_INCLUDE_H "thirdparty/glad/glad/gl.h"
diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub
new file mode 100644
index 0000000000..30c6080355
--- /dev/null
+++ b/platform/linuxbsd/x11/SCsub
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+Import("env")
+
+source_files = [
+ "display_server_x11.cpp",
+ "key_mapping_x11.cpp",
+]
+
+if env["vulkan"]:
+ source_files.append("vulkan_context_x11.cpp")
+
+if env["opengl3"]:
+ source_files.append(["gl_manager_x11.cpp", "detect_prime_x11.cpp", "#thirdparty/glad/glx.c"])
+
+objects = []
+
+for source_file in source_files:
+ objects.append(env.Object(source_file))
+
+Return("objects")
diff --git a/platform/linuxbsd/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp
index fb833ab5e6..ed046432d8 100644
--- a/platform/linuxbsd/detect_prime_x11.cpp
+++ b/platform/linuxbsd/x11/detect_prime_x11.cpp
@@ -38,8 +38,9 @@
#include <stdlib.h>
-#include <GL/gl.h>
-#include <GL/glx.h>
+#include "thirdparty/glad/glad/gl.h"
+#include "thirdparty/glad/glad/glx.h"
+
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -77,8 +78,6 @@ void create_context() {
Window x11_window;
GLXContext glx_context;
- GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte *)"glXCreateContextAttribsARB");
-
static int visual_attribs[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
@@ -101,7 +100,7 @@ void create_context() {
GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
if (!fbc) {
- exit(1);
+ quick_exit(1);
}
vi = glXGetVisualFromFBConfig(x11_display, fbc[0]);
@@ -122,7 +121,7 @@ void create_context() {
x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, 10, 10, 0, vi->depth, InputOutput, vi->visual, valuemask, &swa);
if (!x11_window) {
- exit(1);
+ quick_exit(1);
}
glXMakeCurrent(x11_display, x11_window, glx_context);
@@ -189,8 +188,20 @@ int detect_prime() {
if (i) {
setenv("DRI_PRIME", "1", 1);
}
+
+ if (gladLoaderLoadGLX(NULL, 0) == 0) {
+ print_verbose("Unable to load GLX, GPU detection skipped.");
+ quick_exit(1);
+ }
+
create_context();
+ PFNGLGETSTRINGPROC glGetString = (PFNGLGETSTRINGPROC)glXGetProcAddressARB((GLubyte *)"glGetString");
+ if (!glGetString) {
+ print_verbose("Unable to get glGetString, GPU detection skipped.");
+ quick_exit(1);
+ }
+
const char *vendor = (const char *)glGetString(GL_VENDOR);
const char *renderer = (const char *)glGetString(GL_RENDERER);
@@ -208,7 +219,10 @@ int detect_prime() {
print_verbose("Couldn't write vendor/renderer string.");
}
close(fdset[1]);
- exit(0);
+
+ // The function quick_exit() is used because exit() will call destructors on static objects copied by fork().
+ // These objects will be freed anyway when the process finishes execution.
+ quick_exit(0);
}
}
diff --git a/platform/linuxbsd/detect_prime_x11.h b/platform/linuxbsd/x11/detect_prime_x11.h
index 21ebaead32..7eb7064cc5 100644
--- a/platform/linuxbsd/detect_prime_x11.h
+++ b/platform/linuxbsd/x11/detect_prime_x11.h
@@ -28,11 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef X11_ENABLED
-#if defined(GLES3_ENABLED)
+#ifndef DETECT_PRIME_X11_H
+#define DETECT_PRIME_X11_H
+
+#if defined(X11_ENABLED) && defined(GLES3_ENABLED)
int detect_prime();
-#endif
+#endif // X11_ENABLED && GLES3_ENABLED
#endif // DETECT_PRIME_X11_H
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index c619e8eceb..b86bc10643 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -49,10 +49,14 @@
#include "drivers/gles3/rasterizer_gles3.h"
#endif
+#include <dlfcn.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
@@ -66,17 +70,6 @@
#define _NET_WM_STATE_REMOVE 0L // remove/unset property
#define _NET_WM_STATE_ADD 1L // add/set property
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-//stupid linux.h
-#ifdef KEY_TAB
-#undef KEY_TAB
-#endif
-
#undef CursorShape
#include <X11/XKBlib.h>
@@ -133,7 +126,7 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
case FEATURE_WINDOW_TRANSPARENCY:
//case FEATURE_HIDPI:
case FEATURE_ICON:
- case FEATURE_NATIVE_ICON:
+ //case FEATURE_NATIVE_ICON:
case FEATURE_SWAP_BUFFERS:
#ifdef DBUS_ENABLED
case FEATURE_KEEP_SCREEN_ON:
@@ -383,10 +376,18 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
}
// The only modes that show a cursor are VISIBLE and CONFINED
- bool showCursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED);
+ bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED);
+ bool previously_shown = (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED);
+
+ if (show_cursor && !previously_shown) {
+ WindowID window_id = get_window_at_screen_position(mouse_get_position());
+ if (window_id != INVALID_WINDOW_ID) {
+ _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER);
+ }
+ }
for (const KeyValue<WindowID, WindowData> &E : windows) {
- if (showCursor) {
+ if (show_cursor) {
XDefineCursor(x11_display, E.value.x11_window, cursors[current_cursor]); // show cursor
} else {
XDefineCursor(x11_display, E.value.x11_window, null_cursor); // hide cursor
@@ -397,7 +398,10 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
//flush pending motion events
_flush_mouse_motion();
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
WindowData &window = windows[window_id];
if (XGrabPointer(
@@ -433,7 +437,11 @@ void DisplayServerX11::warp_mouse(const Point2i &p_position) {
if (mouse_mode == MOUSE_MODE_CAPTURED) {
last_mouse_pos = p_position;
} else {
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
+
XWarpPointer(x11_display, None, windows[window_id].x11_window,
0, 0, 0, 0, (int)p_position.x, (int)p_position.y);
}
@@ -1015,7 +1023,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
Rect2i left_rect(pos.x, pos.y + left_start_y, left, left_end_y - left_start_y);
if (left_rect.size.x > 0) {
Rect2i intersection = rect.intersection(left_rect);
- if (!intersection.has_no_area() && intersection.size.x < rect.size.x) {
+ if (intersection.has_area() && intersection.size.x < rect.size.x) {
rect.position.x = left_rect.size.x;
rect.size.x = rect.size.x - intersection.size.x;
}
@@ -1024,7 +1032,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
Rect2i right_rect(pos.x + size.x - right, pos.y + right_start_y, right, right_end_y - right_start_y);
if (right_rect.size.x > 0) {
Rect2i intersection = rect.intersection(right_rect);
- if (!intersection.has_no_area() && right_rect.size.x < rect.size.x) {
+ if (intersection.has_area() && right_rect.size.x < rect.size.x) {
rect.size.x = intersection.position.x - rect.position.x;
}
}
@@ -1032,7 +1040,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
Rect2i top_rect(pos.x + top_start_x, pos.y, top_end_x - top_start_x, top);
if (top_rect.size.y > 0) {
Rect2i intersection = rect.intersection(top_rect);
- if (!intersection.has_no_area() && intersection.size.y < rect.size.y) {
+ if (intersection.has_area() && intersection.size.y < rect.size.y) {
rect.position.y = top_rect.size.y;
rect.size.y = rect.size.y - intersection.size.y;
}
@@ -1041,7 +1049,7 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
Rect2i bottom_rect(pos.x + bottom_start_x, pos.y + size.y - bottom, bottom_end_x - bottom_start_x, bottom);
if (bottom_rect.size.y > 0) {
Rect2i intersection = rect.intersection(bottom_rect);
- if (!intersection.has_no_area() && right_rect.size.y < rect.size.y) {
+ if (intersection.has_area() && right_rect.size.y < rect.size.y) {
rect.size.y = intersection.position.y - rect.position.y;
}
}
@@ -1202,16 +1210,6 @@ float DisplayServerX11::screen_get_refresh_rate(int p_screen) const {
return SCREEN_REFRESH_RATE_FALLBACK;
}
-bool DisplayServerX11::screen_is_touchscreen(int p_screen) const {
- _THREAD_SAFE_METHOD_
-
-#ifndef _MSC_VER
-#warning Need to get from proper window
-#endif
-
- return DisplayServer::screen_is_touchscreen(p_screen);
-}
-
#ifdef DBUS_ENABLED
void DisplayServerX11::screen_set_keep_on(bool p_enable) {
if (screen_is_kept_on() == p_enable) {
@@ -1319,6 +1317,14 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win
case WINDOW_VIEW: {
return 0; // Not supported.
}
+#ifdef GLES3_ENABLED
+ case OPENGL_CONTEXT: {
+ if (gl_manager) {
+ return (int64_t)gl_manager->get_glx_context(p_window);
+ }
+ return 0;
+ }
+#endif
default: {
return 0;
}
@@ -1739,6 +1745,18 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
usleep(10000);
}
+
+ // Keep rendering context window size in sync
+#if defined(VULKAN_ENABLED)
+ if (context_vulkan) {
+ context_vulkan->window_resize(p_window, xwa.width, xwa.height);
+ }
+#endif
+#if defined(GLES3_ENABLED)
+ if (gl_manager) {
+ gl_manager->window_resize(p_window, xwa.width, xwa.height);
+ }
+#endif
}
Size2i DisplayServerX11::window_get_size(WindowID p_window) const {
@@ -3135,9 +3153,14 @@ void DisplayServerX11::_window_changed(XEvent *event) {
return;
}
+ // Query display server about a possible new window state.
+ wd.fullscreen = _window_fullscreen_check(window_id);
+ wd.minimized = _window_minimize_check(window_id);
+ wd.maximized = _window_maximize_check(window_id, "_NET_WM_STATE");
+
{
//the position in xconfigure is not useful here, obtain it manually
- int x, y;
+ int x = 0, y = 0;
Window child;
XTranslateCoordinates(x11_display, wd.x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child);
new_rect.position.x = x;
@@ -3181,6 +3204,15 @@ void DisplayServerX11::_window_changed(XEvent *event) {
}
}
+DisplayServer::WindowID DisplayServerX11::_get_focused_window_or_popup() const {
+ const List<WindowID>::Element *E = popup_list.back();
+ if (E) {
+ return E->get();
+ }
+
+ return last_focused_window;
+}
+
void DisplayServerX11::_dispatch_input_events(const Ref<InputEvent> &p_event) {
static_cast<DisplayServerX11 *>(get_singleton())->_dispatch_input_event(p_event);
}
@@ -3291,7 +3323,7 @@ void DisplayServerX11::_check_pending_events(LocalVector<XEvent> &r_events) {
XFlush(x11_display);
// Non-blocking wait for next event and remove it from the queue.
- XEvent ev;
+ XEvent ev = {};
while (XCheckIfEvent(x11_display, &ev, _predicate_all_events, nullptr)) {
// Check if the input manager wants to process the event.
if (XFilterEvent(&ev, None)) {
@@ -3398,7 +3430,7 @@ bool DisplayServerX11::mouse_process_popups() {
XWindowAttributes root_attrs;
XGetWindowAttributes(x11_display, root, &root_attrs);
Vector2i pos = Vector2i(root_attrs.x + root_x, root_attrs.y + root_y);
- if ((pos != last_mouse_monitor_pos) || (mask != last_mouse_monitor_mask)) {
+ if (mask != last_mouse_monitor_mask) {
if (((mask & Button1Mask) || (mask & Button2Mask) || (mask & Button3Mask) || (mask & Button4Mask) || (mask & Button5Mask))) {
List<WindowID>::Element *C = nullptr;
List<WindowID>::Element *E = popup_list.back();
@@ -3424,7 +3456,6 @@ bool DisplayServerX11::mouse_process_popups() {
}
}
last_mouse_monitor_mask = mask;
- last_mouse_monitor_pos = pos;
}
}
return closed;
@@ -3936,7 +3967,11 @@ void DisplayServerX11::process_events() {
// The X11 API requires filtering one-by-one through the motion
// notify events, in order to figure out which event is the one
// generated by warping the mouse pointer.
- WindowID focused_window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID focused_window_id = _get_focused_window_or_popup();
+ if (!windows.has(focused_window_id)) {
+ focused_window_id = MAIN_WINDOW_ID;
+ }
+
while (true) {
if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[focused_window_id].size.width / 2 && event.xmotion.y == windows[focused_window_id].size.height / 2) {
//this is likely the warp event since it was warped here
@@ -4093,10 +4128,10 @@ void DisplayServerX11::process_events() {
if (event.xselection.target == requested) {
Property p = _read_property(x11_display, windows[window_id].x11_window, XInternAtom(x11_display, "PRIMARY", 0));
- Vector<String> files = String((char *)p.data).split("\n", false);
+ Vector<String> files = String((char *)p.data).split("\r\n", false);
XFree(p.data);
for (int i = 0; i < files.size(); i++) {
- files.write[i] = files[i].replace("file://", "").uri_decode().strip_edges();
+ files.write[i] = files[i].replace("file://", "").uri_decode();
}
if (!windows[window_id].drop_files_callback.is_null()) {
@@ -4412,13 +4447,24 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
return drivers;
}
-DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
+DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
if (r_error != OK) {
- OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan or OpenGL versions.\n"
- "Please update your drivers or if you have a very old or integrated GPU, upgrade it.\n"
- "If you have updated your graphics drivers recently, try rebooting.",
- "Unable to initialize Video driver");
+ if (p_rendering_driver == "vulkan") {
+ String executable_name = OS::get_singleton()->get_executable_path().get_file();
+ OS::get_singleton()->alert("Your video card driver does not support the selected Vulkan version.\n"
+ "Please try updating your GPU driver or try using the OpenGL 3 driver.\n"
+ "You can enable the OpenGL 3 driver by starting the engine from the\n"
+ "command line with the command:\n'./" +
+ executable_name + " --rendering-driver opengl3'.\n "
+ "If you have updated your graphics drivers recently, try rebooting.",
+ "Unable to initialize Video driver");
+ } else {
+ OS::get_singleton()->alert("Your video card driver does not support the selected OpenGL version.\n"
+ "Please try updating your GPU driver.\n"
+ "If you have updated your graphics drivers recently, try rebooting.",
+ "Unable to initialize Video driver");
+ }
}
return ds;
}
@@ -4662,7 +4708,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
return id;
}
-DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+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, Error &r_error) {
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
@@ -4889,6 +4935,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
Point2i window_position(
(screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2);
+
+ if (p_position != nullptr) {
+ window_position = *p_position;
+ }
+
WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution));
if (main_window == INVALID_WINDOW_ID) {
r_error = ERR_CANT_CREATE;
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index ea03b2328c..4be8c3a534 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -47,7 +47,7 @@
#include "servers/rendering_server.h"
#if defined(SPEECHD_ENABLED)
-#include "tts_linux.h"
+#include "../tts_linux.h"
#endif
#if defined(GLES3_ENABLED)
@@ -56,12 +56,12 @@
#if defined(VULKAN_ENABLED)
#include "drivers/vulkan/rendering_device_vulkan.h"
-#include "platform/linuxbsd/vulkan_context_x11.h"
+#include "vulkan_context_x11.h"
#endif
#if defined(DBUS_ENABLED)
-#include "freedesktop_portal_desktop.h"
-#include "freedesktop_screensaver.h"
+#include "../freedesktop_portal_desktop.h"
+#include "../freedesktop_screensaver.h"
#endif
#include <X11/Xcursor/Xcursor.h>
@@ -169,7 +169,6 @@ class DisplayServerX11 : public DisplayServer {
HashMap<WindowID, WindowData> windows;
unsigned int last_mouse_monitor_mask = 0;
- Vector2i last_mouse_monitor_pos;
uint64_t time_since_popup = 0;
List<WindowID> popup_list;
@@ -284,6 +283,8 @@ class DisplayServerX11 : public DisplayServer {
Context context = CONTEXT_ENGINE;
+ WindowID _get_focused_window_or_popup() const;
+
void _send_window_event(const WindowData &wd, WindowEvent p_event);
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
void _dispatch_input_event(const Ref<InputEvent> &p_event);
@@ -347,7 +348,6 @@ public:
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
#if defined(DBUS_ENABLED)
virtual void screen_set_keep_on(bool p_enable) override;
@@ -443,12 +443,12 @@ public:
virtual void set_native_icon(const String &p_filename) override;
virtual void set_icon(const Ref<Image> &p_icon) override;
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_x11_driver();
- DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ 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, Error &r_error);
~DisplayServerX11();
};
diff --git a/platform/linuxbsd/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index 04c1df71fb..4d8d63c64a 100644
--- a/platform/linuxbsd/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -37,9 +37,7 @@
#include <stdlib.h>
#include <unistd.h>
-#define GLX_GLXEXT_PROTOTYPES
-#include <GL/glx.h>
-#include <GL/glxext.h>
+#include "thirdparty/glad/glad/glx.h"
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
@@ -256,7 +254,11 @@ void GLManager_X11::release_current() {
if (!_current_window) {
return;
}
- glXMakeCurrent(_x_windisp.x11_display, None, nullptr);
+
+ if (!glXMakeCurrent(_x_windisp.x11_display, None, nullptr)) {
+ ERR_PRINT("glXMakeCurrent failed");
+ }
+ _current_window = nullptr;
}
void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) {
@@ -276,7 +278,9 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) {
const GLDisplay &disp = get_display(win.gldisplay_id);
- glXMakeCurrent(disp.x11_display, win.x11_window, disp.context->glx_context);
+ if (!glXMakeCurrent(disp.x11_display, win.x11_window, disp.context->glx_context)) {
+ ERR_PRINT("glXMakeCurrent failed");
+ }
_internal_set_current_window(&win);
}
@@ -290,13 +294,12 @@ void GLManager_X11::make_current() {
return;
}
const GLDisplay &disp = get_current_display();
- glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context);
+ if (!glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context)) {
+ ERR_PRINT("glXMakeCurrent failed");
+ }
}
void GLManager_X11::swap_buffers() {
- // NO NEED TO CALL SWAP BUFFERS for each window...
- // see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml
-
if (!_current_window) {
return;
}
@@ -305,7 +308,7 @@ void GLManager_X11::swap_buffers() {
return;
}
- // On X11, when enabled, transparancy is always active, so clear alpha manually.
+ // On X11, when enabled, transparency is always active, so clear alpha manually.
if (OS::get_singleton()->is_layered_allowed()) {
if (!DisplayServer::get_singleton()->window_get_flag(DisplayServer::WINDOW_FLAG_TRANSPARENT, _current_window->window_id)) {
glColorMask(false, false, false, true);
@@ -315,22 +318,18 @@ void GLManager_X11::swap_buffers() {
}
}
- // print_line("\tswap_buffers");
-
- // only for debugging without drawing anything
- // glClearColor(Math::randf(), 0, 1, 1);
- //glClear(GL_COLOR_BUFFER_BIT);
-
- //const GLDisplay &disp = get_current_display();
glXSwapBuffers(_x_windisp.x11_display, _x_windisp.x11_window);
}
Error GLManager_X11::initialize() {
+ if (!gladLoaderLoadGLX(nullptr, 0)) {
+ return ERR_CANT_CREATE;
+ }
+
return OK;
}
void GLManager_X11::set_use_vsync(bool p_use) {
- static bool setup = false;
static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr;
static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA = nullptr;
static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
@@ -347,25 +346,12 @@ void GLManager_X11::set_use_vsync(bool p_use) {
}
const GLDisplay &disp = get_current_display();
- if (!setup) {
- setup = true;
- String extensions = glXQueryExtensionsString(disp.x11_display, DefaultScreen(disp.x11_display));
- if (extensions.find("GLX_EXT_swap_control") != -1) {
- glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT");
- }
- if (extensions.find("GLX_MESA_swap_control") != -1) {
- glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA");
- }
- if (extensions.find("GLX_SGI_swap_control") != -1) {
- glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI");
- }
- }
int val = p_use ? 1 : 0;
- if (glXSwapIntervalMESA) {
+ if (GLAD_GLX_MESA_swap_control) {
glXSwapIntervalMESA(val);
- } else if (glXSwapIntervalSGI) {
+ } else if (GLAD_GLX_SGI_swap_control) {
glXSwapIntervalSGI(val);
- } else if (glXSwapIntervalEXT) {
+ } else if (GLAD_GLX_EXT_swap_control) {
GLXDrawable drawable = glXGetCurrentDrawable();
glXSwapIntervalEXT(disp.x11_display, drawable, val);
} else {
@@ -378,6 +364,17 @@ bool GLManager_X11::is_using_vsync() const {
return use_vsync;
}
+void *GLManager_X11::get_glx_context(DisplayServer::WindowID p_window_id) {
+ if (p_window_id == -1) {
+ return nullptr;
+ }
+
+ const GLWindow &win = _windows[p_window_id];
+ const GLDisplay &disp = get_display(win.gldisplay_id);
+
+ return (void *)disp.context->glx_context;
+}
+
GLManager_X11::GLManager_X11(const Vector2i &p_size, ContextType p_context_type) {
context_type = p_context_type;
diff --git a/platform/linuxbsd/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h
index 4f78c45c88..1594c82801 100644
--- a/platform/linuxbsd/gl_manager_x11.h
+++ b/platform/linuxbsd/x11/gl_manager_x11.h
@@ -116,6 +116,8 @@ public:
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
+ void *get_glx_context(DisplayServer::WindowID p_window_id);
+
GLManager_X11(const Vector2i &p_size, ContextType p_context_type);
~GLManager_X11();
};
diff --git a/platform/linuxbsd/key_mapping_x11.cpp b/platform/linuxbsd/x11/key_mapping_x11.cpp
index 047ee74671..f774c99d99 100644
--- a/platform/linuxbsd/key_mapping_x11.cpp
+++ b/platform/linuxbsd/x11/key_mapping_x11.cpp
@@ -108,17 +108,21 @@ static _XTranslatePair _xkeysym_to_keycode[] = {
{ XK_KP_7, Key::KP_7 },
{ XK_KP_8, Key::KP_8 },
{ XK_KP_9, Key::KP_9 },
- // same but with numlock
- { XK_KP_Insert, Key::KP_0 },
- { XK_KP_End, Key::KP_1 },
- { XK_KP_Down, Key::KP_2 },
- { XK_KP_Page_Down, Key::KP_3 },
- { XK_KP_Left, Key::KP_4 },
- { XK_KP_Begin, Key::KP_5 },
- { XK_KP_Right, Key::KP_6 },
- { XK_KP_Home, Key::KP_7 },
- { XK_KP_Up, Key::KP_8 },
- { XK_KP_Page_Up, Key::KP_9 },
+ // same keys but with numlock off
+ { XK_KP_Insert, Key::INSERT },
+ { XK_KP_End, Key::END },
+ { XK_KP_Down, Key::DOWN },
+ { XK_KP_Page_Down, Key::PAGEDOWN },
+ { XK_KP_Left, Key::LEFT },
+ // X11 documents this (numpad 5) as "begin of line" but no toolkit
+ // seems to interpret it this way.
+ // On Windows this is emitting Key::Clear so for consistency it
+ // will be mapped to Key::Clear
+ { XK_KP_Begin, Key::CLEAR },
+ { XK_KP_Right, Key::RIGHT },
+ { XK_KP_Home, Key::HOME },
+ { XK_KP_Up, Key::UP },
+ { XK_KP_Page_Up, Key::PAGEUP },
{ XK_F1, Key::F1 },
{ XK_F2, Key::F2 },
{ XK_F3, Key::F3 },
diff --git a/platform/linuxbsd/key_mapping_x11.h b/platform/linuxbsd/x11/key_mapping_x11.h
index b7b8a3b787..b7b8a3b787 100644
--- a/platform/linuxbsd/key_mapping_x11.h
+++ b/platform/linuxbsd/x11/key_mapping_x11.h
diff --git a/platform/linuxbsd/vulkan_context_x11.cpp b/platform/linuxbsd/x11/vulkan_context_x11.cpp
index b4f585726f..92aaf33b05 100644
--- a/platform/linuxbsd/vulkan_context_x11.cpp
+++ b/platform/linuxbsd/x11/vulkan_context_x11.cpp
@@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifdef VULKAN_ENABLED
+
#include "vulkan_context_x11.h"
#ifdef USE_VOLK
@@ -59,3 +61,5 @@ VulkanContextX11::VulkanContextX11() {
VulkanContextX11::~VulkanContextX11() {
}
+
+#endif // VULKAN_ENABLED
diff --git a/platform/linuxbsd/vulkan_context_x11.h b/platform/linuxbsd/x11/vulkan_context_x11.h
index 0c4a6cd278..0adb50ef44 100644
--- a/platform/linuxbsd/vulkan_context_x11.h
+++ b/platform/linuxbsd/x11/vulkan_context_x11.h
@@ -31,6 +31,8 @@
#ifndef VULKAN_CONTEXT_X11_H
#define VULKAN_CONTEXT_X11_H
+#ifdef VULKAN_ENABLED
+
#include "drivers/vulkan/vulkan_context.h"
#include <X11/Xlib.h>
@@ -44,4 +46,6 @@ public:
~VulkanContextX11();
};
+#endif // VULKAN_ENABLED
+
#endif // VULKAN_CONTEXT_X11_H