mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-08-16 19:30:27 +03:00
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:
parent
cf3e40cc47
commit
46b6598a94
5
.changes/tauri-close-requested-target-specific.md
Normal file
5
.changes/tauri-close-requested-target-specific.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'tauri': 'patch:bug'
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix JS `onCloseRequested` catching close event from other windows.
|
@ -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.
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user