Open new windows with a default size and position (#9204)
This PR changes GPUI to open windows with a default size and location, and to otherwise inherit from their spawning window. Note: The linux build now crashes on startup. Release Notes: - N/A --------- Co-authored-by: Nathan <nathan@zed.dev> Co-authored-by: Ezekiel Warren <zaucy@users.noreply.github.com>
This commit is contained in:
parent
9a2dceeea1
commit
e792c1a5c5
30 changed files with 443 additions and 347 deletions
|
@ -4,7 +4,7 @@ use std::path::Path;
|
|||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql};
|
||||
use gpui::{point, size, Axis, Bounds, WindowBounds};
|
||||
use gpui::{point, size, Axis, Bounds};
|
||||
|
||||
use sqlez::{
|
||||
bindable::{Bind, Column, StaticColumnCount},
|
||||
|
@ -59,7 +59,7 @@ impl sqlez::bindable::Column for SerializedAxis {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub(crate) struct SerializedWindowsBounds(pub(crate) WindowBounds);
|
||||
pub(crate) struct SerializedWindowsBounds(pub(crate) Bounds<gpui::GlobalPixels>);
|
||||
|
||||
impl StaticColumnCount for SerializedWindowsBounds {
|
||||
fn column_count() -> usize {
|
||||
|
@ -69,30 +69,15 @@ impl StaticColumnCount for SerializedWindowsBounds {
|
|||
|
||||
impl Bind for SerializedWindowsBounds {
|
||||
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
|
||||
let (region, next_index) = match self.0 {
|
||||
WindowBounds::Fullscreen => {
|
||||
let next_index = statement.bind(&"Fullscreen", start_index)?;
|
||||
(None, next_index)
|
||||
}
|
||||
WindowBounds::Maximized => {
|
||||
let next_index = statement.bind(&"Maximized", start_index)?;
|
||||
(None, next_index)
|
||||
}
|
||||
WindowBounds::Fixed(region) => {
|
||||
let next_index = statement.bind(&"Fixed", start_index)?;
|
||||
(Some(region), next_index)
|
||||
}
|
||||
};
|
||||
let next_index = statement.bind(&"Fixed", start_index)?;
|
||||
|
||||
statement.bind(
|
||||
®ion.map(|region| {
|
||||
(
|
||||
SerializedGlobalPixels(region.origin.x),
|
||||
SerializedGlobalPixels(region.origin.y),
|
||||
SerializedGlobalPixels(region.size.width),
|
||||
SerializedGlobalPixels(region.size.height),
|
||||
)
|
||||
}),
|
||||
&(
|
||||
SerializedGlobalPixels(self.0.origin.x),
|
||||
SerializedGlobalPixels(self.0.origin.y),
|
||||
SerializedGlobalPixels(self.0.size.width),
|
||||
SerializedGlobalPixels(self.0.size.height),
|
||||
),
|
||||
next_index,
|
||||
)
|
||||
}
|
||||
|
@ -102,18 +87,16 @@ impl Column for SerializedWindowsBounds {
|
|||
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
|
||||
let (window_state, next_index) = String::column(statement, start_index)?;
|
||||
let bounds = match window_state.as_str() {
|
||||
"Fullscreen" => SerializedWindowsBounds(WindowBounds::Fullscreen),
|
||||
"Maximized" => SerializedWindowsBounds(WindowBounds::Maximized),
|
||||
"Fixed" => {
|
||||
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
|
||||
let x: f64 = x;
|
||||
let y: f64 = y;
|
||||
let width: f64 = width;
|
||||
let height: f64 = height;
|
||||
SerializedWindowsBounds(WindowBounds::Fixed(Bounds {
|
||||
SerializedWindowsBounds(Bounds {
|
||||
origin: point(x.into(), y.into()),
|
||||
size: size(width.into(), height.into()),
|
||||
}))
|
||||
})
|
||||
}
|
||||
_ => bail!("Window State did not have a valid string"),
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ use db::sqlez::{
|
|||
bindable::{Bind, Column, StaticColumnCount},
|
||||
statement::Statement,
|
||||
};
|
||||
use gpui::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
|
||||
use gpui::{AsyncWindowContext, Bounds, GlobalPixels, Model, Task, View, WeakView};
|
||||
use project::Project;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
|
@ -69,7 +69,7 @@ pub(crate) struct SerializedWorkspace {
|
|||
pub(crate) id: WorkspaceId,
|
||||
pub(crate) location: WorkspaceLocation,
|
||||
pub(crate) center_group: SerializedPaneGroup,
|
||||
pub(crate) bounds: Option<WindowBounds>,
|
||||
pub(crate) bounds: Option<Bounds<GlobalPixels>>,
|
||||
pub(crate) display: Option<Uuid>,
|
||||
pub(crate) docks: DockStructure,
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ use gpui::{
|
|||
FocusableView, Global, GlobalPixels, InteractiveElement, IntoElement, KeyContext, Keystroke,
|
||||
LayoutId, ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Pixels, Point,
|
||||
PromptLevel, Render, SharedString, Size, Styled, Subscription, Task, View, ViewContext,
|
||||
VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||
VisualContext, WeakView, WindowContext, WindowHandle, WindowOptions,
|
||||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
||||
use itertools::Itertools;
|
||||
|
@ -362,8 +362,7 @@ pub struct AppState {
|
|||
pub user_store: Model<UserStore>,
|
||||
pub workspace_store: Model<WorkspaceStore>,
|
||||
pub fs: Arc<dyn fs::Fs>,
|
||||
pub build_window_options:
|
||||
fn(Option<WindowBounds>, Option<Uuid>, &mut AppContext) -> WindowOptions,
|
||||
pub build_window_options: fn(Option<Uuid>, &mut AppContext) -> WindowOptions,
|
||||
pub node_runtime: Arc<dyn NodeRuntime>,
|
||||
}
|
||||
|
||||
|
@ -424,7 +423,7 @@ impl AppState {
|
|||
user_store,
|
||||
workspace_store,
|
||||
node_runtime: FakeNodeRuntime::new(),
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
build_window_options: |_, _| Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -690,18 +689,16 @@ impl Workspace {
|
|||
cx.observe_window_bounds(move |_, cx| {
|
||||
if let Some(display) = cx.display() {
|
||||
// Transform fixed bounds to be stored in terms of the containing display
|
||||
let mut bounds = cx.window_bounds();
|
||||
if let WindowBounds::Fixed(window_bounds) = &mut bounds {
|
||||
let display_bounds = display.bounds();
|
||||
window_bounds.origin.x -= display_bounds.origin.x;
|
||||
window_bounds.origin.y -= display_bounds.origin.y;
|
||||
}
|
||||
let mut window_bounds = cx.window_bounds();
|
||||
let display_bounds = display.bounds();
|
||||
window_bounds.origin.x -= display_bounds.origin.x;
|
||||
window_bounds.origin.y -= display_bounds.origin.y;
|
||||
|
||||
if let Some(display_uuid) = display.uuid().log_err() {
|
||||
cx.background_executor()
|
||||
.spawn(DB.set_window_bounds(
|
||||
workspace_id,
|
||||
SerializedWindowsBounds(bounds),
|
||||
SerializedWindowsBounds(window_bounds),
|
||||
display_uuid,
|
||||
))
|
||||
.detach_and_log_err(cx);
|
||||
|
@ -847,19 +844,16 @@ impl Workspace {
|
|||
|
||||
// Stored bounds are relative to the containing display.
|
||||
// So convert back to global coordinates if that screen still exists
|
||||
if let WindowBounds::Fixed(mut window_bounds) = bounds {
|
||||
let screen = cx
|
||||
.update(|cx| {
|
||||
cx.displays().into_iter().find(|display| {
|
||||
display.uuid().ok() == Some(serialized_display)
|
||||
})
|
||||
let screen = cx
|
||||
.update(|cx| {
|
||||
cx.displays().into_iter().find(|display| {
|
||||
display.uuid().ok() == Some(serialized_display)
|
||||
})
|
||||
.ok()??;
|
||||
let screen_bounds = screen.bounds();
|
||||
window_bounds.origin.x += screen_bounds.origin.x;
|
||||
window_bounds.origin.y += screen_bounds.origin.y;
|
||||
bounds = WindowBounds::Fixed(window_bounds);
|
||||
}
|
||||
})
|
||||
.ok()??;
|
||||
let screen_bounds = screen.bounds();
|
||||
bounds.origin.x += screen_bounds.origin.x;
|
||||
bounds.origin.y += screen_bounds.origin.y;
|
||||
|
||||
Some((bounds, serialized_display))
|
||||
})
|
||||
|
@ -867,9 +861,8 @@ impl Workspace {
|
|||
};
|
||||
|
||||
// Use the serialized workspace to construct the new window
|
||||
let options =
|
||||
cx.update(|cx| (app_state.build_window_options)(bounds, display, cx))?;
|
||||
|
||||
let mut options = cx.update(|cx| (app_state.build_window_options)(display, cx))?;
|
||||
options.bounds = bounds;
|
||||
cx.open_window(options, {
|
||||
let app_state = app_state.clone();
|
||||
let project_handle = project_handle.clone();
|
||||
|
@ -3610,7 +3603,7 @@ impl Workspace {
|
|||
client,
|
||||
user_store,
|
||||
fs: project.read(cx).fs().clone(),
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
build_window_options: |_, _| Default::default(),
|
||||
node_runtime: FakeNodeRuntime::new(),
|
||||
});
|
||||
let workspace = Self::new(0, project, app_state, cx);
|
||||
|
@ -3663,17 +3656,15 @@ impl Workspace {
|
|||
}
|
||||
}
|
||||
|
||||
fn window_bounds_env_override(cx: &AsyncAppContext) -> Option<WindowBounds> {
|
||||
fn window_bounds_env_override(cx: &AsyncAppContext) -> Option<Bounds<GlobalPixels>> {
|
||||
let display_origin = cx
|
||||
.update(|cx| Some(cx.displays().first()?.bounds().origin))
|
||||
.ok()??;
|
||||
ZED_WINDOW_POSITION
|
||||
.zip(*ZED_WINDOW_SIZE)
|
||||
.map(|(position, size)| {
|
||||
WindowBounds::Fixed(Bounds {
|
||||
origin: display_origin + position,
|
||||
size,
|
||||
})
|
||||
.map(|(position, size)| Bounds {
|
||||
origin: display_origin + position,
|
||||
size,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -4553,7 +4544,8 @@ pub fn join_hosted_project(
|
|||
|
||||
let window_bounds_override = window_bounds_env_override(&cx);
|
||||
cx.update(|cx| {
|
||||
let options = (app_state.build_window_options)(window_bounds_override, None, cx);
|
||||
let mut options = (app_state.build_window_options)(None, cx);
|
||||
options.bounds = window_bounds_override;
|
||||
cx.open_window(options, |cx| {
|
||||
cx.new_view(|cx| Workspace::new(0, project, app_state.clone(), cx))
|
||||
})
|
||||
|
@ -4611,7 +4603,8 @@ pub fn join_in_room_project(
|
|||
|
||||
let window_bounds_override = window_bounds_env_override(&cx);
|
||||
cx.update(|cx| {
|
||||
let options = (app_state.build_window_options)(window_bounds_override, None, cx);
|
||||
let mut options = (app_state.build_window_options)(None, cx);
|
||||
options.bounds = window_bounds_override;
|
||||
cx.open_window(options, |cx| {
|
||||
cx.new_view(|cx| Workspace::new(0, project, app_state.clone(), cx))
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue