浏览代码

refactor(core): use random window id to simplify window creation, closes #3645 #3597 (#3684)

* refactor(core): window id

* fixes

* reintroduce send_tao_window_event

* cleanup code

* add change file

* fix: windows build

* add getter

* fix windows build
Lucas Fernandes Nogueira 3 年之前
父节点
当前提交
7cd39c70c9
共有 5 个文件被更改,包括 201 次插入171 次删除
  1. 5 0
      .changes/simplify-window-creation.md
  2. 1 0
      core/tauri-runtime-wry/Cargo.toml
  3. 190 169
      core/tauri-runtime-wry/src/lib.rs
  4. 1 1
      core/tauri/Cargo.toml
  5. 4 1
      core/tauri/src/app.rs

+ 5 - 0
.changes/simplify-window-creation.md

@@ -0,0 +1,5 @@
+---
+"tauri-runtime-wry": minor
+---
+
+Use a random window id instead of `tao::window::WindowId` to not block the thread waiting for the event loop to process the window creation.

+ 1 - 0
core/tauri-runtime-wry/Cargo.toml

@@ -17,6 +17,7 @@ wry = { version = "0.13.3", default-features = false, features = [ "file-drop",
 tauri-runtime = { version = "0.3.3", path = "../tauri-runtime" }
 tauri-utils = { version = "1.0.0-rc.3", path = "../tauri-utils" }
 uuid = { version = "0.8.2", features = [ "v4" ] }
+rand = "0.8"
 
 [target."cfg(windows)".dependencies]
 webview2-com = "0.13.0"

+ 190 - 169
core/tauri-runtime-wry/src/lib.rs

@@ -70,7 +70,7 @@ use wry::{
 
 pub use wry::application::window::{Window, WindowBuilder as WryWindowBuilder, WindowId};
 
-#[cfg(target_os = "windows")]
+#[cfg(windows)]
 use wry::webview::WebviewExtWindows;
 
 #[cfg(target_os = "macos")]
@@ -96,6 +96,8 @@ use std::{
   thread::{current as current_thread, ThreadId},
 };
 
+type WebviewId = u64;
+
 #[cfg(feature = "system-tray")]
 mod system_tray;
 #[cfg(feature = "system-tray")]
@@ -105,14 +107,27 @@ type WebContextStore = Arc<Mutex<HashMap<Option<PathBuf>, WebContext>>>;
 // window
 type WindowEventHandler = Box<dyn Fn(&WindowEvent) + Send>;
 type WindowEventListenersMap = Arc<Mutex<HashMap<Uuid, WindowEventHandler>>>;
-type WindowEventListeners = Arc<Mutex<HashMap<WindowId, WindowEventListenersMap>>>;
+type WindowEventListeners = Arc<Mutex<HashMap<WebviewId, WindowEventListenersMap>>>;
 // global shortcut
 type GlobalShortcutListeners = Arc<Mutex<HashMap<AcceleratorId, Box<dyn Fn() + Send>>>>;
 // menu
 pub type MenuEventHandler = Box<dyn Fn(&MenuEvent) + Send>;
-pub type MenuEventListeners = Arc<Mutex<HashMap<WindowId, WindowMenuEventListeners>>>;
+pub type MenuEventListeners = Arc<Mutex<HashMap<WebviewId, WindowMenuEventListeners>>>;
 pub type WindowMenuEventListeners = Arc<Mutex<HashMap<Uuid, MenuEventHandler>>>;
 
+#[derive(Debug, Clone, Default)]
+struct WebviewIdStore(Arc<Mutex<HashMap<WindowId, WebviewId>>>);
+
+impl WebviewIdStore {
+  fn insert(&self, w: WindowId, id: WebviewId) {
+    self.0.lock().unwrap().insert(w, id);
+  }
+
+  fn get(&self, w: &WindowId) -> WebviewId {
+    *self.0.lock().unwrap().get(w).unwrap()
+  }
+}
+
 macro_rules! getter {
   ($self: ident, $rx: expr, $message: expr) => {{
     send_user_message(&$self.context, $message)?;
@@ -154,6 +169,7 @@ fn send_user_message<T: UserEvent>(context: &Context<T>, message: Message<T>) ->
 
 #[derive(Clone)]
 struct Context<T: UserEvent> {
+  webview_id_map: WebviewIdStore,
   main_thread_id: ThreadId,
   proxy: WryEventLoopProxy<Message<T>>,
   window_event_listeners: WindowEventListeners,
@@ -161,13 +177,60 @@ struct Context<T: UserEvent> {
   main_thread: DispatcherMainThreadContext<T>,
 }
 
+impl<T: UserEvent> Context<T> {
+  fn prepare_window(&self, window_id: WebviewId) {
+    self
+      .window_event_listeners
+      .lock()
+      .unwrap()
+      .insert(window_id, WindowEventListenersMap::default());
+
+    self
+      .menu_event_listeners
+      .lock()
+      .unwrap()
+      .insert(window_id, WindowMenuEventListeners::default());
+  }
+
+  fn create_webview(&self, pending: PendingWindow<T, Wry<T>>) -> Result<DetachedWindow<T, Wry<T>>> {
+    let label = pending.label.clone();
+    let menu_ids = pending.menu_ids.clone();
+    let js_event_listeners = pending.js_event_listeners.clone();
+    let context = self.clone();
+    let window_id = rand::random();
+
+    self.prepare_window(window_id);
+
+    self
+      .proxy
+      .send_event(Message::CreateWebview(
+        window_id,
+        Box::new(move |event_loop, web_context| {
+          create_webview(window_id, event_loop, web_context, context, pending)
+        }),
+      ))
+      .map_err(|_| Error::FailedToSendMessage)?;
+
+    let dispatcher = WryDispatcher {
+      window_id,
+      context: self.clone(),
+    };
+    Ok(DetachedWindow {
+      label,
+      dispatcher,
+      menu_ids,
+      js_event_listeners,
+    })
+  }
+}
+
 #[derive(Debug, Clone)]
 struct DispatcherMainThreadContext<T: UserEvent> {
   window_target: EventLoopWindowTarget<Message<T>>,
   web_context: WebContextStore,
   global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
   clipboard_manager: Arc<Mutex<Clipboard>>,
-  windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
+  windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
   #[cfg(feature = "system-tray")]
   tray_context: TrayContext,
 }
@@ -827,7 +890,7 @@ impl WindowBuilder for WindowBuilderWrapper {
     Ok(self)
   }
 
-  #[cfg(any(target_os = "windows", target_os = "linux"))]
+  #[cfg(any(windows, target_os = "linux"))]
   fn skip_taskbar(mut self, skip: bool) -> Self {
     self.inner = self.inner.with_skip_taskbar(skip);
     self
@@ -996,12 +1059,13 @@ pub type CreateWebviewClosure<T> = Box<
 
 pub enum Message<T: 'static> {
   Task(Box<dyn FnOnce() + Send>),
-  Window(WindowId, WindowMessage),
-  Webview(WindowId, WebviewMessage),
+  Window(WebviewId, WindowMessage),
+  Webview(WebviewId, WebviewMessage),
   #[cfg(feature = "system-tray")]
   Tray(TrayMessage),
-  CreateWebview(CreateWebviewClosure<T>, Sender<WindowId>),
+  CreateWebview(WebviewId, CreateWebviewClosure<T>),
   CreateWindow(
+    WebviewId,
     Box<dyn FnOnce() -> (String, WryWindowBuilder) + Send>,
     Sender<Result<Weak<Window>>>,
   ),
@@ -1028,7 +1092,7 @@ impl<T: UserEvent> Clone for Message<T> {
 /// The Tauri [`Dispatch`] for [`Wry`].
 #[derive(Debug, Clone)]
 pub struct WryDispatcher<T: UserEvent> {
-  window_id: WindowId,
+  window_id: WebviewId,
   context: Context<T>,
 }
 
@@ -1198,33 +1262,7 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
     &mut self,
     pending: PendingWindow<T, Self::Runtime>,
   ) -> Result<DetachedWindow<T, Self::Runtime>> {
-    let (tx, rx) = channel();
-    let label = pending.label.clone();
-    let menu_ids = pending.menu_ids.clone();
-    let js_event_listeners = pending.js_event_listeners.clone();
-    let context = self.context.clone();
-
-    send_user_message(
-      &self.context,
-      Message::CreateWebview(
-        Box::new(move |event_loop, web_context| {
-          create_webview(event_loop, web_context, context, pending)
-        }),
-        tx,
-      ),
-    )?;
-    let window_id = rx.recv().unwrap();
-
-    let dispatcher = WryDispatcher {
-      window_id,
-      context: self.context.clone(),
-    };
-    Ok(DetachedWindow {
-      label,
-      dispatcher,
-      menu_ids,
-      js_event_listeners,
-    })
+    self.context.create_webview(pending)
   }
 
   fn set_resizable(&self, resizable: bool) -> Result<()> {
@@ -1475,7 +1513,8 @@ pub struct Wry<T: UserEvent> {
   clipboard_manager: Arc<Mutex<Clipboard>>,
   clipboard_manager_handle: ClipboardManagerWrapper<T>,
   event_loop: EventLoop<Message<T>>,
-  windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
+  windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
+  webview_id_map: WebviewIdStore,
   web_context: WebContextStore,
   window_event_listeners: WindowEventListeners,
   menu_event_listeners: MenuEventListeners,
@@ -1520,10 +1559,25 @@ impl<T: UserEvent> WryHandle<T> {
     f: F,
   ) -> Result<Weak<Window>> {
     let (tx, rx) = channel();
-    send_user_message(&self.context, Message::CreateWindow(Box::new(f), tx))?;
+    send_user_message(
+      &self.context,
+      Message::CreateWindow(rand::random(), Box::new(f), tx),
+    )?;
     rx.recv().unwrap()
   }
 
+  /// Gets the [`WebviewId'] associated with the given [`WindowId`].
+  pub fn window_id(&self, window_id: WindowId) -> WebviewId {
+    *self
+      .context
+      .webview_id_map
+      .0
+      .lock()
+      .unwrap()
+      .get(&window_id)
+      .unwrap()
+  }
+
   /// Send a message to the event loop.
   pub fn send_event(&self, message: Message<T>) -> Result<()> {
     self
@@ -1548,32 +1602,7 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
     &self,
     pending: PendingWindow<T, Self::Runtime>,
   ) -> Result<DetachedWindow<T, Self::Runtime>> {
-    let (tx, rx) = channel();
-    let label = pending.label.clone();
-    let menu_ids = pending.menu_ids.clone();
-    let js_event_listeners = pending.js_event_listeners.clone();
-    let context = self.context.clone();
-    send_user_message(
-      &self.context,
-      Message::CreateWebview(
-        Box::new(move |event_loop, web_context| {
-          create_webview(event_loop, web_context, context, pending)
-        }),
-        tx,
-      ),
-    )?;
-    let window_id = rx.recv().unwrap();
-
-    let dispatcher = WryDispatcher {
-      window_id,
-      context: self.context.clone(),
-    };
-    Ok(DetachedWindow {
-      label,
-      dispatcher,
-      menu_ids,
-      js_event_listeners,
-    })
+    self.context.create_webview(pending)
   }
 
   fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
@@ -1595,6 +1624,7 @@ impl<T: UserEvent> Wry<T> {
     let global_shortcut_manager = Arc::new(Mutex::new(WryShortcutManager::new(&event_loop)));
     let clipboard_manager = Arc::new(Mutex::new(Clipboard::new()));
     let windows = Arc::new(Mutex::new(HashMap::default()));
+    let webview_id_map = WebviewIdStore::default();
     let window_event_listeners = WindowEventListeners::default();
     let menu_event_listeners = MenuEventListeners::default();
 
@@ -1602,6 +1632,7 @@ impl<T: UserEvent> Wry<T> {
     let tray_context = TrayContext::default();
 
     let event_loop_context = Context {
+      webview_id_map: webview_id_map.clone(),
       main_thread_id,
       proxy,
       window_event_listeners: window_event_listeners.clone(),
@@ -1634,6 +1665,7 @@ impl<T: UserEvent> Wry<T> {
       clipboard_manager_handle,
       event_loop,
       windows,
+      webview_id_map,
       web_context,
       window_event_listeners,
       menu_event_listeners,
@@ -1674,6 +1706,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
   fn handle(&self) -> Self::Handle {
     WryHandle {
       context: Context {
+        webview_id_map: self.webview_id_map.clone(),
         main_thread_id: self.main_thread_id,
         proxy: self.event_loop.create_proxy(),
         window_event_listeners: self.window_event_listeners.clone(),
@@ -1704,89 +1737,38 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
     let menu_ids = pending.menu_ids.clone();
     let js_event_listeners = pending.js_event_listeners.clone();
     let proxy = self.event_loop.create_proxy();
+    let window_id = rand::random();
+
+    let context = Context {
+      webview_id_map: self.webview_id_map.clone(),
+      main_thread_id: self.main_thread_id,
+      proxy,
+      window_event_listeners: self.window_event_listeners.clone(),
+      menu_event_listeners: self.menu_event_listeners.clone(),
+      main_thread: DispatcherMainThreadContext {
+        window_target: self.event_loop.deref().clone(),
+        web_context: self.web_context.clone(),
+        global_shortcut_manager: self.global_shortcut_manager.clone(),
+        clipboard_manager: self.clipboard_manager.clone(),
+        windows: self.windows.clone(),
+        #[cfg(feature = "system-tray")]
+        tray_context: self.tray_context.clone(),
+      },
+    };
+
+    context.prepare_window(window_id);
+
     let webview = create_webview(
+      window_id,
       &self.event_loop,
       &self.web_context,
-      Context {
-        main_thread_id: self.main_thread_id,
-        proxy: proxy.clone(),
-        window_event_listeners: self.window_event_listeners.clone(),
-        menu_event_listeners: self.menu_event_listeners.clone(),
-        main_thread: DispatcherMainThreadContext {
-          window_target: self.event_loop.deref().clone(),
-          web_context: self.web_context.clone(),
-          global_shortcut_manager: self.global_shortcut_manager.clone(),
-          clipboard_manager: self.clipboard_manager.clone(),
-          windows: self.windows.clone(),
-          #[cfg(feature = "system-tray")]
-          tray_context: self.tray_context.clone(),
-        },
-      },
+      context.clone(),
       pending,
     )?;
 
-    #[cfg(target_os = "windows")]
-    {
-      let id = webview.inner.window().id();
-      if let WindowHandle::Webview(ref webview) = webview.inner {
-        if let Some(controller) = webview.controller() {
-          let proxy = self.event_loop.create_proxy();
-          let mut token = EventRegistrationToken::default();
-          unsafe {
-            controller.GotFocus(
-              FocusChangedEventHandler::create(Box::new(move |_, _| {
-                let _ = proxy.send_event(Message::Webview(
-                  id,
-                  WebviewMessage::WebviewEvent(WebviewEvent::Focused(true)),
-                ));
-                Ok(())
-              })),
-              &mut token,
-            )
-          }
-          .unwrap();
-          let proxy = self.event_loop.create_proxy();
-          unsafe {
-            controller.LostFocus(
-              FocusChangedEventHandler::create(Box::new(move |_, _| {
-                let _ = proxy.send_event(Message::Webview(
-                  id,
-                  WebviewMessage::WebviewEvent(WebviewEvent::Focused(false)),
-                ));
-                Ok(())
-              })),
-              &mut token,
-            )
-          }
-          .unwrap();
-        }
-      }
-    }
+    let dispatcher = WryDispatcher { window_id, context };
 
-    let dispatcher = WryDispatcher {
-      window_id: webview.inner.window().id(),
-      context: Context {
-        main_thread_id: self.main_thread_id,
-        proxy,
-        window_event_listeners: self.window_event_listeners.clone(),
-        menu_event_listeners: self.menu_event_listeners.clone(),
-        main_thread: DispatcherMainThreadContext {
-          window_target: self.event_loop.deref().clone(),
-          web_context: self.web_context.clone(),
-          global_shortcut_manager: self.global_shortcut_manager.clone(),
-          clipboard_manager: self.clipboard_manager.clone(),
-          windows: self.windows.clone(),
-          #[cfg(feature = "system-tray")]
-          tray_context: self.tray_context.clone(),
-        },
-      },
-    };
-
-    self
-      .windows
-      .lock()
-      .unwrap()
-      .insert(webview.inner.window().id(), webview);
+    self.windows.lock().unwrap().insert(window_id, webview);
 
     Ok(DetachedWindow {
       label,
@@ -1861,6 +1843,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
   fn run_iteration<F: FnMut(RunEvent<T>) + 'static>(&mut self, mut callback: F) -> RunIteration {
     use wry::application::platform::run_return::EventLoopExtRunReturn;
     let windows = self.windows.clone();
+    let webview_id_map = self.webview_id_map.clone();
     let web_context = &self.web_context;
     let window_event_listeners = self.window_event_listeners.clone();
     let menu_event_listeners = self.menu_event_listeners.clone();
@@ -1886,6 +1869,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
           EventLoopIterationContext {
             callback: &mut callback,
             windows: windows.clone(),
+            webview_id_map: webview_id_map.clone(),
             window_event_listeners: &window_event_listeners,
             global_shortcut_manager: global_shortcut_manager.clone(),
             global_shortcut_manager_handle: &global_shortcut_manager_handle,
@@ -1903,6 +1887,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
 
   fn run<F: FnMut(RunEvent<T>) + 'static>(self, mut callback: F) {
     let windows = self.windows.clone();
+    let webview_id_map = self.webview_id_map.clone();
     let web_context = self.web_context;
     let window_event_listeners = self.window_event_listeners.clone();
     let menu_event_listeners = self.menu_event_listeners.clone();
@@ -1919,6 +1904,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
         control_flow,
         EventLoopIterationContext {
           callback: &mut callback,
+          webview_id_map: webview_id_map.clone(),
           windows: windows.clone(),
           window_event_listeners: &window_event_listeners,
           global_shortcut_manager: global_shortcut_manager.clone(),
@@ -1936,7 +1922,8 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
 
 pub struct EventLoopIterationContext<'a, T: UserEvent> {
   callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
-  windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
+  webview_id_map: WebviewIdStore,
+  windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
   window_event_listeners: &'a WindowEventListeners,
   global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
   global_shortcut_manager_handle: &'a GlobalShortcutManagerHandle<T>,
@@ -1951,7 +1938,7 @@ struct UserMessageContext<'a> {
   global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
   clipboard_manager: Arc<Mutex<Clipboard>>,
   menu_event_listeners: &'a MenuEventListeners,
-  windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
+  windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
   #[cfg(feature = "system-tray")]
   tray_context: &'a TrayContext,
 }
@@ -2081,7 +2068,7 @@ fn handle_user_message<T: UserEvent>(
             window.set_window_icon(Some(icon));
           }
           WindowMessage::SetSkipTaskbar(_skip) => {
-            #[cfg(any(target_os = "windows", target_os = "linux"))]
+            #[cfg(any(windows, target_os = "linux"))]
             window.set_skip_taskbar(_skip);
           }
           WindowMessage::DragWindow => {
@@ -2147,34 +2134,30 @@ fn handle_user_message<T: UserEvent>(
         }
       }
     },
-    Message::CreateWebview(handler, sender) => match handler(event_loop, web_context) {
+    Message::CreateWebview(window_id, handler) => match handler(event_loop, web_context) {
       Ok(webview) => {
-        let window_id = webview.inner.window().id();
         windows
           .lock()
           .expect("poisoned webview collection")
           .insert(window_id, webview);
-        sender.send(window_id).unwrap();
       }
       Err(e) => {
         #[cfg(debug_assertions)]
         eprintln!("{}", e);
       }
     },
-    Message::CreateWindow(handler, sender) => {
+    Message::CreateWindow(window_id, handler, sender) => {
       let (label, builder) = handler();
       if let Ok(window) = builder.build(event_loop) {
-        let window_id = window.id();
-
         window_event_listeners
           .lock()
           .unwrap()
-          .insert(window.id(), WindowEventListenersMap::default());
+          .insert(window_id, WindowEventListenersMap::default());
 
         menu_event_listeners
           .lock()
           .unwrap()
-          .insert(window.id(), WindowMenuEventListeners::default());
+          .insert(window_id, WindowMenuEventListeners::default());
 
         let w = Arc::new(window);
 
@@ -2299,6 +2282,7 @@ fn handle_event_loop<T: UserEvent>(
 ) -> RunIteration {
   let EventLoopIterationContext {
     callback,
+    webview_id_map,
     windows,
     window_event_listeners,
     global_shortcut_manager,
@@ -2347,6 +2331,7 @@ fn handle_event_loop<T: UserEvent>(
         menu_item_id: menu_id.0,
       };
       let window_menu_event_listeners = {
+        let window_id = webview_id_map.get(&window_id);
         let listeners = menu_event_listeners.lock().unwrap();
         listeners.get(&window_id).cloned().unwrap_or_default()
       };
@@ -2390,6 +2375,7 @@ fn handle_event_loop<T: UserEvent>(
     Event::WindowEvent {
       event, window_id, ..
     } => {
+      let window_id = webview_id_map.get(&window_id);
       // NOTE(amrbashir): we handle this event here instead of `match` statement below because
       // we want to focus the webview as soon as possible, especially on windows.
       if event == WryWindowEvent::Focused(true) {
@@ -2496,8 +2482,8 @@ fn handle_event_loop<T: UserEvent>(
 
 fn on_close_requested<'a, T: UserEvent>(
   callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
-  window_id: WindowId,
-  windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
+  window_id: WebviewId,
+  windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
   control_flow: &mut ControlFlow,
   window_event_listeners: &WindowEventListeners,
   menu_event_listeners: MenuEventListeners,
@@ -2545,8 +2531,8 @@ fn on_close_requested<'a, T: UserEvent>(
 
 fn on_window_close<'a, T: UserEvent>(
   callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
-  window_id: WindowId,
-  mut windows: MutexGuard<'a, HashMap<WindowId, WindowWrapper>>,
+  window_id: WebviewId,
+  mut windows: MutexGuard<'a, HashMap<WebviewId, WindowWrapper>>,
   control_flow: &mut ControlFlow,
   #[cfg(target_os = "linux")] window_event_listeners: &WindowEventListeners,
   menu_event_listeners: MenuEventListeners,
@@ -2641,6 +2627,7 @@ fn to_wry_menu(
 }
 
 fn create_webview<T: UserEvent>(
+  window_id: WebviewId,
   event_loop: &EventLoopWindowTarget<Message<T>>,
   web_context: &WebContextStore,
   context: Context<T>,
@@ -2658,6 +2645,9 @@ fn create_webview<T: UserEvent>(
     js_event_listeners,
     ..
   } = pending;
+  let webview_id_map = context.webview_id_map.clone();
+  #[cfg(windows)]
+  let proxy = context.proxy.clone();
 
   let is_window_transparent = window_builder.inner.window.transparent;
   let menu_items = if let Some(menu) = window_builder.menu {
@@ -2670,18 +2660,6 @@ fn create_webview<T: UserEvent>(
   };
   let window = window_builder.inner.build(event_loop).unwrap();
 
-  context
-    .window_event_listeners
-    .lock()
-    .unwrap()
-    .insert(window.id(), WindowEventListenersMap::default());
-
-  context
-    .menu_event_listeners
-    .lock()
-    .unwrap()
-    .insert(window.id(), WindowMenuEventListeners::default());
-
   if window_builder.center {
     let _ = center_window(&window, window.inner_size());
   }
@@ -2753,6 +2731,42 @@ fn create_webview<T: UserEvent>(
     .build()
     .map_err(|e| Error::CreateWebview(Box::new(e)))?;
 
+  webview_id_map.insert(webview.window().id(), window_id);
+
+  #[cfg(windows)]
+  {
+    if let Some(controller) = webview.controller() {
+      let proxy_ = proxy.clone();
+      let mut token = EventRegistrationToken::default();
+      unsafe {
+        controller.GotFocus(
+          FocusChangedEventHandler::create(Box::new(move |_, _| {
+            let _ = proxy_.send_event(Message::Webview(
+              window_id,
+              WebviewMessage::WebviewEvent(WebviewEvent::Focused(true)),
+            ));
+            Ok(())
+          })),
+          &mut token,
+        )
+      }
+      .unwrap();
+      unsafe {
+        controller.LostFocus(
+          FocusChangedEventHandler::create(Box::new(move |_, _| {
+            let _ = proxy.send_event(Message::Webview(
+              window_id,
+              WebviewMessage::WebviewEvent(WebviewEvent::Focused(false)),
+            ));
+            Ok(())
+          })),
+          &mut token,
+        )
+      }
+      .unwrap();
+    }
+  }
+
   Ok(WindowWrapper {
     label,
     inner: WindowHandle::Webview(webview),
@@ -2772,7 +2786,13 @@ fn create_ipc_handler<T: UserEvent>(
     handler(
       DetachedWindow {
         dispatcher: WryDispatcher {
-          window_id: window.id(),
+          window_id: *context
+            .webview_id_map
+            .0
+            .lock()
+            .unwrap()
+            .get(&window.id())
+            .unwrap(),
           context: context.clone(),
         },
         label: label.clone(),
@@ -2789,11 +2809,12 @@ fn create_file_drop_handler<T: UserEvent>(
   context: &Context<T>,
 ) -> Box<dyn Fn(&Window, WryFileDropEvent) -> bool + 'static> {
   let window_event_listeners = context.window_event_listeners.clone();
+  let webview_id_map = context.webview_id_map.clone();
   Box::new(move |window, event| {
     let event: FileDropEvent = FileDropEventWrapper(event).into();
     let window_event = WindowEvent::FileDrop(event);
     let listeners = window_event_listeners.lock().unwrap();
-    if let Some(window_listeners) = listeners.get(&window.id()) {
+    if let Some(window_listeners) = listeners.get(&webview_id_map.get(&window.id())) {
       let listeners_map = window_listeners.lock().unwrap();
       let has_listener = !listeners_map.is_empty();
       for listener in listeners_map.values() {

+ 1 - 1
core/tauri/Cargo.toml

@@ -51,7 +51,7 @@ uuid = { version = "0.8", features = [ "v4" ] }
 url = { version = "2.2" }
 anyhow = "1.0"
 thiserror = "1.0"
-once_cell = "1.9"
+once_cell = "1.10"
 tauri-runtime = { version = "0.3.3", path = "../tauri-runtime" }
 tauri-macros = { version = "1.0.0-rc.3", path = "../tauri-macros" }
 tauri-utils = { version = "1.0.0-rc.3", path = "../tauri-utils" }

+ 4 - 1
core/tauri/src/app.rs

@@ -247,7 +247,10 @@ impl AppHandle<crate::Wry> {
   ) -> crate::Result<()> {
     self
       .runtime_handle
-      .send_event(tauri_runtime_wry::Message::Window(window_id, message))
+      .send_event(tauri_runtime_wry::Message::Window(
+        self.runtime_handle.window_id(window_id),
+        message,
+      ))
       .map_err(Into::into)
   }
 }