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 14, 2024
1 parent 7f5c469 commit 9289828
Show file tree
Hide file tree
Showing 11 changed files with 105 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 the 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 for the operating system. 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
27 changes: 27 additions & 0 deletions platform/macos/os_macos.mm
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,33 @@
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;
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 || (ver.majorVersion == 10 && ver.minorVersion == 16)) {
// Big Sur was 10.16 during beta, but it became 11 for the stable version.
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";
} else {
macos_string += "Unknown";
}
// 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 >= 20348) {
// Builds above 20348 correspond to Windows 11 / Windows Server 2022.
// Their major version numbers are still 10 though, not 11.
if (fow.wProductType != VER_NT_WORKSTATION) {
windows_string += "Server 2022";
} else {
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 9289828

Please sign in to comment.