Ver código fonte

fix(core): actually fire `WindowEvent::Destroyed` (#3797)

Lucas Fernandes Nogueira 3 anos atrás
pai
commit
169b5035a9

+ 6 - 0
.changes/fix-wry-window-destroyed-event.md

@@ -0,0 +1,6 @@
+---
+"tauri-runtime-wry": patch
+"tauri": patch
+---
+
+Fixes `WindowEvent::Destroyed` not firing.

+ 42 - 40
core/tauri-runtime-wry/src/lib.rs

@@ -586,13 +586,19 @@ impl TryFrom<WindowIcon> for WryIcon {
 struct WindowEventWrapper(Option<WindowEvent>);
 
 impl WindowEventWrapper {
-  fn parse(webview: &WindowHandle, event: &WryWindowEvent<'_>) -> Self {
+  fn parse(webview: &Option<WindowHandle>, 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<WindowHandle>,
   menu_items: Option<HashMap<u16, WryCustomMenuItem>>,
 }
 
@@ -2008,28 +2014,29 @@ fn handle_user_message<T: UserEvent>(
   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<T: UserEvent>(
             )
             .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<T: UserEvent>(
           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<T: UserEvent>(
             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<T: UserEvent>(
           .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<T: UserEvent>(
           .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<T: UserEvent>(
           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<T: UserEvent>(
           .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<T: UserEvent>(
           );
         }
         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<T: UserEvent>(
             .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<Mutex<HashMap<WebviewId, WindowWrapper>>>,
   window_event_listeners: &WindowEventListeners,
   menu_event_listeners: MenuEventListeners,
-) -> Option<WindowWrapper> {
+) {
   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<WebviewId, WindowWrapper>>,
   menu_event_listeners: MenuEventListeners,
-) -> Option<WindowWrapper> {
-  #[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<u32>) -> Result<()> {
@@ -2803,7 +2805,7 @@ fn create_webview<T: UserEvent>(
 
   Ok(WindowWrapper {
     label,
-    inner: WindowHandle::Webview(webview),
+    inner: Some(WindowHandle::Webview(webview)),
     menu_items,
   })
 }