Detailed changes
@@ -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<PathBuf> {
self.platform().path_for_auxiliary_executable(name)
}
+
+ pub fn display_for_uuid(&self, uuid: Uuid) -> Option<Rc<dyn PlatformDisplay>> {
+ self.platform()
+ .displays()
+ .into_iter()
+ .find(|display| display.uuid().ok() == Some(uuid))
+ }
}
impl MainThread<AppContext> {
@@ -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<Uuid>;
fn as_any(&self) -> &dyn Any;
fn bounds(&self) -> Bounds<GlobalPixels>;
}
@@ -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> {
Self::all().find(|screen| screen.id() == id)
}
+ /// Get the screen with the given persistent [Uuid].
+ pub fn find_by_uuid(uuid: Uuid) -> Option<Self> {
+ 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<Item = Self> {
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<Uuid> {
+ 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
}
@@ -128,6 +128,7 @@ pub trait SearchableItemHandle: ItemHandle {
) -> Option<usize>;
}
+// todo!("here is where we need to use AnyWeakView");
impl<T: SearchableItem> SearchableItemHandle for View<T> {
fn downgrade(&self) -> Box<dyn WeakSearchableItemHandle> {
// Box::new(self.downgrade())
@@ -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<WorkspaceStore>,
pub fs: Arc<dyn fs2::Fs>,
pub build_window_options:
- fn(Option<WindowBounds>, Option<DisplayId>, &MainThread<AppContext>) -> WindowOptions,
+ fn(Option<WindowBounds>, Option<Uuid>, MainThread<AppContext>) -> WindowOptions,
pub initialize_workspace:
fn(WeakModel<Workspace>, bool, Arc<AppState>, AsyncAppContext) -> Task<anyhow::Result<()>>,
pub node_runtime: Arc<dyn NodeRuntime>,
@@ -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;
@@ -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<WindowBounds>,
- display: Option<Uuid>,
- platform: &dyn Platform,
+ display_uuid: Option<Uuid>,
+ cx: MainThread<AppContext>,
) -> 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()),
}
}