diff options
Diffstat (limited to 'platform')
64 files changed, 2653 insertions, 709 deletions
diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp index ee28959adc..3a2ccac481 100644 --- a/platform/android/audio_driver_jandroid.cpp +++ b/platform/android/audio_driver_jandroid.cpp @@ -73,9 +73,9 @@ Error AudioDriverAndroid::init() { // __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); JNIEnv *env = get_jni_env(); - int mix_rate = GLOBAL_GET("audio/mix_rate"); + int mix_rate = GLOBAL_GET("audio/driver/mix_rate"); - int latency = GLOBAL_GET("audio/output_latency"); + int latency = GLOBAL_GET("audio/driver/output_latency"); unsigned int buffer_size = next_power_of_2(latency * mix_rate / 1000); print_verbose("Audio buffer size: " + itos(buffer_size)); diff --git a/platform/android/detect.py b/platform/android/detect.py index 650606ff8b..5f0fcc9b77 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -13,7 +13,7 @@ def get_name(): def can_build(): - return "ANDROID_NDK_ROOT" in os.environ + return ("ANDROID_SDK_ROOT" in os.environ) or ("ANDROID_HOME" in os.environ) def get_platform(platform): @@ -24,13 +24,33 @@ def get_opts(): from SCons.Variables import BoolVariable, EnumVariable return [ - ("ANDROID_NDK_ROOT", "Path to the Android NDK", os.environ.get("ANDROID_NDK_ROOT", 0)), + ("ANDROID_NDK_ROOT", "Path to the Android NDK", get_android_ndk_root()), + ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_android_sdk_root()), ("ndk_platform", 'Target platform (android-<api>, e.g. "android-24")', "android-24"), EnumVariable("android_arch", "Target architecture", "armv7", ("armv7", "arm64v8", "x86", "x86_64")), BoolVariable("android_neon", "Enable NEON support (armv7 only)", True), ] +# Return the ANDROID_SDK_ROOT environment variable. +# While ANDROID_HOME has been deprecated, it's used as a fallback for backward +# compatibility purposes. +def get_android_sdk_root(): + if "ANDROID_SDK_ROOT" in os.environ: + return os.environ.get("ANDROID_SDK_ROOT", 0) + else: + return os.environ.get("ANDROID_HOME", 0) + + +# Return the ANDROID_NDK_ROOT environment variable. +# We generate one for this build using the ANDROID_SDK_ROOT env +# variable and the project ndk version. +# If the env variable is already defined, we override it with +# our own to match what the project expects. +def get_android_ndk_root(): + return get_android_sdk_root() + "/ndk/" + get_project_ndk_version() + + def get_flags(): return [ ("tools", False), @@ -47,7 +67,31 @@ def create(env): return env.Clone(tools=tools) +# Check if ANDROID_NDK_ROOT is valid. +# If not, install the ndk using ANDROID_SDK_ROOT and sdkmanager. +def install_ndk_if_needed(env): + print("Checking for Android NDK...") + env_ndk_version = get_env_ndk_version(env["ANDROID_NDK_ROOT"]) + if env_ndk_version is None: + # Reinstall the ndk and update ANDROID_NDK_ROOT. + print("Installing Android NDK...") + if env["ANDROID_SDK_ROOT"] is None: + raise Exception("Invalid ANDROID_SDK_ROOT environment variable.") + + import subprocess + + extension = ".bat" if os.name == "nt" else "" + sdkmanager_path = env["ANDROID_SDK_ROOT"] + "/cmdline-tools/latest/bin/sdkmanager" + extension + ndk_download_args = "ndk;" + get_project_ndk_version() + subprocess.check_call([sdkmanager_path, ndk_download_args]) + + env["ANDROID_NDK_ROOT"] = env["ANDROID_SDK_ROOT"] + "/ndk/" + get_project_ndk_version() + print("ANDROID_NDK_ROOT: " + env["ANDROID_NDK_ROOT"]) + + def configure(env): + install_ndk_if_needed(env) + # Workaround for MinGW. See: # http://www.scons.org/wiki/LongCmdLinesOnWin32 if os.name == "nt": @@ -270,7 +314,7 @@ def configure(env): # Link flags - ndk_version = get_ndk_version(env["ANDROID_NDK_ROOT"]) + ndk_version = get_env_ndk_version(env["ANDROID_NDK_ROOT"]) if ndk_version != None and LooseVersion(ndk_version) >= LooseVersion("17.1.4828580"): env.Append(LINKFLAGS=["-Wl,--exclude-libs,libgcc.a", "-Wl,--exclude-libs,libatomic.a", "-nostdlib++"]) else: @@ -323,8 +367,14 @@ def configure(env): env.Append(LIBS=["OpenSLES", "EGL", "GLESv2", "vulkan", "android", "log", "z", "dl"]) +# Return the project NDK version. +# This is kept in sync with the value in 'platform/android/java/app/config.gradle'. +def get_project_ndk_version(): + return "21.4.7075529" + + # Return NDK version string in source.properties (adapted from the Chromium project). -def get_ndk_version(path): +def get_env_ndk_version(path): if path is None: return None prop_file_path = os.path.join(path, "source.properties") diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index a963c5a741..888b1546e4 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -37,6 +37,7 @@ #include "core/os/dir_access.h" #include "core/os/file_access.h" #include "core/os/os.h" +#include "core/templates/safe_refcount.h" #include "core/version.h" #include "drivers/png/png_driver_common.h" #include "editor/editor_export.h" @@ -202,6 +203,19 @@ static const char *android_perms[] = { static const char *SPLASH_IMAGE_EXPORT_PATH = "res/drawable/splash.png"; static const char *SPLASH_BG_COLOR_PATH = "res/drawable/splash_bg_color.png"; +static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml"; + +const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/splash_bg_color" /> + <item> + <bitmap + android:gravity="%s" + android:filter="%s" + android:src="@drawable/splash" /> + </item> +</layer-list> +)SPLASH"; struct LauncherIcon { const char *export_path; @@ -264,38 +278,38 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { Vector<PluginConfigAndroid> plugins; String last_plugin_names; uint64_t last_custom_build_time = 0; - volatile bool plugins_changed; + SafeFlag plugins_changed; Mutex plugins_lock; Vector<Device> devices; - volatile bool devices_changed; + SafeFlag devices_changed; Mutex device_lock; Thread check_for_changes_thread; - volatile bool quit_request; + SafeFlag quit_request; static void _check_for_changes_poll_thread(void *ud) { EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud; - while (!ea->quit_request) { + while (!ea->quit_request.is_set()) { // Check for plugins updates { // Nothing to do if we already know the plugins have changed. - if (!ea->plugins_changed) { + if (!ea->plugins_changed.is_set()) { Vector<PluginConfigAndroid> loaded_plugins = get_plugins(); MutexLock lock(ea->plugins_lock); if (ea->plugins.size() != loaded_plugins.size()) { - ea->plugins_changed = true; + ea->plugins_changed.set(); } else { for (int i = 0; i < ea->plugins.size(); i++) { if (ea->plugins[i].name != loaded_plugins[i].name) { - ea->plugins_changed = true; + ea->plugins_changed.set(); break; } } } - if (ea->plugins_changed) { + if (ea->plugins_changed.is_set()) { ea->plugins = loaded_plugins; } } @@ -409,7 +423,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } ea->devices = ndevices; - ea->devices_changed = true; + ea->devices_changed.set(); } } @@ -418,7 +432,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { uint64_t time = OS::get_singleton()->get_ticks_usec(); while (OS::get_singleton()->get_ticks_usec() - time < wait) { OS::get_singleton()->delay_usec(1000 * sleep); - if (ea->quit_request) { + if (ea->quit_request.is_set()) { break; } } @@ -775,6 +789,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } void _write_tmp_manifest(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, bool p_debug) { + print_verbose("Building temporary manifest.."); String manifest_text = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" @@ -795,6 +810,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { manifest_text += _get_application_tag(p_preset, plugins_names); manifest_text += "</manifest>\n"; String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release")); + + print_verbose("Storing manifest into " + manifest_path + ": " + "\n" + manifest_text); store_string_at_path(manifest_path, manifest_text); } @@ -1470,20 +1487,26 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } } - void load_splash_refs(Ref<Image> &splash_image, Ref<Image> &splash_bg_color_image) { - // TODO: Figure out how to handle remaining boot splash parameters (e.g: fullsize, filter) + String load_splash_refs(Ref<Image> &splash_image, Ref<Image> &splash_bg_color_image) { + bool scale_splash = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); + bool apply_filter = ProjectSettings::get_singleton()->get("application/boot_splash/use_filter"); String project_splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); if (!project_splash_path.is_empty()) { splash_image.instance(); + print_verbose("Loading splash image: " + project_splash_path); const Error err = ImageLoader::load_image(project_splash_path, splash_image); if (err) { + if (OS::get_singleton()->is_stdout_verbose()) { + print_error("- unable to load splash image from " + project_splash_path + " (" + itos(err) + ")"); + } splash_image.unref(); } } if (splash_image.is_null()) { // Use the default + print_verbose("Using default splash image."); splash_image = Ref<Image>(memnew(Image(boot_splash_png))); } @@ -1494,9 +1517,14 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { bg_color = boot_splash_bg_color; } + print_verbose("Creating splash background color image."); splash_bg_color_image.instance(); splash_bg_color_image->create(splash_image->get_width(), splash_image->get_height(), false, splash_image->get_format()); splash_bg_color_image->fill(bg_color); + + String gravity = scale_splash ? "fill" : "center"; + String processed_splash_config_xml = vformat(SPLASH_CONFIG_XML_CONTENT, gravity, bool_to_string(apply_filter)); + return processed_splash_config_xml; } void load_icon_refs(const Ref<EditorExportPreset> &p_preset, Ref<Image> &icon, Ref<Image> &foreground, Ref<Image> &background) { @@ -1508,19 +1536,24 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { // Regular icon: user selection -> project icon -> default. String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges(); + print_verbose("Loading regular icon from " + path); if (path.is_empty() || ImageLoader::load_image(path, icon) != OK) { + print_verbose("- falling back to project icon: " + project_icon_path); ImageLoader::load_image(project_icon_path, icon); } // Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default). path = static_cast<String>(p_preset->get(launcher_adaptive_icon_foreground_option)).strip_edges(); + print_verbose("Loading adaptive foreground icon from " + path); if (path.is_empty() || ImageLoader::load_image(path, foreground) != OK) { + print_verbose("- falling back to using the regular icon"); foreground = icon; } // Adaptive background: user selection -> default. path = static_cast<String>(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges(); if (!path.is_empty()) { + print_verbose("Loading adaptive background icon from " + path); ImageLoader::load_image(path, background); } } @@ -1535,13 +1568,21 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } void _copy_icons_to_gradle_project(const Ref<EditorExportPreset> &p_preset, + const String &processed_splash_config_xml, const Ref<Image> &splash_image, const Ref<Image> &splash_bg_color_image, const Ref<Image> &main_image, const Ref<Image> &foreground, const Ref<Image> &background) { + // Store the splash configuration + if (!processed_splash_config_xml.is_empty()) { + print_verbose("Storing processed splash configuration: " + String("\n") + processed_splash_config_xml); + store_string_at_path(SPLASH_CONFIG_PATH, processed_splash_config_xml); + } + // Store the splash image if (splash_image.is_valid() && !splash_image->is_empty()) { + print_verbose("Storing splash image in " + String(SPLASH_IMAGE_EXPORT_PATH)); Vector<uint8_t> data; _load_image_data(splash_image, data); store_image(SPLASH_IMAGE_EXPORT_PATH, data); @@ -1549,6 +1590,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { // Store the splash bg color image if (splash_bg_color_image.is_valid() && !splash_bg_color_image->is_empty()) { + print_verbose("Storing splash background image in " + String(SPLASH_BG_COLOR_PATH)); Vector<uint8_t> data; _load_image_data(splash_bg_color_image, data); store_image(SPLASH_BG_COLOR_PATH, data); @@ -1559,12 +1601,14 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { for (int i = 0; i < icon_densities_count; ++i) { if (main_image.is_valid() && !main_image->is_empty()) { + print_verbose("Processing launcher icon for dimension " + itos(launcher_icons[i].dimensions) + " into " + launcher_icons[i].export_path); Vector<uint8_t> data; _process_launcher_icons(launcher_icons[i].export_path, main_image, launcher_icons[i].dimensions, data); store_image(launcher_icons[i], data); } if (foreground.is_valid() && !foreground->is_empty()) { + print_verbose("Processing launcher adaptive icon foreground for dimension " + itos(launcher_adaptive_icon_foregrounds[i].dimensions) + " into " + launcher_adaptive_icon_foregrounds[i].export_path); Vector<uint8_t> data; _process_launcher_icons(launcher_adaptive_icon_foregrounds[i].export_path, foreground, launcher_adaptive_icon_foregrounds[i].dimensions, data); @@ -1572,6 +1616,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } if (background.is_valid() && !background->is_empty()) { + print_verbose("Processing launcher adaptive icon background for dimension " + itos(launcher_adaptive_icon_backgrounds[i].dimensions) + " into " + launcher_adaptive_icon_backgrounds[i].export_path); Vector<uint8_t> data; _process_launcher_icons(launcher_adaptive_icon_backgrounds[i].export_path, background, launcher_adaptive_icon_backgrounds[i].dimensions, data); @@ -1597,7 +1642,7 @@ public: public: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override { - String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); + String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name"); if (driver == "GLES2") { r_features->push_back("etc"); } @@ -1623,7 +1668,7 @@ public: print_verbose("Found Android plugin " + plugins_configs[i].name); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + plugins_configs[i].name), false)); } - plugins_changed = false; + plugins_changed.clear(); Vector<String> abis = get_abis(); for (int i = 0; i < abis.size(); ++i) { @@ -1693,19 +1738,19 @@ public: } virtual bool should_update_export_options() override { - bool export_options_changed = plugins_changed; + bool export_options_changed = plugins_changed.is_set(); if (export_options_changed) { // don't clear unless we're reporting true, to avoid race - plugins_changed = false; + plugins_changed.clear(); } return export_options_changed; } virtual bool poll_export() override { - bool dc = devices_changed; + bool dc = devices_changed.is_set(); if (dc) { // don't clear unless we're reporting true, to avoid race - devices_changed = false; + devices_changed.clear(); } return dc; } @@ -2239,6 +2284,7 @@ public: String release_password = p_preset->get("keystore/release_password"); String apksigner = get_apksigner_path(); + print_verbose("Starting signing of the " + export_label + " binary using " + apksigner); if (!FileAccess::exists(apksigner)) { EditorNode::add_io_error("'apksigner' could not be found.\nPlease check the command is available in the Android SDK build-tools directory.\nThe resulting " + export_label + " is unsigned."); return OK; @@ -2287,6 +2333,10 @@ public: args.push_back("--ks-key-alias"); args.push_back(user); args.push_back(export_path); + if (p_debug) { + // We only print verbose logs for debug builds to avoid leaking release keystore credentials. + print_verbose("Signing debug binary using: " + String("\n") + apksigner + " " + join_list(args, String(" "))); + } int retval; OS::get_singleton()->execute(apksigner, args, nullptr, &retval); if (retval) { @@ -2302,24 +2352,41 @@ public: args.push_back("verify"); args.push_back("--verbose"); args.push_back(export_path); + if (p_debug) { + print_verbose("Verifying signed build using: " + String("\n") + apksigner + " " + join_list(args, String(" "))); + } OS::get_singleton()->execute(apksigner, args, nullptr, &retval); if (retval) { EditorNode::add_io_error("'apksigner' verification of " + export_label + " failed."); return ERR_CANT_CREATE; } + + print_verbose("Successfully completed signing build."); return OK; } void _clear_assets_directory() { DirAccessRef da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (da_res->dir_exists("res://android/build/assets")) { + print_verbose("Clearing assets directory.."); DirAccessRef da_assets = DirAccess::open("res://android/build/assets"); da_assets->erase_contents_recursive(); da_res->remove("res://android/build/assets"); } } + String join_list(List<String> parts, const String &separator) const { + String ret; + for (int i = 0; i < parts.size(); ++i) { + if (i > 0) { + ret += separator; + } + ret += parts[i]; + } + return ret; + } + virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override { int export_format = int(p_preset->get("custom_template/export_format")); bool should_sign = p_preset->get("package/signed"); @@ -2339,9 +2406,18 @@ public: bool apk_expansion = p_preset->get("apk_expansion/enable"); Vector<String> enabled_abis = get_enabled_abis(p_preset); + print_verbose("Exporting for Android..."); + print_verbose("- debug build: " + bool_to_string(p_debug)); + print_verbose("- export path: " + p_path); + print_verbose("- export format: " + itos(export_format)); + print_verbose("- sign build: " + bool_to_string(should_sign)); + print_verbose("- custom build enabled: " + bool_to_string(use_custom_build)); + print_verbose("- apk expansion enabled: " + bool_to_string(apk_expansion)); + print_verbose("- enabled abis: " + String(",").join(enabled_abis)); + Ref<Image> splash_image; Ref<Image> splash_bg_color_image; - load_splash_refs(splash_image, splash_bg_color_image); + String processed_splash_config_xml = load_splash_refs(splash_image, splash_bg_color_image); Ref<Image> main_image; Ref<Image> foreground; @@ -2374,14 +2450,17 @@ public: } if (use_custom_build) { + print_verbose("Starting custom build.."); //test that installed build version is alright { + print_verbose("Checking build version.."); FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ); if (!f) { EditorNode::get_singleton()->show_warning(TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu.")); return ERR_UNCONFIGURED; } String version = f->get_line().strip_edges(); + print_verbose("- build version: " + version); f->close(); if (version != VERSION_FULL_CONFIG) { EditorNode::get_singleton()->show_warning(vformat(TTR("Android build version mismatch:\n Template installed: %s\n Godot Version: %s\nPlease reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG)); @@ -2389,7 +2468,8 @@ public: } } String sdk_path = EDITOR_GET("export/android/android_sdk_path"); - ERR_FAIL_COND_V_MSG(sdk_path == "", ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'."); + ERR_FAIL_COND_V_MSG(sdk_path.is_empty(), ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'."); + print_verbose("Android sdk path: " + sdk_path); // TODO: should we use "package/name" or "application/config/name"? String project_name = get_project_name(p_preset->get("package/name")); @@ -2398,27 +2478,31 @@ public: EditorNode::add_io_error("Unable to overwrite res://android/build/res/*.xml files with project name"); } // Copies the project icon files into the appropriate Gradle project directory. - _copy_icons_to_gradle_project(p_preset, splash_image, splash_bg_color_image, main_image, foreground, background); + _copy_icons_to_gradle_project(p_preset, processed_splash_config_xml, splash_image, splash_bg_color_image, main_image, foreground, background); // Write an AndroidManifest.xml file into the Gradle project directory. _write_tmp_manifest(p_preset, p_give_internet, p_debug); //stores all the project files inside the Gradle project directory. Also includes all ABIs _clear_assets_directory(); if (!apk_expansion) { + print_verbose("Exporting project files.."); err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, NULL, ignore_so_file); if (err != OK) { EditorNode::add_io_error("Could not export project files to gradle project\n"); return err; } } else { + print_verbose("Saving apk expansion file.."); err = save_apk_expansion_file(p_preset, p_path); if (err != OK) { EditorNode::add_io_error("Could not write expansion package file!"); return err; } } + print_verbose("Storing command line flags.."); store_file_at_path("res://android/build/assets/_cl_", command_line_flags); + print_verbose("Updating ANDROID_HOME environment to " + sdk_path); OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path); //set and overwrite if required String build_command; @@ -2458,6 +2542,8 @@ public: cmdline.push_back(apk_build_command); } + cmdline.push_back("-p"); // argument to specify the start directory. + cmdline.push_back(build_path); // start directory. cmdline.push_back("-Pexport_package_name=" + package_name); // argument to specify the package name. cmdline.push_back("-Pexport_version_code=" + version_code); // argument to specify the version code. cmdline.push_back("-Pexport_version_name=" + version_name); // argument to specify the version name. @@ -2467,6 +2553,13 @@ public: cmdline.push_back("-Pplugins_maven_repos=" + custom_maven_repos); // argument to specify the list of custom maven repos for the plugins dependencies. cmdline.push_back("-Pperform_zipalign=" + zipalign_flag); // argument to specify whether the build should be zipaligned. cmdline.push_back("-Pperform_signing=" + sign_flag); // argument to specify whether the build should be signed. + + // NOTE: The release keystore is not included in the verbose logging + // to avoid accidentally leaking sensitive information when sharing verbose logs for troubleshooting. + // Any non-sensitive additions to the command line arguments must be done above this section. + // Sensitive additions must be done below the logging statement. + print_verbose("Build Android project using gradle command: " + String("\n") + build_command + " " + join_list(cmdline, String(" "))); + if (should_sign && !p_debug) { // Pass the release keystore info as well String release_keystore = p_preset->get("keystore/release"); @@ -2481,8 +2574,6 @@ public: cmdline.push_back("-Prelease_keystore_alias=" + release_username); // argument to specify the release keystore alias. cmdline.push_back("-Prelease_keystore_password=" + release_password); // argument to specity the release keystore password. } - cmdline.push_back("-p"); // argument to specify the start directory. - cmdline.push_back(build_path); // start directory. int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline); if (result != 0) { @@ -2513,15 +2604,18 @@ public: copy_args.push_back("-Pexport_path=file:" + export_path); copy_args.push_back("-Pexport_filename=" + export_filename); + print_verbose("Copying Android binary using gradle command: " + String("\n") + build_command + " " + join_list(copy_args, String(" "))); int copy_result = EditorNode::get_singleton()->execute_and_show_output(TTR("Moving output"), build_command, copy_args); if (copy_result != 0) { EditorNode::get_singleton()->show_warning(TTR("Unable to copy and rename export file, check gradle project directory for outputs.")); return ERR_CANT_CREATE; } + print_verbose("Successfully completed Android custom build."); return OK; } // This is the start of the Legacy build system + print_verbose("Starting legacy build system.."); if (p_debug) src_apk = p_preset->get("custom_template/debug"); else @@ -2845,14 +2939,13 @@ public: run_icon.instance(); run_icon->create_from_image(img); - devices_changed = true; - plugins_changed = true; - quit_request = false; + devices_changed.set(); + plugins_changed.set(); check_for_changes_thread.start(_check_for_changes_poll_thread, this); } ~EditorExportPlatformAndroid() { - quit_request = true; + quit_request.set(); check_for_changes_thread.wait_to_finish(); } }; diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index fc54b65d26..ce6a3c96db 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -146,6 +146,9 @@ Error store_string_at_path(const String &p_path, const String &p_data) { String dir = p_path.get_base_dir(); Error err = create_directory(dir); if (err != OK) { + if (OS::get_singleton()->is_stdout_verbose()) { + print_error("Unable to write data into " + p_path); + } return err; } FileAccess *fa = FileAccess::open(p_path, FileAccess::WRITE); @@ -162,12 +165,14 @@ Error store_string_at_path(const String &p_path, const String &p_data) { // This method will be called ONLY when custom build is enabled. Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { String dst_path = p_path.replace_first("res://", "res://android/build/assets/"); + print_verbose("Saving project files from " + p_path + " into " + dst_path); Error err = store_file_at_path(dst_path, p_data); return err; } // Creates strings.xml files inside the gradle project for different locales. Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset, const String &project_name) { + print_verbose("Creating strings resources for supported locales for project " + project_name); // Stores the string into the default values directory. String processed_default_xml_string = vformat(godot_project_name_xml_string, project_name.xml_escape(true)); store_string_at_path("res://android/build/res/values/godot_project_name_string.xml", processed_default_xml_string); @@ -175,6 +180,9 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset // Searches the Gradle project res/ directory to find all supported locales DirAccessRef da = DirAccess::open("res://android/build/res"); if (!da) { + if (OS::get_singleton()->is_stdout_verbose()) { + print_error("Unable to open Android resources directory."); + } return ERR_CANT_OPEN; } da->list_dir_begin(); @@ -193,6 +201,7 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset if (ProjectSettings::get_singleton()->has_setting(property_name)) { String locale_project_name = ProjectSettings::get_singleton()->get(property_name); String processed_xml_string = vformat(godot_project_name_xml_string, locale_project_name.xml_escape(true)); + print_verbose("Storing project name for locale " + locale + " under " + locale_directory); store_string_at_path(locale_directory, processed_xml_string); } else { // TODO: Once the legacy build system is deprecated we don't need to have xml files for this else branch @@ -208,8 +217,8 @@ String bool_to_string(bool v) { } String _get_gles_tag() { - bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES3" && - !ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2"); + bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/driver/driver_name") == "GLES3" && + !ProjectSettings::get_singleton()->get("rendering/driver/fallback_to_gles2"); return min_gles3 ? " <uses-feature android:glEsVersion=\"0x00030000\" android:required=\"true\" />\n" : ""; } diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle index 53d11fda5b..814cc30613 100644 --- a/platform/android/java/app/build.gradle +++ b/platform/android/java/app/build.gradle @@ -98,6 +98,8 @@ android { disable 'MissingTranslation', 'UnusedResources' } + ndkVersion versions.ndkVersion + packagingOptions { exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index 80cf6f7ede..202b3c35c0 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -1,5 +1,5 @@ ext.versions = [ - androidGradlePlugin: '4.1.0', + androidGradlePlugin: '4.0.1', compileSdk : 29, minSdk : 18, targetSdk : 29, @@ -7,7 +7,8 @@ ext.versions = [ supportCoreUtils : '1.0.0', kotlinVersion : '1.4.10', v4Support : '1.0.0', - javaVersion : 1.8 + javaVersion : 1.8, + ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated. ] diff --git a/platform/android/java/app/res/drawable/splash_drawable.xml b/platform/android/java/app/res/drawable/splash_drawable.xml index 2794a40817..30627b998c 100644 --- a/platform/android/java/app/res/drawable/splash_drawable.xml +++ b/platform/android/java/app/res/drawable/splash_drawable.xml @@ -6,7 +6,7 @@ <item> <bitmap android:gravity="center" + android:filter="false" android:src="@drawable/splash" /> </item> - </layer-list> diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle index 89ce3d15e6..ca5153f7f6 100644 --- a/platform/android/java/lib/build.gradle +++ b/platform/android/java/lib/build.gradle @@ -13,6 +13,8 @@ android { compileSdkVersion versions.compileSdk buildToolsVersion versions.buildTools + ndkVersion versions.ndkVersion + defaultConfig { minSdkVersion versions.minSdk targetSdkVersion versions.targetSdk @@ -68,7 +70,7 @@ android { File sconsExecutableFile = null def sconsName = "scons" def sconsExts = (org.gradle.internal.os.OperatingSystem.current().isWindows() - ? [".bat", ".exe"] + ? [".bat", ".cmd", ".ps1", ".exe"] : [""]) logger.lifecycle("Looking for $sconsName executable path") for (ext in sconsExts) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java index 3368363ce7..435b8b325f 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java @@ -38,6 +38,8 @@ import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener; import android.os.Build; import android.util.Log; +import android.util.SparseArray; +import android.util.SparseIntArray; import android.view.InputDevice; import android.view.InputDevice.MotionRange; import android.view.KeyEvent; @@ -46,17 +48,24 @@ import android.view.MotionEvent; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; /** * Handles input related events for the {@link GodotRenderView} view. */ public class GodotInputHandler implements InputDeviceListener { - private final ArrayList<Joystick> mJoysticksDevices = new ArrayList<Joystick>(); - private final GodotRenderView mRenderView; private final InputManagerCompat mInputManager; + private final String tag = this.getClass().getSimpleName(); + + private final SparseIntArray mJoystickIds = new SparseIntArray(4); + private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<Joystick>(4); + public GodotInputHandler(GodotRenderView godotView) { mRenderView = godotView; mInputManager = InputManagerCompat.Factory.getInputManager(mRenderView.getView().getContext()); @@ -82,19 +91,20 @@ public class GodotInputHandler implements InputDeviceListener { if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { return false; - }; + } int source = event.getSource(); if (isKeyEvent_GameDevice(source)) { - final int button = getGodotButton(keyCode); - final int device_id = findJoystickDevice(event.getDeviceId()); - // Check if the device exists - if (device_id > -1) { + final int deviceId = event.getDeviceId(); + if (mJoystickIds.indexOfKey(deviceId) >= 0) { + final int button = getGodotButton(keyCode); + final int godotJoyId = mJoystickIds.get(deviceId); + queueEvent(new Runnable() { @Override public void run() { - GodotLib.joybutton(device_id, button, false); + GodotLib.joybutton(godotJoyId, button, false); } }); } @@ -107,7 +117,7 @@ public class GodotInputHandler implements InputDeviceListener { GodotLib.key(keyCode, scanCode, chr, false); } }); - }; + } return true; } @@ -122,24 +132,25 @@ public class GodotInputHandler implements InputDeviceListener { if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { return false; - }; + } int source = event.getSource(); //Log.e(TAG, String.format("Key down! source %d, device %d, joystick %d, %d, %d", event.getDeviceId(), source, (source & InputDevice.SOURCE_JOYSTICK), (source & InputDevice.SOURCE_DPAD), (source & InputDevice.SOURCE_GAMEPAD))); + final int deviceId = event.getDeviceId(); + // Check if source is a game device and that the device is a registered gamepad if (isKeyEvent_GameDevice(source)) { if (event.getRepeatCount() > 0) // ignore key echo return true; - final int button = getGodotButton(keyCode); - final int device_id = findJoystickDevice(event.getDeviceId()); + if (mJoystickIds.indexOfKey(deviceId) >= 0) { + final int button = getGodotButton(keyCode); + final int godotJoyId = mJoystickIds.get(deviceId); - // Check if the device exists - if (device_id > -1) { queueEvent(new Runnable() { @Override public void run() { - GodotLib.joybutton(device_id, button, true); + GodotLib.joybutton(godotJoyId, button, true); } }); } @@ -152,7 +163,7 @@ public class GodotInputHandler implements InputDeviceListener { GodotLib.key(keyCode, scanCode, chr, true); } }); - }; + } return true; } @@ -203,38 +214,52 @@ public class GodotInputHandler implements InputDeviceListener { } public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) { - final int device_id = findJoystickDevice(event.getDeviceId()); - + if (event.isFromSource(InputDevice.SOURCE_JOYSTICK) && event.getAction() == MotionEvent.ACTION_MOVE) { // Check if the device exists - if (device_id > -1) { - Joystick joy = mJoysticksDevices.get(device_id); - - for (int i = 0; i < joy.axes.size(); i++) { - InputDevice.MotionRange range = joy.axes.get(i); - final float value = (event.getAxisValue(range.getAxis()) - range.getMin()) / range.getRange() * 2.0f - 1.0f; - final int idx = i; - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyaxis(device_id, idx, value); - } - }); + final int deviceId = event.getDeviceId(); + if (mJoystickIds.indexOfKey(deviceId) >= 0) { + final int godotJoyId = mJoystickIds.get(deviceId); + Joystick joystick = mJoysticksDevices.get(deviceId); + + for (int i = 0; i < joystick.axes.size(); i++) { + final int axis = joystick.axes.get(i); + final float value = event.getAxisValue(axis); + /** + * As all axes are polled for each event, only fire an axis event if the value has actually changed. + * Prevents flooding Godot with repeated events. + */ + if (joystick.axesValues.indexOfKey(axis) < 0 || (float)joystick.axesValues.get(axis) != value) { + // save value to prevent repeats + joystick.axesValues.put(axis, value); + final int godotAxisIdx = i; + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joyaxis(godotJoyId, godotAxisIdx, value); + //Log.i(tag, "GodotLib.joyaxis("+godotJoyId+", "+godotAxisIdx+", "+value+");"); + } + }); + } } - for (int i = 0; i < joy.hats.size(); i += 2) { - final int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis())); - final int hatY = Math.round(event.getAxisValue(joy.hats.get(i + 1).getAxis())); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyhat(device_id, hatX, hatY); - } - }); + if (joystick.hasAxisHat) { + final int hatX = Math.round(event.getAxisValue(MotionEvent.AXIS_HAT_X)); + final int hatY = Math.round(event.getAxisValue(MotionEvent.AXIS_HAT_Y)); + if (joystick.hatX != hatX || joystick.hatY != hatY) { + joystick.hatX = hatX; + joystick.hatY = hatY; + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joyhat(godotJoyId, hatX, hatY); + //Log.i(tag, "GodotLib.joyhat("+godotJoyId+", "+hatX+", "+hatY+");"); + } + }); + } } return true; } - } else if ((event.getSource() & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) { + } else if (event.isFromSource(InputDevice.SOURCE_STYLUS)) { final float x = event.getX(); final float y = event.getY(); final int type = event.getAction(); @@ -245,6 +270,7 @@ public class GodotInputHandler implements InputDeviceListener { } }); return true; + } else if (event.isFromSource(InputDevice.SOURCE_MOUSE) || event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return handleMouseEvent(event); @@ -266,67 +292,98 @@ public class GodotInputHandler implements InputDeviceListener { } } + private int assignJoystickIdNumber(int deviceId) { + int godotJoyId = 0; + while (mJoystickIds.indexOfValue(godotJoyId) >= 0) { + godotJoyId++; + } + mJoystickIds.put(deviceId, godotJoyId); + return godotJoyId; + } + @Override public void onInputDeviceAdded(int deviceId) { - int id = findJoystickDevice(deviceId); - // Check if the device has not been already added - if (id < 0) { - InputDevice device = mInputManager.getInputDevice(deviceId); - //device can be null if deviceId is not found - if (device != null) { - int sources = device.getSources(); - if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) || - ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) { - id = mJoysticksDevices.size(); - - Joystick joy = new Joystick(); - joy.device_id = deviceId; - joy.name = device.getName(); - joy.axes = new ArrayList<InputDevice.MotionRange>(); - joy.hats = new ArrayList<InputDevice.MotionRange>(); - - List<InputDevice.MotionRange> ranges = device.getMotionRanges(); - Collections.sort(ranges, new RangeComparator()); - - for (InputDevice.MotionRange range : ranges) { - if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) { - joy.hats.add(range); - } else { - joy.axes.add(range); - } - } - mJoysticksDevices.add(joy); + if (mJoystickIds.indexOfKey(deviceId) >= 0) { + return; + } + + InputDevice device = mInputManager.getInputDevice(deviceId); + //device can be null if deviceId is not found + if (device == null) { + return; + } + + int sources = device.getSources(); + + // Device may not be a joystick or gamepad + if ((sources & InputDevice.SOURCE_GAMEPAD) != InputDevice.SOURCE_GAMEPAD && + (sources & InputDevice.SOURCE_JOYSTICK) != InputDevice.SOURCE_JOYSTICK) { + return; + } + + // Assign first available number. Re-use numbers where possible. + final int id = assignJoystickIdNumber(deviceId); + + final Joystick joystick = new Joystick(); + joystick.device_id = deviceId; + joystick.name = device.getName(); + + //Helps with creating new joypad mappings. + Log.i(tag, "=== New Input Device: " + joystick.name); - final int device_id = id; - final String name = joy.name; - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyconnectionchanged(device_id, true, name); - } - }); + Set<Integer> already = new HashSet<Integer>(); + for (InputDevice.MotionRange range : device.getMotionRanges()) { + boolean isJoystick = range.isFromSource(InputDevice.SOURCE_JOYSTICK); + boolean isGamepad = range.isFromSource(InputDevice.SOURCE_GAMEPAD); + //Log.i(tag, "axis: "+range.getAxis()+ ", isJoystick: "+isJoystick+", isGamepad: "+isGamepad); + if (!isJoystick && !isGamepad) { + continue; + } + final int axis = range.getAxis(); + if (axis == MotionEvent.AXIS_HAT_X || axis == MotionEvent.AXIS_HAT_Y) { + joystick.hasAxisHat = true; + } else { + if (!already.contains(axis)) { + already.add(axis); + joystick.axes.add(axis); + } else { + Log.w(tag, " - DUPLICATE AXIS VALUE IN LIST: " + axis); } } } + Collections.sort(joystick.axes); + for (int idx = 0; idx < joystick.axes.size(); idx++) { + //Helps with creating new joypad mappings. + Log.i(tag, " - Mapping Android axis " + joystick.axes.get(idx) + " to Godot axis " + idx); + } + mJoysticksDevices.put(deviceId, joystick); + + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joyconnectionchanged(id, true, joystick.name); + } + }); } @Override public void onInputDeviceRemoved(int deviceId) { - final int device_id = findJoystickDevice(deviceId); - - // Check if the evice has not been already removed - if (device_id > -1) { - mJoysticksDevices.remove(device_id); - - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyconnectionchanged(device_id, false, ""); - } - }); + // Check if the device has not been already removed + if (mJoystickIds.indexOfKey(deviceId) < 0) { + return; } + final int godotJoyId = mJoystickIds.get(deviceId); + mJoystickIds.delete(deviceId); + mJoysticksDevices.delete(deviceId); + + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joyconnectionchanged(godotJoyId, false, ""); + } + }); } @Override @@ -407,16 +464,6 @@ public class GodotInputHandler implements InputDeviceListener { return button; } - private int findJoystickDevice(int device_id) { - for (int i = 0; i < mJoysticksDevices.size(); i++) { - if (mJoysticksDevices.get(i).device_id == device_id) { - return i; - } - } - - return -1; - } - private boolean handleMouseEvent(final MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_HOVER_ENTER: diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java index 82bd45ee3f..4b7318c718 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java @@ -30,9 +30,10 @@ package org.godotengine.godot.input; -import android.view.InputDevice.MotionRange; +import android.util.SparseArray; import java.util.ArrayList; +import java.util.List; /** * POJO class to represent a Joystick input device. @@ -40,6 +41,12 @@ import java.util.ArrayList; class Joystick { int device_id; String name; - ArrayList<MotionRange> axes; - ArrayList<MotionRange> hats; + List<Integer> axes = new ArrayList<Integer>(); + protected boolean hasAxisHat = false; + /* + * Keep track of values so we can prevent flooding the engine with useless events. + */ + protected final SparseArray axesValues = new SparseArray<Float>(4); + protected int hatX; + protected int hatY; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java index a22b80761d..993f0e9127 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java @@ -46,7 +46,9 @@ import androidx.annotation.Nullable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -107,14 +109,47 @@ public abstract class GodotPlugin { * This method is invoked on the render thread. */ public final void onRegisterPluginWithGodotNative() { - nativeRegisterSingleton(getPluginName()); + registeredSignals.putAll(registerPluginWithGodotNative(this, new GodotPluginInfoProvider() { + @NonNull + @Override + public String getPluginName() { + return GodotPlugin.this.getPluginName(); + } + + @NonNull + @Override + public List<String> getPluginMethods() { + return GodotPlugin.this.getPluginMethods(); + } + + @NonNull + @Override + public Set<SignalInfo> getPluginSignals() { + return GodotPlugin.this.getPluginSignals(); + } + + @NonNull + @Override + public Set<String> getPluginGDNativeLibrariesPaths() { + return GodotPlugin.this.getPluginGDNativeLibrariesPaths(); + } + })); + } - Class clazz = getClass(); + /** + * Register the plugin with Godot native code. + * + * This method must be invoked on the render thread. + */ + public static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject, GodotPluginInfoProvider pluginInfoProvider) { + nativeRegisterSingleton(pluginInfoProvider.getPluginName(), pluginObject); + + Class clazz = pluginObject.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { boolean found = false; - for (String s : getPluginMethods()) { + for (String s : pluginInfoProvider.getPluginMethods()) { if (s.equals(method.getName())) { found = true; break; @@ -123,7 +158,7 @@ public abstract class GodotPlugin { if (!found) continue; - List<String> ptr = new ArrayList<String>(); + List<String> ptr = new ArrayList<>(); Class[] paramTypes = method.getParameterTypes(); for (Class c : paramTypes) { @@ -133,26 +168,29 @@ public abstract class GodotPlugin { String[] pt = new String[ptr.size()]; ptr.toArray(pt); - nativeRegisterMethod(getPluginName(), method.getName(), method.getReturnType().getName(), pt); + nativeRegisterMethod(pluginInfoProvider.getPluginName(), method.getName(), method.getReturnType().getName(), pt); } // Register the signals for this plugin. - for (SignalInfo signalInfo : getPluginSignals()) { + Map<String, SignalInfo> registeredSignals = new HashMap<>(); + for (SignalInfo signalInfo : pluginInfoProvider.getPluginSignals()) { String signalName = signalInfo.getName(); - nativeRegisterSignal(getPluginName(), signalName, signalInfo.getParamTypesNames()); + nativeRegisterSignal(pluginInfoProvider.getPluginName(), signalName, signalInfo.getParamTypesNames()); registeredSignals.put(signalName, signalInfo); } // Get the list of gdnative libraries to register. - Set<String> gdnativeLibrariesPaths = getPluginGDNativeLibrariesPaths(); + Set<String> gdnativeLibrariesPaths = pluginInfoProvider.getPluginGDNativeLibrariesPaths(); if (!gdnativeLibrariesPaths.isEmpty()) { nativeRegisterGDNativeLibraries(gdnativeLibrariesPaths.toArray(new String[0])); } + + return registeredSignals; } /** * Invoked once during the Godot Android initialization process after creation of the - * {@link org.godotengine.godot.GodotView} view. + * {@link org.godotengine.godot.GodotRenderView} view. * <p> * The plugin can return a non-null {@link View} layout in order to add it to the Godot view * hierarchy. @@ -290,8 +328,8 @@ public abstract class GodotPlugin { /** * Emit a registered Godot signal. - * @param signalName - * @param signalArgs + * @param signalName Name of the signal to emit. It will be validated against the set of registered signals. + * @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the {@link SignalInfo} matching the registered signalName parameter. */ protected void emitSignal(final String signalName, final Object... signalArgs) { try { @@ -301,6 +339,27 @@ public abstract class GodotPlugin { throw new IllegalArgumentException( "Signal " + signalName + " is not registered for this plugin."); } + emitSignal(getGodot(), getPluginName(), signalInfo, signalArgs); + } catch (IllegalArgumentException exception) { + Log.w(TAG, exception.getMessage()); + if (BuildConfig.DEBUG) { + throw exception; + } + } + } + + /** + * Emit a Godot signal. + * @param godot + * @param pluginName Name of the Godot plugin the signal will be emitted from. The plugin must already be registered with the Godot engine. + * @param signalInfo Information about the signal to emit. + * @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the given {@link SignalInfo} parameter. + */ + public static void emitSignal(Godot godot, String pluginName, SignalInfo signalInfo, final Object... signalArgs) { + try { + if (signalInfo == null) { + throw new IllegalArgumentException("Signal must be non null."); + } // Validate the arguments count. Class<?>[] signalParamTypes = signalInfo.getParamTypes(); @@ -317,12 +376,8 @@ public abstract class GodotPlugin { } } - runOnRenderThread(new Runnable() { - @Override - public void run() { - nativeEmitSignal(getPluginName(), signalName, signalArgs); - } - }); + godot.runOnRenderThread(() -> nativeEmitSignal(pluginName, signalInfo.getName(), signalArgs)); + } catch (IllegalArgumentException exception) { Log.w(TAG, exception.getMessage()); if (BuildConfig.DEBUG) { @@ -335,7 +390,7 @@ public abstract class GodotPlugin { * Used to setup a {@link GodotPlugin} instance. * @param p_name Name of the instance. */ - private native void nativeRegisterSingleton(String p_name); + private static native void nativeRegisterSingleton(String p_name, Object object); /** * Used to complete registration of the {@link GodotPlugin} instance's methods. @@ -344,13 +399,13 @@ public abstract class GodotPlugin { * @param p_ret Return type of the registered method * @param p_params Method parameters types */ - private native void nativeRegisterMethod(String p_sname, String p_name, String p_ret, String[] p_params); + private static native void nativeRegisterMethod(String p_sname, String p_name, String p_ret, String[] p_params); /** * Used to register gdnative libraries bundled by the plugin. * @param gdnlibPaths Paths to the libraries relative to the 'assets' directory. */ - private native void nativeRegisterGDNativeLibraries(String[] gdnlibPaths); + private static native void nativeRegisterGDNativeLibraries(String[] gdnlibPaths); /** * Used to complete registration of the {@link GodotPlugin} instance's methods. @@ -358,7 +413,7 @@ public abstract class GodotPlugin { * @param signalName Name of the signal to register * @param signalParamTypes Signal parameters types */ - private native void nativeRegisterSignal(String pluginName, String signalName, String[] signalParamTypes); + private static native void nativeRegisterSignal(String pluginName, String signalName, String[] signalParamTypes); /** * Used to emit signal by {@link GodotPlugin} instance. @@ -366,5 +421,5 @@ public abstract class GodotPlugin { * @param signalName Name of the signal to emit * @param signalParams Signal parameters */ - private native void nativeEmitSignal(String pluginName, String signalName, Object[] signalParams); + private static native void nativeEmitSignal(String pluginName, String signalName, Object[] signalParams); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java new file mode 100644 index 0000000000..c3084b036e --- /dev/null +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java @@ -0,0 +1,67 @@ +/*************************************************************************/ +/* GodotPluginInfoProvider.java */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ + +package org.godotengine.godot.plugin; + +import androidx.annotation.NonNull; + +import java.util.List; +import java.util.Set; + +/** + * Provides the set of information expected from a Godot plugin. + */ +public interface GodotPluginInfoProvider { + /** + * Returns the name of the plugin. + */ + @NonNull + String getPluginName(); + + /** + * Returns the list of methods to be exposed to Godot. + */ + @NonNull + List<String> getPluginMethods(); + + /** + * Returns the list of signals to be exposed to Godot. + */ + @NonNull + Set<SignalInfo> getPluginSignals(); + + /** + * Returns the paths for the plugin's gdnative libraries (if any). + * + * The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file. + */ + @NonNull + Set<String> getPluginGDNativeLibrariesPaths(); +} diff --git a/platform/android/java/nativeSrcsConfigs/build.gradle b/platform/android/java/nativeSrcsConfigs/build.gradle index 65b7bb9dc9..66077060ea 100644 --- a/platform/android/java/nativeSrcsConfigs/build.gradle +++ b/platform/android/java/nativeSrcsConfigs/build.gradle @@ -31,6 +31,8 @@ android { } } + ndkVersion versions.ndkVersion + externalNativeBuild { cmake { path "CMakeLists.txt" diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index 4ee4427aa0..41201db32b 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -187,14 +187,14 @@ String GodotIOJavaWrapper::get_system_dir(int p_dir) { } } -// volatile because it can be changed from non-main thread and we need to +// SafeNumeric because it can be changed from non-main thread and we need to // ensure the change is immediately visible to other threads. -static volatile int virtual_keyboard_height; +static SafeNumeric<int> virtual_keyboard_height; int GodotIOJavaWrapper::get_vk_height() { - return virtual_keyboard_height; + return virtual_keyboard_height.get(); } void GodotIOJavaWrapper::set_vk_height(int p_height) { - virtual_keyboard_height = p_height; + virtual_keyboard_height.set(p_height); } diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp index f602e99e61..ba3e9fa20f 100644 --- a/platform/android/plugin/godot_plugin_jni.cpp +++ b/platform/android/plugin/godot_plugin_jni.cpp @@ -41,7 +41,7 @@ static HashMap<String, JNISingleton *> jni_singletons; extern "C" { -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jobject obj, jstring name) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj) { String singname = jstring_to_string(name, env); JNISingleton *s = (JNISingleton *)ClassDB::instance("JNISingleton"); s->set_instance(env->NewGlobalRef(obj)); @@ -51,7 +51,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis ProjectSettings::get_singleton()->set(singname, s); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jclass clazz, jstring sname, jstring name, jstring ret, jobjectArray args) { String singname = jstring_to_string(sname, env); ERR_FAIL_COND(!jni_singletons.has(singname)); @@ -83,7 +83,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis s->add_method(mname, mid, types, get_jni_type(retval)); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types) { String singleton_name = jstring_to_string(j_plugin_name, env); ERR_FAIL_COND(!jni_singletons.has(singleton_name)); @@ -104,7 +104,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis singleton->add_signal(signal_name, types); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params) { String singleton_name = jstring_to_string(j_plugin_name, env); ERR_FAIL_COND(!jni_singletons.has(singleton_name)); @@ -129,7 +129,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS singleton->emit_signal(signal_name, args, count); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jobject obj, jobjectArray gdnlib_paths) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths) { int gdnlib_count = env->GetArrayLength(gdnlib_paths); if (gdnlib_count == 0) { return; diff --git a/platform/android/plugin/godot_plugin_jni.h b/platform/android/plugin/godot_plugin_jni.h index 8a08ec3709..b87f922e03 100644 --- a/platform/android/plugin/godot_plugin_jni.h +++ b/platform/android/plugin/godot_plugin_jni.h @@ -35,11 +35,11 @@ #include <jni.h> extern "C" { -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jobject obj, jstring name); -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args); -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types); -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params); -JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jobject obj, jobjectArray gdnlib_paths); +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj); +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jclass clazz, jstring sname, jstring name, jstring ret, jobjectArray args); +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types); +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params); +JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths); } #endif // GODOT_PLUGIN_JNI_H diff --git a/platform/iphone/display_layer.mm b/platform/iphone/display_layer.mm index fb57db4518..b8df81b89a 100644 --- a/platform/iphone/display_layer.mm +++ b/platform/iphone/display_layer.mm @@ -89,7 +89,7 @@ // FIXME: Add Vulkan support via MoltenVK. Add fallback code back? // Create GL ES 2 context - if (GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES2") { + if (GLOBAL_GET("rendering/driver/driver_name") == "GLES2") { context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; NSLog(@"Setting up an OpenGL ES 2.0 context."); if (!context) { diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 604ad4e04b..c585c2afbe 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -37,6 +37,7 @@ #include "core/io/zip_io.h" #include "core/os/file_access.h" #include "core/os/os.h" +#include "core/templates/safe_refcount.h" #include "core/version.h" #include "editor/editor_export.h" #include "editor/editor_node.h" @@ -56,9 +57,9 @@ class EditorExportPlatformIOS : public EditorExportPlatform { Ref<ImageTexture> logo; // Plugins - volatile bool plugins_changed; + SafeFlag plugins_changed; Thread check_for_changes_thread; - volatile bool quit_request; + SafeFlag quit_request; Mutex plugins_lock; Vector<PluginConfigIOS> plugins; @@ -141,19 +142,19 @@ class EditorExportPlatformIOS : public EditorExportPlatform { static void _check_for_changes_poll_thread(void *ud) { EditorExportPlatformIOS *ea = (EditorExportPlatformIOS *)ud; - while (!ea->quit_request) { + while (!ea->quit_request.is_set()) { // Nothing to do if we already know the plugins have changed. - if (!ea->plugins_changed) { + if (!ea->plugins_changed.is_set()) { MutexLock lock(ea->plugins_lock); Vector<PluginConfigIOS> loaded_plugins = get_plugins(); if (ea->plugins.size() != loaded_plugins.size()) { - ea->plugins_changed = true; + ea->plugins_changed.set(); } else { for (int i = 0; i < ea->plugins.size(); i++) { if (ea->plugins[i].name != loaded_plugins[i].name || ea->plugins[i].last_updated != loaded_plugins[i].last_updated) { - ea->plugins_changed = true; + ea->plugins_changed.set(); break; } } @@ -165,7 +166,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { while (OS::get_singleton()->get_ticks_usec() - time < wait) { OS::get_singleton()->delay_usec(300000); - if (ea->quit_request) { + if (ea->quit_request.is_set()) { break; } } @@ -182,10 +183,10 @@ public: virtual Ref<Texture2D> get_logo() const override { return logo; } virtual bool should_update_export_options() override { - bool export_options_changed = plugins_changed; + bool export_options_changed = plugins_changed.is_set(); if (export_options_changed) { // don't clear unless we're reporting true, to avoid race - plugins_changed = false; + plugins_changed.clear(); } return export_options_changed; } @@ -291,7 +292,7 @@ public: }; void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { - String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); + String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name"); r_features->push_back("pvrtc"); if (driver == "Vulkan") { // FIXME: Review if this is correct. @@ -364,7 +365,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) for (int i = 0; i < found_plugins.size(); i++) { r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false)); } - plugins_changed = false; + plugins_changed.clear(); plugins = found_plugins; r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false)); @@ -1351,6 +1352,8 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> Vector<String> added_embedded_dependenciy_names; HashMap<String, String> plist_values; + Set<String> plugin_linker_flags; + Error err; for (int i = 0; i < enabled_plugins.size(); i++) { @@ -1417,6 +1420,13 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> p_config_data.capabilities.push_back(capability); } + // Linker flags + // Checking duplicates + for (int j = 0; j < plugin.linker_flags.size(); j++) { + String linker_flag = plugin.linker_flags[j]; + plugin_linker_flags.insert(linker_flag); + } + // Plist // Using hash map container to remove duplicates const String *K = nullptr; @@ -1497,6 +1507,27 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> p_config_data.cpp_code += plugin_cpp_code.format(plugin_format, "$_"); } + + // Update Linker Flag Values + { + String result_linker_flags = " "; + for (Set<String>::Element *E = plugin_linker_flags.front(); E; E = E->next()) { + const String &flag = E->get(); + + if (flag.length() == 0) { + continue; + } + + if (result_linker_flags.length() > 0) { + result_linker_flags += ' '; + } + + result_linker_flags += flag; + } + result_linker_flags = result_linker_flags.replace("\"", "\\\""); + p_config_data.linker_flags += result_linker_flags; + } + return OK; } @@ -1937,14 +1968,13 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() { logo.instance(); logo->create_from_image(img); - plugins_changed = true; - quit_request = false; + plugins_changed.set(); check_for_changes_thread.start(_check_for_changes_poll_thread, this); } EditorExportPlatformIOS::~EditorExportPlatformIOS() { - quit_request = true; + quit_request.set(); check_for_changes_thread.wait_to_finish(); } diff --git a/platform/iphone/godot_app_delegate.h b/platform/iphone/godot_app_delegate.h index 76d8aa409f..6335ada50e 100644 --- a/platform/iphone/godot_app_delegate.h +++ b/platform/iphone/godot_app_delegate.h @@ -31,7 +31,6 @@ #import <UIKit/UIKit.h> typedef NSObject<UIApplicationDelegate> ApplicationDelegateService; -typedef void (^APNSNotification)(UIBackgroundFetchResult); @interface GodotApplicalitionDelegate : NSObject <UIApplicationDelegate> @@ -39,27 +38,4 @@ typedef void (^APNSNotification)(UIBackgroundFetchResult); + (void)addService:(ApplicationDelegateService *)service; -- (void)godot:(UIApplication *)application receivedNotificationToken:(NSData *)deviceToken; -- (void)godot:(UIApplication *)application receivedNotificationError:(NSError *)error; -- (void)godot:(UIApplication *)application receivedNotification:(NSDictionary *)userInfo completion:(APNSNotification)completionHandler; - @end - -#define GODOT_ENABLE_PUSH_NOTIFICATIONS \ - @interface GodotApplicalitionDelegate (PushNotifications) \ - @end \ - @implementation GodotApplicalitionDelegate (PushNotifications) \ - -(void)application : (UIApplication *)application \ - didRegisterForRemoteNotificationsWithDeviceToken : (NSData *)deviceToken { \ - [self godot:application receivedNotificationToken:deviceToken]; \ - } \ - -(void)application : (UIApplication *)application \ - didFailToRegisterForRemoteNotificationsWithError : (NSError *)error { \ - [self godot:application receivedNotificationError:error]; \ - } \ - -(void)application : (UIApplication *)application \ - didReceiveRemoteNotification : (NSDictionary *)userInfo \ - fetchCompletionHandler : (APNSNotification)completionHandler { \ - [self godot:application receivedNotification:userInfo completion:completionHandler]; \ - } \ - @end diff --git a/platform/iphone/godot_app_delegate.m b/platform/iphone/godot_app_delegate.m index 9d298162f3..3ce9bffc79 100644 --- a/platform/iphone/godot_app_delegate.m +++ b/platform/iphone/godot_app_delegate.m @@ -302,37 +302,7 @@ static NSMutableArray<ApplicationDelegateService *> *services = nil; // MARK: Remote Notification -- (void)godot:(UIApplication *)application receivedNotificationToken:(NSData *)deviceToken { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; - } -} - -- (void)godot:(UIApplication *)application receivedNotificationError:(NSError *)error { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application didFailToRegisterForRemoteNotificationsWithError:error]; - } -} - -- (void)godot:(UIApplication *)application receivedNotification:(NSDictionary *)userInfo completion:(APNSNotification)completionHandler { - for (ApplicationDelegateService *service in services) { - if (![service respondsToSelector:_cmd]) { - continue; - } - - [service application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; - } - - completionHandler(UIBackgroundFetchResultNoData); -} +// Moved to the iOS Plugin // MARK: User Activity and Handling Quick Actions diff --git a/platform/iphone/godot_view.h b/platform/iphone/godot_view.h index 29960c47a8..265f826173 100644 --- a/platform/iphone/godot_view.h +++ b/platform/iphone/godot_view.h @@ -32,12 +32,20 @@ class String; +@class GodotView; @protocol DisplayLayer; @protocol GodotViewRendererProtocol; +@protocol GodotViewDelegate + +- (BOOL)godotViewFinishedSetup:(GodotView *)view; + +@end + @interface GodotView : UIView @property(assign, nonatomic) id<GodotViewRendererProtocol> renderer; +@property(assign, nonatomic) id<GodotViewDelegate> delegate; @property(assign, readonly, nonatomic) BOOL isActive; diff --git a/platform/iphone/godot_view.mm b/platform/iphone/godot_view.mm index bf073ae295..887297848e 100644 --- a/platform/iphone/godot_view.mm +++ b/platform/iphone/godot_view.mm @@ -120,6 +120,7 @@ static const int max_touches = 8; [self stopRendering]; self.renderer = nil; + self.delegate = nil; if (self.renderingLayer) { [self.renderingLayer removeFromSuperlayer]; @@ -241,6 +242,14 @@ static const int max_touches = 8; return; } + if (self.delegate) { + BOOL delegateFinishedSetup = [self.delegate godotViewFinishedSetup:self]; + + if (!delegateFinishedSetup) { + return; + } + } + [self handleMotion]; [self.renderer renderOnView:self]; } diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index 625cbf178e..51c4da2960 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -144,8 +144,6 @@ void OSIPhone::deinitialize_modules() { } void OSIPhone::set_main_loop(MainLoop *p_main_loop) { - godot_ios_plugins_initialize(); - main_loop = p_main_loop; if (main_loop) { @@ -179,6 +177,8 @@ bool OSIPhone::iterate() { } void OSIPhone::start() { + godot_ios_plugins_initialize(); + Main::start(); if (joypad_iphone) { diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h index 72fab13600..f4e30c8349 100644 --- a/platform/iphone/plugin/godot_plugin_config.h +++ b/platform/iphone/plugin/godot_plugin_config.h @@ -66,6 +66,7 @@ struct PluginConfigIOS { inline static const char *DEPENDENCIES_SYSTEM_KEY = "system"; inline static const char *DEPENDENCIES_CAPABILITIES_KEY = "capabilities"; inline static const char *DEPENDENCIES_FILES_KEY = "files"; + inline static const char *DEPENDENCIES_LINKER_FLAGS = "linker_flags"; inline static const char *PLIST_SECTION = "plist"; @@ -89,6 +90,8 @@ struct PluginConfigIOS { Vector<String> files_to_copy; Vector<String> capabilities; + Vector<String> linker_flags; + // Optional plist section // Supports only string types for now HashMap<String, String> plist; @@ -260,6 +263,8 @@ static inline PluginConfigIOS load_plugin_config(Ref<ConfigFile> config_file, co plugin_config.files_to_copy = resolve_local_dependencies(config_base_dir, files); plugin_config.capabilities = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_CAPABILITIES_KEY, Vector<String>()); + + plugin_config.linker_flags = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_LINKER_FLAGS, Vector<String>()); } if (config_file->has_section(PluginConfigIOS::PLIST_SECTION)) { diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm index c41aa13bb7..6cef244567 100644 --- a/platform/iphone/view_controller.mm +++ b/platform/iphone/view_controller.mm @@ -40,12 +40,14 @@ #import <AVFoundation/AVFoundation.h> #import <GameController/GameController.h> -@interface ViewController () +@interface ViewController () <GodotViewDelegate> @property(strong, nonatomic) GodotViewRenderer *renderer; @property(strong, nonatomic) GodotNativeVideoView *videoView; @property(strong, nonatomic) GodotKeyboardInputView *keyboardView; +@property(strong, nonatomic) UIView *godotLoadingOverlay; + @end @implementation ViewController @@ -62,6 +64,7 @@ self.view = view; view.renderer = self.renderer; + view.delegate = self; } - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { @@ -97,6 +100,7 @@ [super viewDidLoad]; [self observeKeyboard]; + [self displayLoadingOverlay]; if (@available(iOS 11.0, *)) { [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; @@ -121,6 +125,31 @@ object:nil]; } +- (void)displayLoadingOverlay { + NSBundle *bundle = [NSBundle mainBundle]; + NSString *storyboardName = @"Launch Screen"; + + if ([bundle pathForResource:storyboardName ofType:@"storyboardc"] == nil) { + return; + } + + UIStoryboard *launchStoryboard = [UIStoryboard storyboardWithName:storyboardName bundle:bundle]; + + UIViewController *controller = [launchStoryboard instantiateInitialViewController]; + self.godotLoadingOverlay = controller.view; + self.godotLoadingOverlay.frame = self.view.bounds; + self.godotLoadingOverlay.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + [self.view addSubview:self.godotLoadingOverlay]; +} + +- (BOOL)godotViewFinishedSetup:(GodotView *)view { + [self.godotLoadingOverlay removeFromSuperview]; + self.godotLoadingOverlay = nil; + + return YES; +} + - (void)dealloc { [self.videoView stopVideo]; @@ -130,6 +159,11 @@ self.renderer = nil; + if (self.godotLoadingOverlay) { + [self.godotLoadingOverlay removeFromSuperview]; + self.godotLoadingOverlay = nil; + } + [[NSNotificationCenter defaultCenter] removeObserver:self]; } diff --git a/platform/javascript/.eslintrc.engine.js b/platform/javascript/.eslintrc.engine.js index 00f0f147a9..3725cf164e 100644 --- a/platform/javascript/.eslintrc.engine.js +++ b/platform/javascript/.eslintrc.engine.js @@ -3,6 +3,7 @@ module.exports = { "./.eslintrc.js", ], "globals": { + "EngineConfig": true, "Godot": true, "Preloader": true, "Utils": true, diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index 11a45d2811..ab527ef419 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -74,6 +74,7 @@ sys_env.Depends(build[0], sys_env["JS_EXTERNS"]) engine = [ "js/engine/preloader.js", "js/engine/utils.js", + "js/engine/config.js", "js/engine/engine.js", ] externs = [env.File("#platform/javascript/js/engine/engine.externs.js")] diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp index f7cc9e6540..478e848675 100644 --- a/platform/javascript/audio_driver_javascript.cpp +++ b/platform/javascript/audio_driver_javascript.cpp @@ -105,8 +105,8 @@ void AudioDriverJavaScript::_audio_driver_capture(int p_from, int p_samples) { } Error AudioDriverJavaScript::init() { - mix_rate = GLOBAL_GET("audio/mix_rate"); - int latency = GLOBAL_GET("audio/output_latency"); + mix_rate = GLOBAL_GET("audio/driver/mix_rate"); + int latency = GLOBAL_GET("audio/driver/output_latency"); channel_count = godot_audio_init(mix_rate, latency, &_state_change_callback, &_latency_update_callback); buffer_length = closest_power_of_2((latency * mix_rate / 1000)); diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 653d18f791..4297088c09 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -92,9 +92,9 @@ def configure(env): if not env["threads_enabled"]: print("Threads must be enabled to build the editor. Please add the 'threads_enabled=yes' option") sys.exit(255) - if env["initial_memory"] < 32: - print("Editor build requires at least 32MiB of initial memory. Forcing it.") - env["initial_memory"] = 32 + if env["initial_memory"] < 64: + print("Editor build requires at least 64MiB of initial memory. Forcing it.") + env["initial_memory"] = 64 elif env["builtin_icu"]: env.Append(CCFLAGS=["-frtti"]) else: @@ -229,7 +229,15 @@ def configure(env): env.Append(LINKFLAGS=["-s", "OFFSCREEN_FRAMEBUFFER=1"]) # callMain for manual start. - env.Append(LINKFLAGS=["-s", "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain']"]) + env.Append(LINKFLAGS=["-s", "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain','cwrap']"]) # Add code that allow exiting runtime. env.Append(LINKFLAGS=["-s", "EXIT_RUNTIME=1"]) + + # TODO remove once we have GLES support back (temporary fix undefined symbols due to dead code elimination). + env.Append( + LINKFLAGS=[ + "-s", + "EXPORTED_FUNCTIONS=['_main', '_emscripten_webgl_get_current_context', '_emscripten_webgl_commit_frame', '_emscripten_webgl_create_context']", + ] + ) diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index 915e8eeacf..a605f22e16 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -59,41 +59,20 @@ bool DisplayServerJavaScript::is_canvas_focused() { } bool DisplayServerJavaScript::check_size_force_redraw() { - int canvas_width; - int canvas_height; - emscripten_get_canvas_element_size(DisplayServerJavaScript::canvas_id, &canvas_width, &canvas_height); - if (last_width != canvas_width || last_height != canvas_height) { - last_width = canvas_width; - last_height = canvas_height; - // Update the framebuffer size for redraw. - emscripten_set_canvas_element_size(DisplayServerJavaScript::canvas_id, canvas_width, canvas_height); - return true; - } - return false; + return godot_js_display_size_update() != 0; } Point2 DisplayServerJavaScript::compute_position_in_canvas(int p_x, int p_y) { - DisplayServerJavaScript *display = get_singleton(); - int canvas_x; - int canvas_y; - godot_js_display_canvas_bounding_rect_position_get(&canvas_x, &canvas_y); - int canvas_width; - int canvas_height; - emscripten_get_canvas_element_size(display->canvas_id, &canvas_width, &canvas_height); - - double element_width; - double element_height; - emscripten_get_element_css_size(display->canvas_id, &element_width, &element_height); - - return Point2((int)(canvas_width / element_width * (p_x - canvas_x)), - (int)(canvas_height / element_height * (p_y - canvas_y))); + int point[2]; + godot_js_display_compute_position(p_x, p_y, point, point + 1); + return Point2(point[0], point[1]); } EM_BOOL DisplayServerJavaScript::fullscreen_change_callback(int p_event_type, const EmscriptenFullscreenChangeEvent *p_event, void *p_user_data) { DisplayServerJavaScript *display = get_singleton(); // Empty ID is canvas. String target_id = String::utf8(p_event->id); - if (target_id.is_empty() || target_id == String::utf8(display->canvas_id)) { + if (target_id.is_empty() || target_id == String::utf8(&(display->canvas_id[1]))) { // This event property is the only reliable data on // browser fullscreen state. if (p_event->isFullscreen) { @@ -455,7 +434,7 @@ DisplayServer::MouseMode DisplayServerJavaScript::mouse_get_mode() const { EmscriptenPointerlockChangeEvent ev; emscripten_get_pointerlock_status(&ev); - return (ev.isActive && String::utf8(ev.id) == String::utf8(canvas_id)) ? MOUSE_MODE_CAPTURED : MOUSE_MODE_VISIBLE; + return (ev.isActive && String::utf8(ev.id) == String::utf8(&canvas_id[1])) ? MOUSE_MODE_CAPTURED : MOUSE_MODE_VISIBLE; } // Wheel @@ -703,6 +682,9 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive // Ensure the canvas ID. godot_js_config_canvas_id_get(canvas_id, 256); + // Handle contextmenu, webglcontextlost + godot_js_display_setup_canvas(p_resolution.x, p_resolution.y, p_mode == WINDOW_MODE_FULLSCREEN); + // Check if it's windows. swap_cancel_ok = godot_js_display_is_swap_ok_cancel() == 1; @@ -745,11 +727,6 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive video_driver_index = p_video_driver; #endif - window_set_mode(p_mode); - if (godot_js_config_is_resize_on_start()) { - window_set_size(p_resolution); - } - EMSCRIPTEN_RESULT result; #define EM_CHECK(ev) \ if (result != EMSCRIPTEN_RESULT_SUCCESS) \ @@ -839,20 +816,23 @@ Point2i DisplayServerJavaScript::screen_get_position(int p_screen) const { } Size2i DisplayServerJavaScript::screen_get_size(int p_screen) const { - EmscriptenFullscreenChangeEvent ev; - EMSCRIPTEN_RESULT result = emscripten_get_fullscreen_status(&ev); - ERR_FAIL_COND_V(result != EMSCRIPTEN_RESULT_SUCCESS, Size2i()); - return Size2i(ev.screenWidth, ev.screenHeight); + int size[2]; + godot_js_display_screen_size_get(size, size + 1); + return Size2(size[0], size[1]); } Rect2i DisplayServerJavaScript::screen_get_usable_rect(int p_screen) const { - int canvas[2]; - emscripten_get_canvas_element_size(canvas_id, canvas, canvas + 1); - return Rect2i(0, 0, canvas[0], canvas[1]); + int size[2]; + godot_js_display_window_size_get(size, size + 1); + return Rect2i(0, 0, size[0], size[1]); } int DisplayServerJavaScript::screen_get_dpi(int p_screen) const { - return 96; // TODO maybe check pixel ratio via window.devicePixelRatio * 96? Inexact. + return godot_js_display_screen_dpi_get(); +} + +float DisplayServerJavaScript::screen_get_scale(int p_screen) const { + return godot_js_display_pixel_ratio_get(); } Vector<DisplayServer::WindowID> DisplayServerJavaScript::get_window_list() const { @@ -934,17 +914,13 @@ Size2i DisplayServerJavaScript::window_get_min_size(WindowID p_window) const { } void DisplayServerJavaScript::window_set_size(const Size2i p_size, WindowID p_window) { - last_width = p_size.x; - last_height = p_size.y; - double scale = godot_js_display_pixel_ratio_get(); - emscripten_set_canvas_element_size(canvas_id, p_size.x, p_size.y); - emscripten_set_element_css_size(canvas_id, p_size.x / scale, p_size.y / scale); + godot_js_display_desired_size_set(p_size.x, p_size.y); } Size2i DisplayServerJavaScript::window_get_size(WindowID p_window) const { - int canvas[2]; - emscripten_get_canvas_element_size(canvas_id, canvas, canvas + 1); - return Size2(canvas[0], canvas[1]); + int size[2]; + godot_js_display_window_size_get(size, size + 1); + return Size2i(size[0], size[1]); } Size2i DisplayServerJavaScript::window_get_real_size(WindowID p_window) const { @@ -958,20 +934,13 @@ void DisplayServerJavaScript::window_set_mode(WindowMode p_mode, WindowID p_wind switch (p_mode) { case WINDOW_MODE_WINDOWED: { if (window_mode == WINDOW_MODE_FULLSCREEN) { - emscripten_exit_fullscreen(); + godot_js_display_fullscreen_exit(); } window_mode = WINDOW_MODE_WINDOWED; - window_set_size(Size2i(last_width, last_height)); } break; case WINDOW_MODE_FULLSCREEN: { - EmscriptenFullscreenStrategy strategy; - strategy.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH; - strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; - strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; - strategy.canvasResizedCallback = nullptr; - EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(canvas_id, false, &strategy); - ERR_FAIL_COND_MSG(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED, "Enabling fullscreen is only possible from an input callback for the HTML5 platform."); - ERR_FAIL_COND_MSG(result != EMSCRIPTEN_RESULT_SUCCESS, "Enabling fullscreen is only possible from an input callback for the HTML5 platform."); + int result = godot_js_display_fullscreen_request(); + ERR_FAIL_COND_MSG(result, "The request was denied. Remember that enabling fullscreen is only possible from an input callback for the HTML5 platform."); } break; case WINDOW_MODE_MAXIMIZED: case WINDOW_MODE_MINIMIZED: diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h index e28fbc56f3..47e25ab2a0 100644 --- a/platform/javascript/display_server_javascript.h +++ b/platform/javascript/display_server_javascript.h @@ -57,9 +57,6 @@ private: double last_click_ms = 0; int last_click_button_index = -1; - int last_width = 0; - int last_height = 0; - bool swap_cancel_ok = false; // utilities @@ -136,6 +133,7 @@ public: Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; // windows Vector<DisplayServer::WindowID> get_window_list() const override; diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index f5d8a68994..353cc49ef8 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -285,24 +285,29 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re String str_template = String::utf8(reinterpret_cast<const char *>(p_html.ptr()), p_html.size()); String str_export; Vector<String> lines = str_template.split("\n"); - Vector<String> flags; - String flags_json; - gen_export_flags(flags, p_flags); - flags_json = JSON::print(flags); - String libs; + Array libs; for (int i = 0; i < p_shared_objects.size(); i++) { - libs += "\"" + p_shared_objects[i].path.get_file() + "\","; + libs.push_back(p_shared_objects[i].path.get_file()); } + Vector<String> flags; + gen_export_flags(flags, p_flags & (~DEBUG_FLAG_DUMB_CLIENT)); + Array args; + for (int i = 0; i < flags.size(); i++) { + args.push_back(flags[i]); + } + Dictionary config; + config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy"); + config["gdnativeLibs"] = libs; + config["executable"] = p_name; + config["args"] = args; + const String str_config = JSON::print(config); for (int i = 0; i < lines.size(); i++) { String current_line = lines[i]; - current_line = current_line.replace("$GODOT_BASENAME", p_name); + current_line = current_line.replace("$GODOT_URL", p_name + ".js"); current_line = current_line.replace("$GODOT_PROJECT_NAME", ProjectSettings::get_singleton()->get_setting("application/config/name")); current_line = current_line.replace("$GODOT_HEAD_INCLUDE", p_preset->get("html/head_include")); - current_line = current_line.replace("$GODOT_FULL_WINDOW", p_preset->get("html/full_window_size") ? "true" : "false"); - current_line = current_line.replace("$GODOT_GDNATIVE_LIBS", libs); - current_line = current_line.replace("$GODOT_DEBUG_ENABLED", p_debug ? "true" : "false"); - current_line = current_line.replace("$GODOT_ARGS", flags_json); + current_line = current_line.replace("$GODOT_CONFIG", str_config); str_export += current_line + "\n"; } @@ -319,7 +324,7 @@ void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportP } if (p_preset->get("vram_texture_compression/for_mobile")) { - String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); + String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name"); if (driver == "GLES2") { r_features->push_back("etc"); } else if (driver == "Vulkan") { @@ -345,7 +350,7 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/full_window_size"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "html/canvas_resize_policy", PROPERTY_HINT_ENUM, "None,Project,Adaptive"), 2)); } String EditorExportPlatformJavaScript::get_name() const { diff --git a/platform/javascript/godot_js.h b/platform/javascript/godot_js.h index 0006848756..5aa8677a54 100644 --- a/platform/javascript/godot_js.h +++ b/platform/javascript/godot_js.h @@ -40,7 +40,6 @@ extern "C" { // Config extern void godot_js_config_locale_get(char *p_ptr, int p_ptr_max); extern void godot_js_config_canvas_id_get(char *p_ptr, int p_ptr_max); -extern int godot_js_config_is_resize_on_start(); // OS extern void godot_js_os_finish_async(void (*p_callback)()); @@ -49,8 +48,10 @@ extern int godot_js_os_fs_is_persistent(); extern void godot_js_os_fs_sync(void (*p_callback)()); extern int godot_js_os_execute(const char *p_json); extern void godot_js_os_shell_open(const char *p_uri); +extern int godot_js_os_hw_concurrency_get(); // Display +extern int godot_js_display_screen_dpi_get(); extern double godot_js_display_pixel_ratio_get(); extern void godot_js_display_alert(const char *p_text); extern int godot_js_display_touchscreen_is_available(); @@ -59,10 +60,15 @@ extern int godot_js_display_is_swap_ok_cancel(); // Display canvas extern void godot_js_display_canvas_focus(); extern int godot_js_display_canvas_is_focused(); -extern void godot_js_display_canvas_bounding_rect_position_get(int32_t *p_x, int32_t *p_y); // Display window -extern void godot_js_display_window_request_fullscreen(); +extern void godot_js_display_desired_size_set(int p_width, int p_height); +extern int godot_js_display_size_update(); +extern void godot_js_display_window_size_get(int32_t *p_x, int32_t *p_y); +extern void godot_js_display_screen_size_get(int32_t *p_x, int32_t *p_y); +extern int godot_js_display_fullscreen_request(); +extern int godot_js_display_fullscreen_exit(); +extern void godot_js_display_compute_position(int p_x, int p_y, int32_t *r_x, int32_t *r_y); extern void godot_js_display_window_title_set(const char *p_text); extern void godot_js_display_window_icon_set(const uint8_t *p_ptr, int p_len); @@ -86,6 +92,7 @@ extern int godot_js_display_gamepad_sample_get(int p_idx, float r_btns[16], int3 extern void godot_js_display_notification_cb(void (*p_callback)(int p_notification), int p_enter, int p_exit, int p_in, int p_out); extern void godot_js_display_paste_cb(void (*p_callback)(const char *p_text)); extern void godot_js_display_drop_files_cb(void (*p_callback)(char **p_filev, int p_filec)); +extern void godot_js_display_setup_canvas(int p_width, int p_height, int p_fullscreen); #ifdef __cplusplus } #endif diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp index c8c48dd582..1136ea299d 100644 --- a/platform/javascript/http_client_javascript.cpp +++ b/platform/javascript/http_client_javascript.cpp @@ -104,7 +104,11 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector Error err = prepare_request(p_method, p_url, p_headers); if (err != OK) return err; - godot_xhr_send_data(xhr_id, p_body.ptr(), p_body.size()); + if (p_body.is_empty()) { + godot_xhr_send(xhr_id, nullptr, 0); + } else { + godot_xhr_send(xhr_id, p_body.ptr(), p_body.size()); + } return OK; } @@ -112,7 +116,12 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str Error err = prepare_request(p_method, p_url, p_headers); if (err != OK) return err; - godot_xhr_send_string(xhr_id, p_body.utf8().get_data()); + if (p_body.is_empty()) { + godot_xhr_send(xhr_id, nullptr, 0); + } else { + const CharString cs = p_body.utf8(); + godot_xhr_send(xhr_id, cs.get_data(), cs.length()); + } return OK; } diff --git a/platform/javascript/http_request.h b/platform/javascript/http_request.h index d32b2f265e..a9d6faade2 100644 --- a/platform/javascript/http_request.h +++ b/platform/javascript/http_request.h @@ -53,9 +53,7 @@ extern int godot_xhr_open(int p_xhr_id, const char *p_method, const char *p_url, extern void godot_xhr_set_request_header(int p_xhr_id, const char *p_header, const char *p_value); -extern void godot_xhr_send_null(int p_xhr_id); -extern void godot_xhr_send_string(int p_xhr_id, const char *p_data); -extern void godot_xhr_send_data(int p_xhr_id, const void *p_data, int p_len); +extern void godot_xhr_send(int p_xhr_id, const void *p_data, int p_len); extern void godot_xhr_abort(int p_xhr_id); /* this is an HTTPClient::ResponseCode, not ::Status */ diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp index 0b8af70b13..0fe95b0a8f 100644 --- a/platform/javascript/javascript_main.cpp +++ b/platform/javascript/javascript_main.cpp @@ -88,6 +88,13 @@ extern EMSCRIPTEN_KEEPALIVE int godot_js_main(int argc, char *argv[]) { Main::start(); os->get_main_loop()->initialize(); +#ifdef TOOLS_ENABLED + if (Main::is_project_manager() && FileAccess::exists("/tmp/preload.zip")) { + PackedStringArray ps; + ps.push_back("/tmp/preload.zip"); + os->get_main_loop()->emit_signal("files_dropped", ps, -1); + } +#endif emscripten_set_main_loop(main_loop_callback, -1, false); // Immediately run the first iteration. // We are inside an animation frame, we want to immediately draw on the newly setup canvas. diff --git a/platform/javascript/js/engine/config.js b/platform/javascript/js/engine/config.js new file mode 100644 index 0000000000..97fd718815 --- /dev/null +++ b/platform/javascript/js/engine/config.js @@ -0,0 +1,100 @@ +/** @constructor */ +function EngineConfig(opts) { + // Module config + this.unloadAfterInit = true; + this.onPrintError = function () { + console.error.apply(console, Array.from(arguments)); // eslint-disable-line no-console + }; + this.onPrint = function () { + console.log.apply(console, Array.from(arguments)); // eslint-disable-line no-console + }; + this.onProgress = null; + + // Godot Config + this.canvas = null; + this.executable = ''; + this.mainPack = null; + this.locale = null; + this.canvasResizePolicy = false; + this.persistentPaths = ['/userfs']; + this.gdnativeLibs = []; + this.args = []; + this.onExecute = null; + this.onExit = null; + this.update(opts); +} + +EngineConfig.prototype.update = function (opts) { + const config = opts || {}; + function parse(key, def) { + if (typeof (config[key]) === 'undefined') { + return def; + } + return config[key]; + } + // Module config + this.unloadAfterInit = parse('unloadAfterInit', this.unloadAfterInit); + this.onPrintError = parse('onPrintError', this.onPrintError); + this.onPrint = parse('onPrint', this.onPrint); + this.onProgress = parse('onProgress', this.onProgress); + + // Godot config + this.canvas = parse('canvas', this.canvas); + this.executable = parse('executable', this.executable); + this.mainPack = parse('mainPack', this.mainPack); + this.locale = parse('locale', this.locale); + this.canvasResizePolicy = parse('canvasResizePolicy', this.canvasResizePolicy); + this.persistentPaths = parse('persistentPaths', this.persistentPaths); + this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs); + this.args = parse('args', this.args); + this.onExecute = parse('onExecute', this.onExecute); + this.onExit = parse('onExit', this.onExit); +}; + +EngineConfig.prototype.getModuleConfig = function (loadPath, loadPromise) { + const me = this; + return { + 'print': this.onPrint, + 'printErr': this.onPrintError, + 'locateFile': Utils.createLocateRewrite(loadPath), + 'instantiateWasm': Utils.createInstantiatePromise(loadPromise), + 'thisProgram': me.executable, + 'noExitRuntime': true, + 'dynamicLibraries': [`${me.executable}.side.wasm`], + }; +}; + +EngineConfig.prototype.getGodotConfig = function (cleanup) { + if (!(this.canvas instanceof HTMLCanvasElement)) { + this.canvas = Utils.findCanvas(); + if (!this.canvas) { + throw new Error('No canvas found in page'); + } + } + + // Canvas can grab focus on click, or key events won't work. + if (this.canvas.tabIndex < 0) { + this.canvas.tabIndex = 0; + } + + // Browser locale, or custom one if defined. + let locale = this.locale; + if (!locale) { + locale = navigator.languages ? navigator.languages[0] : navigator.language; + locale = locale.split('.')[0]; + } + const onExit = this.onExit; + // Godot configuration. + return { + 'canvas': this.canvas, + 'canvasResizePolicy': this.canvasResizePolicy, + 'locale': locale, + 'onExecute': this.onExecute, + 'onExit': function (p_code) { + cleanup(); // We always need to call the cleanup callback to free memory. + if (typeof (onExit) === 'function') { + onExit(p_code); + } + }, + }; +}; diff --git a/platform/javascript/js/engine/engine.js b/platform/javascript/js/engine/engine.js index 01232cbece..d14e0e5806 100644 --- a/platform/javascript/js/engine/engine.js +++ b/platform/javascript/js/engine/engine.js @@ -1,20 +1,14 @@ const Engine = (function () { const preloader = new Preloader(); - let wasmExt = '.wasm'; - let unloadAfterInit = true; - let loadPath = ''; let loadPromise = null; + let loadPath = ''; let initPromise = null; - let stderr = null; - let stdout = null; - let progressFunc = null; function load(basePath) { if (loadPromise == null) { loadPath = basePath; - loadPromise = preloader.loadPromise(basePath + wasmExt); - preloader.setProgressFunc(progressFunc); + loadPromise = preloader.loadPromise(`${loadPath}.wasm`); requestAnimationFrame(preloader.animateProgress); } return loadPromise; @@ -25,16 +19,9 @@ const Engine = (function () { } /** @constructor */ - function Engine() { // eslint-disable-line no-shadow - this.canvas = null; - this.executableName = ''; + function Engine(opts) { // eslint-disable-line no-shadow + this.config = new EngineConfig(opts); this.rtenv = null; - this.customLocale = null; - this.resizeCanvasOnStart = false; - this.onExecute = null; - this.onExit = null; - this.persistentPaths = ['/userfs']; - this.gdnativeLibs = []; } Engine.prototype.init = /** @param {string=} basePath */ function (basePath) { @@ -48,25 +35,14 @@ const Engine = (function () { } load(basePath); } - let config = {}; - if (typeof stdout === 'function') { - config.print = stdout; - } - if (typeof stderr === 'function') { - config.printErr = stderr; - } + preloader.setProgressFunc(this.config.onProgress); + let config = this.config.getModuleConfig(loadPath, loadPromise); const me = this; initPromise = new Promise(function (resolve, reject) { - config['locateFile'] = Utils.createLocateRewrite(loadPath); - config['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise); - // Emscripten configuration. - config['thisProgram'] = me.executableName; - config['noExitRuntime'] = true; - config['dynamicLibraries'] = [`${me.executableName}.side.wasm`].concat(me.gdnativeLibs); Godot(config).then(function (module) { - module['initFS'](me.persistentPaths).then(function (fs_err) { + module['initFS'](me.config.persistentPaths).then(function (fs_err) { me.rtenv = module; - if (unloadAfterInit) { + if (me.config.unloadAfterInit) { unload(); } resolve(); @@ -83,163 +59,60 @@ const Engine = (function () { }; /** @type {function(...string):Object} */ - Engine.prototype.start = function () { - // Start from arguments. - const args = []; - for (let i = 0; i < arguments.length; i++) { - args.push(arguments[i]); - } + Engine.prototype.start = function (override) { + this.config.update(override); const me = this; return me.init().then(function () { if (!me.rtenv) { return Promise.reject(new Error('The engine must be initialized before it can be started')); } - if (!(me.canvas instanceof HTMLCanvasElement)) { - me.canvas = Utils.findCanvas(); - if (!me.canvas) { - return Promise.reject(new Error('No canvas found in page')); - } - } - - // Canvas can grab focus on click, or key events won't work. - if (me.canvas.tabIndex < 0) { - me.canvas.tabIndex = 0; - } - - // Disable right-click context menu. - me.canvas.addEventListener('contextmenu', function (ev) { - ev.preventDefault(); - }, false); - - // Until context restoration is implemented warn the user of context loss. - me.canvas.addEventListener('webglcontextlost', function (ev) { - alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert - ev.preventDefault(); - }, false); - - // Browser locale, or custom one if defined. - let locale = me.customLocale; - if (!locale) { - locale = navigator.languages ? navigator.languages[0] : navigator.language; - locale = locale.split('.')[0]; + let config = {}; + try { + config = me.config.getGodotConfig(function () { + me.rtenv = null; + }); + } catch (e) { + return Promise.reject(e); } // Godot configuration. - me.rtenv['initConfig']({ - 'resizeCanvasOnStart': me.resizeCanvasOnStart, - 'canvas': me.canvas, - 'locale': locale, - 'onExecute': function (p_args) { - if (me.onExecute) { - me.onExecute(p_args); - return 0; - } - return 1; - }, - 'onExit': function (p_code) { - me.rtenv['deinitFS'](); - if (me.onExit) { - me.onExit(p_code); - } - me.rtenv = null; - }, - }); + me.rtenv['initConfig'](config); - return new Promise(function (resolve, reject) { - preloader.preloadedFiles.forEach(function (file) { - me.rtenv['copyToFS'](file.path, file.buffer); + // Preload GDNative libraries. + const libs = []; + me.config.gdnativeLibs.forEach(function (lib) { + libs.push(me.rtenv['loadDynamicLibrary'](lib, { 'loadAsync': true })); + }); + return Promise.all(libs).then(function () { + return new Promise(function (resolve, reject) { + preloader.preloadedFiles.forEach(function (file) { + me.rtenv['copyToFS'](file.path, file.buffer); + }); + preloader.preloadedFiles.length = 0; // Clear memory + me.rtenv['callMain'](me.config.args); + initPromise = null; + resolve(); }); - preloader.preloadedFiles.length = 0; // Clear memory - me.rtenv['callMain'](args); - initPromise = null; - resolve(); }); }); }; - Engine.prototype.startGame = function (execName, mainPack, extraArgs) { + Engine.prototype.startGame = function (override) { + this.config.update(override); + // Add main-pack argument. + const exe = this.config.executable; + const pack = this.config.mainPack || `${exe}.pck`; + this.config.args = ['--main-pack', pack].concat(this.config.args); // Start and init with execName as loadPath if not inited. - this.executableName = execName; const me = this; return Promise.all([ - this.init(execName), - this.preloadFile(mainPack, mainPack), + this.init(exe), + this.preloadFile(pack, pack), ]).then(function () { - let args = ['--main-pack', mainPack]; - if (extraArgs) { - args = args.concat(extraArgs); - } - return me.start.apply(me, args); + return me.start.apply(me); }); }; - Engine.prototype.setWebAssemblyFilenameExtension = function (override) { - if (String(override).length === 0) { - throw new Error('Invalid WebAssembly filename extension override'); - } - wasmExt = String(override); - }; - - Engine.prototype.setUnloadAfterInit = function (enabled) { - unloadAfterInit = enabled; - }; - - Engine.prototype.setCanvas = function (canvasElem) { - this.canvas = canvasElem; - }; - - Engine.prototype.setCanvasResizedOnStart = function (enabled) { - this.resizeCanvasOnStart = enabled; - }; - - Engine.prototype.setLocale = function (locale) { - this.customLocale = locale; - }; - - Engine.prototype.setExecutableName = function (newName) { - this.executableName = newName; - }; - - Engine.prototype.setProgressFunc = function (func) { - progressFunc = func; - }; - - Engine.prototype.setStdoutFunc = function (func) { - const print = function (text) { - let msg = text; - if (arguments.length > 1) { - msg = Array.prototype.slice.call(arguments).join(' '); - } - func(msg); - }; - if (this.rtenv) { - this.rtenv.print = print; - } - stdout = print; - }; - - Engine.prototype.setStderrFunc = function (func) { - const printErr = function (text) { - let msg = text; - if (arguments.length > 1) { - msg = Array.prototype.slice.call(arguments).join(' '); - } - func(msg); - }; - if (this.rtenv) { - this.rtenv.printErr = printErr; - } - stderr = printErr; - }; - - Engine.prototype.setOnExecute = function (onExecute) { - this.onExecute = onExecute; - }; - - Engine.prototype.setOnExit = function (onExit) { - this.onExit = onExit; - }; - Engine.prototype.copyToFS = function (path, buffer) { if (this.rtenv == null) { throw new Error('Engine must be inited before copying files'); @@ -247,14 +120,6 @@ const Engine = (function () { this.rtenv['copyToFS'](path, buffer); }; - Engine.prototype.setPersistentPaths = function (persistentPaths) { - this.persistentPaths = persistentPaths; - }; - - Engine.prototype.setGDNativeLibraries = function (gdnativeLibs) { - this.gdnativeLibs = gdnativeLibs; - }; - Engine.prototype.requestQuit = function () { if (this.rtenv) { this.rtenv['request_quit'](); @@ -270,20 +135,7 @@ const Engine = (function () { Engine.prototype['preloadFile'] = Engine.prototype.preloadFile; Engine.prototype['start'] = Engine.prototype.start; Engine.prototype['startGame'] = Engine.prototype.startGame; - Engine.prototype['setWebAssemblyFilenameExtension'] = Engine.prototype.setWebAssemblyFilenameExtension; - Engine.prototype['setUnloadAfterInit'] = Engine.prototype.setUnloadAfterInit; - Engine.prototype['setCanvas'] = Engine.prototype.setCanvas; - Engine.prototype['setCanvasResizedOnStart'] = Engine.prototype.setCanvasResizedOnStart; - Engine.prototype['setLocale'] = Engine.prototype.setLocale; - Engine.prototype['setExecutableName'] = Engine.prototype.setExecutableName; - Engine.prototype['setProgressFunc'] = Engine.prototype.setProgressFunc; - Engine.prototype['setStdoutFunc'] = Engine.prototype.setStdoutFunc; - Engine.prototype['setStderrFunc'] = Engine.prototype.setStderrFunc; - Engine.prototype['setOnExecute'] = Engine.prototype.setOnExecute; - Engine.prototype['setOnExit'] = Engine.prototype.setOnExit; Engine.prototype['copyToFS'] = Engine.prototype.copyToFS; - Engine.prototype['setPersistentPaths'] = Engine.prototype.setPersistentPaths; - Engine.prototype['setGDNativeLibraries'] = Engine.prototype.setGDNativeLibraries; Engine.prototype['requestQuit'] = Engine.prototype.requestQuit; return Engine; }()); diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js index 2977b7c122..fdb5cc0ec2 100644 --- a/platform/javascript/js/libs/library_godot_display.js +++ b/platform/javascript/js/libs/library_godot_display.js @@ -396,15 +396,141 @@ const GodotDisplayGamepads = { }; mergeInto(LibraryManager.library, GodotDisplayGamepads); +const GodotDisplayScreen = { + $GodotDisplayScreen__deps: ['$GodotConfig', '$GodotOS', '$GL', 'emscripten_webgl_get_current_context'], + $GodotDisplayScreen: { + desired_size: [0, 0], + isFullscreen: function () { + const elem = document.fullscreenElement || document.mozFullscreenElement + || document.webkitFullscreenElement || document.msFullscreenElement; + if (elem) { + return elem === GodotConfig.canvas; + } + // But maybe knowing the element is not supported. + return document.fullscreen || document.mozFullScreen + || document.webkitIsFullscreen; + }, + hasFullscreen: function () { + return document.fullscreenEnabled || document.mozFullScreenEnabled + || document.webkitFullscreenEnabled; + }, + requestFullscreen: function () { + if (!GodotDisplayScreen.hasFullscreen()) { + return 1; + } + const canvas = GodotConfig.canvas; + try { + const promise = (canvas.requestFullscreen || canvas.msRequestFullscreen + || canvas.mozRequestFullScreen || canvas.mozRequestFullscreen + || canvas.webkitRequestFullscreen + ).call(canvas); + // Some browsers (Safari) return undefined. + // For the standard ones, we need to catch it. + if (promise) { + promise.catch(function () { + // nothing to do. + }); + } + } catch (e) { + return 1; + } + return 0; + }, + exitFullscreen: function () { + if (!GodotDisplayScreen.isFullscreen()) { + return 0; + } + try { + const promise = document.exitFullscreen(); + if (promise) { + promise.catch(function () { + // nothing to do. + }); + } + } catch (e) { + return 1; + } + return 0; + }, + _updateGL: function () { + const gl_context_handle = _emscripten_webgl_get_current_context(); // eslint-disable-line no-undef + const gl = GL.getContext(gl_context_handle); + if (gl) { + GL.resizeOffscreenFramebuffer(gl); + } + }, + updateSize: function () { + const isFullscreen = GodotDisplayScreen.isFullscreen(); + const wantsFullWindow = GodotConfig.canvas_resize_policy === 2; + const noResize = GodotConfig.canvas_resize_policy === 0; + const wwidth = GodotDisplayScreen.desired_size[0]; + const wheight = GodotDisplayScreen.desired_size[1]; + const canvas = GodotConfig.canvas; + let width = wwidth; + let height = wheight; + if (noResize) { + // Don't resize canvas, just update GL if needed. + if (canvas.width !== width || canvas.height !== height) { + GodotDisplayScreen.desired_size = [canvas.width, canvas.height]; + GodotDisplayScreen._updateGL(); + return 1; + } + return 0; + } + const scale = window.devicePixelRatio || 1; + if (isFullscreen || wantsFullWindow) { + // We need to match screen size. + width = window.innerWidth * scale; + height = window.innerHeight * scale; + } + const csw = `${width / scale}px`; + const csh = `${height / scale}px`; + if (canvas.style.width !== csw || canvas.style.height !== csh || canvas.width !== width || canvas.height !== height) { + // Size doesn't match. + // Resize canvas, set correct CSS pixel size, update GL. + canvas.width = width; + canvas.height = height; + canvas.style.width = csw; + canvas.style.height = csh; + GodotDisplayScreen._updateGL(); + return 1; + } + return 0; + }, + }, +}; +mergeInto(LibraryManager.library, GodotDisplayScreen); + /** * Display server interface. * * Exposes all the functions needed by DisplayServer implementation. */ const GodotDisplay = { - $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop', '$GodotDisplayGamepads'], + $GodotDisplay__deps: ['$GodotConfig', '$GodotRuntime', '$GodotDisplayCursor', '$GodotDisplayListeners', '$GodotDisplayDragDrop', '$GodotDisplayGamepads', '$GodotDisplayScreen'], $GodotDisplay: { window_icon: '', + findDPI: function () { + function testDPI(dpi) { + return window.matchMedia(`(max-resolution: ${dpi}dpi)`).matches; + } + function bisect(low, high, func) { + const mid = parseInt(((high - low) / 2) + low, 10); + if (high - low <= 1) { + return func(high) ? high : low; + } + if (func(mid)) { + return bisect(low, mid, func); + } + return bisect(mid, high, func); + } + try { + const dpi = bisect(0, 800, testDPI); + return dpi >= 96 ? dpi : 96; + } catch (e) { + return 96; + } + }, }, godot_js_display_is_swap_ok_cancel__sig: 'i', @@ -422,11 +548,58 @@ const GodotDisplay = { window.alert(GodotRuntime.parseString(p_text)); // eslint-disable-line no-alert }, + godot_js_display_screen_dpi_get__sig: 'i', + godot_js_display_screen_dpi_get: function () { + return GodotDisplay.findDPI(); + }, + godot_js_display_pixel_ratio_get__sig: 'f', godot_js_display_pixel_ratio_get: function () { return window.devicePixelRatio || 1; }, + godot_js_display_fullscreen_request__sig: 'i', + godot_js_display_fullscreen_request: function () { + return GodotDisplayScreen.requestFullscreen(); + }, + + godot_js_display_fullscreen_exit__sig: 'i', + godot_js_display_fullscreen_exit: function () { + return GodotDisplayScreen.exitFullscreen(); + }, + + godot_js_display_desired_size_set__sig: 'v', + godot_js_display_desired_size_set: function (width, height) { + GodotDisplayScreen.desired_size = [width, height]; + GodotDisplayScreen.updateSize(); + }, + + godot_js_display_size_update__sig: 'i', + godot_js_display_size_update: function () { + return GodotDisplayScreen.updateSize(); + }, + + godot_js_display_screen_size_get__sig: 'vii', + godot_js_display_screen_size_get: function (width, height) { + const scale = window.devicePixelRatio || 1; + GodotRuntime.setHeapValue(width, window.screen.width * scale, 'i32'); + GodotRuntime.setHeapValue(height, window.screen.height * scale, 'i32'); + }, + + godot_js_display_window_size_get: function (p_width, p_height) { + GodotRuntime.setHeapValue(p_width, GodotConfig.canvas.width, 'i32'); + GodotRuntime.setHeapValue(p_height, GodotConfig.canvas.height, 'i32'); + }, + + godot_js_display_compute_position: function (x, y, r_x, r_y) { + const canvas = GodotConfig.canvas; + const rect = canvas.getBoundingClientRect(); + const rw = canvas.width / rect.width; + const rh = canvas.height / rect.height; + GodotRuntime.setHeapValue(r_x, (x - rect.x) * rw, 'i32'); + GodotRuntime.setHeapValue(r_y, (y - rect.y) * rh, 'i32'); + }, + /* * Canvas */ @@ -440,13 +613,6 @@ const GodotDisplay = { return document.activeElement === GodotConfig.canvas; }, - godot_js_display_canvas_bounding_rect_position_get__sig: 'vii', - godot_js_display_canvas_bounding_rect_position_get: function (r_x, r_y) { - const brect = GodotConfig.canvas.getBoundingClientRect(); - GodotRuntime.setHeapValue(r_x, brect.x, 'i32'); - GodotRuntime.setHeapValue(r_y, brect.y, 'i32'); - }, - /* * Touchscreen */ @@ -490,15 +656,6 @@ const GodotDisplay = { /* * Window */ - godot_js_display_window_request_fullscreen__sig: 'v', - godot_js_display_window_request_fullscreen: function () { - const canvas = GodotConfig.canvas; - (canvas.requestFullscreen || canvas.msRequestFullscreen - || canvas.mozRequestFullScreen || canvas.mozRequestFullscreen - || canvas.webkitRequestFullscreen - ).call(canvas); - }, - godot_js_display_window_title_set__sig: 'vi', godot_js_display_window_title_set: function (p_data) { document.title = GodotRuntime.parseString(p_data); @@ -619,6 +776,35 @@ const GodotDisplay = { GodotDisplayListeners.add(canvas, 'drop', GodotDisplayDragDrop.handler(dropFiles)); }, + godot_js_display_setup_canvas__sig: 'viii', + godot_js_display_setup_canvas: function (p_width, p_height, p_fullscreen) { + const canvas = GodotConfig.canvas; + GodotDisplayListeners.add(canvas, 'contextmenu', function (ev) { + ev.preventDefault(); + }, false); + GodotDisplayListeners.add(canvas, 'webglcontextlost', function (ev) { + alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert + ev.preventDefault(); + }, false); + switch (GodotConfig.canvas_resize_policy) { + case 0: // None + GodotDisplayScreen.desired_size = [canvas.width, canvas.height]; + break; + case 1: // Project + GodotDisplayScreen.desired_size = [p_width, p_height]; + break; + default: // Full window + // Ensure we display in the right place, the size will be handled by updateSize + canvas.style.position = 'absolute'; + canvas.style.top = 0; + canvas.style.left = 0; + break; + } + if (p_fullscreen) { + GodotDisplayScreen.requestFullscreen(); + } + }, + /* * Gamepads */ diff --git a/platform/javascript/js/libs/library_godot_http_request.js b/platform/javascript/js/libs/library_godot_http_request.js index 930d3209f8..7dc2a2df29 100644 --- a/platform/javascript/js/libs/library_godot_http_request.js +++ b/platform/javascript/js/libs/library_godot_http_request.js @@ -82,31 +82,13 @@ const GodotHTTPRequest = { GodotHTTPRequest.requests[xhrId].setRequestHeader(GodotRuntime.parseString(header), GodotRuntime.parseString(value)); }, - godot_xhr_send_null__sig: 'vi', - godot_xhr_send_null: function (xhrId) { - GodotHTTPRequest.requests[xhrId].send(); - }, - - godot_xhr_send_string__sig: 'vii', - godot_xhr_send_string: function (xhrId, strPtr) { - if (!strPtr) { - GodotRuntime.error('Failed to send string per XHR: null pointer'); - return; - } - GodotHTTPRequest.requests[xhrId].send(GodotRuntime.parseString(strPtr)); - }, - - godot_xhr_send_data__sig: 'viii', - godot_xhr_send_data: function (xhrId, ptr, len) { - if (!ptr) { - GodotRuntime.error('Failed to send data per XHR: null pointer'); - return; - } - if (len < 0) { - GodotRuntime.error('Failed to send data per XHR: buffer length less than 0'); - return; + godot_xhr_send__sig: 'viii', + godot_xhr_send: function (xhrId, p_ptr, p_len) { + let data = null; + if (p_ptr && p_len) { + data = GodotRuntime.heapCopy(HEAP8, p_ptr, p_len); } - GodotHTTPRequest.requests[xhrId].send(HEAPU8.subarray(ptr, ptr + len)); + GodotHTTPRequest.requests[xhrId].send(data); }, godot_xhr_abort__sig: 'vi', diff --git a/platform/javascript/js/libs/library_godot_os.js b/platform/javascript/js/libs/library_godot_os.js index 9fde4a84e1..0f189b013c 100644 --- a/platform/javascript/js/libs/library_godot_os.js +++ b/platform/javascript/js/libs/library_godot_os.js @@ -58,21 +58,28 @@ const GodotConfig = { $GodotConfig: { canvas: null, locale: 'en', - resize_on_start: false, + canvas_resize_policy: 2, // Adaptive on_execute: null, + on_exit: null, init_config: function (p_opts) { - GodotConfig.resize_on_start = !!p_opts['resizeCanvasOnStart']; + GodotConfig.canvas_resize_policy = p_opts['canvasResizePolicy']; GodotConfig.canvas = p_opts['canvas']; GodotConfig.locale = p_opts['locale'] || GodotConfig.locale; GodotConfig.on_execute = p_opts['onExecute']; - // This is called by emscripten, even if undocumented. - Module['onExit'] = p_opts['onExit']; // eslint-disable-line no-undef + GodotConfig.on_exit = p_opts['onExit']; }, locate_file: function (file) { return Module['locateFile'](file); // eslint-disable-line no-undef }, + clear: function () { + GodotConfig.canvas = null; + GodotConfig.locale = 'en'; + GodotConfig.canvas_resize_policy = 2; + GodotConfig.on_execute = null; + GodotConfig.on_exit = null; + }, }, godot_js_config_canvas_id_get__sig: 'vii', @@ -84,11 +91,6 @@ const GodotConfig = { godot_js_config_locale_get: function (p_ptr, p_ptr_max) { GodotRuntime.stringToHeap(GodotConfig.locale, p_ptr, p_ptr_max); }, - - godot_js_config_is_resize_on_start__sig: 'i', - godot_js_config_is_resize_on_start: function () { - return GodotConfig.resize_on_start ? 1 : 0; - }, }; autoAddDeps(GodotConfig, '$GodotConfig'); @@ -98,7 +100,6 @@ const GodotFS = { $GodotFS__deps: ['$FS', '$IDBFS', '$GodotRuntime'], $GodotFS__postset: [ 'Module["initFS"] = GodotFS.init;', - 'Module["deinitFS"] = GodotFS.deinit;', 'Module["copyToFS"] = GodotFS.copy_to_fs;', ].join(''), $GodotFS: { @@ -210,9 +211,10 @@ const GodotFS = { mergeInto(LibraryManager.library, GodotFS); const GodotOS = { - $GodotOS__deps: ['$GodotFS', '$GodotRuntime'], + $GodotOS__deps: ['$GodotRuntime', '$GodotConfig', '$GodotFS'], $GodotOS__postset: [ 'Module["request_quit"] = function() { GodotOS.request_quit() };', + 'Module["onExit"] = GodotOS.cleanup;', 'GodotOS._fs_sync_promise = Promise.resolve();', ].join(''), $GodotOS: { @@ -224,6 +226,15 @@ const GodotOS = { GodotOS._async_cbs.push(p_promise_cb); }, + cleanup: function (exit_code) { + const cb = GodotConfig.on_exit; + GodotFS.deinit(); + GodotConfig.clear(); + if (cb) { + cb(exit_code); + } + }, + finish_async: function (callback) { GodotOS._fs_sync_promise.then(function (err) { const promises = []; @@ -282,6 +293,11 @@ const GodotOS = { godot_js_os_shell_open: function (p_uri) { window.open(GodotRuntime.parseString(p_uri), '_blank'); }, + + godot_js_os_hw_concurrency_get__sig: 'i', + godot_js_os_hw_concurrency_get: function () { + return navigator.hardwareConcurrency || 1; + }, }; autoAddDeps(GodotOS, '$GodotOS'); diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index b922b2ba91..0b1650076c 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -129,6 +129,10 @@ int OS_JavaScript::get_process_id() const { ERR_FAIL_V_MSG(0, "OS::get_process_id() is not available on the HTML5 platform."); } +int OS_JavaScript::get_processor_count() const { + return godot_js_os_hw_concurrency_get(); +} + bool OS_JavaScript::_check_internal_feature_support(const String &p_feature) { if (p_feature == "HTML5" || p_feature == "web") { return true; diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 8db62d9d1c..81bb9c5f3d 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -74,6 +74,7 @@ public: Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override; Error kill(const ProcessID &p_pid) override; int get_process_id() const override; + int get_processor_count() const override; String get_executable_path() const override; Error shell_open(String p_uri) override; diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub index 6e43ffcedb..46714e9502 100644 --- a/platform/linuxbsd/SCsub +++ b/platform/linuxbsd/SCsub @@ -16,7 +16,10 @@ common_x11 = [ "key_mapping_x11.cpp", ] +if "udev" in env and env["udev"]: + common_x11.append("libudev-so_wrap.c") + prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_x11) -if env["debug_symbols"] == "yes" and env["separate_debug_symbols"]: +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/detect.py b/platform/linuxbsd/detect.py index a819731328..ff521e4e7f 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -64,15 +64,15 @@ 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("pulseaudio", "Detect and use PulseAudio", True), - BoolVariable("udev", "Use udev for gamepad connection callbacks", False), - EnumVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", "yes", ("yes", "no")), + BoolVariable("udev", "Use udev for gamepad connection callbacks", 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), @@ -92,7 +92,7 @@ def configure(env): else: # optimize for size env.Prepend(CCFLAGS=["-Os"]) - if env["debug_symbols"] == "yes": + if env["debug_symbols"]: env.Prepend(CCFLAGS=["-g2"]) elif env["target"] == "release_debug": @@ -102,7 +102,7 @@ def configure(env): env.Prepend(CCFLAGS=["-Os"]) env.Prepend(CPPDEFINES=["DEBUG_ENABLED"]) - if env["debug_symbols"] == "yes": + if env["debug_symbols"]: env.Prepend(CCFLAGS=["-g2"]) elif env["target"] == "debug": @@ -127,6 +127,7 @@ def configure(env): env["CC"] = "clang" env["CXX"] = "clang++" env.extra_suffix = ".llvm" + env.extra_suffix + env.Append(LIBS=["atomic"]) if env["use_lld"]: if env["use_llvm"]: @@ -310,9 +311,8 @@ def configure(env): 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") @@ -320,20 +320,20 @@ def configure(env): 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("PulseAudio development libraries not found, disabling driver") 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") + else: + env["udev"] = False # Linux specific # Linkflags below this line should typically stay the last ones if not env["builtin_zlib"]: @@ -390,4 +390,7 @@ def configure(env): # Link those statically for portability if env["use_static_cpp"]: - env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"]) + # Workaround for GH-31743, Ubuntu 18.04 i386 crashes when it's used. + # That doesn't make any sense but it's likely a Ubuntu bug? + if is64 or env["bits"] == "64": + env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"]) diff --git a/platform/linuxbsd/detect_prime_x11.cpp b/platform/linuxbsd/detect_prime_x11.cpp index 0f8d108dff..da1c95a593 100644 --- a/platform/linuxbsd/detect_prime_x11.cpp +++ b/platform/linuxbsd/detect_prime_x11.cpp @@ -61,6 +61,7 @@ struct vendor { 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/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 53baf17858..fceeb82325 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -2697,7 +2697,7 @@ bool DisplayServerX11::_wait_for_events() const { } void DisplayServerX11::_poll_events() { - while (!events_thread_done) { + while (!events_thread_done.is_set()) { _wait_for_events(); // Process events from the queue. @@ -4279,7 +4279,7 @@ DisplayServerX11::~DisplayServerX11() { _clipboard_transfer_ownership(XA_PRIMARY, x11_main_window); _clipboard_transfer_ownership(XInternAtom(x11_display, "CLIPBOARD", 0), x11_main_window); - events_thread_done = true; + events_thread_done.set(); events_thread.wait_to_finish(); //destroy all windows diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 906710f933..10686d8424 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -253,7 +253,7 @@ class DisplayServerX11 : public DisplayServer { mutable Mutex events_mutex; Thread events_thread; - bool events_thread_done = false; + SafeFlag events_thread_done; LocalVector<XEvent> polled_events; static void _poll_events_thread(void *ud); bool _wait_for_events() const; diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index 4e96e6d687..471259e50f 100644 --- a/platform/linuxbsd/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -39,7 +39,7 @@ #include <unistd.h> #ifdef UDEV_ENABLED -#include <libudev.h> +#include "libudev-so_wrap.h" #endif #define LONG_BITS (sizeof(long) * 8) @@ -72,13 +72,27 @@ 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.start(joy_thread_func, this); } JoypadLinux::~JoypadLinux() { - exit_udev = true; + exit_monitor.set(); joy_thread.wait_to_finish(); close_joypad(); } @@ -92,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 @@ -137,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; @@ -179,7 +202,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) { #endif void JoypadLinux::monitor_joypads() { - while (!exit_udev) { + while (!exit_monitor.is_set()) { { MutexLock lock(joy_mutex); diff --git a/platform/linuxbsd/joypad_linux.h b/platform/linuxbsd/joypad_linux.h index bf343b7ceb..b0d0db047b 100644 --- a/platform/linuxbsd/joypad_linux.h +++ b/platform/linuxbsd/joypad_linux.h @@ -70,10 +70,13 @@ private: void reset(); }; - bool exit_udev; +#ifdef UDEV_ENABLED + bool use_udev = false; +#endif + SafeFlag exit_monitor; Mutex joy_mutex; Thread joy_thread; - Input *input; + Input *input = nullptr; Joypad joypads[JOYPADS_MAX]; Vector<String> attached_devices; 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/osx/SCsub b/platform/osx/SCsub index aa95a89444..46c13d8550 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -18,5 +18,5 @@ files = [ prog = env.add_program("#bin/godot", files) -if env["debug_symbols"] == "yes" and env["separate_debug_symbols"]: +if env["debug_symbols"] and env["separate_debug_symbols"]: env.AddPostAction(prog, run_in_subprocess(platform_osx_builders.make_debug_osx)) diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 466f68d269..acea00c5ac 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -31,7 +31,7 @@ def get_opts(): False, ), EnumVariable("macports_clang", "Build using Clang from MacPorts", "no", ("no", "5.0", "devel")), - EnumVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", "yes", ("yes", "no")), + 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("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False), BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN))", False), @@ -54,7 +54,7 @@ def configure(env): if env["arch"] != "arm64": env.Prepend(CCFLAGS=["-msse2"]) - if env["debug_symbols"] == "yes": + if env["debug_symbols"]: env.Prepend(CCFLAGS=["-g2"]) elif env["target"] == "release_debug": @@ -63,7 +63,7 @@ def configure(env): else: # optimize for size env.Prepend(CCFLAGS=["-Os"]) env.Prepend(CPPDEFINES=["DEBUG_ENABLED"]) - if env["debug_symbols"] == "yes": + if env["debug_symbols"]: env.Prepend(CCFLAGS=["-g2"]) elif env["target"] == "debug": diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index 597ebce6ff..9fac99810b 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -93,6 +93,7 @@ public: List<WarpEvent> warp_events; NSTimeInterval last_warp = 0; + bool ignore_warp = false; Vector<KeyEvent> key_event_buffer; int key_event_pos; diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 2d43454501..ed7d89009f 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -871,6 +871,15 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i NSPoint delta = NSMakePoint([event deltaX], [event deltaY]); NSPoint mpos = [event locationInWindow]; + if (DS_OSX->ignore_warp) { + // Discard late events, before warp + if (([event timestamp]) < DS_OSX->last_warp) { + return; + } + DS_OSX->ignore_warp = false; + return; + } + if (DS_OSX->mouse_mode == DisplayServer::MOUSE_MODE_CONFINED) { // Discard late events if (([event timestamp]) < DS_OSX->last_warp) { @@ -2098,6 +2107,8 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { CGAssociateMouseAndMouseCursorPosition(true); } + last_warp = [[NSProcessInfo processInfo] systemUptime]; + ignore_warp = true; warp_events.clear(); mouse_mode = p_mode; } diff --git a/platform/server/detect.py b/platform/server/detect.py index db503584d3..1c3fa990fe 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -32,13 +32,13 @@ def get_opts(): return [ BoolVariable("use_llvm", "Use the LLVM compiler", 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), - EnumVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", "yes", ("yes", "no")), + 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("execinfo", "Use libexecinfo on systems where glibc is not available", False), ] @@ -58,7 +58,7 @@ def configure(env): else: # optimize for size env.Prepend(CCFLAGS=["-Os"]) - if env["debug_symbols"] == "yes": + if env["debug_symbols"]: env.Prepend(CCFLAGS=["-g2"]) elif env["target"] == "release_debug": @@ -68,7 +68,7 @@ def configure(env): env.Prepend(CCFLAGS=["-Os"]) env.Prepend(CPPDEFINES=["DEBUG_ENABLED"]) - if env["debug_symbols"] == "yes": + if env["debug_symbols"]: env.Prepend(CCFLAGS=["-g2"]) elif env["target"] == "debug": diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 8b60e55d2d..fa97948395 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -44,7 +44,6 @@ #include "platform/windows/windows_terminal_logger.h" #include "servers/audio_server.h" #include "servers/rendering/rendering_server_default.h" -#include "servers/rendering/rendering_server_wrap_mt.h" #include <ppltasks.h> #include <wrl.h> diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 0c9aa77803..47d8e14680 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -32,5 +32,5 @@ if env["vsproj"]: env.vs_srcs += ["platform/windows/" + str(x)] if not os.getenv("VCINSTALLDIR"): - if env["debug_symbols"] == "yes" and env["separate_debug_symbols"]: + if env["debug_symbols"] and env["separate_debug_symbols"]: env.AddPostAction(prog, run_in_subprocess(platform_windows_builders.make_debug_mingw)) diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 5216fca2ca..f26dea8d35 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -64,7 +64,7 @@ def get_opts(): # XP support dropped after EOL due to missing API for IPv6 and other issues # Vista support dropped after EOL due to GH-10243 ("target_win_version", "Targeted Windows version, >= 0x0601 (Windows 7)", "0x0601"), - EnumVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", "yes", ("yes", "no")), + BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True), EnumVariable("windows_subsystem", "Windows subsystem", "default", ("default", "console", "gui")), BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False), ("msvc_version", "MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.", None), @@ -204,12 +204,12 @@ def configure_msvc(env, manual_msvc_config): env.Append(LINKFLAGS=["/OPT:REF"]) elif env["target"] == "debug": - env.AppendUnique(CCFLAGS=["/Z7", "/Od", "/EHsc"]) + env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"]) env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED"]) env.Append(LINKFLAGS=["/DEBUG"]) - if env["debug_symbols"] == "yes": - env.AppendUnique(CCFLAGS=["/Z7"]) + if env["debug_symbols"]: + env.AppendUnique(CCFLAGS=["/Zi", "/FS"]) env.AppendUnique(LINKFLAGS=["/DEBUG"]) if env["windows_subsystem"] == "gui": @@ -224,6 +224,7 @@ def configure_msvc(env, manual_msvc_config): env.AppendUnique(CCFLAGS=["/MT"]) else: env.AppendUnique(CCFLAGS=["/MD"]) + env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"]) # Force to use Unicode encoding env.AppendUnique(CCFLAGS=["/utf-8"]) @@ -339,13 +340,13 @@ def configure_mingw(env): else: # optimize for size env.Prepend(CCFLAGS=["-Os"]) - if env["debug_symbols"] == "yes": + if env["debug_symbols"]: env.Prepend(CCFLAGS=["-g2"]) elif env["target"] == "release_debug": env.Append(CCFLAGS=["-O2"]) env.Append(CPPDEFINES=["DEBUG_ENABLED"]) - if env["debug_symbols"] == "yes": + if env["debug_symbols"]: env.Prepend(CCFLAGS=["-g2"]) if env["optimize"] == "speed": # optimize for speed (default) env.Append(CCFLAGS=["-O2"]) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 14e7d395d3..b9b78f7bd4 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -535,7 +535,7 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) { } #endif - if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[p_window].wtctx) { + if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window].wtctx) { wintab_WTClose(windows[p_window].wtctx); windows[p_window].wtctx = 0; } @@ -1784,7 +1784,10 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) Ref<InputEventFromWindow> event_from_window = p_event; if (event_from_window.is_valid() && event_from_window->get_window_id() != INVALID_WINDOW_ID) { //send to a window - ERR_FAIL_COND(!windows.has(event_from_window->get_window_id())); + if (!windows.has(event_from_window->get_window_id())) { + in_dispatch_input_event = false; + ERR_FAIL_MSG("DisplayServerWindows: Invalid window id in input event."); + } Callable callable = windows[event_from_window->get_window_id()].input_event_callback; if (callable.is_null()) { in_dispatch_input_event = false; @@ -2018,7 +2021,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } break; case WT_CSRCHANGE: case WT_PROXIMITY: { - if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) { + if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) { AXIS pressure; if (wintab_WTInfo(WTI_DEVICES + windows[window_id].wtlc.lcDevice, DVC_NPRESSURE, &pressure)) { windows[window_id].min_pressure = int(pressure.axMin); @@ -2032,7 +2035,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } } break; case WT_PACKET: { - if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) { + if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) { PACKET packet; if (wintab_WTPacket(windows[window_id].wtctx, wParam, &packet)) { float pressure = float(packet.pkNormalPressure - windows[window_id].min_pressure) / float(windows[window_id].max_pressure - windows[window_id].min_pressure); @@ -2111,7 +2114,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA break; } - if ((OS::get_singleton()->get_current_tablet_driver() != "winink") || !winink_available) { + if ((tablet_get_current_driver() != "winink") || !winink_available) { break; } @@ -2137,7 +2140,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA break; } - if ((OS::get_singleton()->get_current_tablet_driver() != "winink") || !winink_available) { + if ((tablet_get_current_driver() != "winink") || !winink_available) { break; } @@ -2301,7 +2304,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_shift((wParam & MK_SHIFT) != 0); mm->set_alt(alt_mem); - if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) { + if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) { // Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not update recently. if (windows[window_id].last_pressure_update < 10) { windows[window_id].last_pressure_update++; @@ -2796,7 +2799,7 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id, WPARAM alt_mem = false; } - if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[p_window_id].wtctx) { + if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window_id].wtctx) { wintab_WTEnable(windows[p_window_id].wtctx, GET_WM_ACTIVATE_STATE(wParam, lParam)); } } @@ -3034,7 +3037,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, DragAcceptFiles(wd.hWnd, true); - if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available) { + if ((tablet_get_current_driver() == "wintab") && wintab_available) { wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc); wd.wtlc.lcOptions |= CXO_MESSAGES; wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION; @@ -3101,6 +3104,40 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS { SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2 } SHC_PROCESS_DPI_AWARENESS; +int DisplayServerWindows::tablet_get_driver_count() const { + return tablet_drivers.size(); +} + +String DisplayServerWindows::tablet_get_driver_name(int p_driver) const { + if (p_driver < 0 || p_driver >= tablet_drivers.size()) { + return ""; + } else { + return tablet_drivers[p_driver]; + } +} + +String DisplayServerWindows::tablet_get_current_driver() const { + return tablet_driver; +} + +void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) { + if (tablet_get_driver_count() == 0) { + return; + } + bool found = false; + for (int i = 0; i < tablet_get_driver_count(); i++) { + if (p_driver == tablet_get_driver_name(i)) { + found = true; + } + } + if (found) { + _update_tablet_ctx(tablet_driver, p_driver); + tablet_driver = p_driver; + } else { + ERR_PRINT("Unknown tablet driver " + p_driver + "."); + } +} + DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { drop_events = false; key_event_pos = 0; @@ -3119,6 +3156,35 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win outside = true; + //Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink. + HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll"); + if (wintab_lib) { + wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW"); + wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose"); + wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW"); + wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket"); + wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable"); + + wintab_available = wintab_WTOpen && wintab_WTClose && wintab_WTInfo && wintab_WTPacket && wintab_WTEnable; + } + + if (wintab_available) { + tablet_drivers.push_back("wintab"); + } + + //Note: Windows Ink API for pen input, available on Windows 8+ only. + HMODULE user32_lib = LoadLibraryW(L"user32.dll"); + if (user32_lib) { + win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType"); + win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo"); + + winink_available = win8p_GetPointerType && win8p_GetPointerPenInfo; + } + + if (winink_available) { + tablet_drivers.push_back("winink"); + } + if (OS::get_singleton()->is_hidpi_allowed()) { HMODULE Shcore = LoadLibraryW(L"Shcore.dll"); diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index c8c6a75bf5..a734077e59 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -264,7 +264,6 @@ class DisplayServerWindows : public DisplayServer { _THREAD_SAFE_CLASS_ -public: // WinTab API static bool wintab_available; static WTOpenPtr wintab_WTOpen; @@ -279,8 +278,9 @@ public: static GetPointerPenInfoPtr win8p_GetPointerPenInfo; void _update_tablet_ctx(const String &p_old_driver, const String &p_new_driver); + String tablet_driver; + Vector<String> tablet_drivers; -private: void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap); enum { @@ -542,6 +542,11 @@ public: virtual String keyboard_get_layout_language(int p_index) const; virtual String keyboard_get_layout_name(int p_index) const; + virtual int tablet_get_driver_count() const; + virtual String tablet_get_driver_name(int p_driver) const; + virtual String tablet_get_current_driver() const; + virtual void tablet_set_current_driver(const String &p_driver); + virtual void process_events(); virtual void force_process_and_drop_events(); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index fe007027da..3280a36e9b 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -45,7 +45,6 @@ #include "platform/windows/display_server_windows.h" #include "servers/audio_server.h" #include "servers/rendering/rendering_server_default.h" -#include "servers/rendering/rendering_server_wrap_mt.h" #include "windows_terminal_logger.h" #include <avrt.h> @@ -766,77 +765,12 @@ Error OS_Windows::move_to_trash(const String &p_path) { return OK; } -int OS_Windows::get_tablet_driver_count() const { - return tablet_drivers.size(); -} - -String OS_Windows::get_tablet_driver_name(int p_driver) const { - if (p_driver < 0 || p_driver >= tablet_drivers.size()) { - return ""; - } else { - return tablet_drivers[p_driver]; - } -} - -String OS_Windows::get_current_tablet_driver() const { - return tablet_driver; -} - -void OS_Windows::set_current_tablet_driver(const String &p_driver) { - if (get_tablet_driver_count() == 0) { - return; - } - bool found = false; - for (int i = 0; i < get_tablet_driver_count(); i++) { - if (p_driver == get_tablet_driver_name(i)) { - found = true; - } - } - if (found) { - if (DisplayServerWindows::get_singleton()) { - ((DisplayServerWindows *)DisplayServerWindows::get_singleton())->_update_tablet_ctx(tablet_driver, p_driver); - } - tablet_driver = p_driver; - } else { - ERR_PRINT("Unknown tablet driver " + p_driver + "."); - } -} - OS_Windows::OS_Windows(HINSTANCE _hInstance) { ticks_per_second = 0; ticks_start = 0; main_loop = nullptr; process_map = nullptr; - //Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink. - HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll"); - if (wintab_lib) { - DisplayServerWindows::wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW"); - DisplayServerWindows::wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose"); - DisplayServerWindows::wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW"); - DisplayServerWindows::wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket"); - DisplayServerWindows::wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable"); - - DisplayServerWindows::wintab_available = DisplayServerWindows::wintab_WTOpen && DisplayServerWindows::wintab_WTClose && DisplayServerWindows::wintab_WTInfo && DisplayServerWindows::wintab_WTPacket && DisplayServerWindows::wintab_WTEnable; - } - - if (DisplayServerWindows::wintab_available) { - tablet_drivers.push_back("wintab"); - } - - //Note: Windows Ink API for pen input, available on Windows 8+ only. - HMODULE user32_lib = LoadLibraryW(L"user32.dll"); - if (user32_lib) { - DisplayServerWindows::win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType"); - DisplayServerWindows::win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo"); - - DisplayServerWindows::winink_available = DisplayServerWindows::win8p_GetPointerType && DisplayServerWindows::win8p_GetPointerPenInfo; - } - - if (DisplayServerWindows::winink_available) { - tablet_drivers.push_back("winink"); - } - force_quit = false; hInstance = _hInstance; diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 1a8791196b..8f9ef254f1 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -73,9 +73,6 @@ class OS_Windows : public OS { HINSTANCE hInstance; MainLoop *main_loop; - String tablet_driver; - Vector<String> tablet_drivers; - #ifdef WASAPI_ENABLED AudioDriverWASAPI driver_wasapi; #endif @@ -119,11 +116,6 @@ public: virtual String get_name() const override; - virtual int get_tablet_driver_count() const override; - virtual String get_tablet_driver_name(int p_driver) const override; - virtual String get_current_tablet_driver() const override; - virtual void set_current_tablet_driver(const String &p_driver) override; - virtual void initialize_joypads() override {} virtual Date get_date(bool utc) const override; |