fix: target specific window for window events (#8826)

* fix: target specific window for CLOSE_REQUESTED_EVENT emission

* fix: use emit_filter() instead of emit_to()

* fix: try sending event regardless of existing js listener

* cleanups

* change file

* emit_self -> emit_to_window

---------

Co-authored-by: amrbashir <amr.bashir2015@gmail.com>
This commit is contained in:
Philipp Bokatius 2024-02-12 16:55:20 +01:00 committed by GitHub
parent cf3e40cc47
commit 46b6598a94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 56 additions and 34 deletions

View File

@ -0,0 +1,5 @@
---
'tauri': 'patch:bug'
---
Fix JS `onCloseRequested` catching close event from other windows.

View File

@ -713,21 +713,23 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
#[cfg(feature = "tracing")] #[cfg(feature = "tracing")]
tracing::Span::current().record("target", format!("{target:?}")); tracing::Span::current().record("target", format!("{target:?}"));
self.manager().emit_filter(event, payload, |s| match s { match target {
t @ EventTarget::Window { label } // if targeting all, emit to all using emit without filter
| t @ EventTarget::Webview { label } EventTarget::Any => self.manager().emit(event, payload),
| t @ EventTarget::WebviewWindow { label } => {
if let EventTarget::AnyLabel { // if targeting any label, emit using emit_filter and filter labels
label: target_label, EventTarget::AnyLabel {
} = &target label: target_label,
{ } => self.manager().emit_filter(event, payload, |t| match t {
label == target_label EventTarget::Window { label }
} else { | EventTarget::Webview { label }
t == &target | EventTarget::WebviewWindow { label } => label == &target_label,
} _ => false,
} }),
t => t == &target,
}) // otherwise match same target
_ => self.manager().emit_filter(event, payload, |t| t == &target),
}
} }
/// Emits an event to all [targets](EventTarget) based on the given filter. /// Emits an event to all [targets](EventTarget) based on the given filter.

View File

@ -130,6 +130,27 @@ impl<R: Runtime> WindowManager<R> {
} }
} }
impl<R: Runtime> Window<R> {
/// Emits event to [`EventTarget::Window`] and [`EventTarget::WebviewWindow`]
fn emit_to_window<S: Serialize + Clone>(&self, event: &str, payload: S) -> crate::Result<()> {
let window_label = self.label();
self.emit_filter(event, payload, |target| match target {
EventTarget::Window { label } | EventTarget::WebviewWindow { label } => label == window_label,
_ => false,
})
}
/// Checks whether has js listener for [`EventTarget::Window`] or [`EventTarget::WebviewWindow`]
fn has_js_listener(&self, event: &str) -> bool {
let window_label = self.label();
let listeners = self.manager().listeners();
listeners.has_js_listener(event, |target| match target {
EventTarget::Window { label } | EventTarget::WebviewWindow { label } => label == window_label,
_ => false,
})
}
}
#[derive(Serialize, Clone)] #[derive(Serialize, Clone)]
struct FileDropPayload<'a> { struct FileDropPayload<'a> {
paths: &'a Vec<PathBuf>, paths: &'a Vec<PathBuf>,
@ -142,24 +163,16 @@ fn on_window_event<R: Runtime>(
event: &WindowEvent, event: &WindowEvent,
) -> crate::Result<()> { ) -> crate::Result<()> {
match event { match event {
WindowEvent::Resized(size) => window.emit(WINDOW_RESIZED_EVENT, size)?, WindowEvent::Resized(size) => window.emit_to_window(WINDOW_RESIZED_EVENT, size)?,
WindowEvent::Moved(position) => window.emit(WINDOW_MOVED_EVENT, position)?, WindowEvent::Moved(position) => window.emit_to_window(WINDOW_MOVED_EVENT, position)?,
WindowEvent::CloseRequested { api } => { WindowEvent::CloseRequested { api } => {
let listeners = window.manager().listeners(); if window.has_js_listener(WINDOW_CLOSE_REQUESTED_EVENT) {
let has_js_listener =
listeners.has_js_listener(WINDOW_CLOSE_REQUESTED_EVENT, |target| match target {
EventTarget::Window { label } | EventTarget::WebviewWindow { label } => {
label == window.label()
}
_ => false,
});
if has_js_listener {
api.prevent_close(); api.prevent_close();
} }
window.emit(WINDOW_CLOSE_REQUESTED_EVENT, ())?; window.emit_to_window(WINDOW_CLOSE_REQUESTED_EVENT, ())?;
} }
WindowEvent::Destroyed => { WindowEvent::Destroyed => {
window.emit(WINDOW_DESTROYED_EVENT, ())?; window.emit_to_window(WINDOW_DESTROYED_EVENT, ())?;
let label = window.label(); let label = window.label();
let webviews_map = manager.webview.webviews_lock(); let webviews_map = manager.webview.webviews_lock();
let webviews = webviews_map.values(); let webviews = webviews_map.values();
@ -169,7 +182,7 @@ fn on_window_event<R: Runtime>(
))?; ))?;
} }
} }
WindowEvent::Focused(focused) => window.emit( WindowEvent::Focused(focused) => window.emit_to_window(
if *focused { if *focused {
WINDOW_FOCUS_EVENT WINDOW_FOCUS_EVENT
} else { } else {
@ -181,7 +194,7 @@ fn on_window_event<R: Runtime>(
scale_factor, scale_factor,
new_inner_size, new_inner_size,
.. ..
} => window.emit( } => window.emit_to_window(
WINDOW_SCALE_FACTOR_CHANGED_EVENT, WINDOW_SCALE_FACTOR_CHANGED_EVENT,
ScaleFactorChanged { ScaleFactorChanged {
scale_factor: *scale_factor, scale_factor: *scale_factor,
@ -191,7 +204,7 @@ fn on_window_event<R: Runtime>(
WindowEvent::FileDrop(event) => match event { WindowEvent::FileDrop(event) => match event {
FileDropEvent::Hovered { paths, position } => { FileDropEvent::Hovered { paths, position } => {
let payload = FileDropPayload { paths, position }; let payload = FileDropPayload { paths, position };
window.emit(WINDOW_FILE_DROP_HOVER_EVENT, payload)? window.emit_to_window(WINDOW_FILE_DROP_HOVER_EVENT, payload)?
} }
FileDropEvent::Dropped { paths, position } => { FileDropEvent::Dropped { paths, position } => {
let scopes = window.state::<Scopes>(); let scopes = window.state::<Scopes>();
@ -203,12 +216,14 @@ fn on_window_event<R: Runtime>(
} }
} }
let payload = FileDropPayload { paths, position }; let payload = FileDropPayload { paths, position };
window.emit(WINDOW_FILE_DROP_EVENT, payload)? window.emit_to_window(WINDOW_FILE_DROP_EVENT, payload)?
} }
FileDropEvent::Cancelled => window.emit(WINDOW_FILE_DROP_CANCELLED_EVENT, ())?, FileDropEvent::Cancelled => window.emit_to_window(WINDOW_FILE_DROP_CANCELLED_EVENT, ())?,
_ => unimplemented!(), _ => unimplemented!(),
}, },
WindowEvent::ThemeChanged(theme) => window.emit(WINDOW_THEME_CHANGED, theme.to_string())?, WindowEvent::ThemeChanged(theme) => {
window.emit_to_window(WINDOW_THEME_CHANGED, theme.to_string())?
}
} }
Ok(()) Ok(())
} }