summaryrefslogtreecommitdiff
path: root/platform/linuxbsd
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/README.md11
-rw-r--r--platform/linuxbsd/SCsub26
-rw-r--r--platform/linuxbsd/context_gl_x11.cpp4
-rw-r--r--platform/linuxbsd/context_gl_x11.h4
-rw-r--r--platform/linuxbsd/crash_handler_linuxbsd.cpp18
-rw-r--r--platform/linuxbsd/crash_handler_linuxbsd.h4
-rw-r--r--platform/linuxbsd/detect.py174
-rw-r--r--platform/linuxbsd/detect_prime_x11.cpp13
-rw-r--r--platform/linuxbsd/detect_prime_x11.h4
-rw-r--r--platform/linuxbsd/display_server_x11.cpp888
-rw-r--r--platform/linuxbsd/display_server_x11.h221
-rw-r--r--platform/linuxbsd/export/export.cpp12
-rw-r--r--platform/linuxbsd/export/export.h4
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.cpp125
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.h47
-rw-r--r--platform/linuxbsd/godot_linuxbsd.cpp4
-rw-r--r--platform/linuxbsd/joypad_linux.cpp115
-rw-r--r--platform/linuxbsd/joypad_linux.h30
-rw-r--r--platform/linuxbsd/key_mapping_x11.cpp43
-rw-r--r--platform/linuxbsd/key_mapping_x11.h9
-rw-r--r--platform/linuxbsd/libudev-so_wrap.c1013
-rw-r--r--platform/linuxbsd/libudev-so_wrap.h378
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp284
-rw-r--r--platform/linuxbsd/os_linuxbsd.h42
-rw-r--r--platform/linuxbsd/platform_config.h4
-rw-r--r--platform/linuxbsd/vulkan_context_x11.cpp16
-rw-r--r--platform/linuxbsd/vulkan_context_x11.h6
27 files changed, 2816 insertions, 683 deletions
diff --git a/platform/linuxbsd/README.md b/platform/linuxbsd/README.md
new file mode 100644
index 0000000000..0d3fb37be5
--- /dev/null
+++ b/platform/linuxbsd/README.md
@@ -0,0 +1,11 @@
+# Linux/*BSD platform port
+
+This folder contains the C++ code for the Linux/*BSD platform port.
+
+## Artwork license
+
+[`logo.png`](logo.png) is derived from the [Linux logo](https://isc.tamu.edu/~lewing/linux/):
+
+> Permission to use and/or modify this image is granted provided you acknowledge me
+ <lewing@isc.tamu.edu> and [The GIMP](https://isc.tamu.edu/~lewing/gimp/)
+ if someone asks.
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index ae75a75830..8aebd57fd2 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -5,18 +5,28 @@ Import("env")
from platform_methods import run_in_subprocess
import platform_linuxbsd_builders
-common_x11 = [
+common_linuxbsd = [
"crash_handler_linuxbsd.cpp",
"os_linuxbsd.cpp",
"joypad_linux.cpp",
- "context_gl_x11.cpp",
- "detect_prime_x11.cpp",
- "display_server_x11.cpp",
- "vulkan_context_x11.cpp",
- "key_mapping_x11.cpp",
+ "freedesktop_screensaver.cpp",
]
-prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_x11)
+if "x11" in env and env["x11"]:
+ common_linuxbsd += [
+ "context_gl_x11.cpp",
+ "detect_prime_x11.cpp",
+ "display_server_x11.cpp",
+ "key_mapping_x11.cpp",
+ ]
-if (env["debug_symbols"] == "full" or env["debug_symbols"] == "yes") and env["separate_debug_symbols"]:
+if "vulkan" in env and env["vulkan"]:
+ common_linuxbsd.append("vulkan_context_x11.cpp")
+
+if "udev" in env and env["udev"]:
+ common_linuxbsd.append("libudev-so_wrap.c")
+
+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))
diff --git a/platform/linuxbsd/context_gl_x11.cpp b/platform/linuxbsd/context_gl_x11.cpp
index 71dc9602b3..1f92370ab7 100644
--- a/platform/linuxbsd/context_gl_x11.cpp
+++ b/platform/linuxbsd/context_gl_x11.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/linuxbsd/context_gl_x11.h b/platform/linuxbsd/context_gl_x11.h
index 7aed280c98..d089886f4d 100644
--- a/platform/linuxbsd/context_gl_x11.h
+++ b/platform/linuxbsd/context_gl_x11.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp
index e2b88b7704..0e98af71fa 100644
--- a/platform/linuxbsd/crash_handler_linuxbsd.cpp
+++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,8 +30,10 @@
#include "crash_handler_linuxbsd.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
+#include "core/version.h"
+#include "core/version_hash.gen.h"
#include "main/main.h"
#ifdef DEBUG_ENABLED
@@ -61,12 +63,19 @@ static void handle_crash(int sig) {
}
// Dump the backtrace to stderr with a message to the user
+ fprintf(stderr, "\n================================================================\n");
fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig);
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_CRASH);
}
+ // Print the engine version just before, so that people are reminded to include the version in backtrace reports.
+ if (String(VERSION_HASH).length() != 0) {
+ fprintf(stderr, "Engine version: " VERSION_FULL_NAME " (" VERSION_HASH ")\n");
+ } else {
+ fprintf(stderr, "Engine version: " VERSION_FULL_NAME "\n");
+ }
fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data());
char **strings = backtrace_symbols(bt_buffer, size);
if (strings) {
@@ -104,7 +113,7 @@ static void handle_crash(int sig) {
// Try to get the file/line number using addr2line
int ret;
- Error err = OS::get_singleton()->execute(String("addr2line"), args, true, nullptr, &output, &ret);
+ Error err = OS::get_singleton()->execute(String("addr2line"), args, &output, &ret);
if (err == OK) {
output.erase(output.length() - 1, 1);
}
@@ -115,6 +124,7 @@ static void handle_crash(int sig) {
free(strings);
}
fprintf(stderr, "-- END OF BACKTRACE --\n");
+ fprintf(stderr, "================================================================\n");
// Abort to pass the error to the OS
abort();
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.h b/platform/linuxbsd/crash_handler_linuxbsd.h
index 9bb03579bc..a3dae0cc22 100644
--- a/platform/linuxbsd/crash_handler_linuxbsd.h
+++ b/platform/linuxbsd/crash_handler_linuxbsd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index f5e2c72bbc..8eb22c1c72 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -12,47 +12,48 @@ def get_name():
def can_build():
-
if os.name != "posix" or sys.platform == "darwin":
return False
# Check the minimal dependencies
x11_error = os.system("pkg-config --version > /dev/null")
if x11_error:
+ print("Error: pkg-config not found. Aborting.")
return False
- x11_error = os.system("pkg-config x11 --modversion > /dev/null ")
+ x11_error = os.system("pkg-config x11 --modversion > /dev/null")
if x11_error:
+ print("Error: X11 libraries not found. Aborting.")
return False
- x11_error = os.system("pkg-config xcursor --modversion > /dev/null ")
+ x11_error = os.system("pkg-config xcursor --modversion > /dev/null")
if x11_error:
- print("xcursor not found.. x11 disabled.")
+ print("Error: Xcursor library not found. Aborting.")
return False
- x11_error = os.system("pkg-config xinerama --modversion > /dev/null ")
+ x11_error = os.system("pkg-config xinerama --modversion > /dev/null")
if x11_error:
- print("xinerama not found.. x11 disabled.")
+ print("Error: Xinerama library not found. Aborting.")
return False
- x11_error = os.system("pkg-config xext --modversion > /dev/null ")
+ x11_error = os.system("pkg-config xext --modversion > /dev/null")
if x11_error:
- print("xext not found.. x11 disabled.")
+ print("Error: Xext library not found. Aborting.")
return False
- x11_error = os.system("pkg-config xrandr --modversion > /dev/null ")
+ x11_error = os.system("pkg-config xrandr --modversion > /dev/null")
if x11_error:
- print("xrandr not found.. x11 disabled.")
+ print("Error: XrandR library not found. Aborting.")
return False
- x11_error = os.system("pkg-config xrender --modversion > /dev/null ")
+ x11_error = os.system("pkg-config xrender --modversion > /dev/null")
if x11_error:
- print("xrender not found.. x11 disabled.")
+ print("Error: XRender library not found. Aborting.")
return False
- x11_error = os.system("pkg-config xi --modversion > /dev/null ")
+ x11_error = os.system("pkg-config xi --modversion > /dev/null")
if x11_error:
- print("xi not found.. Aborting.")
+ print("Error: Xi library not found. Aborting.")
return False
return True
@@ -65,15 +66,18 @@ def get_opts():
BoolVariable("use_llvm", "Use the LLVM compiler", False),
BoolVariable("use_lld", "Use the LLD linker", False),
BoolVariable("use_thinlto", "Use ThinLTO", False),
- BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", 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),
- BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN))", False),
- BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN))", False),
- BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN))", False),
+ BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN)", False),
+ BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN)", False),
+ BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False),
+ BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False),
BoolVariable("pulseaudio", "Detect and use PulseAudio", True),
- BoolVariable("udev", "Use udev for gamepad connection callbacks", False),
- EnumVariable("debug_symbols", "Add debugging symbols to release builds", "yes", ("yes", "no", "full")),
+ BoolVariable("dbus", "Detect and use D-Bus to handle screensaver", 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),
@@ -81,35 +85,29 @@ def get_opts():
def get_flags():
-
return []
def configure(env):
-
## Build type
if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
env.Prepend(CCFLAGS=["-O3"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os"])
- if env["debug_symbols"] == "yes":
- env.Prepend(CCFLAGS=["-g1"])
- if env["debug_symbols"] == "full":
+ 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"])
- else: # optimize for size
+ elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os"])
env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
- if env["debug_symbols"] == "yes":
- env.Prepend(CCFLAGS=["-g1"])
- if env["debug_symbols"] == "full":
+ if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "debug":
@@ -133,8 +131,6 @@ def configure(env):
if "clang++" not in os.path.basename(env["CXX"]):
env["CC"] = "clang"
env["CXX"] = "clang++"
- env["LINK"] = "clang++"
- env.Append(CPPDEFINES=["TYPED_METHOD_BIND"])
env.extra_suffix = ".llvm" + env.extra_suffix
if env["use_lld"]:
@@ -144,22 +140,34 @@ def configure(env):
# A convenience so you don't need to write use_lto too when using SCons
env["use_lto"] = True
else:
- print("Using LLD with GCC is not supported yet, try compiling with 'use_llvm=yes'.")
+ print("Using LLD with GCC is not supported yet. Try compiling with 'use_llvm=yes'.")
sys.exit(255)
if env["use_coverage"]:
env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
env.Append(LINKFLAGS=["-ftest-coverage", "-fprofile-arcs"])
- if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"]:
+ if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"] or env["use_msan"]:
env.extra_suffix += "s"
if env["use_ubsan"]:
- env.Append(CCFLAGS=["-fsanitize=undefined"])
+ env.Append(
+ CCFLAGS=[
+ "-fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin"
+ ]
+ )
env.Append(LINKFLAGS=["-fsanitize=undefined"])
+ if env["use_llvm"]:
+ env.Append(
+ CCFLAGS=[
+ "-fsanitize=nullability-return,nullability-arg,function,nullability-assign,implicit-integer-sign-change"
+ ]
+ )
+ else:
+ env.Append(CCFLAGS=["-fsanitize=bounds-strict"])
if env["use_asan"]:
- env.Append(CCFLAGS=["-fsanitize=address"])
+ env.Append(CCFLAGS=["-fsanitize=address,pointer-subtract,pointer-compare"])
env.Append(LINKFLAGS=["-fsanitize=address"])
if env["use_lsan"]:
@@ -170,6 +178,12 @@ def configure(env):
env.Append(CCFLAGS=["-fsanitize=thread"])
env.Append(LINKFLAGS=["-fsanitize=thread"])
+ if env["use_msan"] and env["use_llvm"]:
+ env.Append(CCFLAGS=["-fsanitize=memory"])
+ env.Append(CCFLAGS=["-fsanitize-memory-track-origins"])
+ env.Append(CCFLAGS=["-fsanitize-recover=memory"])
+ env.Append(LINKFLAGS=["-fsanitize=memory"])
+
if env["use_lto"]:
if not env["use_llvm"] and env.GetOption("num_jobs") > 1:
env.Append(CCFLAGS=["-flto"])
@@ -189,11 +203,6 @@ def configure(env):
env.Append(CCFLAGS=["-pipe"])
env.Append(LINKFLAGS=["-pipe"])
- # -fpie and -no-pie is supported on GCC 6+ and Clang 4+, both below our
- # minimal requirements.
- env.Append(CCFLAGS=["-fpie"])
- env.Append(LINKFLAGS=["-no-pie"])
-
## Dependencies
env.ParseConfig("pkg-config x11 --cflags --libs")
@@ -211,14 +220,31 @@ def configure(env):
# freetype depends on libpng and zlib, so bundling one of them while keeping others
# as shared libraries leads to weird issues
- if env["builtin_freetype"] or env["builtin_libpng"] or env["builtin_zlib"]:
+ if (
+ env["builtin_freetype"]
+ or env["builtin_libpng"]
+ or env["builtin_zlib"]
+ or env["builtin_graphite"]
+ or env["builtin_harfbuzz"]
+ ):
env["builtin_freetype"] = True
env["builtin_libpng"] = True
env["builtin_zlib"] = True
+ env["builtin_graphite"] = True
+ env["builtin_harfbuzz"] = True
if not env["builtin_freetype"]:
env.ParseConfig("pkg-config freetype2 --cflags --libs")
+ if not env["builtin_graphite"]:
+ env.ParseConfig("pkg-config graphite2 --cflags --libs")
+
+ if not env["builtin_icu"]:
+ env.ParseConfig("pkg-config icu-uc --cflags --libs")
+
+ if not env["builtin_harfbuzz"]:
+ env.ParseConfig("pkg-config harfbuzz harfbuzz-icu --cflags --libs")
+
if not env["builtin_libpng"]:
env.ParseConfig("pkg-config libpng16 --cflags --libs")
@@ -298,51 +324,67 @@ def configure(env):
if not env["builtin_pcre2"]:
env.ParseConfig("pkg-config libpcre2-32 --cflags --libs")
+ if not env["builtin_embree"]:
+ # No pkgconfig file so far, hardcode expected lib name.
+ env.Append(LIBS=["embree3"])
+
## Flags
if os.system("pkg-config --exists alsa") == 0: # 0 means found
- print("Enabling ALSA")
+ env["alsa"] = True
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
- # Don't parse --cflags, we don't need to add /usr/include/alsa to include path
- env.ParseConfig("pkg-config alsa --libs")
else:
- print("ALSA libraries not found, disabling driver")
+ print("Warning: ALSA libraries not found. Disabling the ALSA audio driver.")
if env["pulseaudio"]:
if os.system("pkg-config --exists libpulse") == 0: # 0 means found
- print("Enabling PulseAudio")
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"])
- env.ParseConfig("pkg-config --cflags --libs libpulse")
+ env.ParseConfig("pkg-config --cflags libpulse")
+ else:
+ print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.")
+
+ if env["dbus"]:
+ if os.system("pkg-config --exists dbus-1") == 0: # 0 means found
+ env.Append(CPPDEFINES=["DBUS_ENABLED"])
+ env.ParseConfig("pkg-config --cflags --libs dbus-1")
else:
- print("PulseAudio development libraries not found, disabling driver")
+ print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.")
if platform.system() == "Linux":
env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
-
if env["udev"]:
if os.system("pkg-config --exists libudev") == 0: # 0 means found
- print("Enabling udev support")
env.Append(CPPDEFINES=["UDEV_ENABLED"])
- env.ParseConfig("pkg-config libudev --cflags --libs")
else:
- print("libudev development libraries not found, disabling udev support")
+ print("Warning: libudev development libraries not found. Disabling controller hotplugging support.")
+ else:
+ env["udev"] = False # Linux specific
# Linkflags below this line should typically stay the last ones
if not env["builtin_zlib"]:
env.ParseConfig("pkg-config zlib --cflags --libs")
env.Prepend(CPPPATH=["#platform/linuxbsd"])
- env.Append(CPPDEFINES=["X11_ENABLED", "UNIX_ENABLED"])
- env.Append(CPPDEFINES=["VULKAN_ENABLED"])
- if not env["builtin_vulkan"]:
- env.ParseConfig("pkg-config vulkan --cflags --libs")
- if not env["builtin_glslang"]:
- # No pkgconfig file for glslang so far
- env.Append(LIBS=["glslang", "SPIRV"])
+ if env["x11"]:
+ if not env["vulkan"]:
+ print("Error: X11 support requires vulkan=yes")
+ env.Exit(255)
+ env.Append(CPPDEFINES=["X11_ENABLED"])
+
+ env.Append(CPPDEFINES=["UNIX_ENABLED"])
+ env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)])
- # env.Append(CPPDEFINES=['OPENGL_ENABLED'])
- env.Append(LIBS=["GL"])
+ if env["vulkan"]:
+ env.Append(CPPDEFINES=["VULKAN_ENABLED"])
+ if not env["use_volk"]:
+ env.ParseConfig("pkg-config vulkan --cflags --libs")
+ if not env["builtin_glslang"]:
+ # No pkgconfig file for glslang so far
+ env.Append(LIBS=["glslang", "SPIRV"])
+
+ # env.Append(CPPDEFINES=['OPENGL_ENABLED'])
+ env.Append(LIBS=["GL"])
env.Append(LIBS=["pthread"])
@@ -363,7 +405,7 @@ def configure(env):
gnu_ld_version = re.search("^GNU ld [^$]*(\d+\.\d+)$", linker_version_str, re.MULTILINE)
if not gnu_ld_version:
print(
- "Warning: Creating template binaries enabled for PCK embedding is currently only supported with GNU ld"
+ "Warning: Creating template binaries enabled for PCK embedding is currently only supported with GNU ld, not gold or LLD."
)
else:
if float(gnu_ld_version.group(1)) >= 2.30:
@@ -383,3 +425,9 @@ def configure(env):
# Link those statically for portability
if env["use_static_cpp"]:
env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"])
+ if env["use_llvm"]:
+ env["LINKCOM"] = env["LINKCOM"] + " -l:libatomic.a"
+
+ else:
+ if env["use_llvm"]:
+ env.Append(LIBS=["atomic"])
diff --git a/platform/linuxbsd/detect_prime_x11.cpp b/platform/linuxbsd/detect_prime_x11.cpp
index 1e46d3222d..da1c95a593 100644
--- a/platform/linuxbsd/detect_prime_x11.cpp
+++ b/platform/linuxbsd/detect_prime_x11.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,8 +33,8 @@
#include "detect_prime.h"
-#include "core/print_string.h"
-#include "core/ustring.h"
+#include "core/string/print_string.h"
+#include "core/string/ustring.h"
#include <stdlib.h>
@@ -56,11 +56,12 @@ typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLX
struct vendor {
const char *glxvendor;
- int priority;
+ int priority = 0;
};
vendor vendormap[] = {
{ "Advanced Micro Devices, Inc.", 30 },
+ { "AMD", 30 },
{ "NVIDIA Corporation", 30 },
{ "X.Org", 30 },
{ "Intel Open Source Technology Center", 20 },
@@ -128,7 +129,7 @@ void create_context() {
int detect_prime() {
pid_t p;
- int priorities[2];
+ int priorities[2] = {};
String vendors[2];
String renderers[2];
diff --git a/platform/linuxbsd/detect_prime_x11.h b/platform/linuxbsd/detect_prime_x11.h
index 039bdee76b..0b548b849e 100644
--- a/platform/linuxbsd/detect_prime_x11.h
+++ b/platform/linuxbsd/detect_prime_x11.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 176878bc12..f2cd336b39 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,17 +32,18 @@
#ifdef X11_ENABLED
-#include "core/print_string.h"
-#include "core/project_settings.h"
+#include "core/config/project_settings.h"
+#include "core/string/print_string.h"
#include "detect_prime_x11.h"
#include "key_mapping_x11.h"
#include "main/main.h"
#include "scene/resources/texture.h"
#if defined(VULKAN_ENABLED)
-#include "servers/rendering/rasterizer_rd/rasterizer_rd.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#endif
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -94,6 +95,15 @@
static const double abs_resolution_mult = 10000.0;
static const double abs_resolution_range_mult = 10.0;
+// Hints for X11 fullscreen
+struct Hints {
+ unsigned long flags = 0;
+ unsigned long functions = 0;
+ unsigned long decorations = 0;
+ long inputMode = 0;
+ unsigned long status = 0;
+};
+
bool DisplayServerX11::has_feature(Feature p_feature) const {
switch (p_feature) {
case FEATURE_SUBWINDOWS:
@@ -111,6 +121,9 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
case FEATURE_ICON:
case FEATURE_NATIVE_ICON:
case FEATURE_SWAP_BUFFERS:
+#ifdef DBUS_ENABLED
+ case FEATURE_KEEP_SCREEN_ON:
+#endif
return true;
default: {
}
@@ -123,70 +136,6 @@ String DisplayServerX11::get_name() const {
return "X11";
}
-void DisplayServerX11::alert(const String &p_alert, const String &p_title) {
- const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
-
- String path = OS::get_singleton()->get_environment("PATH");
- Vector<String> path_elems = path.split(":", false);
- String program;
-
- for (int i = 0; i < path_elems.size(); i++) {
- for (uint64_t k = 0; k < sizeof(message_programs) / sizeof(char *); k++) {
- String tested_path = path_elems[i].plus_file(message_programs[k]);
-
- if (FileAccess::exists(tested_path)) {
- program = tested_path;
- break;
- }
- }
-
- if (program.length()) {
- break;
- }
- }
-
- List<String> args;
-
- if (program.ends_with("zenity")) {
- args.push_back("--error");
- args.push_back("--width");
- args.push_back("500");
- args.push_back("--title");
- args.push_back(p_title);
- args.push_back("--text");
- args.push_back(p_alert);
- }
-
- if (program.ends_with("kdialog")) {
- args.push_back("--error");
- args.push_back(p_alert);
- args.push_back("--title");
- args.push_back(p_title);
- }
-
- if (program.ends_with("Xdialog")) {
- args.push_back("--title");
- args.push_back(p_title);
- args.push_back("--msgbox");
- args.push_back(p_alert);
- args.push_back("0");
- args.push_back("0");
- }
-
- if (program.ends_with("xmessage")) {
- args.push_back("-center");
- args.push_back("-title");
- args.push_back(p_title);
- args.push_back(p_alert);
- }
-
- if (program.length()) {
- OS::get_singleton()->execute(program, args, true);
- } else {
- print_line(p_alert);
- }
-}
-
void DisplayServerX11::_update_real_mouse_position(const WindowData &wd) {
Window root_return, child_return;
int root_x, root_y, win_x, win_y;
@@ -350,23 +299,23 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
return;
}
- if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) {
+ if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
XUngrabPointer(x11_display, CurrentTime);
}
// The only modes that show a cursor are VISIBLE and CONFINED
bool showCursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED);
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
if (showCursor) {
- XDefineCursor(x11_display, E->get().x11_window, cursors[current_cursor]); // show cursor
+ XDefineCursor(x11_display, E.value.x11_window, cursors[current_cursor]); // show cursor
} else {
- XDefineCursor(x11_display, E->get().x11_window, null_cursor); // hide cursor
+ XDefineCursor(x11_display, E.value.x11_window, null_cursor); // hide cursor
}
}
mouse_mode = p_mode;
- if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) {
+ if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
//flush pending motion events
_flush_mouse_motion();
WindowData &main_window = windows[MAIN_WINDOW_ID];
@@ -440,7 +389,7 @@ Point2i DisplayServerX11::mouse_get_absolute_position() const {
return Vector2i();
}
-int DisplayServerX11::mouse_get_button_state() const {
+MouseButton DisplayServerX11::mouse_get_button_state() const {
return last_button_state;
}
@@ -465,59 +414,138 @@ Bool DisplayServerX11::_predicate_clipboard_selection(Display *display, XEvent *
}
}
+Bool DisplayServerX11::_predicate_clipboard_incr(Display *display, XEvent *event, XPointer arg) {
+ if (event->type == PropertyNotify && event->xproperty.state == PropertyNewValue) {
+ return True;
+ } else {
+ return False;
+ }
+}
+
String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, Atom target) const {
String ret;
- Atom type;
- Atom selection = XA_PRIMARY;
- int format, result;
- unsigned long len, bytes_left, dummy;
- unsigned char *data;
Window selection_owner = XGetSelectionOwner(x11_display, p_source);
-
if (selection_owner == x11_window) {
return internal_clipboard;
}
if (selection_owner != None) {
- {
- // Block events polling while processing selection events.
- MutexLock mutex_lock(events_mutex);
+ // Block events polling while processing selection events.
+ MutexLock mutex_lock(events_mutex);
- XConvertSelection(x11_display, p_source, target, selection,
- x11_window, CurrentTime);
+ Atom selection = XA_PRIMARY;
+ XConvertSelection(x11_display, p_source, target, selection,
+ x11_window, CurrentTime);
- XFlush(x11_display);
+ XFlush(x11_display);
- // Blocking wait for predicate to be True
- // and remove the event from the queue.
- XEvent event;
- XIfEvent(x11_display, &event, _predicate_clipboard_selection, (XPointer)&x11_window);
- }
+ // Blocking wait for predicate to be True and remove the event from the queue.
+ XEvent event;
+ XIfEvent(x11_display, &event, _predicate_clipboard_selection, (XPointer)&x11_window);
- //
- // Do not get any data, see how much data is there
- //
+ // Do not get any data, see how much data is there.
+ Atom type;
+ int format, result;
+ unsigned long len, bytes_left, dummy;
+ unsigned char *data;
XGetWindowProperty(x11_display, x11_window,
selection, // Tricky..
0, 0, // offset - len
0, // Delete 0==FALSE
- AnyPropertyType, //flag
+ AnyPropertyType, // flag
&type, // return type
&format, // return format
- &len, &bytes_left, //that
+ &len, &bytes_left, // data length
&data);
- // DATA is There
- if (bytes_left > 0) {
+
+ if (data) {
+ XFree(data);
+ }
+
+ if (type == XInternAtom(x11_display, "INCR", 0)) {
+ // Data is going to be received incrementally.
+ DEBUG_LOG_X11("INCR selection started.\n");
+
+ LocalVector<uint8_t> incr_data;
+ uint32_t data_size = 0;
+ bool success = false;
+
+ // Delete INCR property to notify the owner.
+ XDeleteProperty(x11_display, x11_window, type);
+
+ // Process events from the queue.
+ bool done = false;
+ while (!done) {
+ if (!_wait_for_events()) {
+ // Error or timeout, abort.
+ break;
+ }
+
+ // Non-blocking wait for next event and remove it from the queue.
+ XEvent ev;
+ while (XCheckIfEvent(x11_display, &ev, _predicate_clipboard_incr, nullptr)) {
+ result = XGetWindowProperty(x11_display, x11_window,
+ selection, // selection type
+ 0, LONG_MAX, // offset - len
+ True, // delete property to notify the owner
+ AnyPropertyType, // flag
+ &type, // return type
+ &format, // return format
+ &len, &bytes_left, // data length
+ &data);
+
+ DEBUG_LOG_X11("PropertyNotify: len=%lu, format=%i\n", len, format);
+
+ if (result == Success) {
+ if (data && (len > 0)) {
+ uint32_t prev_size = incr_data.size();
+ if (prev_size == 0) {
+ // First property contains initial data size.
+ unsigned long initial_size = *(unsigned long *)data;
+ incr_data.resize(initial_size);
+ } else {
+ // New chunk, resize to be safe and append data.
+ incr_data.resize(MAX(data_size + len, prev_size));
+ memcpy(incr_data.ptr() + data_size, data, len);
+ data_size += len;
+ }
+ } else {
+ // Last chunk, process finished.
+ done = true;
+ success = true;
+ }
+ } else {
+ printf("Failed to get selection data chunk.\n");
+ done = true;
+ }
+
+ if (data) {
+ XFree(data);
+ }
+
+ if (done) {
+ break;
+ }
+ }
+ }
+
+ if (success && (data_size > 0)) {
+ ret.parse_utf8((const char *)incr_data.ptr(), data_size);
+ }
+ } else if (bytes_left > 0) {
+ // Data is ready and can be processed all at once.
result = XGetWindowProperty(x11_display, x11_window,
selection, 0, bytes_left, 0,
AnyPropertyType, &type, &format,
&len, &dummy, &data);
+
if (result == Success) {
ret.parse_utf8((const char *)data);
} else {
- printf("FAIL\n");
+ printf("Failed to get selection data.\n");
}
+
if (data) {
XFree(data);
}
@@ -533,7 +561,7 @@ String DisplayServerX11::_clipboard_get(Atom p_source, Window x11_window) const
if (utf8_atom != None) {
ret = _clipboard_get_impl(p_source, x11_window, utf8_atom);
}
- if (ret.empty()) {
+ if (ret.is_empty()) {
ret = _clipboard_get_impl(p_source, x11_window, XA_STRING);
}
return ret;
@@ -545,13 +573,67 @@ String DisplayServerX11::clipboard_get() const {
String ret;
ret = _clipboard_get(XInternAtom(x11_display, "CLIPBOARD", 0), windows[MAIN_WINDOW_ID].x11_window);
- if (ret.empty()) {
+ if (ret.is_empty()) {
ret = _clipboard_get(XA_PRIMARY, windows[MAIN_WINDOW_ID].x11_window);
}
return ret;
}
+Bool DisplayServerX11::_predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg) {
+ if (event->xany.window == *(Window *)arg) {
+ return (event->type == SelectionRequest) ||
+ (event->type == SelectionNotify);
+ } else {
+ return False;
+ }
+}
+
+void DisplayServerX11::_clipboard_transfer_ownership(Atom p_source, Window x11_window) const {
+ _THREAD_SAFE_METHOD_
+
+ Window selection_owner = XGetSelectionOwner(x11_display, p_source);
+
+ if (selection_owner != x11_window) {
+ return;
+ }
+
+ // Block events polling while processing selection events.
+ MutexLock mutex_lock(events_mutex);
+
+ Atom clipboard_manager = XInternAtom(x11_display, "CLIPBOARD_MANAGER", False);
+ Atom save_targets = XInternAtom(x11_display, "SAVE_TARGETS", False);
+ XConvertSelection(x11_display, clipboard_manager, save_targets, None,
+ x11_window, CurrentTime);
+
+ // Process events from the queue.
+ while (true) {
+ if (!_wait_for_events()) {
+ // Error or timeout, abort.
+ break;
+ }
+
+ // Non-blocking wait for next event and remove it from the queue.
+ XEvent ev;
+ while (XCheckIfEvent(x11_display, &ev, _predicate_clipboard_save_targets, (XPointer)&x11_window)) {
+ switch (ev.type) {
+ case SelectionRequest:
+ _handle_selection_request_event(&(ev.xselectionrequest));
+ break;
+
+ case SelectionNotify: {
+ if (ev.xselection.target == save_targets) {
+ // Once SelectionNotify is received, we're done whether it succeeded or not.
+ return;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+}
+
int DisplayServerX11::get_screen_count() const {
_THREAD_SAFE_METHOD_
@@ -584,9 +666,9 @@ Point2i DisplayServerX11::screen_get_position(int p_screen) const {
int count;
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
- if (p_screen >= count) {
- return Point2i(0, 0);
- }
+
+ // Check if screen is valid
+ ERR_FAIL_INDEX_V(p_screen, count, Point2i(0, 0));
Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org);
@@ -615,9 +697,9 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
int count;
XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
- if (p_screen >= count) {
- return Rect2i(0, 0, 0, 0);
- }
+
+ // Check if screen is valid
+ ERR_FAIL_INDEX_V(p_screen, count, Rect2i(0, 0, 0, 0));
Rect2i rect = Rect2i(xsi[p_screen].x_org, xsi[p_screen].y_org, xsi[p_screen].width, xsi[p_screen].height);
XFree(xsi);
@@ -679,20 +761,40 @@ bool DisplayServerX11::screen_is_touchscreen(int p_screen) const {
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) {
+ return;
+ }
+
+ if (p_enable) {
+ screensaver->inhibit();
+ } else {
+ screensaver->uninhibit();
+ }
+
+ keep_screen_on = p_enable;
+}
+
+bool DisplayServerX11::screen_is_kept_on() const {
+ return keep_screen_on;
+}
+#endif
+
Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
_THREAD_SAFE_METHOD_
Vector<int> ret;
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- ret.push_back(E->key());
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ ret.push_back(E.key);
}
return ret;
}
-DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
- WindowID id = _create_window(p_mode, p_flags, p_rect);
+ WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id);
@@ -705,7 +807,9 @@ DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, u
void DisplayServerX11::show_window(WindowID p_id) {
_THREAD_SAFE_METHOD_
- WindowData &wd = windows[p_id];
+ const WindowData &wd = windows[p_id];
+
+ DEBUG_LOG_X11("show_window: %lu (%u) \n", wd.x11_window, p_id);
XMapWindow(x11_display, wd.x11_window);
}
@@ -760,8 +864,8 @@ DisplayServerX11::WindowID DisplayServerX11::get_window_at_screen_position(const
WindowID found_window = INVALID_WINDOW_ID;
WindowID parent_window = INVALID_WINDOW_ID;
unsigned int focus_order = 0;
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- const WindowData &wd = E->get();
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ const WindowData &wd = E.value;
// Discard windows with no focus.
if (wd.focus_order == 0) {
@@ -769,7 +873,7 @@ DisplayServerX11::WindowID DisplayServerX11::get_window_at_screen_position(const
}
// Find topmost window which contains the given position.
- WindowID window_id = E->key();
+ WindowID window_id = E.key;
Rect2i win_rect = Rect2i(window_get_position(window_id), window_get_size(window_id));
if (win_rect.has_point(p_position)) {
// For siblings, pick the window which was focused last.
@@ -794,7 +898,9 @@ void DisplayServerX11::window_set_title(const String &p_title, WindowID p_window
Atom _net_wm_name = XInternAtom(x11_display, "_NET_WM_NAME", false);
Atom utf8_string = XInternAtom(x11_display, "UTF8_STRING", false);
- XChangeProperty(x11_display, wd.x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char *)p_title.utf8().get_data(), p_title.utf8().length());
+ if (_net_wm_name != None && utf8_string != None) {
+ XChangeProperty(x11_display, wd.x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char *)p_title.utf8().get_data(), p_title.utf8().length());
+ }
}
void DisplayServerX11::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) {
@@ -896,11 +1002,13 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- int count = get_screen_count();
- if (p_screen >= count) {
- return;
+ if (p_screen == SCREEN_OF_MAIN_WINDOW) {
+ p_screen = window_get_current_screen();
}
+ // Check if screen is valid
+ ERR_FAIL_INDEX(p_screen, get_screen_count());
+
if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN) {
Point2i position = screen_get_position(p_screen);
Size2i size = screen_get_size(p_screen);
@@ -925,6 +1033,8 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent
WindowID prev_parent = wd_window.transient_parent;
ERR_FAIL_COND(prev_parent == p_parent);
+ DEBUG_LOG_X11("window_set_transient: %lu (%u), prev_parent=%u, parent=%u\n", wd_window.x11_window, p_window, prev_parent, p_parent);
+
ERR_FAIL_COND_MSG(wd_window.on_top, "Windows with the 'on top' can't become transient.");
if (p_parent == INVALID_WINDOW_ID) {
//remove transient
@@ -939,10 +1049,10 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent
XSetTransientForHint(x11_display, wd_window.x11_window, None);
- // Set focus to parent sub window to avoid losing all focus with nested menus.
+ // Set focus to parent sub window to avoid losing all focus when closing a nested sub-menu.
// RevertToPointerRoot is used to make sure we don't lose all focus in case
// a subwindow and its parent are both destroyed.
- if (wd_window.menu_type && !wd_window.no_focus) {
+ if (wd_window.menu_type && !wd_window.no_focus && wd_window.focused) {
if (!wd_parent.no_focus) {
XSetInputFocus(x11_display, wd_parent.x11_window, RevertToPointerRoot, CurrentTime);
}
@@ -1184,6 +1294,10 @@ bool DisplayServerX11::_window_maximize_check(WindowID p_window, const char *p_a
unsigned char *data = nullptr;
bool retval = false;
+ if (property == None) {
+ return false;
+ }
+
int result = XGetWindowProperty(
x11_display,
wd.x11_window,
@@ -1272,7 +1386,9 @@ void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
hints.flags = 2;
hints.decorations = 0;
property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
- XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ if (property != None) {
+ XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ }
}
if (p_enabled) {
@@ -1299,7 +1415,9 @@ void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
// set bypass compositor hint
Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False);
unsigned long compositing_disable_on = p_enabled ? 1 : 0;
- XChangeProperty(x11_display, wd.x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1);
+ if (bypass_compositor != None) {
+ XChangeProperty(x11_display, wd.x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1);
+ }
XFlush(x11_display);
@@ -1313,7 +1431,9 @@ void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) {
hints.flags = 2;
hints.decorations = window_get_flag(WINDOW_FLAG_BORDERLESS, p_window) ? 0 : 1;
property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
- XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ if (property != None) {
+ XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ }
}
}
@@ -1448,6 +1568,10 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c
{ // Test minimized.
// Using ICCCM -- Inter-Client Communication Conventions Manual
Atom property = XInternAtom(x11_display, "WM_STATE", True);
+ if (property == None) {
+ return WINDOW_MODE_WINDOWED;
+ }
+
Atom type;
int format;
unsigned long len;
@@ -1503,7 +1627,9 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
hints.flags = 2;
hints.decorations = p_enabled ? 0 : 1;
property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
- XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ if (property != None) {
+ XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ }
// Preserve window size
window_set_size(window_get_size(p_window), p_window);
@@ -1642,8 +1768,8 @@ bool DisplayServerX11::window_can_draw(WindowID p_window) const {
bool DisplayServerX11::can_any_window_draw() const {
_THREAD_SAFE_METHOD_
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (window_get_mode(E->key()) != WINDOW_MODE_MINIMIZED) {
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ if (window_get_mode(E.key) != WINDOW_MODE_MINIMIZED) {
return true;
}
}
@@ -1715,12 +1841,12 @@ void DisplayServerX11::cursor_set_shape(CursorShape p_shape) {
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
if (cursors[p_shape] != None) {
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- XDefineCursor(x11_display, E->get().x11_window, cursors[p_shape]);
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ XDefineCursor(x11_display, E.value.x11_window, cursors[p_shape]);
}
} else if (cursors[CURSOR_ARROW] != None) {
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- XDefineCursor(x11_display, E->get().x11_window, cursors[CURSOR_ARROW]);
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ XDefineCursor(x11_display, E.value.x11_window, cursors[CURSOR_ARROW]);
}
}
}
@@ -1754,7 +1880,7 @@ void DisplayServerX11::cursor_set_custom_image(const RES &p_cursor, CursorShape
Rect2i atlas_rect;
if (texture.is_valid()) {
- image = texture->get_data();
+ image = texture->get_image();
}
if (!image.is_valid() && atlas_texture.is_valid()) {
@@ -1777,7 +1903,7 @@ void DisplayServerX11::cursor_set_custom_image(const RES &p_cursor, CursorShape
ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256);
ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height);
- image = texture->get_data();
+ image = texture->get_image();
ERR_FAIL_COND(!image.is_valid());
@@ -1818,8 +1944,8 @@ void DisplayServerX11::cursor_set_custom_image(const RES &p_cursor, CursorShape
if (p_shape == current_cursor) {
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- XDefineCursor(x11_display, E->get().x11_window, cursors[p_shape]);
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ XDefineCursor(x11_display, E.value.x11_window, cursors[p_shape]);
}
}
}
@@ -1849,7 +1975,7 @@ int DisplayServerX11::keyboard_get_layout_count() const {
XkbGetNames(x11_display, XkbSymbolsNameMask, kbd);
const Atom *groups = kbd->names->groups;
- if (kbd->ctrls != NULL) {
+ if (kbd->ctrls != nullptr) {
_group_count = kbd->ctrls->num_groups;
} else {
while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) {
@@ -1883,7 +2009,7 @@ String DisplayServerX11::keyboard_get_layout_language(int p_index) const {
int _group_count = 0;
const Atom *groups = kbd->names->groups;
- if (kbd->ctrls != NULL) {
+ if (kbd->ctrls != nullptr) {
_group_count = kbd->ctrls->num_groups;
} else {
while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) {
@@ -1922,7 +2048,7 @@ String DisplayServerX11::keyboard_get_layout_name(int p_index) const {
int _group_count = 0;
const Atom *groups = kbd->names->groups;
- if (kbd->ctrls != NULL) {
+ if (kbd->ctrls != nullptr) {
_group_count = kbd->ctrls->num_groups;
} else {
while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) {
@@ -1942,29 +2068,48 @@ String DisplayServerX11::keyboard_get_layout_name(int p_index) const {
return ret;
}
+Key DisplayServerX11::keyboard_get_keycode_from_physical(Key p_keycode) const {
+ unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK;
+ unsigned int keycode_no_mod = p_keycode & KEY_CODE_MASK;
+ unsigned int xkeycode = KeyMappingX11::get_xlibcode((Key)keycode_no_mod);
+ KeySym xkeysym = XkbKeycodeToKeysym(x11_display, xkeycode, 0, 0);
+ if (xkeysym >= 'a' && xkeysym <= 'z') {
+ xkeysym -= ('a' - 'A');
+ }
+
+ Key key = KeyMappingX11::get_keycode(xkeysym);
+ // If not found, fallback to QWERTY.
+ // This should match the behavior of the event pump
+ if (key == KEY_NONE) {
+ return p_keycode;
+ }
+ return (Key)(key | modifiers);
+}
+
DisplayServerX11::Property DisplayServerX11::_read_property(Display *p_display, Window p_window, Atom p_property) {
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
+ Atom actual_type = None;
+ int actual_format = 0;
+ unsigned long nitems = 0;
+ unsigned long bytes_after = 0;
unsigned char *ret = nullptr;
int read_bytes = 1024;
- //Keep trying to read the property until there are no
- //bytes unread.
- do {
- if (ret != nullptr) {
- XFree(ret);
- }
+ // Keep trying to read the property until there are no bytes unread.
+ if (p_property != None) {
+ do {
+ if (ret != nullptr) {
+ XFree(ret);
+ }
- XGetWindowProperty(p_display, p_window, p_property, 0, read_bytes, False, AnyPropertyType,
- &actual_type, &actual_format, &nitems, &bytes_after,
- &ret);
+ XGetWindowProperty(p_display, p_window, p_property, 0, read_bytes, False, AnyPropertyType,
+ &actual_type, &actual_format, &nitems, &bytes_after,
+ &ret);
- read_bytes *= 2;
+ read_bytes *= 2;
- } while (bytes_after != 0);
+ } while (bytes_after != 0);
+ }
Property p = { ret, actual_format, (int)nitems, actual_type };
@@ -2002,19 +2147,19 @@ static Atom pick_target_from_atoms(Display *p_disp, Atom p_t1, Atom p_t2, Atom p
}
void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state) {
- state->set_shift((p_x11_state & ShiftMask));
- state->set_control((p_x11_state & ControlMask));
- state->set_alt((p_x11_state & Mod1Mask /*|| p_x11_state&Mod5Mask*/)); //altgr should not count as alt
- state->set_metakey((p_x11_state & Mod4Mask));
+ state->set_shift_pressed((p_x11_state & ShiftMask));
+ state->set_ctrl_pressed((p_x11_state & ControlMask));
+ state->set_alt_pressed((p_x11_state & Mod1Mask /*|| p_x11_state&Mod5Mask*/)); //altgr should not count as alt
+ state->set_meta_pressed((p_x11_state & Mod4Mask));
}
-unsigned int DisplayServerX11::_get_mouse_button_state(unsigned int p_x11_button, int p_x11_type) {
- unsigned int mask = 1 << (p_x11_button - 1);
+MouseButton DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) {
+ MouseButton mask = MouseButton(1 << (p_x11_button - 1));
if (p_x11_type == ButtonPress) {
last_button_state |= mask;
} else {
- last_button_state &= ~mask;
+ last_button_state &= MouseButton(~mask);
}
return last_button_state;
@@ -2040,7 +2185,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
// still works in half the cases. (won't handle deadkeys)
// For more complex input methods (deadkeys and more advanced)
// you have to use XmbLookupString (??).
- // So.. then you have to chosse which of both results
+ // So then you have to choose which of both results
// you want to keep.
// This is a real bizarreness and cpu waster.
@@ -2080,7 +2225,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
if (status == XLookupChars) {
bool keypress = xkeyevent->type == KeyPress;
- unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode);
+ Key keycode = KeyMappingX11::get_keycode(keysym_keycode);
unsigned int physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
if (keycode >= 'a' && keycode <= 'z') {
@@ -2091,13 +2236,13 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
tmp.parse_utf8(utf8string, utf8bytes);
for (int i = 0; i < tmp.length(); i++) {
Ref<InputEventKey> k;
- k.instance();
+ k.instantiate();
if (physical_keycode == 0 && keycode == 0 && tmp[i] == 0) {
continue;
}
if (keycode == 0) {
- keycode = physical_keycode;
+ keycode = (Key)physical_keycode;
}
_get_key_modifier_state(xkeyevent->state, k);
@@ -2109,7 +2254,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
k->set_keycode(keycode);
- k->set_physical_keycode(physical_keycode);
+ k->set_physical_keycode((Key)physical_keycode);
k->set_echo(false);
@@ -2117,10 +2262,10 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
//make it consistent across platforms.
k->set_keycode(KEY_TAB);
k->set_physical_keycode(KEY_TAB);
- k->set_shift(true);
+ k->set_shift_pressed(true);
}
- Input::get_singleton()->accumulate_input_event(k);
+ Input::get_singleton()->parse_input_event(k);
}
memfree(utf8string);
return;
@@ -2144,7 +2289,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
// KeyMappingX11 just translated the X11 keysym to a PIGUI
// keysym, so it works in all platforms the same.
- unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode);
+ Key keycode = KeyMappingX11::get_keycode(keysym_keycode);
unsigned int physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
/* Phase 3, obtain a unicode character from the keysym */
@@ -2165,12 +2310,12 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
bool keypress = xkeyevent->type == KeyPress;
- if (physical_keycode == 0 && keycode == 0 && unicode == 0) {
+ if (physical_keycode == 0 && keycode == KEY_NONE && unicode == 0) {
return;
}
- if (keycode == 0) {
- keycode = physical_keycode;
+ if (keycode == KEY_NONE) {
+ keycode = (Key)physical_keycode;
}
/* Phase 5, determine modifier mask */
@@ -2182,7 +2327,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
//print_verbose("mod1: "+itos(xkeyevent->state&Mod1Mask)+" mod 5: "+itos(xkeyevent->state&Mod5Mask));
Ref<InputEventKey> k;
- k.instance();
+ k.instantiate();
k->set_window_id(p_window);
_get_key_modifier_state(xkeyevent->state, k);
@@ -2233,11 +2378,11 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
k->set_pressed(keypress);
if (keycode >= 'a' && keycode <= 'z') {
- keycode -= 'a' - 'A';
+ keycode -= int('a' - 'A');
}
k->set_keycode(keycode);
- k->set_physical_keycode(physical_keycode);
+ k->set_physical_keycode((Key)physical_keycode);
k->set_unicode(unicode);
k->set_echo(p_echo);
@@ -2245,20 +2390,20 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
//make it consistent across platforms.
k->set_keycode(KEY_TAB);
k->set_physical_keycode(KEY_TAB);
- k->set_shift(true);
+ k->set_shift_pressed(true);
}
//don't set mod state if modifier keys are released by themselves
//else event.is_action() will not work correctly here
if (!k->is_pressed()) {
if (k->get_keycode() == KEY_SHIFT) {
- k->set_shift(false);
- } else if (k->get_keycode() == KEY_CONTROL) {
- k->set_control(false);
+ k->set_shift_pressed(false);
+ } else if (k->get_keycode() == KEY_CTRL) {
+ k->set_ctrl_pressed(false);
} else if (k->get_keycode() == KEY_ALT) {
- k->set_alt(false);
+ k->set_alt_pressed(false);
} else if (k->get_keycode() == KEY_META) {
- k->set_metakey(false);
+ k->set_meta_pressed(false);
}
}
@@ -2269,56 +2414,108 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
}
}
- Input::get_singleton()->accumulate_input_event(k);
+ Input::get_singleton()->parse_input_event(k);
}
-void DisplayServerX11::_handle_selection_request_event(XSelectionRequestEvent *p_event) {
- XEvent respond;
- if (p_event->target == XInternAtom(x11_display, "UTF8_STRING", 0) ||
- p_event->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) ||
- p_event->target == XInternAtom(x11_display, "TEXT", 0) ||
- p_event->target == XA_STRING ||
- p_event->target == XInternAtom(x11_display, "text/plain;charset=utf-8", 0) ||
- p_event->target == XInternAtom(x11_display, "text/plain", 0)) {
- // Directly using internal clipboard because we know our window
- // is the owner during a selection request.
- CharString clip = internal_clipboard.utf8();
- XChangeProperty(x11_display,
- p_event->requestor,
- p_event->property,
- p_event->target,
- 8,
- PropModeReplace,
- (unsigned char *)clip.get_data(),
- clip.length());
- respond.xselection.property = p_event->property;
- } else if (p_event->target == XInternAtom(x11_display, "TARGETS", 0)) {
- Atom data[7];
+Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property) const {
+ if (p_target == XInternAtom(x11_display, "TARGETS", 0)) {
+ // Request to list all supported targets.
+ Atom data[9];
data[0] = XInternAtom(x11_display, "TARGETS", 0);
- data[1] = XInternAtom(x11_display, "UTF8_STRING", 0);
- data[2] = XInternAtom(x11_display, "COMPOUND_TEXT", 0);
- data[3] = XInternAtom(x11_display, "TEXT", 0);
- data[4] = XA_STRING;
- data[5] = XInternAtom(x11_display, "text/plain;charset=utf-8", 0);
- data[6] = XInternAtom(x11_display, "text/plain", 0);
+ data[1] = XInternAtom(x11_display, "SAVE_TARGETS", 0);
+ data[2] = XInternAtom(x11_display, "MULTIPLE", 0);
+ data[3] = XInternAtom(x11_display, "UTF8_STRING", 0);
+ data[4] = XInternAtom(x11_display, "COMPOUND_TEXT", 0);
+ data[5] = XInternAtom(x11_display, "TEXT", 0);
+ data[6] = XA_STRING;
+ data[7] = XInternAtom(x11_display, "text/plain;charset=utf-8", 0);
+ data[8] = XInternAtom(x11_display, "text/plain", 0);
XChangeProperty(x11_display,
- p_event->requestor,
- p_event->property,
+ p_requestor,
+ p_property,
XA_ATOM,
32,
PropModeReplace,
(unsigned char *)&data,
sizeof(data) / sizeof(data[0]));
- respond.xselection.property = p_event->property;
-
+ return p_property;
+ } else if (p_target == XInternAtom(x11_display, "SAVE_TARGETS", 0)) {
+ // Request to check if SAVE_TARGETS is supported, nothing special to do.
+ XChangeProperty(x11_display,
+ p_requestor,
+ p_property,
+ XInternAtom(x11_display, "NULL", False),
+ 32,
+ PropModeReplace,
+ nullptr,
+ 0);
+ return p_property;
+ } else if (p_target == XInternAtom(x11_display, "UTF8_STRING", 0) ||
+ p_target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) ||
+ p_target == XInternAtom(x11_display, "TEXT", 0) ||
+ p_target == XA_STRING ||
+ p_target == XInternAtom(x11_display, "text/plain;charset=utf-8", 0) ||
+ p_target == XInternAtom(x11_display, "text/plain", 0)) {
+ // Directly using internal clipboard because we know our window
+ // is the owner during a selection request.
+ CharString clip = internal_clipboard.utf8();
+ XChangeProperty(x11_display,
+ p_requestor,
+ p_property,
+ p_target,
+ 8,
+ PropModeReplace,
+ (unsigned char *)clip.get_data(),
+ clip.length());
+ return p_property;
} else {
- char *targetname = XGetAtomName(x11_display, p_event->target);
- printf("No Target '%s'\n", targetname);
- if (targetname) {
- XFree(targetname);
+ char *target_name = XGetAtomName(x11_display, p_target);
+ printf("Target '%s' not supported.\n", target_name);
+ if (target_name) {
+ XFree(target_name);
}
+ return None;
+ }
+}
+
+void DisplayServerX11::_handle_selection_request_event(XSelectionRequestEvent *p_event) const {
+ XEvent respond;
+ if (p_event->target == XInternAtom(x11_display, "MULTIPLE", 0)) {
+ // Request for multiple target conversions at once.
+ Atom atom_pair = XInternAtom(x11_display, "ATOM_PAIR", False);
respond.xselection.property = None;
+
+ Atom type;
+ int format;
+ unsigned long len;
+ unsigned long remaining;
+ unsigned char *data = nullptr;
+ if (XGetWindowProperty(x11_display, p_event->requestor, p_event->property, 0, LONG_MAX, False, atom_pair, &type, &format, &len, &remaining, &data) == Success) {
+ if ((len >= 2) && data) {
+ Atom *targets = (Atom *)data;
+ for (uint64_t i = 0; i < len; i += 2) {
+ Atom target = targets[i];
+ Atom &property = targets[i + 1];
+ property = _process_selection_request_target(target, p_event->requestor, property);
+ }
+
+ XChangeProperty(x11_display,
+ p_event->requestor,
+ p_event->property,
+ atom_pair,
+ 32,
+ PropModeReplace,
+ (unsigned char *)targets,
+ len);
+
+ respond.xselection.property = p_event->property;
+ }
+ XFree(data);
+ }
+ } else {
+ // Request for target conversion.
+ respond.xselection.property = _process_selection_request_target(p_event->target, p_event->requestor, p_event->property);
}
respond.xselection.type = SelectionNotify;
@@ -2338,8 +2535,8 @@ void DisplayServerX11::_xim_destroy_callback(::XIM im, ::XPointer client_data,
DisplayServerX11 *ds = reinterpret_cast<DisplayServerX11 *>(client_data);
ds->xim = nullptr;
- for (Map<WindowID, WindowData>::Element *E = ds->windows.front(); E; E = E->next()) {
- E->get().xic = nullptr;
+ for (KeyValue<WindowID, WindowData> &E : ds->windows) {
+ E.value.xic = nullptr;
}
}
@@ -2347,9 +2544,9 @@ void DisplayServerX11::_window_changed(XEvent *event) {
WindowID window_id = MAIN_WINDOW_ID;
// Assign the event to the relevant window
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (event->xany.window == E->get().x11_window) {
- window_id = E->key();
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ if (event->xany.window == E.value.x11_window) {
+ window_id = E.key;
break;
}
}
@@ -2390,7 +2587,6 @@ void DisplayServerX11::_window_changed(XEvent *event) {
}
#endif
- print_line("DisplayServer::_window_changed: " + itos(window_id) + " rect: " + new_rect);
if (!wd.rect_changed_callback.is_null()) {
Rect2i r = new_rect;
@@ -2424,8 +2620,8 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) {
callable.call((const Variant **)&evp, 1, ret, ce);
} else {
//send to all windows
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- Callable callable = E->get().input_event_callback;
+ for (KeyValue<WindowID, WindowData> &E : windows) {
+ Callable callable = E.value.input_event_callback;
if (callable.is_null()) {
continue;
}
@@ -2454,32 +2650,43 @@ Bool DisplayServerX11::_predicate_all_events(Display *display, XEvent *event, XP
return True;
}
-void DisplayServerX11::_poll_events() {
+bool DisplayServerX11::_wait_for_events() const {
int x11_fd = ConnectionNumber(x11_display);
fd_set in_fds;
- while (!events_thread_done) {
- XFlush(x11_display);
+ XFlush(x11_display);
+
+ FD_ZERO(&in_fds);
+ FD_SET(x11_fd, &in_fds);
- FD_ZERO(&in_fds);
- FD_SET(x11_fd, &in_fds);
+ struct timeval tv;
+ tv.tv_usec = 0;
+ tv.tv_sec = 1;
- struct timeval tv;
- tv.tv_usec = 0;
- tv.tv_sec = 1;
+ // Wait for next event or timeout.
+ int num_ready_fds = select(x11_fd + 1, &in_fds, nullptr, nullptr, &tv);
- // Wait for next event or timeout.
- int num_ready_fds = select(x11_fd + 1, &in_fds, NULL, NULL, &tv);
+ if (num_ready_fds > 0) {
+ // Event received.
+ return true;
+ } else {
+ // Error or timeout.
if (num_ready_fds < 0) {
- ERR_PRINT("_poll_events: select error: " + itos(errno));
+ ERR_PRINT("_wait_for_events: select error: " + itos(errno));
}
+ return false;
+ }
+}
+
+void DisplayServerX11::_poll_events() {
+ while (!events_thread_done.is_set()) {
+ _wait_for_events();
// Process events from the queue.
{
MutexLock mutex_lock(events_mutex);
- // Non-blocking wait for next event
- // and remove it from the queue.
+ // Non-blocking wait for next event and remove it from the queue.
XEvent ev;
while (XCheckIfEvent(x11_display, &ev, _predicate_all_events, nullptr)) {
// Check if the input manager wants to process the event.
@@ -2514,8 +2721,8 @@ void DisplayServerX11::process_events() {
if (app_focused) {
//verify that one of the windows has focus, else send focus out notification
bool focus_found = false;
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (E->get().focused) {
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ if (E.value.focused) {
focus_found = true;
break;
}
@@ -2540,7 +2747,7 @@ void DisplayServerX11::process_events() {
do_mouse_warp = false;
// Is the current mouse mode one where it needs to be grabbed.
- bool mouse_mode_grab = mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED;
+ bool mouse_mode_grab = mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN;
xi.pressure = 0;
xi.tilt = Vector2();
@@ -2560,9 +2767,9 @@ void DisplayServerX11::process_events() {
WindowID window_id = MAIN_WINDOW_ID;
// Assign the event to the relevant window
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (event.xany.window == E->get().x11_window) {
- window_id = E->key();
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ if (event.xany.window == E.value.x11_window) {
+ window_id = E.key;
break;
}
}
@@ -2678,7 +2885,7 @@ void DisplayServerX11::process_events() {
bool is_begin = event_data->evtype == XI_TouchBegin;
Ref<InputEventScreenTouch> st;
- st.instance();
+ st.instantiate();
st->set_window_id(window_id);
st->set_index(index);
st->set_position(pos);
@@ -2694,13 +2901,13 @@ void DisplayServerX11::process_events() {
// in a spurious mouse motion event being sent to Godot; remember it to be able to filter it out
xi.mouse_pos_to_filter = pos;
}
- Input::get_singleton()->accumulate_input_event(st);
+ Input::get_singleton()->parse_input_event(st);
} else {
if (!xi.state.has(index)) { // Defensive
break;
}
xi.state.erase(index);
- Input::get_singleton()->accumulate_input_event(st);
+ Input::get_singleton()->parse_input_event(st);
}
} break;
@@ -2712,12 +2919,12 @@ void DisplayServerX11::process_events() {
if (curr_pos_elem->value() != pos) {
Ref<InputEventScreenDrag> sd;
- sd.instance();
+ sd.instantiate();
sd->set_window_id(window_id);
sd->set_index(index);
sd->set_position(pos);
sd->set_relative(pos - curr_pos_elem->value());
- Input::get_singleton()->accumulate_input_event(sd);
+ Input::get_singleton()->parse_input_event(sd);
curr_pos_elem->value() = pos;
}
@@ -2801,17 +3008,17 @@ void DisplayServerX11::process_events() {
if (mouse_mode_grab) {
// Show and update the cursor if confined and the window regained focus.
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
if (mouse_mode == MOUSE_MODE_CONFINED) {
- XUndefineCursor(x11_display, E->get().x11_window);
- } else if (mouse_mode == MOUSE_MODE_CAPTURED) { // or re-hide it in captured mode
- XDefineCursor(x11_display, E->get().x11_window, null_cursor);
+ XUndefineCursor(x11_display, E.value.x11_window);
+ } else if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { // Or re-hide it.
+ XDefineCursor(x11_display, E.value.x11_window, null_cursor);
}
XGrabPointer(
- x11_display, E->get().x11_window, True,
+ x11_display, E.value.x11_window, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
- GrabModeAsync, GrabModeAsync, E->get().x11_window, None, CurrentTime);
+ GrabModeAsync, GrabModeAsync, E.value.x11_window, None, CurrentTime);
}
}
#ifdef TOUCH_ENABLED
@@ -2847,11 +3054,11 @@ void DisplayServerX11::process_events() {
_send_window_event(wd, WINDOW_EVENT_FOCUS_OUT);
if (mouse_mode_grab) {
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
//dear X11, I try, I really try, but you never work, you do whathever you want.
if (mouse_mode == MOUSE_MODE_CAPTURED) {
// Show the cursor if we're in captured mode so it doesn't look weird.
- XUndefineCursor(x11_display, E->get().x11_window);
+ XUndefineCursor(x11_display, E.value.x11_window);
}
}
XUngrabPointer(x11_display, CurrentTime);
@@ -2863,13 +3070,13 @@ void DisplayServerX11::process_events() {
}*/
// Release every pointer to avoid sticky points
- for (Map<int, Vector2>::Element *E = xi.state.front(); E; E = E->next()) {
+ for (const KeyValue<int, Vector2> &E : xi.state) {
Ref<InputEventScreenTouch> st;
- st.instance();
- st->set_index(E->key());
+ st.instantiate();
+ st->set_index(E.key);
st->set_window_id(window_id);
- st->set_position(E->get());
- Input::get_singleton()->accumulate_input_event(st);
+ st->set_position(E.value);
+ Input::get_singleton()->parse_input_event(st);
}
xi.state.clear();
#endif
@@ -2900,15 +3107,15 @@ void DisplayServerX11::process_events() {
}
Ref<InputEventMouseButton> mb;
- mb.instance();
+ mb.instantiate();
mb->set_window_id(window_id);
_get_key_modifier_state(event.xbutton.state, mb);
- mb->set_button_index(event.xbutton.button);
- if (mb->get_button_index() == 2) {
- mb->set_button_index(3);
- } else if (mb->get_button_index() == 3) {
- mb->set_button_index(2);
+ mb->set_button_index((MouseButton)event.xbutton.button);
+ if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
+ mb->set_button_index(MOUSE_BUTTON_MIDDLE);
+ } else if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE) {
+ mb->set_button_index(MOUSE_BUTTON_RIGHT);
}
mb->set_button_mask(_get_mouse_button_state(mb->get_button_index(), event.xbutton.type));
mb->set_position(Vector2(event.xbutton.x, event.xbutton.y));
@@ -2935,14 +3142,14 @@ void DisplayServerX11::process_events() {
last_click_ms = 0;
last_click_pos = Point2i(-100, -100);
last_click_button_index = -1;
- mb->set_doubleclick(true);
+ mb->set_double_click(true);
}
} else if (mb->get_button_index() < 4 || mb->get_button_index() > 7) {
last_click_button_index = mb->get_button_index();
}
- if (!mb->is_doubleclick()) {
+ if (!mb->is_double_click()) {
last_click_ms += diff;
last_click_pos = Point2i(event.xbutton.x, event.xbutton.y);
}
@@ -2955,9 +3162,9 @@ void DisplayServerX11::process_events() {
// Note: This is needed for drag & drop to work between windows,
// because the engine expects events to keep being processed
// on the same window dragging started.
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- const WindowData &wd_other = E->get();
- WindowID window_id_other = E->key();
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ const WindowData &wd_other = E.value;
+ WindowID window_id_other = E.key;
if (wd_other.focused) {
if (window_id_other != window_id) {
int x, y;
@@ -2967,7 +3174,7 @@ void DisplayServerX11::process_events() {
mb->set_window_id(window_id_other);
mb->set_position(Vector2(x, y));
mb->set_global_position(mb->get_position());
- Input::get_singleton()->accumulate_input_event(mb);
+ Input::get_singleton()->parse_input_event(mb);
}
break;
}
@@ -2975,7 +3182,7 @@ void DisplayServerX11::process_events() {
}
}
- Input::get_singleton()->accumulate_input_event(mb);
+ Input::get_singleton()->parse_input_event(mb);
} break;
case MotionNotify: {
@@ -3065,13 +3272,13 @@ void DisplayServerX11::process_events() {
}
Ref<InputEventMouseMotion> mm;
- mm.instance();
+ mm.instantiate();
mm->set_window_id(window_id);
if (xi.pressure_supported) {
mm->set_pressure(xi.pressure);
} else {
- mm->set_pressure((mouse_get_button_state() & (1 << (BUTTON_LEFT - 1))) ? 1.0f : 0.0f);
+ mm->set_pressure((mouse_get_button_state() & MOUSE_BUTTON_MASK_LEFT) ? 1.0f : 0.0f);
}
mm->set_tilt(xi.tilt);
@@ -3091,15 +3298,15 @@ void DisplayServerX11::process_events() {
// this is so that the relative motion doesn't get messed up
// after we regain focus.
if (focused) {
- Input::get_singleton()->accumulate_input_event(mm);
+ Input::get_singleton()->parse_input_event(mm);
} else {
// Propagate the event to the focused window,
// because it's received only on the topmost window.
// Note: This is needed for drag & drop to work between windows,
// because the engine expects events to keep being processed
// on the same window dragging started.
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- const WindowData &wd_other = E->get();
+ for (const KeyValue<WindowID, WindowData> &E : windows) {
+ const WindowData &wd_other = E.value;
if (wd_other.focused) {
int x, y;
Window child;
@@ -3107,11 +3314,11 @@ void DisplayServerX11::process_events() {
Point2i pos_focused(x, y);
- mm->set_window_id(E->key());
+ mm->set_window_id(E.key);
mm->set_position(pos_focused);
mm->set_global_position(pos_focused);
mm->set_speed(Input::get_singleton()->get_last_mouse_speed());
- Input::get_singleton()->accumulate_input_event(mm);
+ Input::get_singleton()->parse_input_event(mm);
break;
}
@@ -3135,7 +3342,7 @@ void DisplayServerX11::process_events() {
Vector<String> files = String((char *)p.data).split("\n", false);
for (int i = 0; i < files.size(); i++) {
- files.write[i] = files[i].replace("file://", "").http_unescape().strip_edges();
+ files.write[i] = files[i].replace("file://", "").uri_decode().strip_edges();
}
if (!windows[window_id].drop_files_callback.is_null()) {
@@ -3244,7 +3451,7 @@ void DisplayServerX11::process_events() {
*/
}
- Input::get_singleton()->flush_accumulated_events();
+ Input::get_singleton()->flush_buffered_events();
}
void DisplayServerX11::release_rendering_thread() {
@@ -3298,8 +3505,8 @@ void DisplayServerX11::set_context(Context p_context) {
context = p_context;
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- _update_context(E->get());
+ for (KeyValue<WindowID, WindowData> &E : windows) {
+ _update_context(E.value);
}
}
@@ -3376,7 +3583,9 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) {
pr += 4;
}
- XChangeProperty(x11_display, wd.x11_window, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pd.ptr(), pd.size());
+ if (net_wm_icon != None) {
+ XChangeProperty(x11_display, wd.x11_window, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pd.ptr(), pd.size());
+ }
if (!g_set_icon_error) {
break;
@@ -3390,6 +3599,22 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) {
XSetErrorHandler(oldHandler);
}
+void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#endif
+}
+
+DisplayServer::VSyncMode DisplayServerX11::window_get_vsync_mode(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+#if defined(VULKAN_ENABLED)
+ return context_vulkan->get_vsync_mode(p_window);
+#else
+ return DisplayServer::VSYNC_ENABLED;
+#endif
+}
+
Vector<String> DisplayServerX11::get_rendering_drivers_func() {
Vector<String> drivers;
@@ -3403,17 +3628,18 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
return drivers;
}
-DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_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_resolution, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
- ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
- "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
+ OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan 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");
}
return ds;
}
-DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
//Create window
long visualMask = VisualScreenMask;
@@ -3469,7 +3695,9 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
{
const long pid = OS::get_singleton()->get_process_id();
Atom net_wm_pid = XInternAtom(x11_display, "_NET_WM_PID", False);
- XChangeProperty(x11_display, wd.x11_window, net_wm_pid, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1);
+ if (net_wm_pid != None) {
+ XChangeProperty(x11_display, wd.x11_window, net_wm_pid, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1);
+ }
}
long im_event_mask = 0;
@@ -3517,7 +3745,9 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
/* set the titlebar name */
XStoreName(x11_display, wd.x11_window, "Godot");
XSetWMProtocols(x11_display, wd.x11_window, &wm_delete, 1);
- XChangeProperty(x11_display, wd.x11_window, xdnd_aware, XA_ATOM, 32, PropModeReplace, (unsigned char *)&xdnd_version, 1);
+ if (xdnd_aware != None) {
+ XChangeProperty(x11_display, wd.x11_window, xdnd_aware, XA_ATOM, 32, PropModeReplace, (unsigned char *)&xdnd_version, 1);
+ }
if (xim && xim_style) {
// Block events polling while changing input focus
@@ -3548,27 +3778,32 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
hints.flags = 2;
hints.decorations = 0;
property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
- XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ if (property != None) {
+ XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ }
}
if (wd.menu_type) {
// Set Utility type to disable fade animations.
Atom type_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
Atom wt_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE", False);
-
- XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1);
+ if (wt_atom != None && type_atom != None) {
+ XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1);
+ }
} else {
Atom type_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
Atom wt_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE", False);
- XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1);
+ if (wt_atom != None && type_atom != None) {
+ XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1);
+ }
}
_update_size_hints(id);
#if defined(VULKAN_ENABLED)
if (context_vulkan) {
- Error err = context_vulkan->window_create(id, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height);
+ Error err = context_vulkan->window_create(id, p_vsync_mode, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan window");
}
#endif
@@ -3595,8 +3830,6 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
wd.position.y = xwa.y;
wd.size.width = xwa.width;
wd.size.height = xwa.height;
-
- print_line("DisplayServer::_create_window " + itos(id) + " want rect: " + p_rect + " got rect " + Rect2i(xwa.x, xwa.y, xwa.width, xwa.height));
}
//set cursor
@@ -3607,7 +3840,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u
return id;
}
-DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_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_resolution, Error &r_error) {
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
@@ -3620,8 +3853,6 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
img[i] = nullptr;
}
- last_button_state = 0;
-
xmbstring = nullptr;
last_click_ms = 0;
@@ -3700,8 +3931,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
if (!_refresh_device_info()) {
- alert("Your system does not support XInput 2.\n"
- "Please upgrade your distribution.",
+ OS::get_singleton()->alert("Your system does not support XInput 2.\n"
+ "Please upgrade your distribution.",
"Unable to initialize XInput");
r_error = ERR_UNAVAILABLE;
return;
@@ -3792,7 +4023,10 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
use_prime = 0;
}
- if (getenv("LD_LIBRARY_PATH")) {
+ // Some tools use fake libGL libraries and have them override the real one using
+ // LD_LIBRARY_PATH, so we skip them. *But* Steam also sets LD_LIBRARY_PATH for its
+ // runtime and includes system `/lib` and `/lib64`... so ignore Steam.
+ if (use_prime == -1 && getenv("LD_LIBRARY_PATH") && !getenv("STEAM_RUNTIME_LIBRARY_PATH")) {
String ld_library_path(getenv("LD_LIBRARY_PATH"));
Vector<String> libraries = ld_library_path.split(":");
@@ -3842,7 +4076,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);
- WindowID main_window = _create_window(p_mode, p_flags, Rect2i(window_position, p_resolution));
+ 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;
+ return;
+ }
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, main_window);
@@ -3857,12 +4095,12 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
rendering_device_vulkan = memnew(RenderingDeviceVulkan);
rendering_device_vulkan->initialize(context_vulkan);
- RasterizerRD::make_current();
+ RendererCompositorRD::make_current();
}
#endif
/*
- rendering_server = memnew(RenderingServerRaster);
+ rendering_server = memnew(RenderingServerDefault);
if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
rendering_server = memnew(RenderingServerWrapMT(rendering_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
}
@@ -4026,28 +4264,36 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
}
- events_thread = Thread::create(_poll_events_thread, this);
+ events_thread.start(_poll_events_thread, this);
_update_real_mouse_position(windows[MAIN_WINDOW_ID]);
+#ifdef DBUS_ENABLED
+ screensaver = memnew(FreeDesktopScreenSaver);
+ screen_set_keep_on(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true));
+#endif
+
r_error = OK;
}
DisplayServerX11::~DisplayServerX11() {
- events_thread_done = true;
- Thread::wait_to_finish(events_thread);
- memdelete(events_thread);
- events_thread = nullptr;
+ // Send owned clipboard data to clipboard manager before exit.
+ Window x11_main_window = windows[MAIN_WINDOW_ID].x11_window;
+ _clipboard_transfer_ownership(XA_PRIMARY, x11_main_window);
+ _clipboard_transfer_ownership(XInternAtom(x11_display, "CLIPBOARD", 0), x11_main_window);
+
+ events_thread_done.set();
+ events_thread.wait_to_finish();
//destroy all windows
- for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+ for (KeyValue<WindowID, WindowData> &E : windows) {
#ifdef VULKAN_ENABLED
if (rendering_driver == "vulkan") {
- context_vulkan->window_destroy(E->key());
+ context_vulkan->window_destroy(E.key);
}
#endif
- WindowData &wd = E->get();
+ WindowData &wd = E.value;
if (wd.xic) {
XDestroyIC(wd.xic);
wd.xic = nullptr;
@@ -4091,6 +4337,10 @@ DisplayServerX11::~DisplayServerX11() {
if (xmbstring) {
memfree(xmbstring);
}
+
+#ifdef DBUS_ENABLED
+ memdelete(screensaver);
+#endif
}
void DisplayServerX11::register_x11_driver() {
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 740bf81fd9..1887c7105b 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,14 +36,14 @@
#include "servers/display_server.h"
#include "core/input/input.h"
-#include "core/local_vector.h"
+#include "core/templates/local_vector.h"
#include "drivers/alsa/audio_driver_alsa.h"
#include "drivers/alsamidi/midi_driver_alsamidi.h"
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
#include "drivers/unix/os_unix.h"
#include "joypad_linux.h"
#include "servers/audio_server.h"
-#include "servers/rendering/rasterizer.h"
+#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
#if defined(OPENGL_ENABLED)
@@ -55,33 +55,28 @@
#include "platform/linuxbsd/vulkan_context_x11.h"
#endif
+#if defined(DBUS_ENABLED)
+#include "freedesktop_screensaver.h"
+#endif
+
#include <X11/Xcursor/Xcursor.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xrandr.h>
#include <X11/keysym.h>
-// Hints for X11 fullscreen
-typedef struct {
- unsigned long flags;
- unsigned long functions;
- unsigned long decorations;
- long inputMode;
- unsigned long status;
-} Hints;
-
typedef struct _xrr_monitor_info {
Atom name;
- Bool primary;
- Bool automatic;
- int noutput;
- int x;
- int y;
- int width;
- int height;
- int mwidth;
- int mheight;
- RROutput *outputs;
+ Bool primary = false;
+ Bool automatic = false;
+ int noutput = 0;
+ int x = 0;
+ int y = 0;
+ int width = 0;
+ int height = 0;
+ int mwidth = 0;
+ int mheight = 0;
+ RROutput *outputs = nullptr;
} xrr_monitor_info;
#undef CursorShape
@@ -112,6 +107,11 @@ class DisplayServerX11 : public DisplayServer {
RenderingDeviceVulkan *rendering_device_vulkan;
#endif
+#if defined(DBUS_ENABLED)
+ FreeDesktopScreenSaver *screensaver;
+ bool keep_screen_on = false;
+#endif
+
struct WindowData {
Window x11_window;
::XIC xic;
@@ -152,7 +152,7 @@ class DisplayServerX11 : public DisplayServer {
Map<WindowID, WindowData> windows;
WindowID window_id_counter = MAIN_WINDOW_ID;
- WindowID _create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect);
+ WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
String internal_clipboard;
Window xdnd_source_window;
@@ -171,7 +171,7 @@ class DisplayServerX11 : public DisplayServer {
Point2i last_click_pos;
uint64_t last_click_ms;
int last_click_button_index;
- uint32_t last_button_state;
+ MouseButton last_button_state = MOUSE_BUTTON_NONE;
bool app_focused = false;
uint64_t time_since_no_focus = 0;
@@ -196,7 +196,7 @@ class DisplayServerX11 : public DisplayServer {
bool _refresh_device_info();
- unsigned int _get_mouse_button_state(unsigned int p_x11_button, int p_x11_type);
+ MouseButton _get_mouse_button_state(MouseButton p_x11_button, int p_x11_type);
void _get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state);
void _flush_mouse_motion();
@@ -204,10 +204,13 @@ class DisplayServerX11 : public DisplayServer {
Point2i center;
void _handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector<XEvent> &p_events, uint32_t &p_event_index, bool p_echo = false);
- void _handle_selection_request_event(XSelectionRequestEvent *p_event);
+
+ Atom _process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property) const;
+ void _handle_selection_request_event(XSelectionRequestEvent *p_event) const;
String _clipboard_get_impl(Atom p_source, Window x11_window, Atom target) const;
String _clipboard_get(Atom p_source, Window x11_window) const;
+ void _clipboard_transfer_ownership(Atom p_source, Window x11_window) const;
//bool minimized;
//bool window_has_focus;
@@ -258,126 +261,136 @@ class DisplayServerX11 : public DisplayServer {
void _dispatch_input_event(const Ref<InputEvent> &p_event);
mutable Mutex events_mutex;
- Thread *events_thread = nullptr;
- bool events_thread_done = false;
+ Thread events_thread;
+ SafeFlag events_thread_done;
LocalVector<XEvent> polled_events;
static void _poll_events_thread(void *ud);
+ bool _wait_for_events() const;
void _poll_events();
static Bool _predicate_all_events(Display *display, XEvent *event, XPointer arg);
static Bool _predicate_clipboard_selection(Display *display, XEvent *event, XPointer arg);
+ static Bool _predicate_clipboard_incr(Display *display, XEvent *event, XPointer arg);
+ static Bool _predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg);
protected:
void _window_changed(XEvent *event);
public:
- virtual bool has_feature(Feature p_feature) const;
- virtual String get_name() const;
-
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
-
- virtual void mouse_set_mode(MouseMode p_mode);
- virtual MouseMode mouse_get_mode() const;
-
- virtual void mouse_warp_to_position(const Point2i &p_to);
- virtual Point2i mouse_get_position() const;
- virtual Point2i mouse_get_absolute_position() const;
- virtual int mouse_get_button_state() const;
-
- virtual void clipboard_set(const String &p_text);
- virtual String clipboard_get() const;
+ virtual bool has_feature(Feature p_feature) const override;
+ virtual String get_name() const override;
+
+ virtual void mouse_set_mode(MouseMode p_mode) override;
+ virtual MouseMode mouse_get_mode() const override;
+
+ virtual void mouse_warp_to_position(const Point2i &p_to) override;
+ virtual Point2i mouse_get_position() const override;
+ virtual Point2i mouse_get_absolute_position() const override;
+ virtual MouseButton mouse_get_button_state() const override;
+
+ virtual void clipboard_set(const String &p_text) override;
+ virtual String clipboard_get() const override;
+
+ virtual int get_screen_count() const override;
+ virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ 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 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;
+ virtual bool screen_is_kept_on() const override;
+#endif
- virtual int get_screen_count() const;
- virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual Vector<DisplayServer::WindowID> get_window_list() const override;
- virtual Vector<DisplayServer::WindowID> get_window_list() const;
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual void show_window(WindowID p_id) override;
+ virtual void delete_sub_window(WindowID p_id) override;
- virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
- virtual void show_window(WindowID p_id);
- virtual void delete_sub_window(WindowID p_id);
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override;
- virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
+ virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
- virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
+ virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
- virtual void window_set_transient(WindowID p_window, WindowID p_parent);
+ virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID);
- virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
- virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
+ virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool can_any_window_draw() const override;
- virtual bool can_any_window_draw() const;
+ virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
- virtual void cursor_set_shape(CursorShape p_shape);
- virtual CursorShape cursor_get_shape() const;
- virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
+ virtual void cursor_set_shape(CursorShape p_shape) override;
+ virtual CursorShape cursor_get_shape() const override;
+ virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) override;
- virtual int keyboard_get_layout_count() const;
- virtual int keyboard_get_current_layout() const;
- virtual void keyboard_set_current_layout(int p_index);
- virtual String keyboard_get_layout_language(int p_index) const;
- virtual String keyboard_get_layout_name(int p_index) const;
+ virtual int keyboard_get_layout_count() const override;
+ virtual int keyboard_get_current_layout() const override;
+ virtual void keyboard_set_current_layout(int p_index) override;
+ virtual String keyboard_get_layout_language(int p_index) const override;
+ virtual String keyboard_get_layout_name(int p_index) const override;
+ virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
- virtual void process_events();
+ virtual void process_events() override;
- virtual void release_rendering_thread();
- virtual void make_rendering_thread();
- virtual void swap_buffers();
+ virtual void release_rendering_thread() override;
+ virtual void make_rendering_thread() override;
+ virtual void swap_buffers() override;
- virtual void set_context(Context p_context);
+ virtual void set_context(Context p_context) override;
- virtual void set_native_icon(const String &p_filename);
- virtual void set_icon(const Ref<Image> &p_icon);
+ 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, 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_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, 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_resolution, Error &r_error);
~DisplayServerX11();
};
diff --git a/platform/linuxbsd/export/export.cpp b/platform/linuxbsd/export/export.cpp
index 86ea95c563..965a38ef4e 100644
--- a/platform/linuxbsd/export/export.cpp
+++ b/platform/linuxbsd/export/export.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#include "export.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "editor/editor_export.h"
#include "platform/linuxbsd/logo.gen.h"
#include "scene/resources/texture.h"
@@ -39,11 +39,11 @@ static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start,
void register_linuxbsd_exporter() {
Ref<EditorExportPlatformPC> platform;
- platform.instance();
+ platform.instantiate();
Ref<Image> img = memnew(Image(_linuxbsd_logo));
Ref<ImageTexture> logo;
- logo.instance();
+ logo.instantiate();
logo->create_from_image(img);
platform->set_logo(logo);
platform->set_name("Linux/X11");
@@ -53,7 +53,7 @@ void register_linuxbsd_exporter() {
platform->set_debug_32("linux_x11_32_debug");
platform->set_release_64("linux_x11_64_release");
platform->set_debug_64("linux_x11_64_debug");
- platform->set_os_name("X11");
+ platform->set_os_name("LinuxBSD");
platform->set_chmod_flags(0755);
platform->set_fixup_embedded_pck_func(&fixup_embedded_pck);
diff --git a/platform/linuxbsd/export/export.h b/platform/linuxbsd/export/export.h
index 5ee81f485e..61e96aa2f6 100644
--- a/platform/linuxbsd/export/export.h
+++ b/platform/linuxbsd/export/export.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp
new file mode 100644
index 0000000000..a6a3b27d76
--- /dev/null
+++ b/platform/linuxbsd/freedesktop_screensaver.cpp
@@ -0,0 +1,125 @@
+/*************************************************************************/
+/* freedesktop_screensaver.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 "freedesktop_screensaver.h"
+
+#ifdef DBUS_ENABLED
+
+#include "core/config/project_settings.h"
+
+#include <dbus/dbus.h>
+
+#define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver"
+#define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver"
+#define BUS_INTERFACE "org.freedesktop.ScreenSaver"
+
+void FreeDesktopScreenSaver::inhibit() {
+ if (unsupported) {
+ return;
+ }
+
+ DBusError error;
+ dbus_error_init(&error);
+
+ DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
+ if (dbus_error_is_set(&error)) {
+ unsupported = true;
+ return;
+ }
+
+ String app_name_string = ProjectSettings::get_singleton()->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();
+
+ const char *reason = "Running Godot Engine project";
+
+ DBusMessage *message = dbus_message_new_method_call(
+ BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE,
+ "Inhibit");
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &app_name,
+ DBUS_TYPE_STRING, &reason,
+ DBUS_TYPE_INVALID);
+
+ DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
+ dbus_message_unref(message);
+ if (dbus_error_is_set(&error)) {
+ dbus_connection_unref(bus);
+ unsupported = false;
+ return;
+ }
+
+ DBusMessageIter reply_iter;
+ dbus_message_iter_init(reply, &reply_iter);
+ dbus_message_iter_get_basic(&reply_iter, &cookie);
+ print_verbose("FreeDesktopScreenSaver: Acquired screensaver inhibition cookie: " + uitos(cookie));
+
+ dbus_message_unref(reply);
+ dbus_connection_unref(bus);
+}
+
+void FreeDesktopScreenSaver::uninhibit() {
+ if (unsupported) {
+ return;
+ }
+
+ DBusError error;
+ dbus_error_init(&error);
+
+ DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
+ if (dbus_error_is_set(&error)) {
+ unsupported = true;
+ return;
+ }
+
+ DBusMessage *message = dbus_message_new_method_call(
+ BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE,
+ "UnInhibit");
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT32, &cookie,
+ DBUS_TYPE_INVALID);
+
+ DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
+ if (dbus_error_is_set(&error)) {
+ dbus_connection_unref(bus);
+ unsupported = true;
+ return;
+ }
+
+ print_verbose("FreeDesktopScreenSaver: Released screensaver inhibition cookie: " + uitos(cookie));
+
+ dbus_message_unref(message);
+ dbus_message_unref(reply);
+ dbus_connection_unref(bus);
+}
+
+#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/freedesktop_screensaver.h b/platform/linuxbsd/freedesktop_screensaver.h
new file mode 100644
index 0000000000..f27e60fce4
--- /dev/null
+++ b/platform/linuxbsd/freedesktop_screensaver.h
@@ -0,0 +1,47 @@
+/*************************************************************************/
+/* freedesktop_screensaver.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifdef DBUS_ENABLED
+
+#include <dbus/dbus.h>
+#include <stdint.h>
+
+class FreeDesktopScreenSaver {
+private:
+ uint32_t cookie = 0;
+ bool unsupported = false;
+
+public:
+ FreeDesktopScreenSaver() {}
+ void inhibit();
+ void uninhibit();
+};
+
+#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/godot_linuxbsd.cpp b/platform/linuxbsd/godot_linuxbsd.cpp
index e1796ccefe..6f5c46b59c 100644
--- a/platform/linuxbsd/godot_linuxbsd.cpp
+++ b/platform/linuxbsd/godot_linuxbsd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index fda1358dfd..8b6dbc4c20 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,13 +32,14 @@
#include "joypad_linux.h"
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <unistd.h>
#ifdef UDEV_ENABLED
-#include <libudev.h>
+#include "libudev-so_wrap.h"
#endif
#define LONG_BITS (sizeof(long) * 8)
@@ -49,15 +50,6 @@
static const char *ignore_str = "/dev/input/js";
#endif
-JoypadLinux::Joypad::Joypad() {
- fd = -1;
- dpad = 0;
- devpath = "";
- for (int i = 0; i < MAX_ABS; i++) {
- abs_info[i] = nullptr;
- }
-}
-
JoypadLinux::Joypad::~Joypad() {
for (int i = 0; i < MAX_ABS; i++) {
if (abs_info[i]) {
@@ -70,7 +62,7 @@ void JoypadLinux::Joypad::reset() {
dpad = 0;
fd = -1;
- Input::JoyAxis jx;
+ Input::JoyAxisValue jx;
jx.min = -1;
jx.value = 0.0f;
for (int i = 0; i < MAX_ABS; i++) {
@@ -80,15 +72,28 @@ void JoypadLinux::Joypad::reset() {
}
JoypadLinux::JoypadLinux(Input *in) {
- exit_udev = false;
+#ifdef UDEV_ENABLED
+#ifdef DEBUG_ENABLED
+ int dylibloader_verbose = 1;
+#else
+ int dylibloader_verbose = 0;
+#endif
+ use_udev = initialize_libudev(dylibloader_verbose) == 0;
+ if (use_udev) {
+ print_verbose("JoypadLinux: udev enabled and loaded successfully.");
+ } else {
+ print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads.");
+ }
+#else
+ print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads.");
+#endif
input = in;
- joy_thread = Thread::create(joy_thread_func, this);
+ joy_thread.start(joy_thread_func, this);
}
JoypadLinux::~JoypadLinux() {
- exit_udev = true;
- Thread::wait_to_finish(joy_thread);
- memdelete(joy_thread);
+ exit_monitor.set();
+ joy_thread.wait_to_finish();
close_joypad();
}
@@ -101,11 +106,20 @@ void JoypadLinux::joy_thread_func(void *p_user) {
void JoypadLinux::run_joypad_thread() {
#ifdef UDEV_ENABLED
- udev *_udev = udev_new();
- ERR_FAIL_COND(!_udev);
- enumerate_joypads(_udev);
- monitor_joypads(_udev);
- udev_unref(_udev);
+ if (use_udev) {
+ udev *_udev = udev_new();
+ if (!_udev) {
+ use_udev = false;
+ ERR_PRINT("Failed getting an udev context, falling back to parsing /dev/input.");
+ monitor_joypads();
+ } else {
+ enumerate_joypads(_udev);
+ monitor_joypads(_udev);
+ udev_unref(_udev);
+ }
+ } else {
+ monitor_joypads();
+ }
#else
monitor_joypads();
#endif
@@ -146,7 +160,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) {
udev_monitor_enable_receiving(mon);
int fd = udev_monitor_get_fd(mon);
- while (!exit_udev) {
+ while (!exit_monitor.is_set()) {
fd_set fds;
struct timeval tv;
int ret;
@@ -164,17 +178,18 @@ void JoypadLinux::monitor_joypads(udev *p_udev) {
select() ensured that this will not block. */
dev = udev_monitor_receive_device(mon);
- if (dev && udev_device_get_devnode(dev) != 0) {
+ if (dev && udev_device_get_devnode(dev) != nullptr) {
MutexLock lock(joy_mutex);
String action = udev_device_get_action(dev);
const char *devnode = udev_device_get_devnode(dev);
if (devnode) {
String devnode_str = devnode;
if (devnode_str.find(ignore_str) == -1) {
- if (action == "add")
+ if (action == "add") {
open_joypad(devnode);
- else if (String(action) == "remove")
+ } else if (String(action) == "remove") {
close_joypad(get_joy_from_path(devnode));
+ }
}
}
@@ -188,17 +203,27 @@ void JoypadLinux::monitor_joypads(udev *p_udev) {
#endif
void JoypadLinux::monitor_joypads() {
- while (!exit_udev) {
+ while (!exit_monitor.is_set()) {
{
MutexLock lock(joy_mutex);
- for (int i = 0; i < 32; i++) {
+ DIR *input_directory;
+ input_directory = opendir("/dev/input");
+ if (input_directory) {
+ struct dirent *current;
char fname[64];
- sprintf(fname, "/dev/input/event%d", i);
- if (attached_devices.find(fname) == -1) {
- open_joypad(fname);
+
+ while ((current = readdir(input_directory)) != nullptr) {
+ if (strncmp(current->d_name, "event", 5) != 0) {
+ continue;
+ }
+ sprintf(fname, "/dev/input/%.*s", 16, current->d_name);
+ if (attached_devices.find(fname) == -1) {
+ open_joypad(fname);
+ }
}
}
+ closedir(input_directory);
}
usleep(1000000); // 1s
}
@@ -404,10 +429,10 @@ void JoypadLinux::joypad_vibration_stop(int p_id, uint64_t p_timestamp) {
joy.ff_effect_timestamp = p_timestamp;
}
-Input::JoyAxis JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const {
+Input::JoyAxisValue JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const {
int min = p_abs->minimum;
int max = p_abs->maximum;
- Input::JoyAxis jx;
+ Input::JoyAxisValue jx;
if (min < 0) {
jx.min = -1;
@@ -450,7 +475,7 @@ void JoypadLinux::process_joypads() {
switch (ev.type) {
case EV_KEY:
- input->joy_button(i, joy->key_map[ev.code], ev.value);
+ input->joy_button(i, (JoyButton)joy->key_map[ev.code], ev.value);
break;
case EV_ABS:
@@ -459,29 +484,29 @@ void JoypadLinux::process_joypads() {
case ABS_HAT0X:
if (ev.value != 0) {
if (ev.value < 0) {
- joy->dpad |= Input::HAT_MASK_LEFT;
+ joy->dpad = (HatMask)((joy->dpad | HatMask::HAT_MASK_LEFT) & ~HatMask::HAT_MASK_RIGHT);
} else {
- joy->dpad |= Input::HAT_MASK_RIGHT;
+ joy->dpad = (HatMask)((joy->dpad | HatMask::HAT_MASK_RIGHT) & ~HatMask::HAT_MASK_LEFT);
}
} else {
- joy->dpad &= ~(Input::HAT_MASK_LEFT | Input::HAT_MASK_RIGHT);
+ joy->dpad &= ~(HatMask::HAT_MASK_LEFT | HatMask::HAT_MASK_RIGHT);
}
- input->joy_hat(i, joy->dpad);
+ input->joy_hat(i, (HatMask)joy->dpad);
break;
case ABS_HAT0Y:
if (ev.value != 0) {
if (ev.value < 0) {
- joy->dpad |= Input::HAT_MASK_UP;
+ joy->dpad = (HatMask)((joy->dpad | HatMask::HAT_MASK_UP) & ~HatMask::HAT_MASK_DOWN);
} else {
- joy->dpad |= Input::HAT_MASK_DOWN;
+ joy->dpad = (HatMask)((joy->dpad | HatMask::HAT_MASK_DOWN) & ~HatMask::HAT_MASK_UP);
}
} else {
- joy->dpad &= ~(Input::HAT_MASK_UP | Input::HAT_MASK_DOWN);
+ joy->dpad &= ~(HatMask::HAT_MASK_UP | HatMask::HAT_MASK_DOWN);
}
- input->joy_hat(i, joy->dpad);
+ input->joy_hat(i, (HatMask)joy->dpad);
break;
default:
@@ -489,7 +514,7 @@ void JoypadLinux::process_joypads() {
return;
}
if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) {
- Input::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value);
+ Input::JoyAxisValue value = axis_correct(joy->abs_info[ev.code], ev.value);
joy->curr_axis[joy->abs_map[ev.code]] = value;
}
break;
@@ -501,7 +526,7 @@ void JoypadLinux::process_joypads() {
for (int j = 0; j < MAX_ABS; j++) {
int index = joy->abs_map[j];
if (index != -1) {
- input->joy_axis(i, index, joy->curr_axis[index]);
+ input->joy_axis(i, (JoyAxis)index, joy->curr_axis[index]);
}
}
if (len == 0 || (len < 0 && errno != EAGAIN)) {
diff --git a/platform/linuxbsd/joypad_linux.h b/platform/linuxbsd/joypad_linux.h
index 0d175193a5..177d7a51ce 100644
--- a/platform/linuxbsd/joypad_linux.h
+++ b/platform/linuxbsd/joypad_linux.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,28 +53,30 @@ private:
};
struct Joypad {
- Input::JoyAxis curr_axis[MAX_ABS];
+ Input::JoyAxisValue curr_axis[MAX_ABS];
int key_map[MAX_KEY];
int abs_map[MAX_ABS];
- int dpad;
- int fd;
+ int dpad = 0;
+ int fd = -1;
String devpath;
- input_absinfo *abs_info[MAX_ABS];
+ input_absinfo *abs_info[MAX_ABS] = {};
- bool force_feedback;
- int ff_effect_id;
- uint64_t ff_effect_timestamp;
+ bool force_feedback = false;
+ int ff_effect_id = 0;
+ uint64_t ff_effect_timestamp = 0;
- Joypad();
~Joypad();
void reset();
};
- bool exit_udev;
+#ifdef UDEV_ENABLED
+ bool use_udev = false;
+#endif
+ SafeFlag exit_monitor;
Mutex joy_mutex;
- Thread *joy_thread;
- Input *input;
+ Thread joy_thread;
+ Input *input = nullptr;
Joypad joypads[JOYPADS_MAX];
Vector<String> attached_devices;
@@ -95,7 +97,7 @@ private:
void joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
void joypad_vibration_stop(int p_id, uint64_t p_timestamp);
- Input::JoyAxis axis_correct(const input_absinfo *p_abs, int p_value) const;
+ Input::JoyAxisValue axis_correct(const input_absinfo *p_abs, int p_value) const;
};
#endif
diff --git a/platform/linuxbsd/key_mapping_x11.cpp b/platform/linuxbsd/key_mapping_x11.cpp
index 77512b1a9e..829feda40a 100644
--- a/platform/linuxbsd/key_mapping_x11.cpp
+++ b/platform/linuxbsd/key_mapping_x11.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,7 +34,7 @@
struct _XTranslatePair {
KeySym keysym;
- unsigned int keycode;
+ Key keycode;
};
static _XTranslatePair _xkeysym_to_keycode[] = {
@@ -61,8 +61,8 @@ static _XTranslatePair _xkeysym_to_keycode[] = {
{ XK_Shift_L, KEY_SHIFT },
{ XK_Shift_R, KEY_SHIFT },
{ XK_Shift_Lock, KEY_SHIFT },
- { XK_Control_L, KEY_CONTROL },
- { XK_Control_R, KEY_CONTROL },
+ { XK_Control_L, KEY_CTRL },
+ { XK_Control_R, KEY_CTRL },
{ XK_Meta_L, KEY_META },
{ XK_Meta_R, KEY_META },
{ XK_Alt_L, KEY_ALT },
@@ -176,7 +176,7 @@ static _XTranslatePair _xkeysym_to_keycode[] = {
{ XF86XK_LaunchC, KEY_LAUNCHE },
{ XF86XK_LaunchD, KEY_LAUNCHF },
- { 0, 0 }
+ { 0, KEY_NONE }
};
struct _TranslatePair {
@@ -185,7 +185,6 @@ struct _TranslatePair {
};
static _TranslatePair _scancode_to_keycode[] = {
-
{ KEY_ESCAPE, 0x09 },
{ KEY_1, 0x0A },
{ KEY_2, 0x0B },
@@ -214,7 +213,7 @@ static _TranslatePair _scancode_to_keycode[] = {
{ KEY_BRACELEFT, 0x22 },
{ KEY_BRACERIGHT, 0x23 },
{ KEY_ENTER, 0x24 },
- { KEY_CONTROL, 0x25 },
+ { KEY_CTRL, 0x25 },
{ KEY_A, 0x26 },
{ KEY_S, 0x27 },
{ KEY_D, 0x28 },
@@ -273,7 +272,7 @@ static _TranslatePair _scancode_to_keycode[] = {
{ KEY_F11, 0x5F },
{ KEY_F12, 0x60 },
{ KEY_KP_ENTER, 0x68 },
- { KEY_CONTROL, 0x69 },
+ { KEY_CTRL, 0x69 },
{ KEY_KP_DIVIDE, 0x6A },
{ KEY_PRINT, 0x6B },
{ KEY_ALT, 0x6C },
@@ -310,11 +309,23 @@ unsigned int KeyMappingX11::get_scancode(unsigned int p_code) {
return keycode;
}
-unsigned int KeyMappingX11::get_keycode(KeySym p_keysym) {
+unsigned int KeyMappingX11::get_xlibcode(unsigned int p_keysym) {
+ unsigned int code = 0;
+ for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
+ if (_scancode_to_keycode[i].keysym == p_keysym) {
+ code = _scancode_to_keycode[i].keycode;
+ break;
+ }
+ }
+
+ return code;
+}
+
+Key KeyMappingX11::get_keycode(KeySym p_keysym) {
// kinda bruteforce.. could optimize.
if (p_keysym < 0x100) { // Latin 1, maps 1-1
- return p_keysym;
+ return (Key)p_keysym;
}
// look for special key
@@ -324,14 +335,14 @@ unsigned int KeyMappingX11::get_keycode(KeySym p_keysym) {
}
}
- return 0;
+ return KEY_NONE;
}
-KeySym KeyMappingX11::get_keysym(unsigned int p_code) {
+KeySym KeyMappingX11::get_keysym(Key p_code) {
// kinda bruteforce.. could optimize.
if (p_code < 0x100) { // Latin 1, maps 1-1
- return p_code;
+ return (KeySym)p_code;
}
// look for special key
@@ -341,7 +352,7 @@ KeySym KeyMappingX11::get_keysym(unsigned int p_code) {
}
}
- return 0;
+ return (KeySym)KEY_NONE;
}
/***** UNICODE CONVERSION ******/
@@ -354,7 +365,6 @@ struct _XTranslateUnicodePair {
};
enum {
-
_KEYSYM_MAX = 759
};
@@ -1160,7 +1170,6 @@ struct _XTranslateUnicodePairReverse {
};
enum {
-
_UNICODE_MAX = 750
};
diff --git a/platform/linuxbsd/key_mapping_x11.h b/platform/linuxbsd/key_mapping_x11.h
index 8f5e01a3c2..d4f1554671 100644
--- a/platform/linuxbsd/key_mapping_x11.h
+++ b/platform/linuxbsd/key_mapping_x11.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,9 +44,10 @@ class KeyMappingX11 {
KeyMappingX11() {}
public:
- static unsigned int get_keycode(KeySym p_keysym);
+ static Key get_keycode(KeySym p_keysym);
+ static unsigned int get_xlibcode(unsigned int p_keysym);
static unsigned int get_scancode(unsigned int p_code);
- static KeySym get_keysym(unsigned int p_code);
+ static KeySym get_keysym(Key p_code);
static unsigned int get_unicode_from_keysym(KeySym p_keysym);
static KeySym get_keysym_from_unicode(unsigned int p_unicode);
};
diff --git a/platform/linuxbsd/libudev-so_wrap.c b/platform/linuxbsd/libudev-so_wrap.c
new file mode 100644
index 0000000000..a9fa4a494a
--- /dev/null
+++ b/platform/linuxbsd/libudev-so_wrap.c
@@ -0,0 +1,1013 @@
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-20 00:08:59
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/libudev.h --sys-include <libudev.h> --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ --output-header libudev-so_wrap.h --output-implementation libudev-so_wrap.c
+//
+#include <stdint.h>
+
+#define udev_ref udev_ref_dylibloader_orig_libudev
+#define udev_unref udev_unref_dylibloader_orig_libudev
+#define udev_new udev_new_dylibloader_orig_libudev
+#define udev_set_log_fn udev_set_log_fn_dylibloader_orig_libudev
+#define udev_get_log_priority udev_get_log_priority_dylibloader_orig_libudev
+#define udev_set_log_priority udev_set_log_priority_dylibloader_orig_libudev
+#define udev_get_userdata udev_get_userdata_dylibloader_orig_libudev
+#define udev_set_userdata udev_set_userdata_dylibloader_orig_libudev
+#define udev_list_entry_get_next udev_list_entry_get_next_dylibloader_orig_libudev
+#define udev_list_entry_get_by_name udev_list_entry_get_by_name_dylibloader_orig_libudev
+#define udev_list_entry_get_name udev_list_entry_get_name_dylibloader_orig_libudev
+#define udev_list_entry_get_value udev_list_entry_get_value_dylibloader_orig_libudev
+#define udev_device_ref udev_device_ref_dylibloader_orig_libudev
+#define udev_device_unref udev_device_unref_dylibloader_orig_libudev
+#define udev_device_get_udev udev_device_get_udev_dylibloader_orig_libudev
+#define udev_device_new_from_syspath udev_device_new_from_syspath_dylibloader_orig_libudev
+#define udev_device_new_from_devnum udev_device_new_from_devnum_dylibloader_orig_libudev
+#define udev_device_new_from_subsystem_sysname udev_device_new_from_subsystem_sysname_dylibloader_orig_libudev
+#define udev_device_new_from_device_id udev_device_new_from_device_id_dylibloader_orig_libudev
+#define udev_device_new_from_environment udev_device_new_from_environment_dylibloader_orig_libudev
+#define udev_device_get_parent udev_device_get_parent_dylibloader_orig_libudev
+#define udev_device_get_parent_with_subsystem_devtype udev_device_get_parent_with_subsystem_devtype_dylibloader_orig_libudev
+#define udev_device_get_devpath udev_device_get_devpath_dylibloader_orig_libudev
+#define udev_device_get_subsystem udev_device_get_subsystem_dylibloader_orig_libudev
+#define udev_device_get_devtype udev_device_get_devtype_dylibloader_orig_libudev
+#define udev_device_get_syspath udev_device_get_syspath_dylibloader_orig_libudev
+#define udev_device_get_sysname udev_device_get_sysname_dylibloader_orig_libudev
+#define udev_device_get_sysnum udev_device_get_sysnum_dylibloader_orig_libudev
+#define udev_device_get_devnode udev_device_get_devnode_dylibloader_orig_libudev
+#define udev_device_get_is_initialized udev_device_get_is_initialized_dylibloader_orig_libudev
+#define udev_device_get_devlinks_list_entry udev_device_get_devlinks_list_entry_dylibloader_orig_libudev
+#define udev_device_get_properties_list_entry udev_device_get_properties_list_entry_dylibloader_orig_libudev
+#define udev_device_get_tags_list_entry udev_device_get_tags_list_entry_dylibloader_orig_libudev
+#define udev_device_get_sysattr_list_entry udev_device_get_sysattr_list_entry_dylibloader_orig_libudev
+#define udev_device_get_property_value udev_device_get_property_value_dylibloader_orig_libudev
+#define udev_device_get_driver udev_device_get_driver_dylibloader_orig_libudev
+#define udev_device_get_devnum udev_device_get_devnum_dylibloader_orig_libudev
+#define udev_device_get_action udev_device_get_action_dylibloader_orig_libudev
+#define udev_device_get_seqnum udev_device_get_seqnum_dylibloader_orig_libudev
+#define udev_device_get_usec_since_initialized udev_device_get_usec_since_initialized_dylibloader_orig_libudev
+#define udev_device_get_sysattr_value udev_device_get_sysattr_value_dylibloader_orig_libudev
+#define udev_device_set_sysattr_value udev_device_set_sysattr_value_dylibloader_orig_libudev
+#define udev_device_has_tag udev_device_has_tag_dylibloader_orig_libudev
+#define udev_monitor_ref udev_monitor_ref_dylibloader_orig_libudev
+#define udev_monitor_unref udev_monitor_unref_dylibloader_orig_libudev
+#define udev_monitor_get_udev udev_monitor_get_udev_dylibloader_orig_libudev
+#define udev_monitor_new_from_netlink udev_monitor_new_from_netlink_dylibloader_orig_libudev
+#define udev_monitor_enable_receiving udev_monitor_enable_receiving_dylibloader_orig_libudev
+#define udev_monitor_set_receive_buffer_size udev_monitor_set_receive_buffer_size_dylibloader_orig_libudev
+#define udev_monitor_get_fd udev_monitor_get_fd_dylibloader_orig_libudev
+#define udev_monitor_receive_device udev_monitor_receive_device_dylibloader_orig_libudev
+#define udev_monitor_filter_add_match_subsystem_devtype udev_monitor_filter_add_match_subsystem_devtype_dylibloader_orig_libudev
+#define udev_monitor_filter_add_match_tag udev_monitor_filter_add_match_tag_dylibloader_orig_libudev
+#define udev_monitor_filter_update udev_monitor_filter_update_dylibloader_orig_libudev
+#define udev_monitor_filter_remove udev_monitor_filter_remove_dylibloader_orig_libudev
+#define udev_enumerate_ref udev_enumerate_ref_dylibloader_orig_libudev
+#define udev_enumerate_unref udev_enumerate_unref_dylibloader_orig_libudev
+#define udev_enumerate_get_udev udev_enumerate_get_udev_dylibloader_orig_libudev
+#define udev_enumerate_new udev_enumerate_new_dylibloader_orig_libudev
+#define udev_enumerate_add_match_subsystem udev_enumerate_add_match_subsystem_dylibloader_orig_libudev
+#define udev_enumerate_add_nomatch_subsystem udev_enumerate_add_nomatch_subsystem_dylibloader_orig_libudev
+#define udev_enumerate_add_match_sysattr udev_enumerate_add_match_sysattr_dylibloader_orig_libudev
+#define udev_enumerate_add_nomatch_sysattr udev_enumerate_add_nomatch_sysattr_dylibloader_orig_libudev
+#define udev_enumerate_add_match_property udev_enumerate_add_match_property_dylibloader_orig_libudev
+#define udev_enumerate_add_match_sysname udev_enumerate_add_match_sysname_dylibloader_orig_libudev
+#define udev_enumerate_add_match_tag udev_enumerate_add_match_tag_dylibloader_orig_libudev
+#define udev_enumerate_add_match_parent udev_enumerate_add_match_parent_dylibloader_orig_libudev
+#define udev_enumerate_add_match_is_initialized udev_enumerate_add_match_is_initialized_dylibloader_orig_libudev
+#define udev_enumerate_add_syspath udev_enumerate_add_syspath_dylibloader_orig_libudev
+#define udev_enumerate_scan_devices udev_enumerate_scan_devices_dylibloader_orig_libudev
+#define udev_enumerate_scan_subsystems udev_enumerate_scan_subsystems_dylibloader_orig_libudev
+#define udev_enumerate_get_list_entry udev_enumerate_get_list_entry_dylibloader_orig_libudev
+#define udev_queue_ref udev_queue_ref_dylibloader_orig_libudev
+#define udev_queue_unref udev_queue_unref_dylibloader_orig_libudev
+#define udev_queue_get_udev udev_queue_get_udev_dylibloader_orig_libudev
+#define udev_queue_new udev_queue_new_dylibloader_orig_libudev
+#define udev_queue_get_kernel_seqnum udev_queue_get_kernel_seqnum_dylibloader_orig_libudev
+#define udev_queue_get_udev_seqnum udev_queue_get_udev_seqnum_dylibloader_orig_libudev
+#define udev_queue_get_udev_is_active udev_queue_get_udev_is_active_dylibloader_orig_libudev
+#define udev_queue_get_queue_is_empty udev_queue_get_queue_is_empty_dylibloader_orig_libudev
+#define udev_queue_get_seqnum_is_finished udev_queue_get_seqnum_is_finished_dylibloader_orig_libudev
+#define udev_queue_get_seqnum_sequence_is_finished udev_queue_get_seqnum_sequence_is_finished_dylibloader_orig_libudev
+#define udev_queue_get_fd udev_queue_get_fd_dylibloader_orig_libudev
+#define udev_queue_flush udev_queue_flush_dylibloader_orig_libudev
+#define udev_queue_get_queued_list_entry udev_queue_get_queued_list_entry_dylibloader_orig_libudev
+#define udev_hwdb_new udev_hwdb_new_dylibloader_orig_libudev
+#define udev_hwdb_ref udev_hwdb_ref_dylibloader_orig_libudev
+#define udev_hwdb_unref udev_hwdb_unref_dylibloader_orig_libudev
+#define udev_hwdb_get_properties_list_entry udev_hwdb_get_properties_list_entry_dylibloader_orig_libudev
+#define udev_util_encode_string udev_util_encode_string_dylibloader_orig_libudev
+#include <libudev.h>
+#undef udev_ref
+#undef udev_unref
+#undef udev_new
+#undef udev_set_log_fn
+#undef udev_get_log_priority
+#undef udev_set_log_priority
+#undef udev_get_userdata
+#undef udev_set_userdata
+#undef udev_list_entry_get_next
+#undef udev_list_entry_get_by_name
+#undef udev_list_entry_get_name
+#undef udev_list_entry_get_value
+#undef udev_device_ref
+#undef udev_device_unref
+#undef udev_device_get_udev
+#undef udev_device_new_from_syspath
+#undef udev_device_new_from_devnum
+#undef udev_device_new_from_subsystem_sysname
+#undef udev_device_new_from_device_id
+#undef udev_device_new_from_environment
+#undef udev_device_get_parent
+#undef udev_device_get_parent_with_subsystem_devtype
+#undef udev_device_get_devpath
+#undef udev_device_get_subsystem
+#undef udev_device_get_devtype
+#undef udev_device_get_syspath
+#undef udev_device_get_sysname
+#undef udev_device_get_sysnum
+#undef udev_device_get_devnode
+#undef udev_device_get_is_initialized
+#undef udev_device_get_devlinks_list_entry
+#undef udev_device_get_properties_list_entry
+#undef udev_device_get_tags_list_entry
+#undef udev_device_get_sysattr_list_entry
+#undef udev_device_get_property_value
+#undef udev_device_get_driver
+#undef udev_device_get_devnum
+#undef udev_device_get_action
+#undef udev_device_get_seqnum
+#undef udev_device_get_usec_since_initialized
+#undef udev_device_get_sysattr_value
+#undef udev_device_set_sysattr_value
+#undef udev_device_has_tag
+#undef udev_monitor_ref
+#undef udev_monitor_unref
+#undef udev_monitor_get_udev
+#undef udev_monitor_new_from_netlink
+#undef udev_monitor_enable_receiving
+#undef udev_monitor_set_receive_buffer_size
+#undef udev_monitor_get_fd
+#undef udev_monitor_receive_device
+#undef udev_monitor_filter_add_match_subsystem_devtype
+#undef udev_monitor_filter_add_match_tag
+#undef udev_monitor_filter_update
+#undef udev_monitor_filter_remove
+#undef udev_enumerate_ref
+#undef udev_enumerate_unref
+#undef udev_enumerate_get_udev
+#undef udev_enumerate_new
+#undef udev_enumerate_add_match_subsystem
+#undef udev_enumerate_add_nomatch_subsystem
+#undef udev_enumerate_add_match_sysattr
+#undef udev_enumerate_add_nomatch_sysattr
+#undef udev_enumerate_add_match_property
+#undef udev_enumerate_add_match_sysname
+#undef udev_enumerate_add_match_tag
+#undef udev_enumerate_add_match_parent
+#undef udev_enumerate_add_match_is_initialized
+#undef udev_enumerate_add_syspath
+#undef udev_enumerate_scan_devices
+#undef udev_enumerate_scan_subsystems
+#undef udev_enumerate_get_list_entry
+#undef udev_queue_ref
+#undef udev_queue_unref
+#undef udev_queue_get_udev
+#undef udev_queue_new
+#undef udev_queue_get_kernel_seqnum
+#undef udev_queue_get_udev_seqnum
+#undef udev_queue_get_udev_is_active
+#undef udev_queue_get_queue_is_empty
+#undef udev_queue_get_seqnum_is_finished
+#undef udev_queue_get_seqnum_sequence_is_finished
+#undef udev_queue_get_fd
+#undef udev_queue_flush
+#undef udev_queue_get_queued_list_entry
+#undef udev_hwdb_new
+#undef udev_hwdb_ref
+#undef udev_hwdb_unref
+#undef udev_hwdb_get_properties_list_entry
+#undef udev_util_encode_string
+#include <dlfcn.h>
+#include <stdio.h>
+struct udev* (*udev_ref_dylibloader_wrapper_libudev)(struct udev*);
+struct udev* (*udev_unref_dylibloader_wrapper_libudev)(struct udev*);
+struct udev* (*udev_new_dylibloader_wrapper_libudev)( void);
+void (*udev_set_log_fn_dylibloader_wrapper_libudev)(struct udev*, void*);
+int (*udev_get_log_priority_dylibloader_wrapper_libudev)(struct udev*);
+void (*udev_set_log_priority_dylibloader_wrapper_libudev)(struct udev*, int);
+void* (*udev_get_userdata_dylibloader_wrapper_libudev)(struct udev*);
+void (*udev_set_userdata_dylibloader_wrapper_libudev)(struct udev*, void*);
+struct udev_list_entry* (*udev_list_entry_get_next_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+struct udev_list_entry* (*udev_list_entry_get_by_name_dylibloader_wrapper_libudev)(struct udev_list_entry*,const char*);
+const char* (*udev_list_entry_get_name_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+const char* (*udev_list_entry_get_value_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+struct udev_device* (*udev_device_ref_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_device* (*udev_device_unref_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev* (*udev_device_get_udev_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_device* (*udev_device_new_from_syspath_dylibloader_wrapper_libudev)(struct udev*,const char*);
+struct udev_device* (*udev_device_new_from_devnum_dylibloader_wrapper_libudev)(struct udev*, char, dev_t);
+struct udev_device* (*udev_device_new_from_subsystem_sysname_dylibloader_wrapper_libudev)(struct udev*,const char*,const char*);
+struct udev_device* (*udev_device_new_from_device_id_dylibloader_wrapper_libudev)(struct udev*,const char*);
+struct udev_device* (*udev_device_new_from_environment_dylibloader_wrapper_libudev)(struct udev*);
+struct udev_device* (*udev_device_get_parent_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_device* (*udev_device_get_parent_with_subsystem_devtype_dylibloader_wrapper_libudev)(struct udev_device*,const char*,const char*);
+const char* (*udev_device_get_devpath_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_subsystem_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_devtype_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_syspath_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_sysname_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_sysnum_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_devnode_dylibloader_wrapper_libudev)(struct udev_device*);
+int (*udev_device_get_is_initialized_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_list_entry* (*udev_device_get_devlinks_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_list_entry* (*udev_device_get_properties_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_list_entry* (*udev_device_get_tags_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+struct udev_list_entry* (*udev_device_get_sysattr_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_property_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+const char* (*udev_device_get_driver_dylibloader_wrapper_libudev)(struct udev_device*);
+dev_t (*udev_device_get_devnum_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_action_dylibloader_wrapper_libudev)(struct udev_device*);
+unsigned long long int (*udev_device_get_seqnum_dylibloader_wrapper_libudev)(struct udev_device*);
+unsigned long long int (*udev_device_get_usec_since_initialized_dylibloader_wrapper_libudev)(struct udev_device*);
+const char* (*udev_device_get_sysattr_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+int (*udev_device_set_sysattr_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*,const char*);
+int (*udev_device_has_tag_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+struct udev_monitor* (*udev_monitor_ref_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev_monitor* (*udev_monitor_unref_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev* (*udev_monitor_get_udev_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev_monitor* (*udev_monitor_new_from_netlink_dylibloader_wrapper_libudev)(struct udev*,const char*);
+int (*udev_monitor_enable_receiving_dylibloader_wrapper_libudev)(struct udev_monitor*);
+int (*udev_monitor_set_receive_buffer_size_dylibloader_wrapper_libudev)(struct udev_monitor*, int);
+int (*udev_monitor_get_fd_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev_device* (*udev_monitor_receive_device_dylibloader_wrapper_libudev)(struct udev_monitor*);
+int (*udev_monitor_filter_add_match_subsystem_devtype_dylibloader_wrapper_libudev)(struct udev_monitor*,const char*,const char*);
+int (*udev_monitor_filter_add_match_tag_dylibloader_wrapper_libudev)(struct udev_monitor*,const char*);
+int (*udev_monitor_filter_update_dylibloader_wrapper_libudev)(struct udev_monitor*);
+int (*udev_monitor_filter_remove_dylibloader_wrapper_libudev)(struct udev_monitor*);
+struct udev_enumerate* (*udev_enumerate_ref_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev_enumerate* (*udev_enumerate_unref_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev* (*udev_enumerate_get_udev_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev_enumerate* (*udev_enumerate_new_dylibloader_wrapper_libudev)(struct udev*);
+int (*udev_enumerate_add_match_subsystem_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_add_nomatch_subsystem_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_add_match_sysattr_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+int (*udev_enumerate_add_nomatch_sysattr_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+int (*udev_enumerate_add_match_property_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+int (*udev_enumerate_add_match_sysname_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_add_match_tag_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_add_match_parent_dylibloader_wrapper_libudev)(struct udev_enumerate*,struct udev_device*);
+int (*udev_enumerate_add_match_is_initialized_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+int (*udev_enumerate_add_syspath_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+int (*udev_enumerate_scan_devices_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+int (*udev_enumerate_scan_subsystems_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev_list_entry* (*udev_enumerate_get_list_entry_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+struct udev_queue* (*udev_queue_ref_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev_queue* (*udev_queue_unref_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev* (*udev_queue_get_udev_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev_queue* (*udev_queue_new_dylibloader_wrapper_libudev)(struct udev*);
+unsigned long long int (*udev_queue_get_kernel_seqnum_dylibloader_wrapper_libudev)(struct udev_queue*);
+unsigned long long int (*udev_queue_get_udev_seqnum_dylibloader_wrapper_libudev)(struct udev_queue*);
+int (*udev_queue_get_udev_is_active_dylibloader_wrapper_libudev)(struct udev_queue*);
+int (*udev_queue_get_queue_is_empty_dylibloader_wrapper_libudev)(struct udev_queue*);
+int (*udev_queue_get_seqnum_is_finished_dylibloader_wrapper_libudev)(struct udev_queue*, unsigned long long int);
+int (*udev_queue_get_seqnum_sequence_is_finished_dylibloader_wrapper_libudev)(struct udev_queue*, unsigned long long int, unsigned long long int);
+int (*udev_queue_get_fd_dylibloader_wrapper_libudev)(struct udev_queue*);
+int (*udev_queue_flush_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev_list_entry* (*udev_queue_get_queued_list_entry_dylibloader_wrapper_libudev)(struct udev_queue*);
+struct udev_hwdb* (*udev_hwdb_new_dylibloader_wrapper_libudev)(struct udev*);
+struct udev_hwdb* (*udev_hwdb_ref_dylibloader_wrapper_libudev)(struct udev_hwdb*);
+struct udev_hwdb* (*udev_hwdb_unref_dylibloader_wrapper_libudev)(struct udev_hwdb*);
+struct udev_list_entry* (*udev_hwdb_get_properties_list_entry_dylibloader_wrapper_libudev)(struct udev_hwdb*,const char*, unsigned);
+int (*udev_util_encode_string_dylibloader_wrapper_libudev)(const char*, char*, size_t);
+int initialize_libudev(int verbose) {
+ void *handle;
+ char *error;
+ handle = dlopen("libudev.so.1", RTLD_LAZY);
+ if (!handle) {
+ if (verbose) {
+ fprintf(stderr, "%s\n", dlerror());
+ }
+ return(1);
+ }
+ dlerror();
+// udev_ref
+ *(void **) (&udev_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_unref
+ *(void **) (&udev_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_new
+ *(void **) (&udev_new_dylibloader_wrapper_libudev) = dlsym(handle, "udev_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_set_log_fn
+ *(void **) (&udev_set_log_fn_dylibloader_wrapper_libudev) = dlsym(handle, "udev_set_log_fn");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_get_log_priority
+ *(void **) (&udev_get_log_priority_dylibloader_wrapper_libudev) = dlsym(handle, "udev_get_log_priority");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_set_log_priority
+ *(void **) (&udev_set_log_priority_dylibloader_wrapper_libudev) = dlsym(handle, "udev_set_log_priority");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_get_userdata
+ *(void **) (&udev_get_userdata_dylibloader_wrapper_libudev) = dlsym(handle, "udev_get_userdata");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_set_userdata
+ *(void **) (&udev_set_userdata_dylibloader_wrapper_libudev) = dlsym(handle, "udev_set_userdata");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_list_entry_get_next
+ *(void **) (&udev_list_entry_get_next_dylibloader_wrapper_libudev) = dlsym(handle, "udev_list_entry_get_next");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_list_entry_get_by_name
+ *(void **) (&udev_list_entry_get_by_name_dylibloader_wrapper_libudev) = dlsym(handle, "udev_list_entry_get_by_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_list_entry_get_name
+ *(void **) (&udev_list_entry_get_name_dylibloader_wrapper_libudev) = dlsym(handle, "udev_list_entry_get_name");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_list_entry_get_value
+ *(void **) (&udev_list_entry_get_value_dylibloader_wrapper_libudev) = dlsym(handle, "udev_list_entry_get_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_ref
+ *(void **) (&udev_device_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_unref
+ *(void **) (&udev_device_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_udev
+ *(void **) (&udev_device_get_udev_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_udev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_syspath
+ *(void **) (&udev_device_new_from_syspath_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_syspath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_devnum
+ *(void **) (&udev_device_new_from_devnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_devnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_subsystem_sysname
+ *(void **) (&udev_device_new_from_subsystem_sysname_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_subsystem_sysname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_device_id
+ *(void **) (&udev_device_new_from_device_id_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_device_id");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_new_from_environment
+ *(void **) (&udev_device_new_from_environment_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_new_from_environment");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_parent
+ *(void **) (&udev_device_get_parent_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_parent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_parent_with_subsystem_devtype
+ *(void **) (&udev_device_get_parent_with_subsystem_devtype_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_parent_with_subsystem_devtype");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devpath
+ *(void **) (&udev_device_get_devpath_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devpath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_subsystem
+ *(void **) (&udev_device_get_subsystem_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_subsystem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devtype
+ *(void **) (&udev_device_get_devtype_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devtype");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_syspath
+ *(void **) (&udev_device_get_syspath_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_syspath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_sysname
+ *(void **) (&udev_device_get_sysname_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_sysname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_sysnum
+ *(void **) (&udev_device_get_sysnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_sysnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devnode
+ *(void **) (&udev_device_get_devnode_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devnode");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_is_initialized
+ *(void **) (&udev_device_get_is_initialized_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_is_initialized");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devlinks_list_entry
+ *(void **) (&udev_device_get_devlinks_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devlinks_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_properties_list_entry
+ *(void **) (&udev_device_get_properties_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_properties_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_tags_list_entry
+ *(void **) (&udev_device_get_tags_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_tags_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_sysattr_list_entry
+ *(void **) (&udev_device_get_sysattr_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_sysattr_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_property_value
+ *(void **) (&udev_device_get_property_value_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_property_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_driver
+ *(void **) (&udev_device_get_driver_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_driver");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_devnum
+ *(void **) (&udev_device_get_devnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_devnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_action
+ *(void **) (&udev_device_get_action_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_action");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_seqnum
+ *(void **) (&udev_device_get_seqnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_seqnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_usec_since_initialized
+ *(void **) (&udev_device_get_usec_since_initialized_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_usec_since_initialized");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_get_sysattr_value
+ *(void **) (&udev_device_get_sysattr_value_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_get_sysattr_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_set_sysattr_value
+ *(void **) (&udev_device_set_sysattr_value_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_set_sysattr_value");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_device_has_tag
+ *(void **) (&udev_device_has_tag_dylibloader_wrapper_libudev) = dlsym(handle, "udev_device_has_tag");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_ref
+ *(void **) (&udev_monitor_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_unref
+ *(void **) (&udev_monitor_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_get_udev
+ *(void **) (&udev_monitor_get_udev_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_get_udev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_new_from_netlink
+ *(void **) (&udev_monitor_new_from_netlink_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_new_from_netlink");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_enable_receiving
+ *(void **) (&udev_monitor_enable_receiving_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_enable_receiving");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_set_receive_buffer_size
+ *(void **) (&udev_monitor_set_receive_buffer_size_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_set_receive_buffer_size");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_get_fd
+ *(void **) (&udev_monitor_get_fd_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_get_fd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_receive_device
+ *(void **) (&udev_monitor_receive_device_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_receive_device");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_filter_add_match_subsystem_devtype
+ *(void **) (&udev_monitor_filter_add_match_subsystem_devtype_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_filter_add_match_subsystem_devtype");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_filter_add_match_tag
+ *(void **) (&udev_monitor_filter_add_match_tag_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_filter_add_match_tag");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_filter_update
+ *(void **) (&udev_monitor_filter_update_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_filter_update");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_monitor_filter_remove
+ *(void **) (&udev_monitor_filter_remove_dylibloader_wrapper_libudev) = dlsym(handle, "udev_monitor_filter_remove");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_ref
+ *(void **) (&udev_enumerate_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_unref
+ *(void **) (&udev_enumerate_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_get_udev
+ *(void **) (&udev_enumerate_get_udev_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_get_udev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_new
+ *(void **) (&udev_enumerate_new_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_subsystem
+ *(void **) (&udev_enumerate_add_match_subsystem_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_subsystem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_nomatch_subsystem
+ *(void **) (&udev_enumerate_add_nomatch_subsystem_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_nomatch_subsystem");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_sysattr
+ *(void **) (&udev_enumerate_add_match_sysattr_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_sysattr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_nomatch_sysattr
+ *(void **) (&udev_enumerate_add_nomatch_sysattr_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_nomatch_sysattr");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_property
+ *(void **) (&udev_enumerate_add_match_property_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_property");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_sysname
+ *(void **) (&udev_enumerate_add_match_sysname_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_sysname");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_tag
+ *(void **) (&udev_enumerate_add_match_tag_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_tag");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_parent
+ *(void **) (&udev_enumerate_add_match_parent_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_parent");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_match_is_initialized
+ *(void **) (&udev_enumerate_add_match_is_initialized_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_match_is_initialized");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_add_syspath
+ *(void **) (&udev_enumerate_add_syspath_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_add_syspath");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_scan_devices
+ *(void **) (&udev_enumerate_scan_devices_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_scan_devices");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_scan_subsystems
+ *(void **) (&udev_enumerate_scan_subsystems_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_scan_subsystems");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_enumerate_get_list_entry
+ *(void **) (&udev_enumerate_get_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_enumerate_get_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_ref
+ *(void **) (&udev_queue_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_unref
+ *(void **) (&udev_queue_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_udev
+ *(void **) (&udev_queue_get_udev_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_udev");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_new
+ *(void **) (&udev_queue_new_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_kernel_seqnum
+ *(void **) (&udev_queue_get_kernel_seqnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_kernel_seqnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_udev_seqnum
+ *(void **) (&udev_queue_get_udev_seqnum_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_udev_seqnum");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_udev_is_active
+ *(void **) (&udev_queue_get_udev_is_active_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_udev_is_active");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_queue_is_empty
+ *(void **) (&udev_queue_get_queue_is_empty_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_queue_is_empty");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_seqnum_is_finished
+ *(void **) (&udev_queue_get_seqnum_is_finished_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_seqnum_is_finished");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_seqnum_sequence_is_finished
+ *(void **) (&udev_queue_get_seqnum_sequence_is_finished_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_seqnum_sequence_is_finished");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_fd
+ *(void **) (&udev_queue_get_fd_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_fd");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_flush
+ *(void **) (&udev_queue_flush_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_flush");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_queue_get_queued_list_entry
+ *(void **) (&udev_queue_get_queued_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_queue_get_queued_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_hwdb_new
+ *(void **) (&udev_hwdb_new_dylibloader_wrapper_libudev) = dlsym(handle, "udev_hwdb_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_hwdb_ref
+ *(void **) (&udev_hwdb_ref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_hwdb_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_hwdb_unref
+ *(void **) (&udev_hwdb_unref_dylibloader_wrapper_libudev) = dlsym(handle, "udev_hwdb_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_hwdb_get_properties_list_entry
+ *(void **) (&udev_hwdb_get_properties_list_entry_dylibloader_wrapper_libudev) = dlsym(handle, "udev_hwdb_get_properties_list_entry");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// udev_util_encode_string
+ *(void **) (&udev_util_encode_string_dylibloader_wrapper_libudev) = dlsym(handle, "udev_util_encode_string");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+return 0;
+}
diff --git a/platform/linuxbsd/libudev-so_wrap.h b/platform/linuxbsd/libudev-so_wrap.h
new file mode 100644
index 0000000000..dd43fd1191
--- /dev/null
+++ b/platform/linuxbsd/libudev-so_wrap.h
@@ -0,0 +1,378 @@
+#ifndef DYLIBLOAD_WRAPPER_LIBUDEV
+#define DYLIBLOAD_WRAPPER_LIBUDEV
+// This file is generated. Do not edit!
+// see https://github.com/hpvb/dynload-wrapper for details
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-20 00:08:59
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/libudev.h --sys-include <libudev.h> --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ --output-header libudev-so_wrap.h --output-implementation libudev-so_wrap.c
+//
+#include <stdint.h>
+
+#define udev_ref udev_ref_dylibloader_orig_libudev
+#define udev_unref udev_unref_dylibloader_orig_libudev
+#define udev_new udev_new_dylibloader_orig_libudev
+#define udev_set_log_fn udev_set_log_fn_dylibloader_orig_libudev
+#define udev_get_log_priority udev_get_log_priority_dylibloader_orig_libudev
+#define udev_set_log_priority udev_set_log_priority_dylibloader_orig_libudev
+#define udev_get_userdata udev_get_userdata_dylibloader_orig_libudev
+#define udev_set_userdata udev_set_userdata_dylibloader_orig_libudev
+#define udev_list_entry_get_next udev_list_entry_get_next_dylibloader_orig_libudev
+#define udev_list_entry_get_by_name udev_list_entry_get_by_name_dylibloader_orig_libudev
+#define udev_list_entry_get_name udev_list_entry_get_name_dylibloader_orig_libudev
+#define udev_list_entry_get_value udev_list_entry_get_value_dylibloader_orig_libudev
+#define udev_device_ref udev_device_ref_dylibloader_orig_libudev
+#define udev_device_unref udev_device_unref_dylibloader_orig_libudev
+#define udev_device_get_udev udev_device_get_udev_dylibloader_orig_libudev
+#define udev_device_new_from_syspath udev_device_new_from_syspath_dylibloader_orig_libudev
+#define udev_device_new_from_devnum udev_device_new_from_devnum_dylibloader_orig_libudev
+#define udev_device_new_from_subsystem_sysname udev_device_new_from_subsystem_sysname_dylibloader_orig_libudev
+#define udev_device_new_from_device_id udev_device_new_from_device_id_dylibloader_orig_libudev
+#define udev_device_new_from_environment udev_device_new_from_environment_dylibloader_orig_libudev
+#define udev_device_get_parent udev_device_get_parent_dylibloader_orig_libudev
+#define udev_device_get_parent_with_subsystem_devtype udev_device_get_parent_with_subsystem_devtype_dylibloader_orig_libudev
+#define udev_device_get_devpath udev_device_get_devpath_dylibloader_orig_libudev
+#define udev_device_get_subsystem udev_device_get_subsystem_dylibloader_orig_libudev
+#define udev_device_get_devtype udev_device_get_devtype_dylibloader_orig_libudev
+#define udev_device_get_syspath udev_device_get_syspath_dylibloader_orig_libudev
+#define udev_device_get_sysname udev_device_get_sysname_dylibloader_orig_libudev
+#define udev_device_get_sysnum udev_device_get_sysnum_dylibloader_orig_libudev
+#define udev_device_get_devnode udev_device_get_devnode_dylibloader_orig_libudev
+#define udev_device_get_is_initialized udev_device_get_is_initialized_dylibloader_orig_libudev
+#define udev_device_get_devlinks_list_entry udev_device_get_devlinks_list_entry_dylibloader_orig_libudev
+#define udev_device_get_properties_list_entry udev_device_get_properties_list_entry_dylibloader_orig_libudev
+#define udev_device_get_tags_list_entry udev_device_get_tags_list_entry_dylibloader_orig_libudev
+#define udev_device_get_sysattr_list_entry udev_device_get_sysattr_list_entry_dylibloader_orig_libudev
+#define udev_device_get_property_value udev_device_get_property_value_dylibloader_orig_libudev
+#define udev_device_get_driver udev_device_get_driver_dylibloader_orig_libudev
+#define udev_device_get_devnum udev_device_get_devnum_dylibloader_orig_libudev
+#define udev_device_get_action udev_device_get_action_dylibloader_orig_libudev
+#define udev_device_get_seqnum udev_device_get_seqnum_dylibloader_orig_libudev
+#define udev_device_get_usec_since_initialized udev_device_get_usec_since_initialized_dylibloader_orig_libudev
+#define udev_device_get_sysattr_value udev_device_get_sysattr_value_dylibloader_orig_libudev
+#define udev_device_set_sysattr_value udev_device_set_sysattr_value_dylibloader_orig_libudev
+#define udev_device_has_tag udev_device_has_tag_dylibloader_orig_libudev
+#define udev_monitor_ref udev_monitor_ref_dylibloader_orig_libudev
+#define udev_monitor_unref udev_monitor_unref_dylibloader_orig_libudev
+#define udev_monitor_get_udev udev_monitor_get_udev_dylibloader_orig_libudev
+#define udev_monitor_new_from_netlink udev_monitor_new_from_netlink_dylibloader_orig_libudev
+#define udev_monitor_enable_receiving udev_monitor_enable_receiving_dylibloader_orig_libudev
+#define udev_monitor_set_receive_buffer_size udev_monitor_set_receive_buffer_size_dylibloader_orig_libudev
+#define udev_monitor_get_fd udev_monitor_get_fd_dylibloader_orig_libudev
+#define udev_monitor_receive_device udev_monitor_receive_device_dylibloader_orig_libudev
+#define udev_monitor_filter_add_match_subsystem_devtype udev_monitor_filter_add_match_subsystem_devtype_dylibloader_orig_libudev
+#define udev_monitor_filter_add_match_tag udev_monitor_filter_add_match_tag_dylibloader_orig_libudev
+#define udev_monitor_filter_update udev_monitor_filter_update_dylibloader_orig_libudev
+#define udev_monitor_filter_remove udev_monitor_filter_remove_dylibloader_orig_libudev
+#define udev_enumerate_ref udev_enumerate_ref_dylibloader_orig_libudev
+#define udev_enumerate_unref udev_enumerate_unref_dylibloader_orig_libudev
+#define udev_enumerate_get_udev udev_enumerate_get_udev_dylibloader_orig_libudev
+#define udev_enumerate_new udev_enumerate_new_dylibloader_orig_libudev
+#define udev_enumerate_add_match_subsystem udev_enumerate_add_match_subsystem_dylibloader_orig_libudev
+#define udev_enumerate_add_nomatch_subsystem udev_enumerate_add_nomatch_subsystem_dylibloader_orig_libudev
+#define udev_enumerate_add_match_sysattr udev_enumerate_add_match_sysattr_dylibloader_orig_libudev
+#define udev_enumerate_add_nomatch_sysattr udev_enumerate_add_nomatch_sysattr_dylibloader_orig_libudev
+#define udev_enumerate_add_match_property udev_enumerate_add_match_property_dylibloader_orig_libudev
+#define udev_enumerate_add_match_sysname udev_enumerate_add_match_sysname_dylibloader_orig_libudev
+#define udev_enumerate_add_match_tag udev_enumerate_add_match_tag_dylibloader_orig_libudev
+#define udev_enumerate_add_match_parent udev_enumerate_add_match_parent_dylibloader_orig_libudev
+#define udev_enumerate_add_match_is_initialized udev_enumerate_add_match_is_initialized_dylibloader_orig_libudev
+#define udev_enumerate_add_syspath udev_enumerate_add_syspath_dylibloader_orig_libudev
+#define udev_enumerate_scan_devices udev_enumerate_scan_devices_dylibloader_orig_libudev
+#define udev_enumerate_scan_subsystems udev_enumerate_scan_subsystems_dylibloader_orig_libudev
+#define udev_enumerate_get_list_entry udev_enumerate_get_list_entry_dylibloader_orig_libudev
+#define udev_queue_ref udev_queue_ref_dylibloader_orig_libudev
+#define udev_queue_unref udev_queue_unref_dylibloader_orig_libudev
+#define udev_queue_get_udev udev_queue_get_udev_dylibloader_orig_libudev
+#define udev_queue_new udev_queue_new_dylibloader_orig_libudev
+#define udev_queue_get_kernel_seqnum udev_queue_get_kernel_seqnum_dylibloader_orig_libudev
+#define udev_queue_get_udev_seqnum udev_queue_get_udev_seqnum_dylibloader_orig_libudev
+#define udev_queue_get_udev_is_active udev_queue_get_udev_is_active_dylibloader_orig_libudev
+#define udev_queue_get_queue_is_empty udev_queue_get_queue_is_empty_dylibloader_orig_libudev
+#define udev_queue_get_seqnum_is_finished udev_queue_get_seqnum_is_finished_dylibloader_orig_libudev
+#define udev_queue_get_seqnum_sequence_is_finished udev_queue_get_seqnum_sequence_is_finished_dylibloader_orig_libudev
+#define udev_queue_get_fd udev_queue_get_fd_dylibloader_orig_libudev
+#define udev_queue_flush udev_queue_flush_dylibloader_orig_libudev
+#define udev_queue_get_queued_list_entry udev_queue_get_queued_list_entry_dylibloader_orig_libudev
+#define udev_hwdb_new udev_hwdb_new_dylibloader_orig_libudev
+#define udev_hwdb_ref udev_hwdb_ref_dylibloader_orig_libudev
+#define udev_hwdb_unref udev_hwdb_unref_dylibloader_orig_libudev
+#define udev_hwdb_get_properties_list_entry udev_hwdb_get_properties_list_entry_dylibloader_orig_libudev
+#define udev_util_encode_string udev_util_encode_string_dylibloader_orig_libudev
+#include <libudev.h>
+#undef udev_ref
+#undef udev_unref
+#undef udev_new
+#undef udev_set_log_fn
+#undef udev_get_log_priority
+#undef udev_set_log_priority
+#undef udev_get_userdata
+#undef udev_set_userdata
+#undef udev_list_entry_get_next
+#undef udev_list_entry_get_by_name
+#undef udev_list_entry_get_name
+#undef udev_list_entry_get_value
+#undef udev_device_ref
+#undef udev_device_unref
+#undef udev_device_get_udev
+#undef udev_device_new_from_syspath
+#undef udev_device_new_from_devnum
+#undef udev_device_new_from_subsystem_sysname
+#undef udev_device_new_from_device_id
+#undef udev_device_new_from_environment
+#undef udev_device_get_parent
+#undef udev_device_get_parent_with_subsystem_devtype
+#undef udev_device_get_devpath
+#undef udev_device_get_subsystem
+#undef udev_device_get_devtype
+#undef udev_device_get_syspath
+#undef udev_device_get_sysname
+#undef udev_device_get_sysnum
+#undef udev_device_get_devnode
+#undef udev_device_get_is_initialized
+#undef udev_device_get_devlinks_list_entry
+#undef udev_device_get_properties_list_entry
+#undef udev_device_get_tags_list_entry
+#undef udev_device_get_sysattr_list_entry
+#undef udev_device_get_property_value
+#undef udev_device_get_driver
+#undef udev_device_get_devnum
+#undef udev_device_get_action
+#undef udev_device_get_seqnum
+#undef udev_device_get_usec_since_initialized
+#undef udev_device_get_sysattr_value
+#undef udev_device_set_sysattr_value
+#undef udev_device_has_tag
+#undef udev_monitor_ref
+#undef udev_monitor_unref
+#undef udev_monitor_get_udev
+#undef udev_monitor_new_from_netlink
+#undef udev_monitor_enable_receiving
+#undef udev_monitor_set_receive_buffer_size
+#undef udev_monitor_get_fd
+#undef udev_monitor_receive_device
+#undef udev_monitor_filter_add_match_subsystem_devtype
+#undef udev_monitor_filter_add_match_tag
+#undef udev_monitor_filter_update
+#undef udev_monitor_filter_remove
+#undef udev_enumerate_ref
+#undef udev_enumerate_unref
+#undef udev_enumerate_get_udev
+#undef udev_enumerate_new
+#undef udev_enumerate_add_match_subsystem
+#undef udev_enumerate_add_nomatch_subsystem
+#undef udev_enumerate_add_match_sysattr
+#undef udev_enumerate_add_nomatch_sysattr
+#undef udev_enumerate_add_match_property
+#undef udev_enumerate_add_match_sysname
+#undef udev_enumerate_add_match_tag
+#undef udev_enumerate_add_match_parent
+#undef udev_enumerate_add_match_is_initialized
+#undef udev_enumerate_add_syspath
+#undef udev_enumerate_scan_devices
+#undef udev_enumerate_scan_subsystems
+#undef udev_enumerate_get_list_entry
+#undef udev_queue_ref
+#undef udev_queue_unref
+#undef udev_queue_get_udev
+#undef udev_queue_new
+#undef udev_queue_get_kernel_seqnum
+#undef udev_queue_get_udev_seqnum
+#undef udev_queue_get_udev_is_active
+#undef udev_queue_get_queue_is_empty
+#undef udev_queue_get_seqnum_is_finished
+#undef udev_queue_get_seqnum_sequence_is_finished
+#undef udev_queue_get_fd
+#undef udev_queue_flush
+#undef udev_queue_get_queued_list_entry
+#undef udev_hwdb_new
+#undef udev_hwdb_ref
+#undef udev_hwdb_unref
+#undef udev_hwdb_get_properties_list_entry
+#undef udev_util_encode_string
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define udev_ref udev_ref_dylibloader_wrapper_libudev
+#define udev_unref udev_unref_dylibloader_wrapper_libudev
+#define udev_new udev_new_dylibloader_wrapper_libudev
+#define udev_set_log_fn udev_set_log_fn_dylibloader_wrapper_libudev
+#define udev_get_log_priority udev_get_log_priority_dylibloader_wrapper_libudev
+#define udev_set_log_priority udev_set_log_priority_dylibloader_wrapper_libudev
+#define udev_get_userdata udev_get_userdata_dylibloader_wrapper_libudev
+#define udev_set_userdata udev_set_userdata_dylibloader_wrapper_libudev
+#define udev_list_entry_get_next udev_list_entry_get_next_dylibloader_wrapper_libudev
+#define udev_list_entry_get_by_name udev_list_entry_get_by_name_dylibloader_wrapper_libudev
+#define udev_list_entry_get_name udev_list_entry_get_name_dylibloader_wrapper_libudev
+#define udev_list_entry_get_value udev_list_entry_get_value_dylibloader_wrapper_libudev
+#define udev_device_ref udev_device_ref_dylibloader_wrapper_libudev
+#define udev_device_unref udev_device_unref_dylibloader_wrapper_libudev
+#define udev_device_get_udev udev_device_get_udev_dylibloader_wrapper_libudev
+#define udev_device_new_from_syspath udev_device_new_from_syspath_dylibloader_wrapper_libudev
+#define udev_device_new_from_devnum udev_device_new_from_devnum_dylibloader_wrapper_libudev
+#define udev_device_new_from_subsystem_sysname udev_device_new_from_subsystem_sysname_dylibloader_wrapper_libudev
+#define udev_device_new_from_device_id udev_device_new_from_device_id_dylibloader_wrapper_libudev
+#define udev_device_new_from_environment udev_device_new_from_environment_dylibloader_wrapper_libudev
+#define udev_device_get_parent udev_device_get_parent_dylibloader_wrapper_libudev
+#define udev_device_get_parent_with_subsystem_devtype udev_device_get_parent_with_subsystem_devtype_dylibloader_wrapper_libudev
+#define udev_device_get_devpath udev_device_get_devpath_dylibloader_wrapper_libudev
+#define udev_device_get_subsystem udev_device_get_subsystem_dylibloader_wrapper_libudev
+#define udev_device_get_devtype udev_device_get_devtype_dylibloader_wrapper_libudev
+#define udev_device_get_syspath udev_device_get_syspath_dylibloader_wrapper_libudev
+#define udev_device_get_sysname udev_device_get_sysname_dylibloader_wrapper_libudev
+#define udev_device_get_sysnum udev_device_get_sysnum_dylibloader_wrapper_libudev
+#define udev_device_get_devnode udev_device_get_devnode_dylibloader_wrapper_libudev
+#define udev_device_get_is_initialized udev_device_get_is_initialized_dylibloader_wrapper_libudev
+#define udev_device_get_devlinks_list_entry udev_device_get_devlinks_list_entry_dylibloader_wrapper_libudev
+#define udev_device_get_properties_list_entry udev_device_get_properties_list_entry_dylibloader_wrapper_libudev
+#define udev_device_get_tags_list_entry udev_device_get_tags_list_entry_dylibloader_wrapper_libudev
+#define udev_device_get_sysattr_list_entry udev_device_get_sysattr_list_entry_dylibloader_wrapper_libudev
+#define udev_device_get_property_value udev_device_get_property_value_dylibloader_wrapper_libudev
+#define udev_device_get_driver udev_device_get_driver_dylibloader_wrapper_libudev
+#define udev_device_get_devnum udev_device_get_devnum_dylibloader_wrapper_libudev
+#define udev_device_get_action udev_device_get_action_dylibloader_wrapper_libudev
+#define udev_device_get_seqnum udev_device_get_seqnum_dylibloader_wrapper_libudev
+#define udev_device_get_usec_since_initialized udev_device_get_usec_since_initialized_dylibloader_wrapper_libudev
+#define udev_device_get_sysattr_value udev_device_get_sysattr_value_dylibloader_wrapper_libudev
+#define udev_device_set_sysattr_value udev_device_set_sysattr_value_dylibloader_wrapper_libudev
+#define udev_device_has_tag udev_device_has_tag_dylibloader_wrapper_libudev
+#define udev_monitor_ref udev_monitor_ref_dylibloader_wrapper_libudev
+#define udev_monitor_unref udev_monitor_unref_dylibloader_wrapper_libudev
+#define udev_monitor_get_udev udev_monitor_get_udev_dylibloader_wrapper_libudev
+#define udev_monitor_new_from_netlink udev_monitor_new_from_netlink_dylibloader_wrapper_libudev
+#define udev_monitor_enable_receiving udev_monitor_enable_receiving_dylibloader_wrapper_libudev
+#define udev_monitor_set_receive_buffer_size udev_monitor_set_receive_buffer_size_dylibloader_wrapper_libudev
+#define udev_monitor_get_fd udev_monitor_get_fd_dylibloader_wrapper_libudev
+#define udev_monitor_receive_device udev_monitor_receive_device_dylibloader_wrapper_libudev
+#define udev_monitor_filter_add_match_subsystem_devtype udev_monitor_filter_add_match_subsystem_devtype_dylibloader_wrapper_libudev
+#define udev_monitor_filter_add_match_tag udev_monitor_filter_add_match_tag_dylibloader_wrapper_libudev
+#define udev_monitor_filter_update udev_monitor_filter_update_dylibloader_wrapper_libudev
+#define udev_monitor_filter_remove udev_monitor_filter_remove_dylibloader_wrapper_libudev
+#define udev_enumerate_ref udev_enumerate_ref_dylibloader_wrapper_libudev
+#define udev_enumerate_unref udev_enumerate_unref_dylibloader_wrapper_libudev
+#define udev_enumerate_get_udev udev_enumerate_get_udev_dylibloader_wrapper_libudev
+#define udev_enumerate_new udev_enumerate_new_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_subsystem udev_enumerate_add_match_subsystem_dylibloader_wrapper_libudev
+#define udev_enumerate_add_nomatch_subsystem udev_enumerate_add_nomatch_subsystem_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_sysattr udev_enumerate_add_match_sysattr_dylibloader_wrapper_libudev
+#define udev_enumerate_add_nomatch_sysattr udev_enumerate_add_nomatch_sysattr_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_property udev_enumerate_add_match_property_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_sysname udev_enumerate_add_match_sysname_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_tag udev_enumerate_add_match_tag_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_parent udev_enumerate_add_match_parent_dylibloader_wrapper_libudev
+#define udev_enumerate_add_match_is_initialized udev_enumerate_add_match_is_initialized_dylibloader_wrapper_libudev
+#define udev_enumerate_add_syspath udev_enumerate_add_syspath_dylibloader_wrapper_libudev
+#define udev_enumerate_scan_devices udev_enumerate_scan_devices_dylibloader_wrapper_libudev
+#define udev_enumerate_scan_subsystems udev_enumerate_scan_subsystems_dylibloader_wrapper_libudev
+#define udev_enumerate_get_list_entry udev_enumerate_get_list_entry_dylibloader_wrapper_libudev
+#define udev_queue_ref udev_queue_ref_dylibloader_wrapper_libudev
+#define udev_queue_unref udev_queue_unref_dylibloader_wrapper_libudev
+#define udev_queue_get_udev udev_queue_get_udev_dylibloader_wrapper_libudev
+#define udev_queue_new udev_queue_new_dylibloader_wrapper_libudev
+#define udev_queue_get_kernel_seqnum udev_queue_get_kernel_seqnum_dylibloader_wrapper_libudev
+#define udev_queue_get_udev_seqnum udev_queue_get_udev_seqnum_dylibloader_wrapper_libudev
+#define udev_queue_get_udev_is_active udev_queue_get_udev_is_active_dylibloader_wrapper_libudev
+#define udev_queue_get_queue_is_empty udev_queue_get_queue_is_empty_dylibloader_wrapper_libudev
+#define udev_queue_get_seqnum_is_finished udev_queue_get_seqnum_is_finished_dylibloader_wrapper_libudev
+#define udev_queue_get_seqnum_sequence_is_finished udev_queue_get_seqnum_sequence_is_finished_dylibloader_wrapper_libudev
+#define udev_queue_get_fd udev_queue_get_fd_dylibloader_wrapper_libudev
+#define udev_queue_flush udev_queue_flush_dylibloader_wrapper_libudev
+#define udev_queue_get_queued_list_entry udev_queue_get_queued_list_entry_dylibloader_wrapper_libudev
+#define udev_hwdb_new udev_hwdb_new_dylibloader_wrapper_libudev
+#define udev_hwdb_ref udev_hwdb_ref_dylibloader_wrapper_libudev
+#define udev_hwdb_unref udev_hwdb_unref_dylibloader_wrapper_libudev
+#define udev_hwdb_get_properties_list_entry udev_hwdb_get_properties_list_entry_dylibloader_wrapper_libudev
+#define udev_util_encode_string udev_util_encode_string_dylibloader_wrapper_libudev
+extern struct udev* (*udev_ref_dylibloader_wrapper_libudev)(struct udev*);
+extern struct udev* (*udev_unref_dylibloader_wrapper_libudev)(struct udev*);
+extern struct udev* (*udev_new_dylibloader_wrapper_libudev)( void);
+extern void (*udev_set_log_fn_dylibloader_wrapper_libudev)(struct udev*, void*);
+extern int (*udev_get_log_priority_dylibloader_wrapper_libudev)(struct udev*);
+extern void (*udev_set_log_priority_dylibloader_wrapper_libudev)(struct udev*, int);
+extern void* (*udev_get_userdata_dylibloader_wrapper_libudev)(struct udev*);
+extern void (*udev_set_userdata_dylibloader_wrapper_libudev)(struct udev*, void*);
+extern struct udev_list_entry* (*udev_list_entry_get_next_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+extern struct udev_list_entry* (*udev_list_entry_get_by_name_dylibloader_wrapper_libudev)(struct udev_list_entry*,const char*);
+extern const char* (*udev_list_entry_get_name_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+extern const char* (*udev_list_entry_get_value_dylibloader_wrapper_libudev)(struct udev_list_entry*);
+extern struct udev_device* (*udev_device_ref_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_device* (*udev_device_unref_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev* (*udev_device_get_udev_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_device* (*udev_device_new_from_syspath_dylibloader_wrapper_libudev)(struct udev*,const char*);
+extern struct udev_device* (*udev_device_new_from_devnum_dylibloader_wrapper_libudev)(struct udev*, char, dev_t);
+extern struct udev_device* (*udev_device_new_from_subsystem_sysname_dylibloader_wrapper_libudev)(struct udev*,const char*,const char*);
+extern struct udev_device* (*udev_device_new_from_device_id_dylibloader_wrapper_libudev)(struct udev*,const char*);
+extern struct udev_device* (*udev_device_new_from_environment_dylibloader_wrapper_libudev)(struct udev*);
+extern struct udev_device* (*udev_device_get_parent_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_device* (*udev_device_get_parent_with_subsystem_devtype_dylibloader_wrapper_libudev)(struct udev_device*,const char*,const char*);
+extern const char* (*udev_device_get_devpath_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_subsystem_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_devtype_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_syspath_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_sysname_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_sysnum_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_devnode_dylibloader_wrapper_libudev)(struct udev_device*);
+extern int (*udev_device_get_is_initialized_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_list_entry* (*udev_device_get_devlinks_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_list_entry* (*udev_device_get_properties_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_list_entry* (*udev_device_get_tags_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+extern struct udev_list_entry* (*udev_device_get_sysattr_list_entry_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_property_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+extern const char* (*udev_device_get_driver_dylibloader_wrapper_libudev)(struct udev_device*);
+extern dev_t (*udev_device_get_devnum_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_action_dylibloader_wrapper_libudev)(struct udev_device*);
+extern unsigned long long int (*udev_device_get_seqnum_dylibloader_wrapper_libudev)(struct udev_device*);
+extern unsigned long long int (*udev_device_get_usec_since_initialized_dylibloader_wrapper_libudev)(struct udev_device*);
+extern const char* (*udev_device_get_sysattr_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+extern int (*udev_device_set_sysattr_value_dylibloader_wrapper_libudev)(struct udev_device*,const char*,const char*);
+extern int (*udev_device_has_tag_dylibloader_wrapper_libudev)(struct udev_device*,const char*);
+extern struct udev_monitor* (*udev_monitor_ref_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev_monitor* (*udev_monitor_unref_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev* (*udev_monitor_get_udev_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev_monitor* (*udev_monitor_new_from_netlink_dylibloader_wrapper_libudev)(struct udev*,const char*);
+extern int (*udev_monitor_enable_receiving_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern int (*udev_monitor_set_receive_buffer_size_dylibloader_wrapper_libudev)(struct udev_monitor*, int);
+extern int (*udev_monitor_get_fd_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev_device* (*udev_monitor_receive_device_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern int (*udev_monitor_filter_add_match_subsystem_devtype_dylibloader_wrapper_libudev)(struct udev_monitor*,const char*,const char*);
+extern int (*udev_monitor_filter_add_match_tag_dylibloader_wrapper_libudev)(struct udev_monitor*,const char*);
+extern int (*udev_monitor_filter_update_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern int (*udev_monitor_filter_remove_dylibloader_wrapper_libudev)(struct udev_monitor*);
+extern struct udev_enumerate* (*udev_enumerate_ref_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev_enumerate* (*udev_enumerate_unref_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev* (*udev_enumerate_get_udev_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev_enumerate* (*udev_enumerate_new_dylibloader_wrapper_libudev)(struct udev*);
+extern int (*udev_enumerate_add_match_subsystem_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_add_nomatch_subsystem_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_add_match_sysattr_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+extern int (*udev_enumerate_add_nomatch_sysattr_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+extern int (*udev_enumerate_add_match_property_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*,const char*);
+extern int (*udev_enumerate_add_match_sysname_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_add_match_tag_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_add_match_parent_dylibloader_wrapper_libudev)(struct udev_enumerate*,struct udev_device*);
+extern int (*udev_enumerate_add_match_is_initialized_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern int (*udev_enumerate_add_syspath_dylibloader_wrapper_libudev)(struct udev_enumerate*,const char*);
+extern int (*udev_enumerate_scan_devices_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern int (*udev_enumerate_scan_subsystems_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev_list_entry* (*udev_enumerate_get_list_entry_dylibloader_wrapper_libudev)(struct udev_enumerate*);
+extern struct udev_queue* (*udev_queue_ref_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev_queue* (*udev_queue_unref_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev* (*udev_queue_get_udev_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev_queue* (*udev_queue_new_dylibloader_wrapper_libudev)(struct udev*);
+extern unsigned long long int (*udev_queue_get_kernel_seqnum_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern unsigned long long int (*udev_queue_get_udev_seqnum_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern int (*udev_queue_get_udev_is_active_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern int (*udev_queue_get_queue_is_empty_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern int (*udev_queue_get_seqnum_is_finished_dylibloader_wrapper_libudev)(struct udev_queue*, unsigned long long int);
+extern int (*udev_queue_get_seqnum_sequence_is_finished_dylibloader_wrapper_libudev)(struct udev_queue*, unsigned long long int, unsigned long long int);
+extern int (*udev_queue_get_fd_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern int (*udev_queue_flush_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev_list_entry* (*udev_queue_get_queued_list_entry_dylibloader_wrapper_libudev)(struct udev_queue*);
+extern struct udev_hwdb* (*udev_hwdb_new_dylibloader_wrapper_libudev)(struct udev*);
+extern struct udev_hwdb* (*udev_hwdb_ref_dylibloader_wrapper_libudev)(struct udev_hwdb*);
+extern struct udev_hwdb* (*udev_hwdb_unref_dylibloader_wrapper_libudev)(struct udev_hwdb*);
+extern struct udev_list_entry* (*udev_hwdb_get_properties_list_entry_dylibloader_wrapper_libudev)(struct udev_hwdb*,const char*, unsigned);
+extern int (*udev_util_encode_string_dylibloader_wrapper_libudev)(const char*, char*, size_t);
+int initialize_libudev(int verbose);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index e00a32e3ba..2c9801f512 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#include "os_linuxbsd.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include "main/main.h"
#ifdef X11_ENABLED
@@ -51,6 +51,70 @@
#include <sys/types.h>
#include <unistd.h>
+void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
+ const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
+
+ String path = get_environment("PATH");
+ Vector<String> path_elems = path.split(":", false);
+ String program;
+
+ for (int i = 0; i < path_elems.size(); i++) {
+ for (uint64_t k = 0; k < sizeof(message_programs) / sizeof(char *); k++) {
+ String tested_path = path_elems[i].plus_file(message_programs[k]);
+
+ if (FileAccess::exists(tested_path)) {
+ program = tested_path;
+ break;
+ }
+ }
+
+ if (program.length()) {
+ break;
+ }
+ }
+
+ List<String> args;
+
+ if (program.ends_with("zenity")) {
+ args.push_back("--error");
+ args.push_back("--width");
+ args.push_back("500");
+ args.push_back("--title");
+ args.push_back(p_title);
+ args.push_back("--text");
+ args.push_back(p_alert);
+ }
+
+ if (program.ends_with("kdialog")) {
+ args.push_back("--error");
+ args.push_back(p_alert);
+ args.push_back("--title");
+ args.push_back(p_title);
+ }
+
+ if (program.ends_with("Xdialog")) {
+ args.push_back("--title");
+ args.push_back(p_title);
+ args.push_back("--msgbox");
+ args.push_back(p_alert);
+ args.push_back("0");
+ args.push_back("0");
+ }
+
+ if (program.ends_with("xmessage")) {
+ args.push_back("-center");
+ args.push_back("-title");
+ args.push_back(p_title);
+ args.push_back(p_alert);
+ }
+
+ if (program.length()) {
+ execute(program, args);
+ } else {
+ print_line(p_alert);
+ }
+}
+
void OS_LinuxBSD::initialize() {
crash_handler.initialize();
@@ -65,9 +129,9 @@ void OS_LinuxBSD::initialize_joypads() {
String OS_LinuxBSD::get_unique_id() const {
static String machine_id;
- if (machine_id.empty()) {
+ if (machine_id.is_empty()) {
if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) {
- while (machine_id.empty() && !f->eof_reached()) {
+ while (machine_id.is_empty() && !f->eof_reached()) {
machine_id = f->get_line().strip_edges();
}
f->close();
@@ -116,6 +180,8 @@ String OS_LinuxBSD::get_name() const {
return "FreeBSD";
#elif defined(__NetBSD__)
return "NetBSD";
+#elif defined(__OpenBSD__)
+ return "OpenBSD";
#else
return "BSD";
#endif
@@ -123,18 +189,39 @@ String OS_LinuxBSD::get_name() const {
Error OS_LinuxBSD::shell_open(String p_uri) {
Error ok;
+ int err_code;
List<String> args;
args.push_back(p_uri);
- ok = execute("xdg-open", args, false);
- if (ok == OK) {
+
+ // Agnostic
+ ok = execute("xdg-open", args, nullptr, &err_code);
+ if (ok == OK && !err_code) {
return OK;
+ } else if (err_code == 2) {
+ return ERR_FILE_NOT_FOUND;
}
- ok = execute("gnome-open", args, false);
- if (ok == OK) {
+ // GNOME
+ args.push_front("open"); // The command is `gio open`, so we need to add it to args
+ ok = execute("gio", args, nullptr, &err_code);
+ if (ok == OK && !err_code) {
return OK;
+ } else if (err_code == 2) {
+ return ERR_FILE_NOT_FOUND;
}
- ok = execute("kde-open", args, false);
- return ok;
+ args.pop_front();
+ ok = execute("gvfs-open", args, nullptr, &err_code);
+ if (ok == OK && !err_code) {
+ return OK;
+ } else if (err_code == 2) {
+ return ERR_FILE_NOT_FOUND;
+ }
+ // KDE
+ ok = execute("kde-open5", args, nullptr, &err_code);
+ if (ok == OK && !err_code) {
+ return OK;
+ }
+ ok = execute("kde-open", args, nullptr, &err_code);
+ return !err_code ? ok : FAILED;
}
bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
@@ -143,7 +230,12 @@ bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
String OS_LinuxBSD::get_config_path() const {
if (has_environment("XDG_CONFIG_HOME")) {
- return get_environment("XDG_CONFIG_HOME");
+ if (get_environment("XDG_CONFIG_HOME").is_absolute_path()) {
+ return get_environment("XDG_CONFIG_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CONFIG_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.config` or `.` per the XDG Base Directory specification.");
+ return has_environment("HOME") ? get_environment("HOME").plus_file(".config") : ".";
+ }
} else if (has_environment("HOME")) {
return get_environment("HOME").plus_file(".config");
} else {
@@ -153,7 +245,12 @@ String OS_LinuxBSD::get_config_path() const {
String OS_LinuxBSD::get_data_path() const {
if (has_environment("XDG_DATA_HOME")) {
- return get_environment("XDG_DATA_HOME");
+ if (get_environment("XDG_DATA_HOME").is_absolute_path()) {
+ return get_environment("XDG_DATA_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_DATA_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.local/share` or `get_config_path()` per the XDG Base Directory specification.");
+ return has_environment("HOME") ? get_environment("HOME").plus_file(".local/share") : get_config_path();
+ }
} else if (has_environment("HOME")) {
return get_environment("HOME").plus_file(".local/share");
} else {
@@ -163,7 +260,12 @@ String OS_LinuxBSD::get_data_path() const {
String OS_LinuxBSD::get_cache_path() const {
if (has_environment("XDG_CACHE_HOME")) {
- return get_environment("XDG_CACHE_HOME");
+ if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
+ return get_environment("XDG_CACHE_HOME");
+ } else {
+ WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/.cache` or `get_config_path()` per the XDG Base Directory specification.");
+ return has_environment("HOME") ? get_environment("HOME").plus_file(".cache") : get_config_path();
+ }
} else if (has_environment("HOME")) {
return get_environment("HOME").plus_file(".cache");
} else {
@@ -171,7 +273,7 @@ String OS_LinuxBSD::get_cache_path() const {
}
}
-String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
+String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
String xdgparam;
switch (p_dir) {
@@ -211,7 +313,7 @@ String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
String pipe;
List<String> arg;
arg.push_back(xdgparam);
- Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, true, nullptr, &pipe);
+ Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, &pipe);
if (err != OK) {
return ".";
}
@@ -225,7 +327,7 @@ void OS_LinuxBSD::run() {
return;
}
- main_loop->init();
+ main_loop->initialize();
//uint64_t last_ticks=get_ticks_usec();
@@ -242,7 +344,7 @@ void OS_LinuxBSD::run() {
}
};
- main_loop->finish();
+ main_loop->finalize();
}
void OS_LinuxBSD::disable_crash_handler() {
@@ -282,65 +384,147 @@ static String get_mountpoint(const String &p_path) {
}
Error OS_LinuxBSD::move_to_trash(const String &p_path) {
- String trash_can = "";
+ int err_code;
+ List<String> args;
+ args.push_back(p_path);
+ args.push_front("trash"); // The command is `gio trash <file_name>` so we need to add it to args.
+ Error result = execute("gio", args, nullptr, &err_code); // For GNOME based machines.
+ if (result == OK && !err_code) {
+ return OK;
+ } else if (err_code == 2) {
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ args.pop_front();
+ args.push_front("move");
+ args.push_back("trash:/"); // The command is `kioclient5 move <file_name> trash:/`.
+ result = execute("kioclient5", args, nullptr, &err_code); // For KDE based machines.
+ if (result == OK && !err_code) {
+ return OK;
+ } else if (err_code == 2) {
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ args.pop_front();
+ args.pop_back();
+ result = execute("gvfs-trash", args, nullptr, &err_code); // For older Linux machines.
+ if (result == OK && !err_code) {
+ return OK;
+ } else if (err_code == 2) {
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ // If the commands `kioclient5`, `gio` or `gvfs-trash` don't exist on the system we do it manually.
+ String trash_path = "";
String mnt = get_mountpoint(p_path);
- // If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can.
+ // If there is a directory "[Mountpoint]/.Trash-[UID], use it as the trash can.
if (mnt != "") {
- String path(mnt + "/.Trash-" + itos(getuid()) + "/files");
+ String path(mnt + "/.Trash-" + itos(getuid()));
struct stat s;
if (!stat(path.utf8().get_data(), &s)) {
- trash_can = path;
+ trash_path = path;
}
}
- // Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can.
- if (trash_can == "") {
+ // Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash" as the trash can.
+ if (trash_path == "") {
char *dhome = getenv("XDG_DATA_HOME");
if (dhome) {
- trash_can = String(dhome) + "/Trash/files";
+ trash_path = String(dhome) + "/Trash";
}
}
- // Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can.
- if (trash_can == "") {
+ // Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash" as the trash can.
+ if (trash_path == "") {
char *home = getenv("HOME");
if (home) {
- trash_can = String(home) + "/.local/share/Trash/files";
+ trash_path = String(home) + "/.local/share/Trash";
}
}
// Issue an error if none of the previous locations is appropriate for the trash can.
- if (trash_can == "") {
- ERR_PRINT("move_to_trash: Could not determine the trash can location");
- return FAILED;
- }
+ ERR_FAIL_COND_V_MSG(trash_path == "", FAILED, "Could not determine the trash can location");
// Create needed directories for decided trash can location.
- DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- Error err = dir_access->make_dir_recursive(trash_can);
- memdelete(dir_access);
+ {
+ DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Error err = dir_access->make_dir_recursive(trash_path);
+
+ // Issue an error if trash can is not created properly.
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"");
+ err = dir_access->make_dir_recursive(trash_path + "/files");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files");
+ err = dir_access->make_dir_recursive(trash_path + "/info");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info");
+ memdelete(dir_access);
+ }
- // Issue an error if trash can is not created proprely.
- if (err != OK) {
- ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\"");
- return err;
+ // The trash can is successfully created, now we check that we don't exceed our file name length limit.
+ // If the file name is too long trim it so we can add the identifying number and ".trashinfo".
+ // Assumes that the file name length limit is 255 characters.
+ String file_name = basename(p_path.utf8().get_data());
+ if (file_name.length() > 240) {
+ file_name = file_name.substr(0, file_name.length() - 15);
}
- // The trash can is successfully created, now move the given resource to it.
+ String dest_path = trash_path + "/files/" + file_name;
+ struct stat buff;
+ int id_number = 0;
+ String fn = file_name;
+
+ // Checks if a resource with the same name already exist in the trash can,
+ // if there is, add an identifying number to our resource's name.
+ while (stat(dest_path.utf8().get_data(), &buff) == 0) {
+ id_number++;
+
+ // Added a limit to check for identically named files already on the trash can
+ // if there are too many it could make the editor unresponsive.
+ ERR_FAIL_COND_V_MSG(id_number > 99, FAILED, "Too many identically named resources already in the trash can.");
+ fn = file_name + "." + itos(id_number);
+ dest_path = trash_path + "/files/" + fn;
+ }
+ file_name = fn;
+
+ // 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.
+ String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
+ {
+ Error err;
+ FileAccess *file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo");
+ file->store_string(trash_info);
+ file->close();
+
+ // Rename our resource before moving it to the trash can.
+ DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\"");
+ memdelete(dir_access);
+ }
+
+ // Move the given resource to the trash can.
// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
List<String> mv_args;
- mv_args.push_back(p_path);
- mv_args.push_back(trash_can);
- int retval;
- err = execute("mv", mv_args, true, nullptr, nullptr, &retval);
-
- // Issue an error if "mv" failed to move the given resource to the trash can.
- if (err != OK || retval != 0) {
- ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\"");
- return FAILED;
+ mv_args.push_back(p_path.get_base_dir() + "/" + file_name);
+ mv_args.push_back(trash_path + "/files");
+ {
+ int retval;
+ Error err = execute("mv", mv_args, nullptr, &retval);
+
+ // Issue an error if "mv" failed to move the given resource to the trash can.
+ if (err != OK || retval != 0) {
+ ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_path + "/files\"");
+ DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ err = dir_access->rename(p_path.get_base_dir() + "/" + file_name, p_path);
+ memdelete(dir_access);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename " + p_path.get_base_dir() + "/" + file_name + " back to its original name:" + p_path);
+ return FAILED;
+ }
}
-
return OK;
}
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index cd4fbd9db5..35c80e3f9b 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,11 +39,11 @@
#include "drivers/unix/os_unix.h"
#include "joypad_linux.h"
#include "servers/audio_server.h"
-#include "servers/rendering/rasterizer.h"
+#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
class OS_LinuxBSD : public OS_Unix {
- virtual void delete_main_loop();
+ virtual void delete_main_loop() override;
bool force_quit;
@@ -68,36 +68,38 @@ class OS_LinuxBSD : public OS_Unix {
MainLoop *main_loop;
protected:
- virtual void initialize();
- virtual void finalize();
+ virtual void initialize() override;
+ virtual void finalize() override;
- virtual void initialize_joypads();
+ virtual void initialize_joypads() override;
- virtual void set_main_loop(MainLoop *p_main_loop);
+ virtual void set_main_loop(MainLoop *p_main_loop) override;
public:
- virtual String get_name() const;
+ virtual String get_name() const override;
- virtual MainLoop *get_main_loop() const;
+ virtual MainLoop *get_main_loop() const override;
- virtual String get_config_path() const;
- virtual String get_data_path() const;
- virtual String get_cache_path() const;
+ virtual String get_config_path() const override;
+ virtual String get_data_path() const override;
+ virtual String get_cache_path() const override;
- virtual String get_system_dir(SystemDir p_dir) const;
+ virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
- virtual Error shell_open(String p_uri);
+ virtual Error shell_open(String p_uri) override;
- virtual String get_unique_id() const;
+ virtual String get_unique_id() const override;
- virtual bool _check_internal_feature_support(const String &p_feature);
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+
+ virtual bool _check_internal_feature_support(const String &p_feature) override;
void run();
- void disable_crash_handler();
- bool is_disable_crash_handler() const;
+ virtual void disable_crash_handler() override;
+ virtual bool is_disable_crash_handler() const override;
- virtual Error move_to_trash(const String &p_path);
+ virtual Error move_to_trash(const String &p_path) override;
OS_LinuxBSD();
};
diff --git a/platform/linuxbsd/platform_config.h b/platform/linuxbsd/platform_config.h
index 571ad03db0..3195d08935 100644
--- a/platform/linuxbsd/platform_config.h
+++ b/platform/linuxbsd/platform_config.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/platform/linuxbsd/vulkan_context_x11.cpp b/platform/linuxbsd/vulkan_context_x11.cpp
index 2eaa9f9446..4d58e4999b 100644
--- a/platform/linuxbsd/vulkan_context_x11.cpp
+++ b/platform/linuxbsd/vulkan_context_x11.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,13 +29,17 @@
/*************************************************************************/
#include "vulkan_context_x11.h"
-#include <vulkan/vulkan_xlib.h>
+#ifdef USE_VOLK
+#include <volk.h>
+#else
+#include <vulkan/vulkan.h>
+#endif
const char *VulkanContextX11::_get_platform_surface_extension() const {
return VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
}
-Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height) {
+Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, ::Window p_window, Display *p_display, int p_width, int p_height) {
VkXlibSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
@@ -44,9 +48,9 @@ Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, ::Win
createInfo.window = p_window;
VkSurfaceKHR surface;
- VkResult err = vkCreateXlibSurfaceKHR(_get_instance(), &createInfo, nullptr, &surface);
+ VkResult err = vkCreateXlibSurfaceKHR(get_instance(), &createInfo, nullptr, &surface);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
- return _window_create(p_window_id, surface, p_width, p_height);
+ return _window_create(p_window_id, p_vsync_mode, surface, p_width, p_height);
}
VulkanContextX11::VulkanContextX11() {
diff --git a/platform/linuxbsd/vulkan_context_x11.h b/platform/linuxbsd/vulkan_context_x11.h
index af3d923cfe..de4a9c7b90 100644
--- a/platform/linuxbsd/vulkan_context_x11.h
+++ b/platform/linuxbsd/vulkan_context_x11.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,7 +38,7 @@ class VulkanContextX11 : public VulkanContext {
virtual const char *_get_platform_surface_extension() const;
public:
- Error window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height);
+ Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, ::Window p_window, Display *p_display, int p_width, int p_height);
VulkanContextX11();
~VulkanContextX11();