From a9f464345a92ec8bb7b3ce83ebafc69ea5b1047d Mon Sep 17 00:00:00 2001 From: Jamie Pine <32987599+jamiepine@users.noreply.github.com> Date: Wed, 20 Mar 2024 00:07:20 -0700 Subject: [PATCH] Fix window not opening (#2224) the fix --- Cargo.lock | 4 +- .../tauri-plugin-window-state/Cargo.toml | 16 - .../tauri-plugin-window-state/REAMDE.md | 1 - .../tauri-plugin-window-state/src/cmd.rs | 28 -- .../tauri-plugin-window-state/src/lib.rs | 380 ------------------ apps/desktop/src-tauri/Cargo.toml | 2 +- 6 files changed, 4 insertions(+), 427 deletions(-) delete mode 100644 apps/desktop/crates/tauri-plugin-window-state/Cargo.toml delete mode 100644 apps/desktop/crates/tauri-plugin-window-state/REAMDE.md delete mode 100644 apps/desktop/crates/tauri-plugin-window-state/src/cmd.rs delete mode 100644 apps/desktop/crates/tauri-plugin-window-state/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 5c0bd3710..f521ee2cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9819,7 +9819,9 @@ dependencies = [ [[package]] name = "tauri-plugin-window-state" -version = "0.1.0" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa47eaa4047a7b51064caff32f0c6282e2c5adc6ceacdd493ecf1b01fa4b0eaa" dependencies = [ "bincode 1.3.3", "bitflags 2.4.1", diff --git a/apps/desktop/crates/tauri-plugin-window-state/Cargo.toml b/apps/desktop/crates/tauri-plugin-window-state/Cargo.toml deleted file mode 100644 index a418acf12..000000000 --- a/apps/desktop/crates/tauri-plugin-window-state/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "tauri-plugin-window-state" -publish = false -version = "0.1.0" -license.workspace = true -edition.workspace = true -repository.workspace = true - -[dependencies] -serde = { version = "1", features = ["derive"] } -serde_json = "1" -tauri = "1" -thiserror = "1" -log = "0.4" -bincode = "1.3" -bitflags = "2" diff --git a/apps/desktop/crates/tauri-plugin-window-state/REAMDE.md b/apps/desktop/crates/tauri-plugin-window-state/REAMDE.md deleted file mode 100644 index d519c604d..000000000 --- a/apps/desktop/crates/tauri-plugin-window-state/REAMDE.md +++ /dev/null @@ -1 +0,0 @@ -Fork of [tauri-plugin-window-state](https://github.com/tauri-apps/plugins-workspace/blob/v1/plugins/window-state). diff --git a/apps/desktop/crates/tauri-plugin-window-state/src/cmd.rs b/apps/desktop/crates/tauri-plugin-window-state/src/cmd.rs deleted file mode 100644 index ec86f0e40..000000000 --- a/apps/desktop/crates/tauri-plugin-window-state/src/cmd.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::{AppHandleExt, StateFlags, WindowExt}; -use tauri::{command, AppHandle, Manager, Runtime}; - -#[command] -pub async fn save_window_state( - app: AppHandle, - 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( - app: AppHandle, - 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(()) -} diff --git a/apps/desktop/crates/tauri-plugin-window-state/src/lib.rs b/apps/desktop/crates/tauri-plugin-window-state/src/lib.rs deleted file mode 100644 index bceba4dd5..000000000 --- a/apps/desktop/crates/tauri-plugin-window-state/src/lib.rs +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2021 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -use bitflags::bitflags; -use serde::{Deserialize, Serialize}; -use tauri::{ - plugin::{Builder as PluginBuilder, TauriPlugin}, - LogicalSize, Manager, Monitor, PhysicalPosition, PhysicalSize, RunEvent, Runtime, Window, - WindowEvent, -}; - -use std::{ - collections::{HashMap, HashSet}, - fs::{create_dir_all, File}, - io::Write, - sync::{Arc, Mutex}, -}; - -mod cmd; - -pub const STATE_FILENAME: &str = ".window-state"; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error(transparent)] - Io(#[from] std::io::Error), - #[error(transparent)] - Tauri(#[from] tauri::Error), - #[error(transparent)] - TauriApi(#[from] tauri::api::Error), - #[error(transparent)] - Bincode(#[from] Box), -} - -pub type Result = std::result::Result; - -bitflags! { - #[derive(Clone, Copy, Debug)] - pub struct StateFlags: u32 { - const SIZE = 1 << 0; - const POSITION = 1 << 1; - const MAXIMIZED = 1 << 2; - const VISIBLE = 1 << 3; - const DECORATIONS = 1 << 4; - const FULLSCREEN = 1 << 5; - } -} - -impl Default for StateFlags { - fn default() -> Self { - Self::all() - } -} - -#[derive(Debug, Deserialize, Serialize, PartialEq)] -struct WindowState { - width: f64, - height: f64, - x: i32, - y: i32, - maximized: bool, - visible: bool, - decorated: bool, - fullscreen: bool, -} - -impl Default for WindowState { - fn default() -> Self { - Self { - width: Default::default(), - height: Default::default(), - x: Default::default(), - y: Default::default(), - maximized: Default::default(), - visible: true, - decorated: true, - fullscreen: Default::default(), - } - } -} - -struct WindowStateCache(Arc>>); -pub trait AppHandleExt { - /// Saves all open windows state to disk - fn save_window_state(&self, flags: StateFlags) -> Result<()>; -} - -impl AppHandleExt for tauri::AppHandle { - fn save_window_state(&self, flags: StateFlags) -> Result<()> { - if let Some(app_dir) = self.path_resolver().app_config_dir() { - let state_path = app_dir.join(STATE_FILENAME); - let cache = self.state::(); - let mut state = cache.0.lock().unwrap(); - for (label, s) in state.iter_mut() { - if let Some(window) = self.get_window(label) { - window.update_state(s, flags)?; - } - } - - create_dir_all(&app_dir) - .map_err(Error::Io) - .and_then(|_| File::create(state_path).map_err(Into::into)) - .and_then(|mut f| { - f.write_all(&bincode::serialize(&*state).map_err(Error::Bincode)?) - .map_err(Into::into) - }) - } else { - Ok(()) - } - } -} - -pub trait WindowExt { - /// Restores this window state from disk - fn restore_state(&self, flags: StateFlags) -> tauri::Result<()>; -} - -impl WindowExt for Window { - fn restore_state(&self, flags: StateFlags) -> tauri::Result<()> { - let cache = self.state::(); - 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)?; - } - - if flags.contains(StateFlags::SIZE) { - self.set_size(LogicalSize { - width: state.width, - height: state.height, - })?; - } - - if flags.contains(StateFlags::POSITION) { - // restore position to saved value if saved monitor exists - // otherwise, let the OS decide where to place the window - for m in self.available_monitors()? { - if m.contains((state.x, state.y).into()) { - self.set_position(PhysicalPosition { - x: state.x, - y: state.y, - })?; - } - } - } - - if flags.contains(StateFlags::MAXIMIZED) && state.maximized { - self.maximize()?; - } - - if flags.contains(StateFlags::FULLSCREEN) { - self.set_fullscreen(state.fullscreen)?; - } - - should_show = state.visible; - } else { - let mut metadata = WindowState::default(); - - if flags.contains(StateFlags::SIZE) { - let scale_factor = self - .current_monitor()? - .map(|m| m.scale_factor()) - .unwrap_or(1.); - let size = self.inner_size()?.to_logical(scale_factor); - metadata.width = size.width; - metadata.height = size.height; - } - - if flags.contains(StateFlags::POSITION) { - let pos = self.outer_position()?; - metadata.x = pos.x; - metadata.y = pos.y; - } - - if flags.contains(StateFlags::MAXIMIZED) { - metadata.maximized = self.is_maximized()?; - } - - if flags.contains(StateFlags::VISIBLE) { - metadata.visible = self.is_visible()?; - } - - if flags.contains(StateFlags::DECORATIONS) { - metadata.decorated = self.is_decorated()?; - } - - if flags.contains(StateFlags::FULLSCREEN) { - metadata.fullscreen = self.is_fullscreen()?; - } - - c.insert(self.label().into(), metadata); - } - - if flags.contains(StateFlags::VISIBLE) && should_show { - self.show()?; - self.set_focus()?; - } - - Ok(()) - } -} - -trait WindowExtInternal { - fn update_state(&self, state: &mut WindowState, flags: StateFlags) -> tauri::Result<()>; -} - -impl WindowExtInternal for Window { - fn update_state(&self, state: &mut WindowState, flags: StateFlags) -> tauri::Result<()> { - let is_maximized = match flags.intersects(StateFlags::MAXIMIZED | StateFlags::SIZE) { - true => self.is_maximized()?, - false => false, - }; - - if flags.contains(StateFlags::MAXIMIZED) { - state.maximized = is_maximized; - } - - if flags.contains(StateFlags::FULLSCREEN) { - state.fullscreen = self.is_fullscreen()?; - } - - if flags.contains(StateFlags::DECORATIONS) { - state.decorated = self.is_decorated()?; - } - - if flags.contains(StateFlags::VISIBLE) { - state.visible = self.is_visible()?; - } - - if flags.contains(StateFlags::SIZE) { - let scale_factor = self - .current_monitor()? - .map(|m| m.scale_factor()) - .unwrap_or(1.); - let size = self.inner_size()?.to_logical(scale_factor); - - // It doesn't make sense to save a self with 0 height or width - if size.width > 0. && size.height > 0. && !is_maximized { - state.width = size.width; - state.height = size.height; - } - } - - if flags.contains(StateFlags::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 { - state.x = position.x; - state.y = position.y; - } - } - } - - Ok(()) - } -} - -#[derive(Default)] -pub struct Builder { - denylist: HashSet, - skip_initial_state: HashSet, - state_flags: StateFlags, -} - -impl Builder { - /// Sets the state flags to control what state gets restored and saved. - pub fn with_state_flags(mut self, flags: StateFlags) -> Self { - self.state_flags = flags; - self - } - - /// Sets a list of windows that shouldn't be tracked and managed by this plugin - /// for example splash screen windows. - pub fn with_denylist(mut self, denylist: &[&str]) -> Self { - self.denylist = denylist.iter().map(|l| l.to_string()).collect(); - self - } - - /// Adds the given window label to a list of windows to skip initial state restore. - pub fn skip_initial_state(mut self, label: &str) -> Self { - self.skip_initial_state.insert(label.into()); - self - } - - pub fn build(self) -> TauriPlugin { - let flags = self.state_flags; - PluginBuilder::new("window-state") - .invoke_handler(tauri::generate_handler![ - cmd::save_window_state, - cmd::restore_state - ]) - .setup(|app| { - let cache: Arc>> = if let Some(app_dir) = - app.path_resolver().app_config_dir() - { - let state_path = app_dir.join(STATE_FILENAME); - if state_path.exists() { - Arc::new(Mutex::new( - tauri::api::file::read_binary(state_path) - .map_err(Error::TauriApi) - .and_then(|state| bincode::deserialize(&state).map_err(Into::into)) - .unwrap_or_default(), - )) - } else { - Default::default() - } - } else { - Default::default() - }; - app.manage(WindowStateCache(cache)); - Ok(()) - }) - .on_webview_ready(move |window| { - if self.denylist.contains(window.label()) { - return; - } - - if !self.skip_initial_state.contains(window.label()) { - let _ = window.restore_state(self.state_flags); - } - - let cache = window.state::(); - let cache = cache.0.clone(); - 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(); - if let Some(state) = c.get_mut(&label) { - let _ = window_clone.update_state(state, flags); - } - } - }); - }) - .on_event(move |app, event| { - if let RunEvent::Exit = event { - let _ = app.save_window_state(flags); - } - }) - .build() - } -} - -trait MonitorExt { - fn contains(&self, position: PhysicalPosition) -> bool; -} - -impl MonitorExt for Monitor { - fn contains(&self, position: PhysicalPosition) -> bool { - let PhysicalPosition { x, y } = *self.position(); - let PhysicalSize { width, height } = *self.size(); - - x < position.x as _ - && position.x < (x + width as i32) - && y < position.y as _ - && position.y < (y + height as i32) - } -} diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 21737a212..7afb98c3b 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -45,8 +45,8 @@ tauri = { version = "=1.5.3", features = [ "native-tls-vendored", "tracing", ] } -tauri-plugin-window-state = { path = "../crates/tauri-plugin-window-state" } directories = "5.0.1" +tauri-plugin-window-state = "0.1.1" [target.'cfg(target_os = "linux")'.dependencies] sd-desktop-linux = { path = "../crates/linux" }