Merge pull request #2124 from zed-industries/fix-display-uuid-panic

Kay Simmons created

Make display uuid optional if the display is disconnected

Change summary

crates/gpui/src/app.rs                 | 32 ++++++++++++++-------------
crates/gpui/src/platform.rs            |  2 
crates/gpui/src/platform/mac/screen.rs | 12 +++++++---
crates/gpui/src/platform/test.rs       |  4 +-
4 files changed, 28 insertions(+), 22 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -914,7 +914,7 @@ impl MutableAppContext {
         self.presenters_and_platform_windows[&window_id].1.bounds()
     }
 
-    pub fn window_display_uuid(&self, window_id: usize) -> Uuid {
+    pub fn window_display_uuid(&self, window_id: usize) -> Option<Uuid> {
         self.presenters_and_platform_windows[&window_id]
             .1
             .screen()
@@ -2375,12 +2375,13 @@ impl MutableAppContext {
                 callback(is_fullscreen, this)
             });
 
-            let bounds = this.window_bounds(window_id);
-            let uuid = this.window_display_uuid(window_id);
-            let mut bounds_observations = this.window_bounds_observations.clone();
-            bounds_observations.emit(window_id, this, |callback, this| {
-                callback(bounds, uuid, this)
-            });
+            if let Some(uuid) = this.window_display_uuid(window_id) {
+                let bounds = this.window_bounds(window_id);
+                let mut bounds_observations = this.window_bounds_observations.clone();
+                bounds_observations.emit(window_id, this, |callback, this| {
+                    callback(bounds, uuid, this)
+                });
+            }
 
             Some(())
         });
@@ -2559,14 +2560,15 @@ impl MutableAppContext {
     }
 
     fn handle_window_moved(&mut self, window_id: usize) {
-        let bounds = self.window_bounds(window_id);
-        let display = self.window_display_uuid(window_id);
-        self.window_bounds_observations
-            .clone()
-            .emit(window_id, self, move |callback, this| {
-                callback(bounds, display, this);
-                true
-            });
+        if let Some(display) = self.window_display_uuid(window_id) {
+            let bounds = self.window_bounds(window_id);
+            self.window_bounds_observations
+                .clone()
+                .emit(window_id, self, move |callback, this| {
+                    callback(bounds, display, this);
+                    true
+                });
+        }
     }
 
     pub fn focus(&mut self, window_id: usize, view_id: Option<usize>) {

crates/gpui/src/platform.rs 🔗

@@ -124,7 +124,7 @@ pub trait InputHandler {
 pub trait Screen: Debug {
     fn as_any(&self) -> &dyn Any;
     fn bounds(&self) -> RectF;
-    fn display_uuid(&self) -> Uuid;
+    fn display_uuid(&self) -> Option<Uuid>;
 }
 
 pub trait Window {

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

@@ -35,7 +35,7 @@ impl Screen {
                 .map(|ix| Screen {
                     native_screen: native_screens.objectAtIndex(ix),
                 })
-                .find(|screen| platform::Screen::display_uuid(screen) == uuid)
+                .find(|screen| platform::Screen::display_uuid(screen) == Some(uuid))
         }
     }
 
@@ -58,7 +58,7 @@ impl platform::Screen for Screen {
         self
     }
 
-    fn display_uuid(&self) -> uuid::Uuid {
+    fn display_uuid(&self) -> Option<uuid::Uuid> {
         unsafe {
             // Screen ids are not stable. Further, the default device id is also unstable across restarts.
             // CGDisplayCreateUUIDFromDisplayID is stable but not exposed in the bindings we use.
@@ -74,8 +74,12 @@ impl platform::Screen for Screen {
                 (&mut device_id) as *mut _ as *mut c_void,
             );
             let cfuuid = CGDisplayCreateUUIDFromDisplayID(device_id as CGDirectDisplayID);
+            if cfuuid.is_null() {
+                return None;
+            }
+
             let bytes = CFUUIDGetUUIDBytes(cfuuid);
-            Uuid::from_bytes([
+            Some(Uuid::from_bytes([
                 bytes.byte0,
                 bytes.byte1,
                 bytes.byte2,
@@ -92,7 +96,7 @@ impl platform::Screen for Screen {
                 bytes.byte13,
                 bytes.byte14,
                 bytes.byte15,
-            ])
+            ]))
         }
     }
 

crates/gpui/src/platform/test.rs 🔗

@@ -238,8 +238,8 @@ impl super::Screen for Screen {
         RectF::new(Vector2F::zero(), Vector2F::new(1920., 1080.))
     }
 
-    fn display_uuid(&self) -> uuid::Uuid {
-        uuid::Uuid::new_v4()
+    fn display_uuid(&self) -> Option<uuid::Uuid> {
+        Some(uuid::Uuid::new_v4())
     }
 }