Add get_distribution_name() and get_version() to OS

supports: LinuxBSD, Windows, macOS, iOS, Android, UWP

Co-authored-by: bruvzg
This commit is contained in:
MJacred 2022-09-16 11:14:14 +02:00
parent d1b2a191ab
commit ac9786c525
18 changed files with 218 additions and 0 deletions

View File

@ -322,6 +322,14 @@ String OS::get_name() const {
return ::OS::get_singleton()->get_name(); return ::OS::get_singleton()->get_name();
} }
String OS::get_distribution_name() const {
return ::OS::get_singleton()->get_distribution_name();
}
String OS::get_version() const {
return ::OS::get_singleton()->get_version();
}
Vector<String> OS::get_cmdline_args() { Vector<String> OS::get_cmdline_args() {
List<String> cmdline = ::OS::get_singleton()->get_cmdline_args(); List<String> cmdline = ::OS::get_singleton()->get_cmdline_args();
Vector<String> cmdlinev; Vector<String> cmdlinev;
@ -535,6 +543,8 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_environment", "variable"), &OS::has_environment); ClassDB::bind_method(D_METHOD("has_environment", "variable"), &OS::has_environment);
ClassDB::bind_method(D_METHOD("get_name"), &OS::get_name); ClassDB::bind_method(D_METHOD("get_name"), &OS::get_name);
ClassDB::bind_method(D_METHOD("get_distribution_name"), &OS::get_distribution_name);
ClassDB::bind_method(D_METHOD("get_version"), &OS::get_version);
ClassDB::bind_method(D_METHOD("get_cmdline_args"), &OS::get_cmdline_args); ClassDB::bind_method(D_METHOD("get_cmdline_args"), &OS::get_cmdline_args);
ClassDB::bind_method(D_METHOD("get_cmdline_user_args"), &OS::get_cmdline_user_args); ClassDB::bind_method(D_METHOD("get_cmdline_user_args"), &OS::get_cmdline_user_args);

View File

@ -193,6 +193,8 @@ public:
bool set_environment(const String &p_var, const String &p_value) const; bool set_environment(const String &p_var, const String &p_value) const;
String get_name() const; String get_name() const;
String get_distribution_name() const;
String get_version() const;
Vector<String> get_cmdline_args(); Vector<String> get_cmdline_args();
Vector<String> get_cmdline_user_args(); Vector<String> get_cmdline_user_args();

View File

@ -161,6 +161,8 @@ public:
virtual bool set_environment(const String &p_var, const String &p_value) const = 0; virtual bool set_environment(const String &p_var, const String &p_value) const = 0;
virtual String get_name() const = 0; virtual String get_name() const = 0;
virtual String get_distribution_name() const = 0;
virtual String get_version() const = 0;
virtual List<String> get_cmdline_args() const { return _cmdline; } virtual List<String> get_cmdline_args() const { return _cmdline; }
virtual List<String> get_cmdline_user_args() const { return _user_args; } virtual List<String> get_cmdline_user_args() const { return _user_args; }
virtual List<String> get_cmdline_platform_args() const { return List<String>(); } virtual List<String> get_cmdline_platform_args() const { return List<String>(); }

View File

@ -216,6 +216,15 @@
Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path. Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path.
</description> </description>
</method> </method>
<method name="get_distribution_name" qualifiers="const">
<return type="String" />
<description>
Returns the name of the distribution for Linux and BSD platforms (e.g. Ubuntu, Manjaro, OpenBSD, etc.).
Returns the same value as [method get_name] for stock Android ROMs, but attempts to return the custom ROM name for popular Android derivatives such as LineageOS.
Returns the same value as [method get_name] for other platforms.
[b]Note:[/b] This method is not supported on the web platform. It returns an empty string.
</description>
</method>
<method name="get_environment" qualifiers="const"> <method name="get_environment" qualifiers="const">
<return type="String" /> <return type="String" />
<param index="0" name="variable" type="String" /> <param index="0" name="variable" type="String" />
@ -430,6 +439,18 @@
Not to be confused with [method get_data_dir], which returns the [i]global[/i] (non-project-specific) user home directory. Not to be confused with [method get_data_dir], which returns the [i]global[/i] (non-project-specific) user home directory.
</description> </description>
</method> </method>
<method name="get_version" qualifiers="const">
<return type="String" />
<description>
Returns the exact production and build version of the operating system. This is different from the branded version used in marketing. This helps to distinguish between different releases of operating systems, including minor versions, and insider and custom builds.
For Windows, the major and minor version are returned, as well as the build number. For example, the returned string can look like [code]10.0.9926[/code] for a build of Windows 10, and it can look like [code]6.1.7601[/code] for a build of Windows 7 SP1.
For rolling distributions, such as Arch Linux, an empty string is returned.
For macOS and iOS, the major and minor version are returned, as well as the patch number.
For UWP, the device family version is returned.
For Android, the SDK version and the incremental build number are returned. If it's a custom ROM, it attempts to return its version instead.
[b]Note:[/b] This method is not supported on the web platform. It returns an empty string.
</description>
</method>
<method name="has_environment" qualifiers="const"> <method name="has_environment" qualifiers="const">
<return type="bool" /> <return type="bool" />
<param index="0" name="variable" type="String" /> <param index="0" name="variable" type="String" />

View File

@ -194,6 +194,14 @@ String OS_Unix::get_name() const {
return "Unix"; return "Unix";
} }
String OS_Unix::get_distribution_name() const {
return "";
}
String OS_Unix::get_version() const {
return "";
}
double OS_Unix::get_unix_time() const { double OS_Unix::get_unix_time() const {
struct timeval tv_now; struct timeval tv_now;
gettimeofday(&tv_now, nullptr); gettimeofday(&tv_now, nullptr);

View File

@ -62,6 +62,8 @@ public:
virtual Error set_cwd(const String &p_cwd) override; virtual Error set_cwd(const String &p_cwd) override;
virtual String get_name() const override; virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
virtual DateTime get_datetime(bool p_utc) const override; virtual DateTime get_datetime(bool p_utc) const override;
virtual TimeZoneInfo get_time_zone_info() const override; virtual TimeZoneInfo get_time_zone_info() const override;

View File

@ -44,6 +44,7 @@
#include "net_socket_android.h" #include "net_socket_android.h"
#include <dlfcn.h> #include <dlfcn.h>
#include <sys/system_properties.h>
#include "java_godot_io_wrapper.h" #include "java_godot_io_wrapper.h"
#include "java_godot_wrapper.h" #include "java_godot_wrapper.h"
@ -175,6 +176,79 @@ String OS_Android::get_name() const {
return "Android"; return "Android";
} }
String OS_Android::get_system_property(const char *key) const {
static String value;
char value_str[PROP_VALUE_MAX];
if (__system_property_get(key, value_str)) {
value = String(value_str);
}
return value;
}
String OS_Android::get_distribution_name() const {
if (!get_system_property("ro.havoc.version").is_empty()) {
return "Havoc OS";
} else if (!get_system_property("org.pex.version").is_empty()) { // Putting before "Pixel Experience", because it's derivating from it.
return "Pixel Extended";
} else if (!get_system_property("org.pixelexperience.version").is_empty()) {
return "Pixel Experience";
} else if (!get_system_property("ro.potato.version").is_empty()) {
return "POSP";
} else if (!get_system_property("ro.xtended.version").is_empty()) {
return "Project-Xtended";
} else if (!get_system_property("org.evolution.version").is_empty()) {
return "Evolution X";
} else if (!get_system_property("ro.corvus.version").is_empty()) {
return "Corvus-Q";
} else if (!get_system_property("ro.pa.version").is_empty()) {
return "Paranoid Android";
} else if (!get_system_property("ro.crdroid.version").is_empty()) {
return "crDroid Android";
} else if (!get_system_property("ro.syberia.version").is_empty()) {
return "Syberia Project";
} else if (!get_system_property("ro.arrow.version").is_empty()) {
return "ArrowOS";
} else if (!get_system_property("ro.lineage.version").is_empty()) { // Putting LineageOS last, just in case any derivative writes to "ro.lineage.version".
return "LineageOS";
}
if (!get_system_property("ro.modversion").is_empty()) { // Handles other Android custom ROMs.
return vformat("%s %s", get_name(), "Custom ROM");
}
// Handles stock Android.
return get_name();
}
String OS_Android::get_version() const {
const Vector<const char *> roms = { "ro.havoc.version", "org.pex.version", "org.pixelexperience.version",
"ro.potato.version", "ro.xtended.version", "org.evolution.version", "ro.corvus.version", "ro.pa.version",
"ro.crdroid.version", "ro.syberia.version", "ro.arrow.version", "ro.lineage.version" };
for (int i = 0; i < roms.size(); i++) {
static String rom_version = get_system_property(roms[i]);
if (!rom_version.is_empty()) {
return rom_version;
}
}
static String mod_version = get_system_property("ro.modversion"); // Handles other Android custom ROMs.
if (!mod_version.is_empty()) {
return mod_version;
}
// Handles stock Android.
static String sdk_version = get_system_property("ro.build.version.sdk_int");
static String build = get_system_property("ro.build.version.incremental");
if (!sdk_version.is_empty()) {
if (!build.is_empty()) {
return vformat("%s.%s", sdk_version, build);
}
return sdk_version;
}
return "";
}
MainLoop *OS_Android::get_main_loop() const { MainLoop *OS_Android::get_main_loop() const {
return main_loop; return main_loop;
} }

View File

@ -65,6 +65,8 @@ private:
GodotJavaWrapper *godot_java = nullptr; GodotJavaWrapper *godot_java = nullptr;
GodotIOJavaWrapper *godot_io_java = nullptr; GodotIOJavaWrapper *godot_io_java = nullptr;
String get_system_property(const char *key) const;
public: public:
static const char *ANDROID_EXEC_PATH; static const char *ANDROID_EXEC_PATH;
@ -93,6 +95,8 @@ public:
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override; virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
virtual String get_name() const override; virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
virtual MainLoop *get_main_loop() const override; virtual MainLoop *get_main_loop() const override;
void main_loop_begin(); void main_loop_begin();

View File

@ -100,6 +100,8 @@ public:
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override; virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
virtual String get_name() const override; virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
virtual String get_model_name() const override; virtual String get_model_name() const override;
virtual Error shell_open(String p_uri) override; virtual Error shell_open(String p_uri) override;

View File

@ -240,6 +240,15 @@ String OS_IOS::get_name() const {
return "iOS"; return "iOS";
} }
String OS_IOS::get_distribution_name() const {
return get_name();
}
String OS_IOS::get_version() const {
NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion;
return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion);
}
String OS_IOS::get_model_name() const { String OS_IOS::get_model_name() const {
String model = ios->get_model(); String model = ios->get_model();
if (model != "") { if (model != "") {

View File

@ -50,6 +50,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h> #include <unistd.h>
#ifdef FONTCONFIG_ENABLED #ifdef FONTCONFIG_ENABLED
@ -205,6 +206,42 @@ String OS_LinuxBSD::get_name() const {
#endif #endif
} }
String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const {
static String info;
if (info.is_empty()) {
Ref<FileAccess> f = FileAccess::open("/etc/os-release", FileAccess::READ);
if (f.is_valid()) {
while (!f->eof_reached()) {
const String line = f->get_line();
if (line.find(key) != -1) {
return line.split("=")[1].strip_edges();
}
}
}
}
return info;
}
String OS_LinuxBSD::get_distribution_name() const {
static String systemd_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string.
if (!systemd_name.is_empty()) {
return systemd_name;
}
struct utsname uts; // returns a decent value for BSD family.
uname(&uts);
return uts.sysname;
}
String OS_LinuxBSD::get_version() const {
static String systemd_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string.
if (!systemd_version.is_empty()) {
return systemd_version;
}
struct utsname uts; // returns a decent value for BSD family.
uname(&uts);
return uts.version;
}
Error OS_LinuxBSD::shell_open(String p_uri) { Error OS_LinuxBSD::shell_open(String p_uri) {
Error ok; Error ok;
int err_code; int err_code;

View File

@ -67,6 +67,8 @@ class OS_LinuxBSD : public OS_Unix {
MainLoop *main_loop = nullptr; MainLoop *main_loop = nullptr;
String get_systemd_os_release_info_value(const String &key) const;
protected: protected:
virtual void initialize() override; virtual void initialize() override;
virtual void finalize() override; virtual void finalize() override;
@ -77,6 +79,8 @@ protected:
public: public:
virtual String get_name() const override; virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
virtual MainLoop *get_main_loop() const override; virtual MainLoop *get_main_loop() const override;

View File

@ -75,6 +75,8 @@ public:
virtual List<String> get_cmdline_platform_args() const override; virtual List<String> get_cmdline_platform_args() const override;
virtual String get_name() const override; virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override; virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;

View File

@ -134,6 +134,15 @@ String OS_MacOS::get_name() const {
return "macOS"; return "macOS";
} }
String OS_MacOS::get_distribution_name() const {
return get_name();
}
String OS_MacOS::get_version() const {
NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion;
return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion);
}
void OS_MacOS::alert(const String &p_alert, const String &p_title) { void OS_MacOS::alert(const String &p_alert, const String &p_title) {
NSAlert *window = [[NSAlert alloc] init]; NSAlert *window = [[NSAlert alloc] init];
NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()]; NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()];

View File

@ -444,6 +444,16 @@ String OS_UWP::get_name() const {
return "UWP"; return "UWP";
} }
String OS_UWP::get_distribution_name() const {
return get_name();
}
String OS_UWP::get_version() const {
winrt::hstring df_version = VersionInfo().DeviceFamilyVersion();
static String version = String(winrt::to_string(df_version).c_str());
return version;
}
OS::DateTime OS_UWP::get_datetime(bool p_utc) const { OS::DateTime OS_UWP::get_datetime(bool p_utc) const {
SYSTEMTIME systemtime; SYSTEMTIME systemtime;
if (p_utc) { if (p_utc) {

View File

@ -183,6 +183,8 @@ public:
virtual MainLoop *get_main_loop() const; virtual MainLoop *get_main_loop() const;
virtual String get_name() const; virtual String get_name() const;
virtual String get_distribution_name() const;
virtual String get_version() const;
virtual DateTime get_datetime(bool p_utc) const; virtual DateTime get_datetime(bool p_utc) const;
virtual TimeZoneInfo get_time_zone_info() const; virtual TimeZoneInfo get_time_zone_info() const;

View File

@ -290,6 +290,24 @@ String OS_Windows::get_name() const {
return "Windows"; return "Windows";
} }
String OS_Windows::get_distribution_name() const {
return get_name();
}
String OS_Windows::get_version() const {
typedef LONG NTSTATUS, *PNTSTATUS;
typedef NTSTATUS(WINAPI * RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
if (version_ptr != nullptr) {
RTL_OSVERSIONINFOW fow = { 0 };
fow.dwOSVersionInfoSize = sizeof(fow);
if (version_ptr(&fow) == 0x00000000) {
return vformat("%d.%d.%d", (int64_t)fow.dwMajorVersion, (int64_t)fow.dwMinorVersion, (int64_t)fow.dwBuildNumber);
}
}
return "";
}
OS::DateTime OS_Windows::get_datetime(bool p_utc) const { OS::DateTime OS_Windows::get_datetime(bool p_utc) const {
SYSTEMTIME systemtime; SYSTEMTIME systemtime;
if (p_utc) { if (p_utc) {

View File

@ -143,6 +143,8 @@ public:
virtual MainLoop *get_main_loop() const override; virtual MainLoop *get_main_loop() const override;
virtual String get_name() const override; virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
virtual void initialize_joypads() override {} virtual void initialize_joypads() override {}