From 0a2fde8707a0ccd050bf02203432942641aafe77 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 31 Oct 2023 11:03:01 -0600 Subject: [PATCH] WIP --- crates/gpui2/src/app.rs | 15 ++++++-- crates/gpui2/src/platform.rs | 4 +++ crates/gpui2/src/platform/mac/display.rs | 44 +++++++++++++++++++++++- crates/workspace2/src/searchable.rs | 1 + crates/workspace2/src/workspace2.rs | 3 +- crates/zed2/src/main.rs | 2 +- crates/zed2/src/zed2.rs | 12 +++---- 7 files changed, 69 insertions(+), 12 deletions(-) diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index c71b2d28d0ee8f4fb0a717e3244ea091e816c19e..1e09136bdbf732a1fe7ad90a4ae0d07b1d127a3a 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -11,14 +11,15 @@ use refineable::Refineable; use smallvec::SmallVec; #[cfg(any(test, feature = "test-support"))] pub use test_context::*; +use uuid::Uuid; use crate::{ current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AnyWindowHandle, AppMetadata, AssetSource, ClipboardItem, Context, DispatchPhase, DisplayId, Entity, Executor, FocusEvent, FocusHandle, FocusId, KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly, - Pixels, Platform, Point, Render, SharedString, SubscriberSet, Subscription, SvgRenderer, Task, - TextStyle, TextStyleRefinement, TextSystem, View, ViewContext, Window, WindowContext, - WindowHandle, WindowId, + Pixels, Platform, PlatformDisplay, Point, Render, SharedString, SubscriberSet, Subscription, + SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, ViewContext, Window, + WindowContext, WindowHandle, WindowId, }; use anyhow::{anyhow, Result}; use collections::{HashMap, HashSet, VecDeque}; @@ -32,6 +33,7 @@ use std::{ mem, ops::{Deref, DerefMut}, path::PathBuf, + rc::Rc, sync::{atomic::Ordering::SeqCst, Arc, Weak}, time::Duration, }; @@ -847,6 +849,13 @@ where pub fn path_for_auxiliary_executable(&self, name: &str) -> Result { self.platform().path_for_auxiliary_executable(name) } + + pub fn display_for_uuid(&self, uuid: Uuid) -> Option> { + self.platform() + .displays() + .into_iter() + .find(|display| display.uuid().ok() == Some(uuid)) + } } impl MainThread { diff --git a/crates/gpui2/src/platform.rs b/crates/gpui2/src/platform.rs index 295a89a190b049266acb97eb1746c545034f5d76..bf047a4947ffcb42c143a84074ce1162f6ff855a 100644 --- a/crates/gpui2/src/platform.rs +++ b/crates/gpui2/src/platform.rs @@ -28,6 +28,7 @@ use std::{ str::FromStr, sync::Arc, }; +use uuid::Uuid; pub use keystroke::*; #[cfg(target_os = "macos")] @@ -106,6 +107,9 @@ pub(crate) trait Platform: 'static { pub trait PlatformDisplay: Send + Sync + Debug { fn id(&self) -> DisplayId; + /// Returns a stable identifier for this display that can be persisted and used + /// across system restarts. + fn uuid(&self) -> Result; fn as_any(&self) -> &dyn Any; fn bounds(&self) -> Bounds; } diff --git a/crates/gpui2/src/platform/mac/display.rs b/crates/gpui2/src/platform/mac/display.rs index dc064293f342a9106f49ecf500dc8d3bb140efc0..b326eaa66d07bc674ebf6fb0c09d549db2dcb61f 100644 --- a/crates/gpui2/src/platform/mac/display.rs +++ b/crates/gpui2/src/platform/mac/display.rs @@ -1,9 +1,12 @@ use crate::{point, size, Bounds, DisplayId, GlobalPixels, PlatformDisplay}; +use anyhow::Result; +use core_foundation::uuid::{CFUUIDGetUUIDBytes, CFUUIDRef}; use core_graphics::{ display::{CGDirectDisplayID, CGDisplayBounds, CGGetActiveDisplayList}, geometry::{CGPoint, CGRect, CGSize}, }; use std::any::Any; +use uuid::Uuid; #[derive(Debug)] pub struct MacDisplay(pub(crate) CGDirectDisplayID); @@ -11,17 +14,23 @@ pub struct MacDisplay(pub(crate) CGDirectDisplayID); unsafe impl Send for MacDisplay {} impl MacDisplay { - /// Get the screen with the given UUID. + /// Get the screen with the given [DisplayId]. pub fn find_by_id(id: DisplayId) -> Option { Self::all().find(|screen| screen.id() == id) } + /// Get the screen with the given persistent [Uuid]. + pub fn find_by_uuid(uuid: Uuid) -> Option { + Self::all().find(|screen| screen.uuid().ok() == Some(uuid)) + } + /// Get the primary screen - the one with the menu bar, and whose bottom left /// corner is at the origin of the AppKit coordinate system. pub fn primary() -> Self { Self::all().next().unwrap() } + /// Obtains an iterator over all currently active system displays. pub fn all() -> impl Iterator { unsafe { let mut display_count: u32 = 0; @@ -40,6 +49,11 @@ impl MacDisplay { } } +#[link(name = "ApplicationServices", kind = "framework")] +extern "C" { + pub fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef; +} + /// Convert the given rectangle from CoreGraphics' native coordinate space to GPUI's coordinate space. /// /// CoreGraphics' coordinate space has its origin at the bottom left of the primary screen, @@ -88,6 +102,34 @@ impl PlatformDisplay for MacDisplay { DisplayId(self.0) } + fn uuid(&self) -> Result { + let cfuuid = unsafe { CGDisplayCreateUUIDFromDisplayID(self.0 as CGDirectDisplayID) }; + anyhow::ensure!( + !cfuuid.is_null(), + "AppKit returned a null from CGDisplayCreateUUIDFromDisplayID" + ); + + let bytes = unsafe { CFUUIDGetUUIDBytes(cfuuid) }; + Ok(Uuid::from_bytes([ + bytes.byte0, + bytes.byte1, + bytes.byte2, + bytes.byte3, + bytes.byte4, + bytes.byte5, + bytes.byte6, + bytes.byte7, + bytes.byte8, + bytes.byte9, + bytes.byte10, + bytes.byte11, + bytes.byte12, + bytes.byte13, + bytes.byte14, + bytes.byte15, + ])) + } + fn as_any(&self) -> &dyn Any { self } diff --git a/crates/workspace2/src/searchable.rs b/crates/workspace2/src/searchable.rs index 7b911b75d04215ab050705e79e3ebdba3ae9f422..ff132a8d80dfdaf5849c90d23363b49b4b41d0ab 100644 --- a/crates/workspace2/src/searchable.rs +++ b/crates/workspace2/src/searchable.rs @@ -128,6 +128,7 @@ pub trait SearchableItemHandle: ItemHandle { ) -> Option; } +// todo!("here is where we need to use AnyWeakView"); impl SearchableItemHandle for View { fn downgrade(&self) -> Box { // Box::new(self.downgrade()) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index a5d73b29047ad756603c0646679a02c33a3453ba..e7745dc763d43db8790a56362b62978745e3a034 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -42,6 +42,7 @@ use std::{ }; pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; use util::ResultExt; +use uuid::Uuid; use crate::persistence::model::{ DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup, @@ -414,7 +415,7 @@ pub struct AppState { pub workspace_store: Model, pub fs: Arc, pub build_window_options: - fn(Option, Option, &MainThread) -> WindowOptions, + fn(Option, Option, MainThread) -> WindowOptions, pub initialize_workspace: fn(WeakModel, bool, Arc, AsyncAppContext) -> Task>, pub node_runtime: Arc, diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index a736a205747e0f2846f6f3b981761761643d4f6f..8b1d087687204c23019dab1d0e8bf6c3d1182b4e 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -46,7 +46,7 @@ use util::{ }; use uuid::Uuid; use workspace2::{AppState, WorkspaceStore}; -use zed2::languages; +use zed2::{build_window_options, languages}; use zed2::{ensure_only_instance, Assets, IsOnlyInstance}; mod open_listener; diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index 4f9aad042f236e180794a1b7740afece91c30638..478e3a20d2c92628e0c76816cce2060208257390 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -6,8 +6,8 @@ mod open_listener; pub use assets::*; use collections::HashMap; use gpui2::{ - point, px, AsyncAppContext, Point, Styled, TitlebarOptions, WindowBounds, WindowKind, - WindowOptions, + point, px, AppContext, AsyncAppContext, MainThread, Point, TitlebarOptions, WindowBounds, + WindowKind, WindowOptions, }; pub use only_instance::*; pub use open_listener::*; @@ -218,11 +218,11 @@ pub async fn handle_cli_connection( pub fn build_window_options( bounds: Option, - display: Option, - platform: &dyn Platform, + display_uuid: Option, + cx: MainThread, ) -> WindowOptions { let bounds = bounds.unwrap_or(WindowBounds::Maximized); - let display_id = display.and_then(|display| platform.screen_by_id(display)); + let display = display_uuid.and_then(|uuid| cx.display_for_uuid(uuid)); WindowOptions { bounds, @@ -236,6 +236,6 @@ pub fn build_window_options( show: false, kind: WindowKind::Normal, is_movable: false, - display_id, + display_id: display.map(|display| display.id()), } }