mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-06-06 13:53:54 +02:00
Merge remote-tracking branch 'origin/dev' into next
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
use crate::{AppHandleExt, StateFlags, WindowExt};
|
||||
use tauri::{command, AppHandle, Manager, Runtime};
|
||||
|
||||
#[command]
|
||||
pub async fn save_window_state<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
flags: u32,
|
||||
) -> std::result::Result<(), String> {
|
||||
let flags = StateFlags::from_bits(flags)
|
||||
.ok_or_else(|| format!("Invalid state flags bits: {}", flags))?;
|
||||
app.save_window_state(flags).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub async fn restore_state<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
label: String,
|
||||
flags: u32,
|
||||
) -> std::result::Result<(), String> {
|
||||
let flags = StateFlags::from_bits(flags)
|
||||
.ok_or_else(|| format!("Invalid state flags bits: {}", flags))?;
|
||||
app.get_window(&label)
|
||||
.ok_or_else(|| format!("Couldn't find window with label: {}", label))?
|
||||
.restore_state(flags)
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -17,6 +17,8 @@ use std::{
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
mod cmd;
|
||||
|
||||
pub const STATE_FILENAME: &str = ".window-state";
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
@@ -34,6 +36,7 @@ pub enum Error {
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct StateFlags: u32 {
|
||||
const SIZE = 1 << 0;
|
||||
const POSITION = 1 << 1;
|
||||
@@ -50,7 +53,7 @@ impl Default for StateFlags {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
#[derive(Debug, Default, Deserialize, Serialize, PartialEq)]
|
||||
struct WindowState {
|
||||
width: f64,
|
||||
height: f64,
|
||||
@@ -64,6 +67,7 @@ struct WindowState {
|
||||
|
||||
struct WindowStateCache(Arc<Mutex<HashMap<String, WindowState>>>);
|
||||
pub trait AppHandleExt {
|
||||
/// Saves all open windows state to disk
|
||||
fn save_window_state(&self, flags: StateFlags) -> Result<()>;
|
||||
}
|
||||
|
||||
@@ -93,6 +97,7 @@ impl<R: Runtime> AppHandleExt for tauri::AppHandle<R> {
|
||||
}
|
||||
|
||||
pub trait WindowExt {
|
||||
/// Restores this window state from disk
|
||||
fn restore_state(&self, flags: StateFlags) -> tauri::Result<()>;
|
||||
}
|
||||
|
||||
@@ -100,9 +105,15 @@ impl<R: Runtime> WindowExt for Window<R> {
|
||||
fn restore_state(&self, flags: StateFlags) -> tauri::Result<()> {
|
||||
let cache = self.state::<WindowStateCache>();
|
||||
let mut c = cache.0.lock().unwrap();
|
||||
|
||||
let mut should_show = true;
|
||||
|
||||
if let Some(state) = c.get(self.label()) {
|
||||
// avoid restoring the default zeroed state
|
||||
if *state == WindowState::default() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if flags.contains(StateFlags::DECORATIONS) {
|
||||
self.set_decorations(state.decorated)?;
|
||||
}
|
||||
@@ -225,7 +236,7 @@ impl<R: Runtime> WindowExtInternal for Window<R> {
|
||||
}
|
||||
|
||||
if flags.contains(StateFlags::POSITION) {
|
||||
let position = self.inner_position()?;
|
||||
let position = self.outer_position()?;
|
||||
if let Ok(Some(monitor)) = self.current_monitor() {
|
||||
// save only window positions that are inside the current monitor
|
||||
if monitor.contains(position) && !is_maximized {
|
||||
@@ -269,6 +280,10 @@ impl Builder {
|
||||
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
|
||||
let flags = self.state_flags;
|
||||
PluginBuilder::new("window-state")
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
cmd::save_window_state,
|
||||
cmd::restore_state
|
||||
])
|
||||
.setup(|app, _api| {
|
||||
let cache: Arc<Mutex<HashMap<String, WindowState>>> = if let Ok(app_dir) =
|
||||
app.path().app_config_dir()
|
||||
@@ -304,6 +319,17 @@ impl Builder {
|
||||
let label = window.label().to_string();
|
||||
let window_clone = window.clone();
|
||||
let flags = self.state_flags;
|
||||
|
||||
// insert a default state if this window should be tracked and
|
||||
// the disk cache doesn't have a state for it
|
||||
{
|
||||
cache
|
||||
.lock()
|
||||
.unwrap()
|
||||
.entry(label.clone())
|
||||
.or_insert_with(WindowState::default);
|
||||
}
|
||||
|
||||
window.on_window_event(move |e| {
|
||||
if let WindowEvent::CloseRequested { .. } = e {
|
||||
let mut c = cache.lock().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user