cleanup & defer saving state until `ClosedRequest`

pull/104/head
amrbashir 2 years ago
parent c41a1d072a
commit 1930a1aa84
No known key found for this signature in database
GPG Key ID: BBD7A47A2003FF33

@ -51,7 +51,7 @@ impl Default for StateFlags {
} }
#[derive(Debug, Default, Deserialize, Serialize)] #[derive(Debug, Default, Deserialize, Serialize)]
struct WindowMetadata { struct WindowState {
width: f64, width: f64,
height: f64, height: f64,
x: i32, x: i32,
@ -62,7 +62,7 @@ struct WindowMetadata {
fullscreen: bool, fullscreen: bool,
} }
struct WindowStateCache(Arc<Mutex<HashMap<String, WindowMetadata>>>); struct WindowStateCache(Arc<Mutex<HashMap<String, WindowState>>>);
pub trait AppHandleExt { pub trait AppHandleExt {
fn save_window_state(&self) -> Result<()>; fn save_window_state(&self) -> Result<()>;
} }
@ -131,55 +131,41 @@ impl<R: Runtime> WindowExt for Window<R> {
should_show = state.visible; should_show = state.visible;
} else { } else {
let LogicalSize { width, height } = match flags.contains(StateFlags::SIZE) { let mut metadata = WindowState::default();
true => {
if flags.contains(StateFlags::SIZE) {
let scale_factor = self let scale_factor = self
.current_monitor()? .current_monitor()?
.map(|m| m.scale_factor()) .map(|m| m.scale_factor())
.unwrap_or(1.); .unwrap_or(1.);
self.inner_size()?.to_logical(scale_factor) let size = self.inner_size()?.to_logical(scale_factor);
metadata.width = size.width;
metadata.height = size.height;
} }
false => (0, 0).into(),
};
let PhysicalPosition { x, y } = match flags.contains(StateFlags::POSITION) { if flags.contains(StateFlags::POSITION) {
true => self.outer_position()?, let pos = self.outer_position()?;
false => (0, 0).into(), metadata.x = pos.x;
}; metadata.y = pos.y;
}
let maximized = match flags.contains(StateFlags::MAXIMIZED) { if flags.contains(StateFlags::MAXIMIZED) {
true => self.is_maximized().unwrap_or(false), metadata.maximized = self.is_maximized()?;
false => false, }
};
let visible = match flags.contains(StateFlags::VISIBLE) { if flags.contains(StateFlags::VISIBLE) {
true => self.is_visible().unwrap_or(true), metadata.visible = self.is_visible()?;
false => true, }
};
let decorated = match flags.contains(StateFlags::DECORATIONS) { if flags.contains(StateFlags::DECORATIONS) {
true => self.is_visible().unwrap_or(true), metadata.visible = self.is_visible()?;
false => true, }
};
let fullscreen = match flags.contains(StateFlags::FULLSCREEN) { if flags.contains(StateFlags::FULLSCREEN) {
true => self.is_fullscreen().unwrap_or(false), metadata.fullscreen = self.is_fullscreen()?;
false => false, }
};
c.insert( c.insert(self.label().into(), metadata);
self.label().into(),
WindowMetadata {
width,
height,
x,
y,
maximized,
visible,
decorated,
fullscreen,
},
);
} }
if flags.contains(StateFlags::VISIBLE) && should_show { if flags.contains(StateFlags::VISIBLE) && should_show {
@ -191,6 +177,62 @@ impl<R: Runtime> WindowExt for Window<R> {
} }
} }
trait WindowExtInternal {
fn update_state(&self, state: &mut WindowState, flags: StateFlags) -> tauri::Result<()>;
}
impl<R: Runtime> WindowExtInternal for Window<R> {
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.inner_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)] #[derive(Default)]
pub struct Builder { pub struct Builder {
denylist: HashSet<String>, denylist: HashSet<String>,
@ -221,7 +263,7 @@ impl Builder {
pub fn build<R: Runtime>(self) -> TauriPlugin<R> { pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
PluginBuilder::new("window-state") PluginBuilder::new("window-state")
.setup(|app| { .setup(|app| {
let cache: Arc<Mutex<HashMap<String, WindowMetadata>>> = if let Some(app_dir) = let cache: Arc<Mutex<HashMap<String, WindowState>>> = if let Some(app_dir) =
app.path_resolver().app_config_dir() app.path_resolver().app_config_dir()
{ {
let state_path = app_dir.join(STATE_FILENAME); let state_path = app_dir.join(STATE_FILENAME);
@ -256,75 +298,10 @@ impl Builder {
let window_clone = window.clone(); let window_clone = window.clone();
let flags = self.state_flags; let flags = self.state_flags;
window.on_window_event(move |e| match e { window.on_window_event(move |e| match e {
WindowEvent::Moved(position) => {
let mut c = cache.lock().unwrap();
if let Some(state) = c.get_mut(&label) {
if flags.intersects(StateFlags::MAXIMIZED | StateFlags::POSITION) {
let is_maximized = window_clone.is_maximized().unwrap_or(false);
if flags.contains(StateFlags::MAXIMIZED) {
state.maximized = is_maximized;
}
if flags.contains(StateFlags::POSITION) {
if let Some(monitor) = window_clone.current_monitor().unwrap() {
let monitor_position = monitor.position();
// save only window positions that are inside the current monitor
if position.x > monitor_position.x
&& position.y > monitor_position.y
&& !is_maximized
{
state.x = position.x;
state.y = position.y;
}
}
}
}
}
}
WindowEvent::Resized(size) => {
let mut c = cache.lock().unwrap();
if let Some(state) = c.get_mut(&label) {
let is_maximized =
match flags.intersects(StateFlags::MAXIMIZED | StateFlags::SIZE) {
true => window_clone.is_maximized().unwrap_or(false),
false => false,
};
if flags.contains(StateFlags::MAXIMIZED) {
state.maximized = is_maximized;
}
if flags.contains(StateFlags::FULLSCREEN) {
state.fullscreen = window_clone.is_fullscreen().unwrap_or(false);
}
if flags.contains(StateFlags::DECORATIONS) {
state.decorated = window_clone.is_decorated().unwrap_or(true);
}
if flags.contains(StateFlags::SIZE) {
let scale_factor = window_clone
.current_monitor()
.ok()
.map(|m| m.map(|m| m.scale_factor()).unwrap_or(1.))
.unwrap_or(1.);
let size = size.to_logical(scale_factor);
// It doesn't make sense to save a window with 0 height or width
if size.width > 0. && size.height > 0. && !is_maximized {
state.width = size.width;
state.height = size.height;
}
}
}
}
WindowEvent::CloseRequested { .. } => { WindowEvent::CloseRequested { .. } => {
let mut c = cache.lock().unwrap(); let mut c = cache.lock().unwrap();
if let Some(state) = c.get_mut(&label) { if let Some(mut state) = c.get_mut(&label) {
if flags.contains(StateFlags::VISIBLE) { let _ = window_clone.update_state(&mut state, flags);
state.visible = window_clone.is_visible().unwrap_or(true);
}
} }
} }
_ => {} _ => {}

Loading…
Cancel
Save