diff --git a/.changes/window-state-filter-callback.md b/.changes/window-state-filter-callback.md new file mode 100644 index 0000000000..e5846966b5 --- /dev/null +++ b/.changes/window-state-filter-callback.md @@ -0,0 +1,6 @@ +--- +window-state: patch +window-state-js: patch +--- + +Add `Builder::with_filter` callback to exclude specific windows from saving their state. This allows for more flexibility by enabling dynamic exclusion of windows based on custom logic. \ No newline at end of file diff --git a/plugins/window-state/src/lib.rs b/plugins/window-state/src/lib.rs index 8c675d4dab..1f4abdd633 100644 --- a/plugins/window-state/src/lib.rs +++ b/plugins/window-state/src/lib.rs @@ -27,6 +27,7 @@ use std::{ mod cmd; type LabelMapperFn = dyn Fn(&str) -> &str + Send + Sync; +type FilterCallbackFn = dyn Fn(&str) -> bool + Send + Sync; /// Default filename used to store window state. /// @@ -320,6 +321,7 @@ impl WindowExtInternal for Window { #[derive(Default)] pub struct Builder { denylist: HashSet, + filter_callback: Option>, skip_initial_state: HashSet, state_flags: StateFlags, map_label: Option>, @@ -344,12 +346,22 @@ impl Builder { } /// Sets a list of windows that shouldn't be tracked and managed by this plugin - /// for example splash screen windows. + /// 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 } + /// Sets a filter callback to exclude specific windows from being tracked. + /// Return `true` to save the state, or `false` to skip and not save it. + pub fn with_filter(mut self, filter_callback: F) -> Self + where + F: Fn(&str) -> bool + Send + Sync + 'static, + { + self.filter_callback = Some(Box::new(filter_callback)); + 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()); @@ -413,10 +425,19 @@ impl Builder { .map(|map| map(window.label())) .unwrap_or_else(|| window.label()); + // Check deny list names if self.denylist.contains(label) { return; } + // Check deny list callback + if let Some(filter_callback) = &self.filter_callback { + // Don't save the state if the callback returns false + if !filter_callback(label) { + return; + } + } + if !self.skip_initial_state.contains(label) { let _ = window.restore_state(self.state_flags); }