zed: Persist window stack order across restarts (#15419)

This changes the workspace/session serialization to also persist the
order of windows across restarts.

Release Notes:

- Improved restoring of windows across restarts: the order of the
windows is now also restored. That means windows that were in the
foreground when Zed was quit will be in the foreground after restart.
(Right now only supported on Linux/X11, not on Linux/Wayland.)

Demo:



https://github.com/user-attachments/assets/0b8162f8-f06d-43df-88d3-c45d8460fb68
This commit is contained in:
Thorsten Ball 2024-07-29 17:05:56 +02:00 committed by GitHub
parent 6e1f7c6e1d
commit f58ef9b82b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 365 additions and 55 deletions

View file

@ -36,7 +36,7 @@ use gpui::{
EventEmitter, Flatten, FocusHandle, FocusableView, Global, Hsla, KeyContext, Keystroke,
ManagedView, Model, ModelContext, MouseButton, PathPromptOptions, Point, PromptLevel, Render,
ResizeEdge, Size, Stateful, Subscription, Task, Tiling, View, WeakView, WindowBounds,
WindowHandle, WindowOptions,
WindowHandle, WindowId, WindowOptions,
};
use item::{
FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings,
@ -58,7 +58,7 @@ pub use persistence::{
use postage::stream::Stream;
use project::{DirectoryLister, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
use serde::Deserialize;
use session::Session;
use session::AppSession;
use settings::Settings;
use shared_screen::SharedScreen;
use sqlez::{
@ -539,7 +539,7 @@ pub struct AppState {
pub fs: Arc<dyn fs::Fs>,
pub build_window_options: fn(Option<Uuid>, &mut AppContext) -> WindowOptions,
pub node_runtime: Arc<dyn NodeRuntime>,
pub session: Session,
pub session: Model<AppSession>,
}
struct GlobalAppState(Weak<AppState>);
@ -587,7 +587,7 @@ impl AppState {
let clock = Arc::new(clock::FakeSystemClock::default());
let http_client = http_client::FakeHttpClient::with_404_response();
let client = Client::new(clock, http_client.clone(), cx);
let session = Session::test();
let session = cx.new_model(|cx| AppSession::new(Session::test(), cx));
let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
@ -917,7 +917,7 @@ impl Workspace {
let modal_layer = cx.new_view(|_| ModalLayer::new());
let session_id = app_state.session.id().to_owned();
let session_id = app_state.session.read(cx).id().to_owned();
let mut active_call = None;
if let Some(call) = ActiveCall::try_global(cx) {
@ -4032,6 +4032,7 @@ impl Workspace {
docks,
centered_layout: self.centered_layout,
session_id: self.session_id.clone(),
window_id: Some(cx.window_handle().window_id().as_u64()),
};
return cx.spawn(|_| persistence::DB.save_workspace(serialized_workspace));
}
@ -4291,6 +4292,7 @@ impl Workspace {
let user_store = project.read(cx).user_store();
let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
let session = cx.new_model(|cx| AppSession::new(Session::test(), cx));
cx.activate_window();
let app_state = Arc::new(AppState {
languages: project.read(cx).languages().clone(),
@ -4300,7 +4302,7 @@ impl Workspace {
fs: project.read(cx).fs().clone(),
build_window_options: |_, _| Default::default(),
node_runtime: FakeNodeRuntime::new(),
session: Session::test(),
session,
});
let workspace = Self::new(Default::default(), project, app_state, cx);
workspace.active_pane.update(cx, |pane, cx| pane.focus(cx));
@ -4902,8 +4904,11 @@ pub async fn last_opened_workspace_paths() -> Option<LocalPaths> {
DB.last_workspace().await.log_err().flatten()
}
pub fn last_session_workspace_locations(last_session_id: &str) -> Option<Vec<LocalPaths>> {
DB.last_session_workspace_locations(last_session_id)
pub fn last_session_workspace_locations(
last_session_id: &str,
last_session_window_stack: Option<Vec<WindowId>>,
) -> Option<Vec<LocalPaths>> {
DB.last_session_workspace_locations(last_session_id, last_session_window_stack)
.log_err()
}