Add the ability to specify a level when creating windows

Antonio Scandurra created

This lets some windows stay on top of others, independently of
whether the application is in the foreground.

Change summary

crates/contacts_status_item/src/contacts_status_item.rs | 19 +++++-----
crates/gpui/src/platform.rs                             |  8 ++++
crates/gpui/src/platform/mac/window.rs                  | 13 ++++++
crates/zed/src/zed.rs                                   |  3 +
4 files changed, 31 insertions(+), 12 deletions(-)

Detailed changes

crates/contacts_status_item/src/contacts_status_item.rs 🔗

@@ -62,17 +62,16 @@ impl ContactsStatusItem {
                 let size = vec2f(360., 460.);
                 let origin = window_bounds.lower_left()
                     + vec2f(window_bounds.width() / 2. - size.x() / 2., 0.);
-                self.popover = Some(
-                    cx.add_window(
-                        gpui::WindowOptions {
-                            bounds: gpui::WindowBounds::Fixed(RectF::new(origin, size)),
-                            titlebar: None,
-                            center: false,
-                        },
-                        |_| ContactsPopover::new(),
-                    )
-                    .1,
+                let (_, popover) = cx.add_window(
+                    gpui::WindowOptions {
+                        bounds: gpui::WindowBounds::Fixed(RectF::new(origin, size)),
+                        titlebar: None,
+                        center: false,
+                        level: gpui::WindowLevel::PopUp,
+                    },
+                    |_| ContactsPopover::new(),
                 );
+                self.popover = Some(popover);
             }
         }
     }

crates/gpui/src/platform.rs 🔗

@@ -142,6 +142,7 @@ pub struct WindowOptions<'a> {
     pub bounds: WindowBounds,
     pub titlebar: Option<TitlebarOptions<'a>>,
     pub center: bool,
+    pub level: WindowLevel,
 }
 
 #[derive(Debug)]
@@ -165,6 +166,12 @@ impl Default for Appearance {
     }
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum WindowLevel {
+    Normal,
+    PopUp,
+}
+
 #[derive(Debug)]
 pub enum WindowBounds {
     Maximized,
@@ -276,6 +283,7 @@ impl<'a> Default for WindowOptions<'a> {
                 traffic_light_position: Default::default(),
             }),
             center: false,
+            level: WindowLevel::Normal,
         }
     }
 }

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

@@ -12,7 +12,7 @@ use crate::{
         Event, WindowBounds,
     },
     InputHandler, KeyDownEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
-    MouseMovedEvent, Scene,
+    MouseMovedEvent, Scene, WindowLevel,
 };
 use block::ConcreteBlock;
 use cocoa::{
@@ -56,6 +56,12 @@ const WINDOW_STATE_IVAR: &str = "windowState";
 static mut WINDOW_CLASS: *const Class = ptr::null();
 static mut VIEW_CLASS: *const Class = ptr::null();
 
+#[allow(non_upper_case_globals)]
+const NSNormalWindowLevel: NSInteger = 0;
+
+#[allow(non_upper_case_globals)]
+const NSPopUpWindowLevel: NSInteger = 101;
+
 #[repr(C)]
 #[derive(Copy, Clone, Debug)]
 struct NSRange {
@@ -452,6 +458,11 @@ impl Window {
             }
 
             native_window.makeKeyAndOrderFront_(nil);
+            let native_level = match options.level {
+                WindowLevel::Normal => NSNormalWindowLevel,
+                WindowLevel::PopUp => NSPopUpWindowLevel,
+            };
+            native_window.setLevel_(native_level);
 
             window.0.borrow().move_traffic_light();
             pool.drain();

crates/zed/src/zed.rs 🔗

@@ -20,7 +20,7 @@ use gpui::{
     geometry::vector::vec2f,
     impl_actions,
     platform::{WindowBounds, WindowOptions},
-    AssetSource, AsyncAppContext, TitlebarOptions, ViewContext,
+    AssetSource, AsyncAppContext, TitlebarOptions, ViewContext, WindowLevel,
 };
 use language::Rope;
 pub use lsp;
@@ -336,6 +336,7 @@ pub fn build_window_options() -> WindowOptions<'static> {
             traffic_light_position: Some(vec2f(8., 8.)),
         }),
         center: false,
+        level: WindowLevel::Normal,
     }
 }