summaryrefslogtreecommitdiff
path: root/platform/linuxbsd
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/README.md2
-rw-r--r--platform/linuxbsd/crash_handler_linuxbsd.cpp46
-rw-r--r--platform/linuxbsd/detect.py17
-rw-r--r--platform/linuxbsd/export/export.cpp1
-rw-r--r--platform/linuxbsd/export/export_plugin.cpp344
-rw-r--r--platform/linuxbsd/export/export_plugin.h45
-rw-r--r--platform/linuxbsd/joypad_linux.cpp24
-rw-r--r--platform/linuxbsd/joypad_linux.h2
-rw-r--r--platform/linuxbsd/logo.pngbin1679 -> 0 bytes
-rw-r--r--platform/linuxbsd/logo.svg1
-rw-r--r--platform/linuxbsd/run_icon.svg1
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp202
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h19
13 files changed, 568 insertions, 136 deletions
diff --git a/platform/linuxbsd/README.md b/platform/linuxbsd/README.md
index efa8682062..c4f287cc6c 100644
--- a/platform/linuxbsd/README.md
+++ b/platform/linuxbsd/README.md
@@ -7,7 +7,7 @@ used by this platform.
## Documentation
-- [Compiling for Linux/*BSD](https://docs.godotengine.org/en/latest/development/compiling/compiling_for_linuxbsd.html)
+- [Compiling for Linux/*BSD](https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_linuxbsd.html)
- Instructions on building this platform port from source.
- [Exporting for Linux/*BSD](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_linux.html)
- Instructions on using the compiled export templates to export a project.
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp
index add69c436f..3a245460b4 100644
--- a/platform/linuxbsd/crash_handler_linuxbsd.cpp
+++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp
@@ -44,6 +44,7 @@
#include <cxxabi.h>
#include <dlfcn.h>
#include <execinfo.h>
+#include <link.h>
#include <signal.h>
#include <stdlib.h>
@@ -79,7 +80,33 @@ static void handle_crash(int sig) {
}
print_error(vformat("Dumping the backtrace. %s", msg));
char **strings = backtrace_symbols(bt_buffer, size);
+ // PIE executable relocation, zero for non-PIE executables
+#ifdef __GLIBC__
+ // This is a glibc only thing apparently.
+ uintptr_t relocation = _r_debug.r_map->l_addr;
+#else
+ // Non glibc systems apparently don't give PIE relocation info.
+ uintptr_t relocation = 0;
+#endif //__GLIBC__
if (strings) {
+ List<String> args;
+ for (size_t i = 0; i < size; i++) {
+ char str[1024];
+ snprintf(str, 1024, "%p", (void *)((uintptr_t)bt_buffer[i] - relocation));
+ args.push_back(str);
+ }
+ args.push_back("-e");
+ args.push_back(_execpath);
+
+ // Try to get the file/line number using addr2line
+ int ret;
+ String output = "";
+ Error err = OS::get_singleton()->execute(String("addr2line"), args, &output, &ret);
+ Vector<String> addr2line_results;
+ if (err == OK) {
+ addr2line_results = output.substr(0, output.length() - 1).split("\n", false);
+ }
+
for (size_t i = 1; i < size; i++) {
char fname[1024];
Dl_info info;
@@ -102,24 +129,7 @@ static void handle_crash(int sig) {
}
}
- List<String> args;
-
- char str[1024];
- snprintf(str, 1024, "%p", bt_buffer[i]);
- args.push_back(str);
- args.push_back("-e");
- args.push_back(_execpath);
-
- String output = "";
-
- // Try to get the file/line number using addr2line
- int ret;
- Error err = OS::get_singleton()->execute(String("addr2line"), args, &output, &ret);
- if (err == OK) {
- output = output.substr(0, output.length() - 1);
- }
-
- print_error(vformat("[%d] %s (%s)", (int64_t)i, fname, output));
+ print_error(vformat("[%d] %s (%s)", (int64_t)i, fname, err == OK ? addr2line_results[i] : ""));
}
free(strings);
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 747dcbd76c..7bed1a3447 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -271,7 +271,7 @@ def configure(env: "Environment"):
env.Append(LIBS=["miniupnpc"])
# On Linux wchar_t should be 32-bits
- # 16-bit library shouldn't be required due to compiler optimisations
+ # 16-bit library shouldn't be required due to compiler optimizations
if not env["builtin_pcre2"]:
env.ParseConfig("pkg-config libpcre2-32 --cflags --libs")
@@ -338,12 +338,17 @@ def configure(env: "Environment"):
env.Prepend(CPPPATH=["#platform/linuxbsd"])
+ env.Append(
+ CPPDEFINES=[
+ "LINUXBSD_ENABLED",
+ "UNIX_ENABLED",
+ ("_FILE_OFFSET_BITS", 64),
+ ]
+ )
+
if env["x11"]:
env.Append(CPPDEFINES=["X11_ENABLED"])
- env.Append(CPPDEFINES=["UNIX_ENABLED"])
- env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)])
-
if env["vulkan"]:
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
if not env["use_volk"]:
@@ -400,9 +405,9 @@ def configure(env: "Environment"):
# Link those statically for portability
if env["use_static_cpp"]:
env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"])
- if env["use_llvm"]:
+ if env["use_llvm"] and platform.system() != "FreeBSD":
env["LINKCOM"] = env["LINKCOM"] + " -l:libatomic.a"
else:
- if env["use_llvm"]:
+ if env["use_llvm"] and platform.system() != "FreeBSD":
env.Append(LIBS=["atomic"])
diff --git a/platform/linuxbsd/export/export.cpp b/platform/linuxbsd/export/export.cpp
index e6925a2011..2c5a945b6c 100644
--- a/platform/linuxbsd/export/export.cpp
+++ b/platform/linuxbsd/export/export.cpp
@@ -36,7 +36,6 @@
void register_linuxbsd_exporter() {
Ref<EditorExportPlatformLinuxBSD> platform;
platform.instantiate();
- platform->set_logo(ImageTexture::create_from_image(memnew(Image(_linuxbsd_logo))));
platform->set_name("Linux/X11");
platform->set_os_name("Linux");
platform->set_chmod_flags(0755);
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp
index f6e59bf465..c900cad007 100644
--- a/platform/linuxbsd/export/export_plugin.cpp
+++ b/platform/linuxbsd/export/export_plugin.cpp
@@ -32,6 +32,15 @@
#include "core/config/project_settings.h"
#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
+#include "editor/editor_scale.h"
+#include "platform/linuxbsd/logo_svg.gen.h"
+#include "platform/linuxbsd/run_icon_svg.gen.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#ifdef MODULE_SVG_ENABLED
+#include "modules/svg/image_loader_svg.h"
+#endif
Error EditorExportPlatformLinuxBSD::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
@@ -49,26 +58,47 @@ Error EditorExportPlatformLinuxBSD::_export_debug_script(const Ref<EditorExportP
}
Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, p_path, p_flags);
-
- if (err != OK) {
- return err;
- }
+ bool export_as_zip = p_path.ends_with("zip");
- String app_name;
+ String pkg_name;
if (String(GLOBAL_GET("application/config/name")) != "") {
- app_name = String(GLOBAL_GET("application/config/name"));
+ pkg_name = String(GLOBAL_GET("application/config/name"));
} else {
- app_name = "Unnamed";
+ pkg_name = "Unnamed";
+ }
+
+ pkg_name = OS::get_singleton()->get_safe_dir_name(pkg_name);
+
+ // Setup temp folder.
+ String path = p_path;
+ String tmp_dir_path = EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name);
+
+ Ref<DirAccess> tmp_app_dir = DirAccess::create_for_path(tmp_dir_path);
+ if (export_as_zip) {
+ if (tmp_app_dir.is_null()) {
+ return ERR_CANT_CREATE;
+ }
+ if (DirAccess::exists(tmp_dir_path)) {
+ if (tmp_app_dir->change_dir(tmp_dir_path) == OK) {
+ tmp_app_dir->erase_contents_recursive();
+ }
+ }
+ tmp_app_dir->make_dir_recursive(tmp_dir_path);
+ path = tmp_dir_path.path_join(p_path.get_file().get_basename());
+ }
+
+ // Export project.
+ Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, path, p_flags);
+ if (err != OK) {
+ return err;
}
- app_name = OS::get_singleton()->get_safe_dir_name(app_name);
// Save console script.
if (err == OK) {
int con_scr = p_preset->get("debug/export_console_script");
if ((con_scr == 1 && p_debug) || (con_scr == 2)) {
- String scr_path = p_path.get_basename() + ".sh";
- err = _export_debug_script(p_preset, app_name, p_path.get_file(), scr_path);
+ String scr_path = path.get_basename() + ".sh";
+ err = _export_debug_script(p_preset, pkg_name, path.get_file(), scr_path);
FileAccess::set_unix_permissions(scr_path, 0755);
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Debug Script Export"), TTR("Could not create console script."));
@@ -76,6 +106,27 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset>
}
}
+ // ZIP project.
+ if (export_as_zip) {
+ if (FileAccess::exists(p_path)) {
+ OS::get_singleton()->move_to_trash(p_path);
+ }
+
+ Ref<FileAccess> io_fa_dst;
+ zlib_filefunc_def io_dst = zipio_create_io(&io_fa_dst);
+ zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io_dst);
+
+ zip_folder_recursive(zip, tmp_dir_path, "", pkg_name);
+
+ zipClose(zip, nullptr);
+
+ if (tmp_app_dir->change_dir(tmp_dir_path) == OK) {
+ tmp_app_dir->erase_contents_recursive();
+ tmp_app_dir->change_dir("..");
+ tmp_app_dir->remove(pkg_name);
+ }
+ }
+
return err;
}
@@ -86,12 +137,51 @@ String EditorExportPlatformLinuxBSD::get_template_file_name(const String &p_targ
List<String> EditorExportPlatformLinuxBSD::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const {
List<String> list;
list.push_back(p_preset->get("binary_format/architecture"));
+ list.push_back("zip");
+
return list;
}
void EditorExportPlatformLinuxBSD::get_export_options(List<ExportOption> *r_options) {
EditorExportPlatformPC::get_export_options(r_options);
+
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32,arm64,arm32,rv64,ppc64,ppc32"), "x86_64"));
+
+ String run_script = "#!/usr/bin/env bash\n"
+ "export DISPLAY=:0\n"
+ "unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"\n"
+ "\"{temp_dir}/{exe_name}\" {cmd_args}";
+
+ String cleanup_script = "#!/usr/bin/env bash\n"
+ "kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")\n"
+ "rm -rf \"{temp_dir}\"";
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "ssh_remote_deploy/enabled"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "ssh_remote_deploy/host"), "user@host_ip"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "ssh_remote_deploy/port"), "22"));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "ssh_remote_deploy/extra_args_ssh", PROPERTY_HINT_MULTILINE_TEXT), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "ssh_remote_deploy/extra_args_scp", PROPERTY_HINT_MULTILINE_TEXT), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "ssh_remote_deploy/run_script", PROPERTY_HINT_MULTILINE_TEXT), run_script));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "ssh_remote_deploy/cleanup_script", PROPERTY_HINT_MULTILINE_TEXT), cleanup_script));
+}
+
+bool EditorExportPlatformLinuxBSD::is_elf(const String &p_path) const {
+ Ref<FileAccess> fb = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(fb.is_null(), false, vformat("Can't open file: \"%s\".", p_path));
+ uint32_t magic = fb->get_32();
+ return (magic == 0x464c457f);
+}
+
+bool EditorExportPlatformLinuxBSD::is_shebang(const String &p_path) const {
+ Ref<FileAccess> fb = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(fb.is_null(), false, vformat("Can't open file: \"%s\".", p_path));
+ uint16_t magic = fb->get_16();
+ return (magic == 0x2123);
+}
+
+bool EditorExportPlatformLinuxBSD::is_executable(const String &p_path) const {
+ return is_elf(p_path) || is_shebang(p_path);
}
Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
@@ -200,3 +290,235 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
}
return OK;
}
+
+Ref<Texture2D> EditorExportPlatformLinuxBSD::get_run_icon() const {
+ return run_icon;
+}
+
+bool EditorExportPlatformLinuxBSD::poll_export() {
+ Ref<EditorExportPreset> preset;
+
+ for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) {
+ Ref<EditorExportPreset> ep = EditorExport::get_singleton()->get_export_preset(i);
+ if (ep->is_runnable() && ep->get_platform() == this) {
+ preset = ep;
+ break;
+ }
+ }
+
+ int prev = menu_options;
+ menu_options = (preset.is_valid() && preset->get("ssh_remote_deploy/enabled").operator bool());
+ if (ssh_pid != 0 || !cleanup_commands.is_empty()) {
+ if (menu_options == 0) {
+ cleanup();
+ } else {
+ menu_options += 1;
+ }
+ }
+ return menu_options != prev;
+}
+
+Ref<ImageTexture> EditorExportPlatformLinuxBSD::get_option_icon(int p_index) const {
+ return p_index == 1 ? stop_icon : EditorExportPlatform::get_option_icon(p_index);
+}
+
+int EditorExportPlatformLinuxBSD::get_options_count() const {
+ return menu_options;
+}
+
+String EditorExportPlatformLinuxBSD::get_option_label(int p_index) const {
+ return (p_index) ? TTR("Stop and uninstall") : TTR("Run on remote Linux/BSD system");
+}
+
+String EditorExportPlatformLinuxBSD::get_option_tooltip(int p_index) const {
+ return (p_index) ? TTR("Stop and uninstall running project from the remote system") : TTR("Run exported project on remote Linux/BSD system");
+}
+
+void EditorExportPlatformLinuxBSD::cleanup() {
+ if (ssh_pid != 0 && OS::get_singleton()->is_process_running(ssh_pid)) {
+ print_line("Terminating connection...");
+ OS::get_singleton()->kill(ssh_pid);
+ OS::get_singleton()->delay_usec(1000);
+ }
+
+ if (!cleanup_commands.is_empty()) {
+ print_line("Stopping and deleting previous version...");
+ for (const SSHCleanupCommand &cmd : cleanup_commands) {
+ if (cmd.wait) {
+ ssh_run_on_remote(cmd.host, cmd.port, cmd.ssh_args, cmd.cmd_args);
+ } else {
+ ssh_run_on_remote_no_wait(cmd.host, cmd.port, cmd.ssh_args, cmd.cmd_args);
+ }
+ }
+ }
+ ssh_pid = 0;
+ cleanup_commands.clear();
+}
+
+Error EditorExportPlatformLinuxBSD::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
+ cleanup();
+ if (p_device) { // Stop command, cleanup only.
+ return OK;
+ }
+
+ EditorProgress ep("run", TTR("Running..."), 5);
+
+ const String dest = EditorPaths::get_singleton()->get_cache_dir().path_join("linuxbsd");
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (!da->dir_exists(dest)) {
+ Error err = da->make_dir_recursive(dest);
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(TTR("Could not create temp directory:") + "\n" + dest);
+ return err;
+ }
+ }
+
+ String host = p_preset->get("ssh_remote_deploy/host").operator String();
+ String port = p_preset->get("ssh_remote_deploy/port").operator String();
+ if (port.is_empty()) {
+ port = "22";
+ }
+ Vector<String> extra_args_ssh = p_preset->get("ssh_remote_deploy/extra_args_ssh").operator String().split(" ");
+ Vector<String> extra_args_scp = p_preset->get("ssh_remote_deploy/extra_args_scp").operator String().split(" ");
+
+ const String basepath = dest.path_join("tmp_linuxbsd_export");
+
+#define CLEANUP_AND_RETURN(m_err) \
+ { \
+ if (da->file_exists(basepath + ".zip")) { \
+ da->remove(basepath + ".zip"); \
+ } \
+ if (da->file_exists(basepath + "_start.sh")) { \
+ da->remove(basepath + "_start.sh"); \
+ } \
+ if (da->file_exists(basepath + "_clean.sh")) { \
+ da->remove(basepath + "_clean.sh"); \
+ } \
+ return m_err; \
+ } \
+ ((void)0)
+
+ if (ep.step(TTR("Exporting project..."), 1)) {
+ return ERR_SKIP;
+ }
+ Error err = export_project(p_preset, true, basepath + ".zip", p_debug_flags);
+ if (err != OK) {
+ DirAccess::remove_file_or_error(basepath + ".zip");
+ return err;
+ }
+
+ String cmd_args;
+ {
+ Vector<String> cmd_args_list;
+ gen_debug_flags(cmd_args_list, p_debug_flags);
+ for (int i = 0; i < cmd_args_list.size(); i++) {
+ if (i != 0) {
+ cmd_args += " ";
+ }
+ cmd_args += cmd_args_list[i];
+ }
+ }
+
+ const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT);
+ int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port");
+
+ print_line("Creating temporary directory...");
+ ep.step(TTR("Creating temporary directory..."), 2);
+ String temp_dir;
+ err = ssh_run_on_remote(host, port, extra_args_ssh, "mktemp -d", &temp_dir);
+ if (err != OK || temp_dir.is_empty()) {
+ CLEANUP_AND_RETURN(err);
+ }
+
+ print_line("Uploading archive...");
+ ep.step(TTR("Uploading archive..."), 3);
+ err = ssh_push_to_remote(host, port, extra_args_scp, basepath + ".zip", temp_dir);
+ if (err != OK) {
+ CLEANUP_AND_RETURN(err);
+ }
+
+ {
+ String run_script = p_preset->get("ssh_remote_deploy/run_script");
+ run_script = run_script.replace("{temp_dir}", temp_dir);
+ run_script = run_script.replace("{archive_name}", basepath.get_file() + ".zip");
+ run_script = run_script.replace("{exe_name}", basepath.get_file());
+ run_script = run_script.replace("{cmd_args}", cmd_args);
+
+ Ref<FileAccess> f = FileAccess::open(basepath + "_start.sh", FileAccess::WRITE);
+ if (f.is_null()) {
+ CLEANUP_AND_RETURN(err);
+ }
+
+ f->store_string(run_script);
+ }
+
+ {
+ String clean_script = p_preset->get("ssh_remote_deploy/cleanup_script");
+ clean_script = clean_script.replace("{temp_dir}", temp_dir);
+ clean_script = clean_script.replace("{archive_name}", basepath.get_file() + ".zip");
+ clean_script = clean_script.replace("{exe_name}", basepath.get_file());
+ clean_script = clean_script.replace("{cmd_args}", cmd_args);
+
+ Ref<FileAccess> f = FileAccess::open(basepath + "_clean.sh", FileAccess::WRITE);
+ if (f.is_null()) {
+ CLEANUP_AND_RETURN(err);
+ }
+
+ f->store_string(clean_script);
+ }
+
+ print_line("Uploading scripts...");
+ ep.step(TTR("Uploading scripts..."), 4);
+ err = ssh_push_to_remote(host, port, extra_args_scp, basepath + "_start.sh", temp_dir);
+ if (err != OK) {
+ CLEANUP_AND_RETURN(err);
+ }
+ err = ssh_run_on_remote(host, port, extra_args_ssh, vformat("chmod +x \"%s/%s\"", temp_dir, basepath.get_file() + "_start.sh"));
+ if (err != OK || temp_dir.is_empty()) {
+ CLEANUP_AND_RETURN(err);
+ }
+ err = ssh_push_to_remote(host, port, extra_args_scp, basepath + "_clean.sh", temp_dir);
+ if (err != OK) {
+ CLEANUP_AND_RETURN(err);
+ }
+ err = ssh_run_on_remote(host, port, extra_args_ssh, vformat("chmod +x \"%s/%s\"", temp_dir, basepath.get_file() + "_clean.sh"));
+ if (err != OK || temp_dir.is_empty()) {
+ CLEANUP_AND_RETURN(err);
+ }
+
+ print_line("Starting project...");
+ ep.step(TTR("Starting project..."), 5);
+ err = ssh_run_on_remote_no_wait(host, port, extra_args_ssh, vformat("\"%s/%s\"", temp_dir, basepath.get_file() + "_start.sh"), &ssh_pid, (use_remote) ? dbg_port : -1);
+ if (err != OK) {
+ CLEANUP_AND_RETURN(err);
+ }
+
+ cleanup_commands.clear();
+ cleanup_commands.push_back(SSHCleanupCommand(host, port, extra_args_ssh, vformat("\"%s/%s\"", temp_dir, basepath.get_file() + "_clean.sh")));
+
+ print_line("Project started.");
+
+ CLEANUP_AND_RETURN(OK);
+#undef CLEANUP_AND_RETURN
+}
+
+EditorExportPlatformLinuxBSD::EditorExportPlatformLinuxBSD() {
+#ifdef MODULE_SVG_ENABLED
+ Ref<Image> img = memnew(Image);
+ const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
+
+ ImageLoaderSVG img_loader;
+ img_loader.create_image_from_string(img, _linuxbsd_logo_svg, EDSCALE, upsample, false);
+ set_logo(ImageTexture::create_from_image(img));
+
+ img_loader.create_image_from_string(img, _linuxbsd_run_icon_svg, EDSCALE, upsample, false);
+ run_icon = ImageTexture::create_from_image(img);
+#endif
+
+ Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
+ if (theme.is_valid()) {
+ stop_icon = theme->get_icon(SNAME("Stop"), SNAME("EditorIcons"));
+ } else {
+ stop_icon.instantiate();
+ }
+}
diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h
index 71cf18ff3e..4f860c3fd0 100644
--- a/platform/linuxbsd/export/export_plugin.h
+++ b/platform/linuxbsd/export/export_plugin.h
@@ -34,19 +34,58 @@
#include "core/io/file_access.h"
#include "editor/editor_settings.h"
#include "editor/export/editor_export_platform_pc.h"
-#include "platform/linuxbsd/logo.gen.h"
#include "scene/resources/texture.h"
class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC {
+ HashMap<String, String> extensions;
+
+ struct SSHCleanupCommand {
+ String host;
+ String port;
+ Vector<String> ssh_args;
+ String cmd_args;
+ bool wait = false;
+
+ SSHCleanupCommand(){};
+ SSHCleanupCommand(const String &p_host, const String &p_port, const Vector<String> &p_ssh_arg, const String &p_cmd_args, bool p_wait = false) {
+ host = p_host;
+ port = p_port;
+ ssh_args = p_ssh_arg;
+ cmd_args = p_cmd_args;
+ wait = p_wait;
+ };
+ };
+
+ Ref<ImageTexture> run_icon;
+ Ref<ImageTexture> stop_icon;
+
+ Vector<SSHCleanupCommand> cleanup_commands;
+ OS::ProcessID ssh_pid = 0;
+ int menu_options = 0;
+
+ bool is_elf(const String &p_path) const;
+ bool is_shebang(const String &p_path) const;
+
Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path);
public:
- void set_extension(const String &p_extension, const String &p_feature_key = "default");
- virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
virtual void get_export_options(List<ExportOption> *r_options) override;
+ virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
virtual String get_template_file_name(const String &p_target, const String &p_arch) const override;
virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override;
+ virtual bool is_executable(const String &p_path) const override;
+
+ virtual Ref<Texture2D> get_run_icon() const override;
+ virtual bool poll_export() override;
+ virtual Ref<ImageTexture> get_option_icon(int p_index) const override;
+ virtual int get_options_count() const override;
+ virtual String get_option_label(int p_index) const override;
+ virtual String get_option_tooltip(int p_index) const override;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
+ virtual void cleanup() override;
+
+ EditorExportPlatformLinuxBSD();
};
#endif // LINUXBSD_EXPORT_PLUGIN_H
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index 672c48addc..b77f989677 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -59,7 +59,7 @@ JoypadLinux::Joypad::~Joypad() {
}
void JoypadLinux::Joypad::reset() {
- dpad = HatMask::CENTER;
+ dpad = 0;
fd = -1;
for (int i = 0; i < MAX_ABS; i++) {
abs_map[i] = -1;
@@ -485,27 +485,33 @@ void JoypadLinux::process_joypads() {
case ABS_HAT0X:
if (joypad_event.value != 0) {
if (joypad_event.value < 0) {
- joypad.dpad = (HatMask)((joypad.dpad | HatMask::LEFT) & ~HatMask::RIGHT);
+ joypad.dpad.set_flag(HatMask::LEFT);
+ joypad.dpad.clear_flag(HatMask::RIGHT);
} else {
- joypad.dpad = (HatMask)((joypad.dpad | HatMask::RIGHT) & ~HatMask::LEFT);
+ joypad.dpad.set_flag(HatMask::RIGHT);
+ joypad.dpad.clear_flag(HatMask::LEFT);
}
} else {
- joypad.dpad &= ~(HatMask::LEFT | HatMask::RIGHT);
+ joypad.dpad.clear_flag(HatMask::LEFT);
+ joypad.dpad.clear_flag(HatMask::RIGHT);
}
- input->joy_hat(i, (HatMask)joypad.dpad);
+ input->joy_hat(i, joypad.dpad);
break;
case ABS_HAT0Y:
if (joypad_event.value != 0) {
if (joypad_event.value < 0) {
- joypad.dpad = (HatMask)((joypad.dpad | HatMask::UP) & ~HatMask::DOWN);
+ joypad.dpad.set_flag(HatMask::UP);
+ joypad.dpad.clear_flag(HatMask::DOWN);
} else {
- joypad.dpad = (HatMask)((joypad.dpad | HatMask::DOWN) & ~HatMask::UP);
+ joypad.dpad.set_flag(HatMask::DOWN);
+ joypad.dpad.clear_flag(HatMask::UP);
}
} else {
- joypad.dpad &= ~(HatMask::UP | HatMask::DOWN);
+ joypad.dpad.clear_flag(HatMask::UP);
+ joypad.dpad.clear_flag(HatMask::DOWN);
}
- input->joy_hat(i, (HatMask)joypad.dpad);
+ input->joy_hat(i, joypad.dpad);
break;
default:
diff --git a/platform/linuxbsd/joypad_linux.h b/platform/linuxbsd/joypad_linux.h
index 7926756cbe..6661abdb37 100644
--- a/platform/linuxbsd/joypad_linux.h
+++ b/platform/linuxbsd/joypad_linux.h
@@ -62,7 +62,7 @@ private:
float curr_axis[MAX_ABS];
int key_map[MAX_KEY];
int abs_map[MAX_ABS];
- HatMask dpad = HatMask::CENTER;
+ BitField<HatMask> dpad;
int fd = -1;
String devpath;
diff --git a/platform/linuxbsd/logo.png b/platform/linuxbsd/logo.png
deleted file mode 100644
index 078654b757..0000000000
--- a/platform/linuxbsd/logo.png
+++ /dev/null
Binary files differ
diff --git a/platform/linuxbsd/logo.svg b/platform/linuxbsd/logo.svg
new file mode 100644
index 0000000000..e5f9f03e0c
--- /dev/null
+++ b/platform/linuxbsd/logo.svg
@@ -0,0 +1 @@
+<svg height="32" width="32"><path d="M13 31h6s3 0 6-6c2.864-5.727-6-17-6-17h-6S3.775 18.55 7 25c3 6 6 6 6 6z" fill="#fff"/><path d="M15.876 28.636c-.05.322-.116.637-.204.941-.142.496-.35.993-.659 1.416.32.02.649.023.985.007a9.1 9.1 0 0 0 .985-.007c-.309-.423-.516-.92-.659-1.416a7.666 7.666 0 0 1-.203-.94l-.123.003c-.04 0-.081-.003-.122-.004z" fill="#333"/><path d="M21.693 21.916c-.629.01-.934.633-1.497.7-.694.08-1.128-.722-2.11-.123-.98.6-1.826 7.473.45 8.409 2.274.935 6.506-4.545 6.23-5.662-.275-1.116-1.146-.853-1.582-1.399-.436-.545.003-1.41-.995-1.82a1.246 1.246 0 0 0-.496-.105zm-11.461 0a1.315 1.315 0 0 0-.421.105c-.998.41-.56 1.275-.995 1.82-.436.546-1.31.283-1.586 1.4-.275 1.116 3.956 6.596 6.232 5.66 2.275-.935 1.429-7.808.448-8.408-.981-.6-1.415.204-2.11.122-.584-.068-.888-.739-1.568-.7z" fill="#f4bb37"/><path d="M15.998.99c-2.934 0-4.657 1.79-4.982 4.204-.324 2.414.198 2.856-.614 5.328-.813 2.472-4.456 6.71-4.37 10.62.026 1.217.166 2.27.41 3.192.3-.496.743-.846 1.066-.995.253-.117.375-.173.432-.194.008-.062.04-.205.098-.485.08-.386.387-.99.91-1.386-.005-.12-.01-.239-.013-.363-.06-3.033 3.073-6.318 3.65-8.236.577-1.917.326-2.114.421-2.59.096-.477.463-1.032.992-1.475a.23.23 0 0 1 .15-.06c.482-.005.965 1.75 1.898 1.752.933 0 1.419-2.141 1.956-1.692.529.443.896.998.992 1.474.095.477-.156.674.42 2.591.578 1.918 3.708 5.203 3.648 8.236-.003.123-.008.24-.014.36.526.396.834 1.002.914 1.389.058.28.09.423.098.485.057.021.18.08.432.197.323.15.764.499 1.063.995.244-.922.387-1.976.414-3.195.085-3.91-3.562-8.148-4.374-10.62-.813-2.472-.287-2.914-.611-5.328C20.659 2.78 18.933.99 15.998.99z" fill="#333"/></svg>
diff --git a/platform/linuxbsd/run_icon.svg b/platform/linuxbsd/run_icon.svg
new file mode 100644
index 0000000000..56465a0df3
--- /dev/null
+++ b/platform/linuxbsd/run_icon.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M7.941 13.966a3.62 3.62 0 0 1-.096.444 2.129 2.129 0 0 1-.31.668c.15.01.305.01.464.003.16.008.314.007.465-.003a2.129 2.129 0 0 1-.31-.668 3.62 3.62 0 0 1-.097-.444l-.058.001-.058-.001z" fill="#333" style="stroke-width:.472092;fill:#e0e0e0;fill-opacity:1"/><path d="M10.688 10.793c-.297.005-.441.299-.707.33-.328.038-.533-.34-.996-.058-.463.283-.862 3.528.212 3.97 1.074.442 3.072-2.146 2.942-2.673-.13-.527-.542-.403-.747-.66-.206-.258 0-.666-.47-.86a.588.588 0 0 0-.234-.05zm-5.411 0a.62.62 0 0 0-.199.05c-.47.193-.264.601-.47.859-.205.257-.618.133-.748.66s1.867 3.115 2.942 2.673c1.074-.442.674-3.687.211-3.97-.463-.283-.668.096-.995.058-.277-.032-.42-.349-.741-.33z" fill="#f4bb37" style="stroke-width:.472092;fill:#e0e0e0;fill-opacity:1"/><path d="M8 .914c-1.386 0-2.2.845-2.353 1.985-.153 1.14.094 1.348-.29 2.515s-2.103 3.168-2.063 5.013c.012.575.078 1.072.194 1.507a1.25 1.25 0 0 1 .503-.47 4.37 4.37 0 0 1 .204-.09c.004-.03.019-.098.046-.23.038-.182.183-.467.43-.654a4.773 4.773 0 0 1-.006-.172c-.029-1.431 1.45-2.982 1.723-3.888.272-.905.154-.998.199-1.223.045-.225.218-.487.468-.696a.11.11 0 0 1 .07-.028c.228-.003.456.826.897.827.44 0 .67-1.01.923-.799.25.21.423.471.468.696.045.225-.073.318.199 1.223.272.906 1.75 2.457 1.722 3.888-.001.058-.004.114-.007.17a1.2 1.2 0 0 1 .432.656c.027.132.042.2.046.23.027.01.085.037.204.092.153.07.36.236.502.47.115-.435.183-.933.195-1.509.04-1.845-1.681-3.846-2.065-5.013-.383-1.167-.135-1.376-.288-2.515C10.2 1.759 9.385.914 7.999.914Z" fill="#333" style="stroke-width:.472092;fill:#e0e0e0;fill-opacity:1"/></svg>
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index a9561ababb..d4f82cc81e 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -458,7 +458,7 @@ Point2i DisplayServerX11::mouse_get_position() const {
return Vector2i();
}
-MouseButton DisplayServerX11::mouse_get_button_state() const {
+BitField<MouseButtonMask> DisplayServerX11::mouse_get_button_state() const {
return last_button_state;
}
@@ -751,11 +751,22 @@ int DisplayServerX11::get_screen_count() const {
return count;
}
+int DisplayServerX11::get_primary_screen() const {
+ return XDefaultScreen(x11_display);
+}
+
Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const {
Rect2i rect(0, 0, 0, 0);
- if (p_screen == SCREEN_OF_MAIN_WINDOW) {
- p_screen = window_get_current_screen();
+ switch (p_screen) {
+ case SCREEN_PRIMARY: {
+ p_screen = get_primary_screen();
+ } break;
+ case SCREEN_OF_MAIN_WINDOW: {
+ p_screen = window_get_current_screen(MAIN_WINDOW_ID);
+ } break;
+ default:
+ break;
}
ERR_FAIL_COND_V(p_screen < 0, rect);
@@ -822,8 +833,15 @@ int bad_window_error_handler(Display *display, XErrorEvent *error) {
Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_
- if (p_screen == SCREEN_OF_MAIN_WINDOW) {
- p_screen = window_get_current_screen();
+ switch (p_screen) {
+ case SCREEN_PRIMARY: {
+ p_screen = get_primary_screen();
+ } break;
+ case SCREEN_OF_MAIN_WINDOW: {
+ p_screen = window_get_current_screen(MAIN_WINDOW_ID);
+ } break;
+ default:
+ break;
}
int screen_count = get_screen_count();
@@ -1102,8 +1120,15 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
int DisplayServerX11::screen_get_dpi(int p_screen) const {
_THREAD_SAFE_METHOD_
- if (p_screen == SCREEN_OF_MAIN_WINDOW) {
- p_screen = window_get_current_screen();
+ switch (p_screen) {
+ case SCREEN_PRIMARY: {
+ p_screen = get_primary_screen();
+ } break;
+ case SCREEN_OF_MAIN_WINDOW: {
+ p_screen = window_get_current_screen(MAIN_WINDOW_ID);
+ } break;
+ default:
+ break;
}
//invalid screen?
@@ -1147,8 +1172,15 @@ int DisplayServerX11::screen_get_dpi(int p_screen) const {
float DisplayServerX11::screen_get_refresh_rate(int p_screen) const {
_THREAD_SAFE_METHOD_
- if (p_screen == SCREEN_OF_MAIN_WINDOW) {
- p_screen = window_get_current_screen();
+ switch (p_screen) {
+ case SCREEN_PRIMARY: {
+ p_screen = get_primary_screen();
+ } break;
+ case SCREEN_OF_MAIN_WINDOW: {
+ p_screen = window_get_current_screen(MAIN_WINDOW_ID);
+ } break;
+ default:
+ break;
}
//invalid screen?
@@ -1235,10 +1267,10 @@ Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
return ret;
}
-DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
+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_vsync_mode, p_flags, p_rect, p_screen);
+ 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);
@@ -1388,31 +1420,35 @@ void DisplayServerX11::window_set_mouse_passthrough(const Vector<Vector2> &p_reg
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
- const WindowData &wd = windows[p_window];
+ windows[p_window].mpath = p_region;
+ _update_window_mouse_passthrough(p_window);
+}
+
+void DisplayServerX11::_update_window_mouse_passthrough(WindowID p_window) {
+ ERR_FAIL_COND(!windows.has(p_window));
+
+ const Vector<Vector2> region_path = windows[p_window].mpath;
int event_base, error_base;
const Bool ext_okay = XShapeQueryExtension(x11_display, &event_base, &error_base);
if (ext_okay) {
- Region region;
- if (p_region.size() == 0) {
- region = XCreateRegion();
- XRectangle rect;
- rect.x = 0;
- rect.y = 0;
- rect.width = window_get_size_with_decorations(p_window).x;
- rect.height = window_get_size_with_decorations(p_window).y;
- XUnionRectWithRegion(&rect, region, region);
+ if (windows[p_window].mpass) {
+ Region region = XCreateRegion();
+ XShapeCombineRegion(x11_display, windows[p_window].x11_window, ShapeInput, 0, 0, region, ShapeSet);
+ XDestroyRegion(region);
+ } else if (region_path.size() == 0) {
+ XShapeCombineMask(x11_display, windows[p_window].x11_window, ShapeInput, 0, 0, None, ShapeSet);
} else {
- XPoint *points = (XPoint *)memalloc(sizeof(XPoint) * p_region.size());
- for (int i = 0; i < p_region.size(); i++) {
- points[i].x = p_region[i].x;
- points[i].y = p_region[i].y;
+ XPoint *points = (XPoint *)memalloc(sizeof(XPoint) * region_path.size());
+ for (int i = 0; i < region_path.size(); i++) {
+ points[i].x = region_path[i].x;
+ points[i].y = region_path[i].y;
}
- region = XPolygonRegion(points, p_region.size(), EvenOddRule);
+ Region region = XPolygonRegion(points, region_path.size(), EvenOddRule);
memfree(points);
+ XShapeCombineRegion(x11_display, windows[p_window].x11_window, ShapeInput, 0, 0, region, ShapeSet);
+ XDestroyRegion(region);
}
- XShapeCombineRegion(x11_display, wd.x11_window, ShapeInput, 0, 0, region, ShapeSet);
- XDestroyRegion(region);
}
}
@@ -1500,8 +1536,15 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if (p_screen == SCREEN_OF_MAIN_WINDOW) {
- p_screen = window_get_current_screen();
+ switch (p_screen) {
+ case SCREEN_PRIMARY: {
+ p_screen = get_primary_screen();
+ } break;
+ case SCREEN_OF_MAIN_WINDOW: {
+ p_screen = window_get_current_screen(MAIN_WINDOW_ID);
+ } break;
+ default:
+ break;
}
// Check if screen is valid
@@ -1521,9 +1564,10 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window));
Size2i wsize = window_get_size(p_window);
wpos += srect.position;
-
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - wsize.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
+ if (srect != Rect2i()) {
+ wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - wsize.width / 3);
+ wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
+ }
window_set_position(wpos, p_window);
}
}
@@ -2272,6 +2316,7 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
window_set_size(window_get_size(p_window), p_window);
wd.borderless = p_enabled;
+ _update_window_mouse_passthrough(p_window);
} break;
case WINDOW_FLAG_ALWAYS_ON_TOP: {
ERR_FAIL_COND_MSG(wd.transient_parent != INVALID_WINDOW_ID, "Can't make a window transient if the 'on top' flag is active.");
@@ -2305,6 +2350,10 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
case WINDOW_FLAG_NO_FOCUS: {
wd.no_focus = p_enabled;
} break;
+ case WINDOW_FLAG_MOUSE_PASSTHROUGH: {
+ wd.mpass = p_enabled;
+ _update_window_mouse_passthrough(p_window);
+ } break;
case WINDOW_FLAG_POPUP: {
XWindowAttributes xwa;
XSync(x11_display, False);
@@ -2358,6 +2407,9 @@ bool DisplayServerX11::window_get_flag(WindowFlags p_flag, WindowID p_window) co
case WINDOW_FLAG_NO_FOCUS: {
return wd.no_focus;
} break;
+ case WINDOW_FLAG_MOUSE_PASSTHROUGH: {
+ return wd.mpass;
+ } break;
case WINDOW_FLAG_POPUP: {
return wd.is_popup;
} break;
@@ -2803,13 +2855,13 @@ void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<Inp
state->set_meta_pressed((p_x11_state & Mod4Mask));
}
-MouseButton DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) {
- MouseButton mask = mouse_button_to_mask(p_x11_button);
+BitField<MouseButtonMask> DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) {
+ MouseButtonMask mask = mouse_button_to_mask(p_x11_button);
if (p_x11_type == ButtonPress) {
- last_button_state |= mask;
+ last_button_state.set_flag(mask);
} else {
- last_button_state &= ~mask;
+ last_button_state.clear_flag(mask);
}
return last_button_state;
@@ -4131,13 +4183,13 @@ void DisplayServerX11::process_events() {
if (xi.pressure_supported) {
mm->set_pressure(xi.pressure);
} else {
- mm->set_pressure(bool(mouse_get_button_state() & MouseButton::MASK_LEFT) ? 1.0f : 0.0f);
+ mm->set_pressure(bool(mouse_get_button_state().has_flag(MouseButtonMask::LEFT)) ? 1.0f : 0.0f);
}
mm->set_tilt(xi.tilt);
mm->set_pen_inverted(xi.pen_inverted);
_get_key_modifier_state(event.xmotion.state, mm);
- mm->set_button_mask((MouseButton)mouse_get_button_state());
+ mm->set_button_mask(mouse_get_button_state());
mm->set_position(pos);
mm->set_global_position(pos);
mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());
@@ -4519,29 +4571,31 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
return drivers;
}
-DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
- DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
+DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
+ DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error));
if (r_error != OK) {
if (p_rendering_driver == "vulkan") {
String executable_name = OS::get_singleton()->get_executable_path().get_file();
- OS::get_singleton()->alert("Your video card driver does not support the selected Vulkan version.\n"
- "Please try updating your GPU driver or try using the OpenGL 3 driver.\n"
- "You can enable the OpenGL 3 driver by starting the engine from the\n"
- "command line with the command:\n'./" +
- executable_name + " --rendering-driver opengl3'.\n "
- "If you have updated your graphics drivers recently, try rebooting.",
- "Unable to initialize Video driver");
+ OS::get_singleton()->alert(
+ vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
+ "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
+ "You can enable the OpenGL 3 driver by starting the engine from the\n"
+ "command line with the command:\n'%s --rendering-driver opengl3'\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ executable_name),
+ "Unable to initialize Vulkan video driver");
} else {
- OS::get_singleton()->alert("Your video card driver does not support the selected OpenGL version.\n"
- "Please try updating your GPU driver.\n"
- "If you have updated your graphics drivers recently, try rebooting.",
- "Unable to initialize Video driver");
+ OS::get_singleton()->alert(
+ "Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
+ "If possible, consider updating your video card drivers.\n\n"
+ "If you recently updated your video card drivers, try rebooting.",
+ "Unable to initialize OpenGL video driver");
}
}
return ds;
}
-DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
+DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
//Create window
XVisualInfo visualInfo;
@@ -4617,30 +4671,19 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
valuemask |= CWOverrideRedirect | CWSaveUnder;
}
+ int rq_screen = get_screen_from_rect(p_rect);
+ if (rq_screen < 0) {
+ rq_screen = get_primary_screen(); // Requested window rect is outside any screen bounds.
+ }
+
Rect2i win_rect = p_rect;
if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
- Rect2i screen_rect = Rect2i(screen_get_position(p_screen), screen_get_size(p_screen));
+ Rect2i screen_rect = Rect2i(screen_get_position(rq_screen), screen_get_size(rq_screen));
win_rect = screen_rect;
} else {
- int nearest_area = 0;
- int pos_screen = -1;
- for (int i = 0; i < get_screen_count(); i++) {
- Rect2i r;
- r.position = screen_get_position(i);
- r.size = screen_get_size(i);
- Rect2 inters = r.intersection(p_rect);
-
- int area = inters.size.width * inters.size.height;
- if (area > nearest_area) {
- pos_screen = i;
- nearest_area = area;
- }
- }
-
- Rect2i srect = screen_get_usable_rect(p_screen);
- Point2i wpos = p_rect.position - ((pos_screen >= 0) ? screen_get_position(pos_screen) : Vector2i());
- wpos += srect.position;
+ Rect2i srect = screen_get_usable_rect(rq_screen);
+ Point2i wpos = p_rect.position;
wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
@@ -4811,7 +4854,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
return id;
}
-DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
+DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
@@ -5075,16 +5118,17 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
ERR_FAIL_MSG("Video driver not found");
}
- Point2i window_position(
- (screen_get_size(0).width - p_resolution.width) / 2,
- (screen_get_size(0).height - p_resolution.height) / 2);
- window_position += screen_get_position(0);
-
+ Point2i window_position;
if (p_position != nullptr) {
window_position = *p_position;
+ } else {
+ if (p_screen == SCREEN_OF_MAIN_WINDOW) {
+ p_screen = SCREEN_PRIMARY;
+ }
+ window_position = screen_get_position(p_screen) + (screen_get_size(p_screen) - p_resolution) / 2;
}
- WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution), 0);
+ 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;
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index b8820c843b..437766d953 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -149,6 +149,8 @@ class DisplayServerX11 : public DisplayServer {
Callable input_text_callback;
Callable drop_files_callback;
+ Vector<Vector2> mpath;
+
WindowID transient_parent = INVALID_WINDOW_ID;
HashSet<WindowID> transient_children;
@@ -169,6 +171,7 @@ class DisplayServerX11 : public DisplayServer {
bool maximized = false;
bool is_popup = false;
bool layered_window = false;
+ bool mpass = false;
Rect2i parent_safe_rect;
@@ -185,7 +188,7 @@ class DisplayServerX11 : public DisplayServer {
WindowID last_focused_window = INVALID_WINDOW_ID;
WindowID window_id_counter = MAIN_WINDOW_ID;
- WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen);
+ WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
String internal_clipboard;
String internal_clipboard_primary;
@@ -205,7 +208,7 @@ class DisplayServerX11 : public DisplayServer {
Point2i last_click_pos = Point2i(-100, -100);
uint64_t last_click_ms = 0;
MouseButton last_click_button_index = MouseButton::NONE;
- MouseButton last_button_state = MouseButton::NONE;
+ BitField<MouseButtonMask> last_button_state;
bool app_focused = false;
uint64_t time_since_no_focus = 0;
@@ -234,7 +237,7 @@ class DisplayServerX11 : public DisplayServer {
Rect2i _screen_get_rect(int p_screen) const;
- MouseButton _get_mouse_button_state(MouseButton p_x11_button, int p_x11_type);
+ BitField<MouseButtonMask> _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();
@@ -245,6 +248,7 @@ class DisplayServerX11 : public DisplayServer {
Atom _process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property, Atom p_selection) const;
void _handle_selection_request_event(XSelectionRequestEvent *p_event) const;
+ void _update_window_mouse_passthrough(WindowID p_window);
String _clipboard_get_impl(Atom p_source, Window x11_window, Atom target) const;
String _clipboard_get(Atom p_source, Window x11_window) const;
@@ -344,7 +348,7 @@ public:
virtual void warp_mouse(const Point2i &p_position) override;
virtual Point2i mouse_get_position() const override;
- virtual MouseButton mouse_get_button_state() const override;
+ virtual BitField<MouseButtonMask> mouse_get_button_state() const override;
virtual void clipboard_set(const String &p_text) override;
virtual String clipboard_get() const override;
@@ -352,6 +356,7 @@ public:
virtual String clipboard_get_primary() const override;
virtual int get_screen_count() const override;
+ virtual int get_primary_screen() 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;
@@ -365,7 +370,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
- virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), int p_screen = 0) override;
+ 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;
@@ -453,12 +458,12 @@ public:
virtual void set_native_icon(const String &p_filename) override;
virtual void set_icon(const Ref<Image> &p_icon) override;
- static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_x11_driver();
- DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
+ DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
~DisplayServerX11();
};