diff --git a/.changes/tauri-close-requested-target-specific.md b/.changes/tauri-close-requested-target-specific.md new file mode 100644 index 000000000..bbe08852e --- /dev/null +++ b/.changes/tauri-close-requested-target-specific.md @@ -0,0 +1,5 @@ +--- +'tauri': 'patch:bug' +--- + +Fix JS `onCloseRequested` catching close event from other windows. diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 3e3de49db..0f915f280 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -713,21 +713,23 @@ pub trait Manager: sealed::ManagerBase { #[cfg(feature = "tracing")] tracing::Span::current().record("target", format!("{target:?}")); - self.manager().emit_filter(event, payload, |s| match s { - t @ EventTarget::Window { label } - | t @ EventTarget::Webview { label } - | t @ EventTarget::WebviewWindow { label } => { - if let EventTarget::AnyLabel { - label: target_label, - } = &target - { - label == target_label - } else { - t == &target - } - } - t => t == &target, - }) + match target { + // if targeting all, emit to all using emit without filter + EventTarget::Any => self.manager().emit(event, payload), + + // if targeting any label, emit using emit_filter and filter labels + EventTarget::AnyLabel { + label: target_label, + } => self.manager().emit_filter(event, payload, |t| match t { + EventTarget::Window { label } + | EventTarget::Webview { label } + | EventTarget::WebviewWindow { label } => label == &target_label, + _ => false, + }), + + // 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. diff --git a/core/tauri/src/manager/window.rs b/core/tauri/src/manager/window.rs index e22d33382..a1cb55961 100644 --- a/core/tauri/src/manager/window.rs +++ b/core/tauri/src/manager/window.rs @@ -130,6 +130,27 @@ impl WindowManager { } } +impl Window { + /// Emits event to [`EventTarget::Window`] and [`EventTarget::WebviewWindow`] + fn emit_to_window(&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)] struct FileDropPayload<'a> { paths: &'a Vec, @@ -142,24 +163,16 @@ fn on_window_event( event: &WindowEvent, ) -> crate::Result<()> { match event { - WindowEvent::Resized(size) => window.emit(WINDOW_RESIZED_EVENT, size)?, - WindowEvent::Moved(position) => window.emit(WINDOW_MOVED_EVENT, position)?, + WindowEvent::Resized(size) => window.emit_to_window(WINDOW_RESIZED_EVENT, size)?, + WindowEvent::Moved(position) => window.emit_to_window(WINDOW_MOVED_EVENT, position)?, WindowEvent::CloseRequested { api } => { - let listeners = window.manager().listeners(); - 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 { + if window.has_js_listener(WINDOW_CLOSE_REQUESTED_EVENT) { api.prevent_close(); } - window.emit(WINDOW_CLOSE_REQUESTED_EVENT, ())?; + window.emit_to_window(WINDOW_CLOSE_REQUESTED_EVENT, ())?; } WindowEvent::Destroyed => { - window.emit(WINDOW_DESTROYED_EVENT, ())?; + window.emit_to_window(WINDOW_DESTROYED_EVENT, ())?; let label = window.label(); let webviews_map = manager.webview.webviews_lock(); let webviews = webviews_map.values(); @@ -169,7 +182,7 @@ fn on_window_event( ))?; } } - WindowEvent::Focused(focused) => window.emit( + WindowEvent::Focused(focused) => window.emit_to_window( if *focused { WINDOW_FOCUS_EVENT } else { @@ -181,7 +194,7 @@ fn on_window_event( scale_factor, new_inner_size, .. - } => window.emit( + } => window.emit_to_window( WINDOW_SCALE_FACTOR_CHANGED_EVENT, ScaleFactorChanged { scale_factor: *scale_factor, @@ -191,7 +204,7 @@ fn on_window_event( WindowEvent::FileDrop(event) => match event { FileDropEvent::Hovered { 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 } => { let scopes = window.state::(); @@ -203,12 +216,14 @@ fn on_window_event( } } 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!(), }, - 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(()) }