This commit is contained in:
Nathan Sobo 2023-10-31 11:03:01 -06:00
parent fed391fe6b
commit 0a2fde8707
7 changed files with 69 additions and 12 deletions

View File

@ -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> {

View File

@ -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>;
}

View File

@ -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
}

View File

@ -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())

View File

@ -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>,

View File

@ -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;

View File

@ -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()),
}
}