Skip to content

Commit

Permalink
Add OS.get_version_alias() to return a human-readable Windows/macOS…
Browse files Browse the repository at this point in the history
… version number

Windows 11's major version number is actually 10.x.x, which can be confusing
if you don't know about this quirk. `OS.get_version_alias()` avoids this
by displaying the "branding" version number and the build number as a suffix,
so that individual updates can still be distinguished from each other.

On macOS, `OS.get_version_alias()` returns the version number prepended
with the version name (e.g. Sequoia for macOS 15).

On other operating systems, this returns the same value as `OS.get_version()`.
  • Loading branch information
Calinou committed Dec 13, 2024
1 parent 7f5c469 commit f7a8c1a
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 5 deletions.
5 changes: 5 additions & 0 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,10 @@ String OS::get_version() const {
return ::OS::get_singleton()->get_version();
}

String OS::get_version_alias() const {
return ::OS::get_singleton()->get_version_alias();
}

Vector<String> OS::get_video_adapter_driver_info() const {
return ::OS::get_singleton()->get_video_adapter_driver_info();
}
Expand Down Expand Up @@ -680,6 +684,7 @@ void OS::_bind_methods() {
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_version_alias"), &OS::get_version_alias);
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);

Expand Down
1 change: 1 addition & 0 deletions core/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ class OS : public Object {
String get_name() const;
String get_distribution_name() const;
String get_version() const;
String get_version_alias() const;
Vector<String> get_cmdline_args();
Vector<String> get_cmdline_user_args();

Expand Down
1 change: 1 addition & 0 deletions core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ class OS {
virtual String get_identifier() const;
virtual String get_distribution_name() const = 0;
virtual String get_version() const = 0;
virtual String get_version_alias() const { return get_version(); }
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_platform_args() const { return List<String>(); }
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/OS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,13 @@
[b]Note:[/b] This method is not supported on the Web platform. It returns an empty string.
</description>
</method>
<method name="get_version_alias" qualifiers="const">
<return type="String" />
<description>
Returns the branded version used in marketing followed by the build number (on Windows) or version number (on macOS). Examples include [code]11 (build 22000)[/code] and [code]Sequoia (15.0.0)"[/code]. This value can then be appended to [method get_name] to get a full human-readable operating system name and version combination. Windows feature updates such as 24H2 are not contained in the resulting string, but Windows Server is recognized as such (e.g. [code]2025 (build 26100)[/code] for Windows Server 2025).
[b]Note:[/b] This method is only supported on Windows and macOS. On other operating systems, it returns the same value as [method get_version].
</description>
</method>
<method name="get_video_adapter_driver_info" qualifiers="const">
<return type="PackedStringArray" />
<description>
Expand Down
2 changes: 1 addition & 1 deletion editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4977,7 +4977,7 @@ String EditorNode::_get_system_info() const {
if (distribution_name.is_empty()) {
distribution_name = "Other";
}
const String distribution_version = OS::get_singleton()->get_version();
const String distribution_version = OS::get_singleton()->get_version_alias();

String godot_version = "Godot v" + String(VERSION_FULL_CONFIG);
if (String(VERSION_BUILD) != "official") {
Expand Down
1 change: 1 addition & 0 deletions platform/macos/os_macos.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class OS_MacOS : public OS_Unix {
virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
virtual String get_version_alias() const override;

virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;

Expand Down
25 changes: 25 additions & 0 deletions platform/macos/os_macos.mm
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,31 @@
return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion);
}

String OS_MacOS::get_version_alias() const {
NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion;
String macos_string = "macOS";
if (ver.majorVersion == 15) {
macos_string += " Sequoia";
} else if (ver.majorVersion == 14) {
macos_string += " Sonoma";
} else if (ver.majorVersion == 13) {
macos_string += " Ventura";
} else if (ver.majorVersion == 12) {
macos_string += " Monterey";
} else if (ver.majorVersion == 11) {
macos_string += " Big Sur";
} else if (ver.majorVersion == 10 && ver.minorVersion == 15) {
macos_string += " Catalina";
} else if (ver.majorVersion == 10 && ver.minorVersion == 14) {
macos_string += " Mojave";
} else if (ver.majorVersion == 10 && ver.minorVersion == 13) {
macos_string += " High Sierra";
}
// macOS versions older than 10.13 cannot run Godot.

return vformat("%s (%s)", macos_string, get_version());
}

void OS_MacOS::alert(const String &p_alert, const String &p_title) {
NSAlert *window = [[NSAlert alloc] init];
NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()];
Expand Down
1 change: 0 additions & 1 deletion platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1480,7 +1480,6 @@ void DisplayServerWindows::screen_set_keep_on(bool p_enable) {
if (p_enable) {
const String reason = "Godot Engine running with display/window/energy_saving/keep_screen_on = true";
Char16String reason_utf16 = reason.utf16();

REASON_CONTEXT context;
context.Version = POWER_REQUEST_CONTEXT_VERSION;
context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
Expand Down
4 changes: 2 additions & 2 deletions platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ typedef bool(WINAPI *ShouldAppsUseDarkModePtr)();
typedef DWORD(WINAPI *GetImmersiveColorFromColorSetExPtr)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode);
typedef int(WINAPI *GetImmersiveColorTypeFromNamePtr)(const WCHAR *name);
typedef int(WINAPI *GetImmersiveUserColorSetPreferencePtr)(bool bForceCheckRegistry, bool bSkipCheckOnFail);
typedef HRESULT(WINAPI *RtlGetVersionPtr)(OSVERSIONINFOW *lpVersionInformation);
typedef HRESULT(WINAPI *RtlGetVersionPtr)(OSVERSIONINFOEXW *lpVersionInformation);
typedef bool(WINAPI *AllowDarkModeForAppPtr)(bool darkMode);
typedef PreferredAppMode(WINAPI *SetPreferredAppModePtr)(PreferredAppMode appMode);
typedef void(WINAPI *RefreshImmersiveColorPolicyStatePtr)();
Expand Down Expand Up @@ -419,7 +419,7 @@ class DisplayServerWindows : public DisplayServer {
TIMER_ID_WINDOW_ACTIVATION = 2,
};

OSVERSIONINFOW os_ver;
OSVERSIONINFOEXW os_ver;

enum {
KEY_EVENT_BUFFER_SIZE = 512
Expand Down
60 changes: 59 additions & 1 deletion platform/windows/os_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ String OS_Windows::get_distribution_name() const {
String OS_Windows::get_version() const {
RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
if (version_ptr != nullptr) {
RTL_OSVERSIONINFOW fow;
RTL_OSVERSIONINFOEXW fow;
ZeroMemory(&fow, sizeof(fow));
fow.dwOSVersionInfoSize = sizeof(fow);
if (version_ptr(&fow) == 0x00000000) {
Expand All @@ -592,6 +592,64 @@ String OS_Windows::get_version() const {
return "";
}

String OS_Windows::get_version_alias() const {
RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
if (version_ptr != nullptr) {
RTL_OSVERSIONINFOEXW fow;
ZeroMemory(&fow, sizeof(fow));
fow.dwOSVersionInfoSize = sizeof(fow);
if (version_ptr(&fow) == 0x00000000) {
String windows_string;
if (fow.wProductType != VER_NT_WORKSTATION && fow.dwMajorVersion == 10 && fow.dwBuildNumber >= 26100) {
windows_string = "Server 2025";
} else if (fow.dwMajorVersion == 10 && fow.dwBuildNumber >= 22000) {
if (fow.wProductType != VER_NT_WORKSTATION) {
windows_string += "Server 2022";
} else {
// Build 22000 corresponds to Windows 11 21H2, the first publicly available Windows 11 version.
// Its major version number is still 10 though.
windows_string += "11";
}
} else if (fow.dwMajorVersion == 10) {
if (fow.wProductType != VER_NT_WORKSTATION && fow.dwBuildNumber >= 17763) {
windows_string += "Server 2019";
} else {
if (fow.wProductType != VER_NT_WORKSTATION) {
windows_string += "Server 2016";
} else {
windows_string += "10";
}
}
} else if (fow.dwMajorVersion == 6 && fow.dwMinorVersion == 3) {
if (fow.wProductType != VER_NT_WORKSTATION) {
windows_string = "Server 2012 R2";
} else {
windows_string += "8.1";
}
} else if (fow.dwMajorVersion == 6 && fow.dwMinorVersion == 2) {
if (fow.wProductType != VER_NT_WORKSTATION) {
windows_string += "Server 2012";
} else {
windows_string += "8";
}
} else if (fow.dwMajorVersion == 6 && fow.dwMinorVersion == 1) {
if (fow.wProductType != VER_NT_WORKSTATION) {
windows_string = "Server 2008 R2";
} else {
windows_string += "7";
}
} else {
windows_string += "Unknown";
}
// Windows versions older than 7 cannot run Godot.

return vformat("%s (build %d)", windows_string, (int64_t)fow.dwBuildNumber);
}
}

return "";
}

Vector<String> OS_Windows::get_video_adapter_driver_info() const {
if (RenderingServer::get_singleton() == nullptr) {
return Vector<String>();
Expand Down
1 change: 1 addition & 0 deletions platform/windows/os_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class OS_Windows : public OS {
virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
virtual String get_version_alias() const override;

virtual Vector<String> get_video_adapter_driver_info() const override;
virtual bool get_user_prefers_integrated_gpu() const override;
Expand Down

0 comments on commit f7a8c1a

Please sign in to comment.