macOS: Fix window turning black on fullscreen mode (#26547)

Smit Barmase and MrSubidubi created

Closes #26534

Recently, we fixed a title bar transparency issue that only occurred on
macOS 15.3 and later. PR:
https://github.com/zed-industries/zed/pull/26403

However, this seems to have broken multi-window fullscreen behavior on
earlier macOS versions. This PR adds versioning so that the title bar
transparency fix only applies to macOS 15.3.0 and later.

No release notes, as this bug only exists on main right now.  

Release Notes:

- N/A

Co-authored-by: MrSubidubi <dev@bahn.sh>

Change summary

crates/gpui/src/platform/mac/window.rs | 29 +++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 3 deletions(-)

Detailed changes

crates/gpui/src/platform/mac/window.rs 🔗

@@ -1498,21 +1498,44 @@ extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
     let window_state = unsafe { get_window_state(this) };
     let mut lock = window_state.as_ref().lock();
     lock.fullscreen_restore_bounds = lock.bounds();
-    unsafe {
-        lock.native_window.setTitlebarAppearsTransparent_(NO);
+
+    if is_macos_version_at_least(15, 3, 0) {
+        unsafe {
+            lock.native_window.setTitlebarAppearsTransparent_(NO);
+        }
     }
 }
 
 extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) {
     let window_state = unsafe { get_window_state(this) };
     let mut lock = window_state.as_ref().lock();
-    if lock.transparent_titlebar {
+
+    if is_macos_version_at_least(15, 3, 0) && lock.transparent_titlebar {
         unsafe {
             lock.native_window.setTitlebarAppearsTransparent_(YES);
         }
     }
 }
 
+#[repr(C)]
+struct NSOperatingSystemVersion {
+    major_version: NSInteger,
+    minor_version: NSInteger,
+    patch_version: NSInteger,
+}
+
+fn is_macos_version_at_least(major: NSInteger, minor: NSInteger, patch: NSInteger) -> bool {
+    unsafe {
+        let process_info: id = msg_send![class!(NSProcessInfo), processInfo];
+        let os_version: NSOperatingSystemVersion = msg_send![process_info, operatingSystemVersion];
+        (os_version.major_version > major)
+            || (os_version.major_version == major && os_version.minor_version > minor)
+            || (os_version.major_version == major
+                && os_version.minor_version == minor
+                && os_version.patch_version >= patch)
+    }
+}
+
 extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
     let window_state = unsafe { get_window_state(this) };
     let mut lock = window_state.as_ref().lock();