Add support for persistent storage of panel layouts, sizes, and active tabs (#4017)

* Add persistence to panel layouts

* Fix and persist the Window > Focus Document mode

* Add a Window > Reset Workspace action

* workspace_layout.json -> workspace_layout.ron

* Fix native app hole punch

* Cleanup review pass
This commit is contained in:
Keavon Chambers
2026-04-08 21:05:58 -07:00
committed by GitHub
parent b099e2faca
commit b100892bfa
20 changed files with 346 additions and 107 deletions

View File

@@ -21,6 +21,7 @@ use crate::persist::PersistentData;
use crate::preferences;
use crate::render::{RenderError, RenderState};
use crate::window::Window;
use crate::workspace_layout;
use crate::wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, InputMessage, MouseKeys, MouseState, Preferences};
use crate::wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, serialize_frontend_messages};
@@ -304,6 +305,15 @@ impl App {
let message = DesktopWrapperMessage::LoadPreferences { preferences };
responses.push(message);
}
DesktopFrontendMessage::PersistenceWriteWorkspaceLayout { workspace_layout: layout } => {
workspace_layout::write(&layout);
}
DesktopFrontendMessage::PersistenceLoadWorkspaceLayout => {
if let Some(workspace_layout) = workspace_layout::read() {
let message = DesktopWrapperMessage::LoadWorkspaceLayout { workspace_layout };
responses.push(message);
}
}
DesktopFrontendMessage::PersistenceLoadCurrentDocument => {
if let Some((id, document)) = self.persistent_data.current_document() {
let message = DesktopWrapperMessage::LoadDocument {

View File

@@ -9,6 +9,7 @@ pub(crate) const APP_DIRECTORY_NAME: &str = "Graphite";
pub(crate) const APP_LOCK_FILE_NAME: &str = "instance.lock";
pub(crate) const APP_STATE_FILE_NAME: &str = "state.ron";
pub(crate) const APP_PREFERENCES_FILE_NAME: &str = "preferences.ron";
pub(crate) const APP_WORKSPACE_LAYOUT_FILE_NAME: &str = "workspace_layout.ron";
pub(crate) const APP_DOCUMENTS_DIRECTORY_NAME: &str = "documents";
// CEF configuration constants

View File

@@ -20,6 +20,7 @@ mod persist;
mod preferences;
mod render;
mod window;
mod workspace_layout;
pub(crate) mod consts;

View File

@@ -72,7 +72,7 @@ impl NativeWindowHandle {
// Subclass the main window.
// https://learn.microsoft.com/windows/win32/api/winuser/nf-winuser-setwindowlongptra
let prev_window_message_handler = unsafe { SetWindowLongPtrW(main, GWLP_WNDPROC, main_window_handle_message as isize) };
let prev_window_message_handler = unsafe { SetWindowLongPtrW(main, GWLP_WNDPROC, main_window_handle_message as *const () as isize) };
if prev_window_message_handler == 0 {
let _ = unsafe { DestroyWindow(helper) };
panic!("SetWindowLongPtrW failed");

View File

@@ -0,0 +1,15 @@
pub(crate) fn write(workspace_layout: &str) {
std::fs::write(file_path(), workspace_layout).unwrap_or_else(|e| {
tracing::error!("Failed to write workspace layout to disk: {e}");
});
}
pub(crate) fn read() -> Option<String> {
std::fs::read_to_string(file_path()).ok()
}
fn file_path() -> std::path::PathBuf {
let mut path = crate::dirs::app_data_dir();
path.push(crate::consts::APP_WORKSPACE_LAYOUT_FILE_NAME);
path
}