use std::path::PathBuf;
use log::{error, warn};
use serde::{Deserialize, Serialize};
use winit::dpi::{PhysicalPosition, PhysicalSize};
use crate::{
settings::Settings, units::GridSize, window::WindowSettings, window::WinitWindowWrapper,
};
const SETTINGS_FILE: &str = "neovide-settings.json";
pub const DEFAULT_GRID_SIZE: GridSize<u32> = GridSize { width: 100, height: 50 };
pub const MIN_GRID_SIZE: GridSize<u32> = GridSize { width: 20, height: 6 };
pub const MAX_GRID_SIZE: GridSize<u32> = GridSize { width: 10000, height: 1000 };
#[derive(Serialize, Deserialize, Debug)]
pub enum PersistentWindowSettings {
Maximized {
#[serde(default)]
grid_size: Option<GridSize<u32>>,
},
Windowed {
#[serde(default)]
position: PhysicalPosition<i32>,
#[serde(default)]
pixel_size: Option<PhysicalSize<u32>>,
#[serde(default)]
grid_size: Option<GridSize<u32>>,
},
}
#[derive(Serialize, Deserialize)]
struct PersistentSettings {
window: PersistentWindowSettings,
}
fn settings_path() -> PathBuf {
let mut settings_path = neovide_std_datapath();
settings_path.push(SETTINGS_FILE);
settings_path
}
fn load_settings() -> Result<PersistentSettings, String> {
let settings_path = settings_path();
let json = std::fs::read_to_string(settings_path).map_err(|e| e.to_string())?;
serde_json::from_str(&json).map_err(|e| e.to_string())
}
pub fn neovide_std_datapath() -> PathBuf {
dirs::data_local_dir()
.unwrap_or_else(|| {
warn!("Could not determine local data directory, falling back to current directory");
PathBuf::from(".")
})
.join("neovide")
}
pub fn load_last_window_settings() -> Result<PersistentWindowSettings, String> {
let settings = load_settings()?;
let loaded_settings = settings.window;
log::debug!("Loaded window settings: {loaded_settings:?}");
Ok(loaded_settings)
}
pub fn save_window_size(window_wrapper: &WinitWindowWrapper, settings: &Settings) {
if window_wrapper.routes.is_empty() {
return;
}
let window_id = window_wrapper.get_focused_route().unwrap();
let route = window_wrapper.routes.get(&window_id).unwrap();
let window = route.window.winit_window.clone();
if window.is_minimized() == Some(true) {
return;
}
let maximized = window.is_maximized();
let pixel_size = window.inner_size();
let grid_size = window_wrapper.get_grid_size();
let position = window.outer_position().ok();
let window_settings = settings.get::<WindowSettings>();
let settings = PersistentSettings {
window: if maximized && window_settings.remember_window_size {
PersistentWindowSettings::Maximized {
grid_size: { window_settings.remember_window_size.then_some(grid_size) },
}
} else {
PersistentWindowSettings::Windowed {
pixel_size: { window_settings.remember_window_size.then_some(pixel_size) },
grid_size: { window_settings.remember_window_size.then_some(grid_size) },
position: {
window_settings
.remember_window_position
.then_some(position)
.flatten()
.unwrap_or_default()
},
}
},
};
let settings_path = settings_path();
if let Err(write_error) = std::fs::create_dir_all(neovide_std_datapath()) {
error!("Could not create settings directory: {write_error}");
return;
}
let json = match serde_json::to_string(&settings) {
Ok(json) => json,
Err(serialize_error) => {
error!("Could not serialize window settings: {serialize_error}");
return;
}
};
log::debug!("Saved Window Settings: {json}");
if let Err(write_error) = std::fs::write(&settings_path, json) {
error!("Can't write to {settings_path:?}: {write_error}");
}
}
pub fn clamped_grid_size(grid_size: &GridSize<u32>) -> GridSize<u32> {
grid_size.clamp(MIN_GRID_SIZE, MAX_GRID_SIZE)
}