From 169b5035a93e3f33a420d4b2b0f8943e6404e07f Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Mon, 28 Mar 2022 18:43:07 -0700 Subject: [PATCH] fix(core): actually fire `WindowEvent::Destroyed` (#3797) --- .changes/fix-wry-window-destroyed-event.md | 6 ++ core/tauri-runtime-wry/src/lib.rs | 82 +++++++++++----------- 2 files changed, 48 insertions(+), 40 deletions(-) create mode 100644 .changes/fix-wry-window-destroyed-event.md diff --git a/.changes/fix-wry-window-destroyed-event.md b/.changes/fix-wry-window-destroyed-event.md new file mode 100644 index 00000000000..e7ce9d5792f --- /dev/null +++ b/.changes/fix-wry-window-destroyed-event.md @@ -0,0 +1,6 @@ +--- +"tauri-runtime-wry": patch +"tauri": patch +--- + +Fixes `WindowEvent::Destroyed` not firing. diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index fe08daf5db5..5512330d926 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/core/tauri-runtime-wry/src/lib.rs @@ -586,13 +586,19 @@ impl TryFrom for WryIcon { struct WindowEventWrapper(Option); impl WindowEventWrapper { - fn parse(webview: &WindowHandle, event: &WryWindowEvent<'_>) -> Self { + fn parse(webview: &Option, event: &WryWindowEvent<'_>) -> Self { match event { // resized event from tao doesn't include a reliable size on macOS // because wry replaces the NSView - WryWindowEvent::Resized(_) => Self(Some(WindowEvent::Resized( - PhysicalSizeWrapper(webview.inner_size()).into(), - ))), + WryWindowEvent::Resized(_) => { + if let Some(webview) = webview { + Self(Some(WindowEvent::Resized( + PhysicalSizeWrapper(webview.inner_size()).into(), + ))) + } else { + Self(None) + } + } e => e.into(), } } @@ -1536,7 +1542,7 @@ impl WindowHandle { #[derive(Debug)] pub struct WindowWrapper { label: String, - inner: WindowHandle, + inner: Option, menu_items: Option>, } @@ -2008,28 +2014,29 @@ fn handle_user_message( match message { Message::Task(task) => task(), Message::Window(id, window_message) => { - if let Some(webview) = windows + if let Some((Some(window_handle), menu_items)) = windows .lock() .expect("poisoned webview collection") .get_mut(&id) + .map(|w| (w.inner.as_ref(), &mut w.menu_items)) { - let window = webview.inner.window(); + let window = window_handle.window(); match window_message { #[cfg(any(debug_assertions, feature = "devtools"))] WindowMessage::OpenDevTools => { - if let WindowHandle::Webview(w) = &webview.inner { + if let WindowHandle::Webview(w) = &window_handle { w.open_devtools(); } } #[cfg(any(debug_assertions, feature = "devtools"))] WindowMessage::CloseDevTools => { - if let WindowHandle::Webview(w) = &webview.inner { + if let WindowHandle::Webview(w) = &window_handle { w.close_devtools(); } } #[cfg(any(debug_assertions, feature = "devtools"))] WindowMessage::IsDevToolsOpen(tx) => { - if let WindowHandle::Webview(w) = &webview.inner { + if let WindowHandle::Webview(w) = &window_handle { tx.send(w.is_devtools_open()).unwrap(); } else { tx.send(false).unwrap(); @@ -2054,7 +2061,7 @@ fn handle_user_message( ) .unwrap(), WindowMessage::InnerSize(tx) => tx - .send(PhysicalSizeWrapper(webview.inner.inner_size()).into()) + .send(PhysicalSizeWrapper(window_handle.inner_size()).into()) .unwrap(), WindowMessage::OuterSize(tx) => tx .send(PhysicalSizeWrapper(window.outer_size()).into()) @@ -2084,7 +2091,7 @@ fn handle_user_message( WindowMessage::GtkWindow(tx) => tx.send(GtkWindow(window.gtk_window().clone())).unwrap(), // Setters WindowMessage::Center(tx) => { - tx.send(center_window(window, webview.inner.inner_size())) + tx.send(center_window(window, window_handle.inner_size())) .unwrap(); } WindowMessage::RequestUserAttention(request_type) => { @@ -2136,7 +2143,7 @@ fn handle_user_message( let _ = window.drag_window(); } WindowMessage::UpdateMenuItem(id, update) => { - if let Some(menu_items) = webview.menu_items.as_mut() { + if let Some(menu_items) = menu_items.as_mut() { let item = menu_items.get_mut(&id).expect("menu item not found"); match update { MenuUpdate::SetEnabled(enabled) => item.set_enabled(enabled), @@ -2161,7 +2168,7 @@ fn handle_user_message( .lock() .expect("poisoned webview collection") .get(&id) - .map(|w| &w.inner) + .and_then(|w| w.inner.as_ref()) { if let Err(e) = webview.evaluate_script(&script) { #[cfg(debug_assertions)] @@ -2174,7 +2181,7 @@ fn handle_user_message( .lock() .expect("poisoned webview collection") .get(&id) - .map(|w| &w.inner) + .and_then(|w| w.inner.as_ref()) { let _ = webview.print(); } @@ -2226,7 +2233,7 @@ fn handle_user_message( window_id, WindowWrapper { label, - inner: WindowHandle::Window(w.clone()), + inner: Some(WindowHandle::Window(w.clone())), menu_items: Default::default(), }, ); @@ -2445,7 +2452,7 @@ fn handle_event_loop( .lock() .expect("poisoned webview collection") .get(&window_id) - .map(|w| &w.inner) + .and_then(|w| w.inner.as_ref()) { // only focus the webview if the window is visible // somehow tao is sending a Focused(true) event even when the window is invisible, @@ -2494,16 +2501,18 @@ fn handle_event_loop( ); } WryWindowEvent::Destroyed => { - let is_empty = windows.lock().unwrap().is_empty(); - if is_empty { - let (tx, rx) = channel(); - callback(RunEvent::ExitRequested { tx }); + if windows.lock().unwrap().remove(&window_id).is_some() { + let is_empty = windows.lock().unwrap().is_empty(); + if is_empty { + let (tx, rx) = channel(); + callback(RunEvent::ExitRequested { tx }); - let recv = rx.try_recv(); - let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent)); + let recv = rx.try_recv(); + let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent)); - if !should_prevent { - *control_flow = ControlFlow::Exit; + if !should_prevent { + *control_flow = ControlFlow::Exit; + } } } } @@ -2512,7 +2521,7 @@ fn handle_event_loop( .lock() .expect("poisoned webview collection") .get(&window_id) - .map(|w| &w.inner) + .and_then(|w| w.inner.as_ref()) { if let Err(e) = webview.resize() { #[cfg(debug_assertions)] @@ -2564,7 +2573,7 @@ fn on_close_requested<'a, T: UserEvent>( windows: Arc>>, window_event_listeners: &WindowEventListeners, menu_event_listeners: MenuEventListeners, -) -> Option { +) { let (tx, rx) = channel(); let windows_guard = windows.lock().expect("poisoned webview collection"); if let Some(w) = windows_guard.get(&window_id) { @@ -2588,16 +2597,13 @@ fn on_close_requested<'a, T: UserEvent>( event: WindowEvent::CloseRequested { signal_tx: tx }, }); if let Ok(true) = rx.try_recv() { - None } else { on_window_close( window_id, windows.lock().expect("poisoned webview collection"), menu_event_listeners, - ) + ); } - } else { - None } } @@ -2605,15 +2611,11 @@ fn on_window_close( window_id: WebviewId, mut windows: MutexGuard<'_, HashMap>, menu_event_listeners: MenuEventListeners, -) -> Option { - #[allow(unused_mut)] - let w = if let Some(mut webview) = windows.remove(&window_id) { +) { + if let Some(mut window_wrapper) = windows.get_mut(&window_id) { + window_wrapper.inner = None; menu_event_listeners.lock().unwrap().remove(&window_id); - Some(webview) - } else { - None - }; - w + } } fn center_window(window: &Window, window_size: WryPhysicalSize) -> Result<()> { @@ -2803,7 +2805,7 @@ fn create_webview( Ok(WindowWrapper { label, - inner: WindowHandle::Webview(webview), + inner: Some(WindowHandle::Webview(webview)), menu_items, }) }