Browse Source

fix(wry): menu must be created on the main thread, closes #2038 (#2039)

Lucas Fernandes Nogueira 4 years ago
parent
commit
d0bbc6d309
2 changed files with 48 additions and 14 deletions
  1. 10 7
      core/tauri-runtime-wry/src/lib.rs
  2. 38 7
      core/tauri-runtime-wry/src/menu.rs

+ 10 - 7
core/tauri-runtime-wry/src/lib.rs

@@ -405,7 +405,7 @@ pub struct WindowBuilderWrapper {
   inner: WryWindowBuilder,
   center: bool,
   #[cfg(feature = "menu")]
-  menu_items: HashMap<u16, WryCustomMenuItem>,
+  menu: Menu<u16>,
 }
 
 // safe since `menu_items` are read only here
@@ -449,10 +449,7 @@ impl WindowBuilder for WindowBuilderWrapper {
 
   #[cfg(feature = "menu")]
   fn menu<I: MenuId>(mut self, menu: Menu<I>) -> Self {
-    let mut items = HashMap::new();
-    let window_menu = to_wry_menu(&mut items, menu);
-    self.menu_items = items;
-    self.inner = self.inner.with_menu(window_menu);
+    self.menu = convert_menu_id(Menu::new(), menu);
     self
   }
 
@@ -1794,9 +1791,10 @@ fn create_webview<P: Params<Runtime = Wry>>(
   context: DispatcherContext,
   pending: PendingWindow<P>,
 ) -> Result<WebviewWrapper> {
+  #[allow(unused_mut)]
   let PendingWindow {
     webview_attributes,
-    window_builder,
+    mut window_builder,
     rpc_handler,
     file_drop_handler,
     label,
@@ -1806,7 +1804,12 @@ fn create_webview<P: Params<Runtime = Wry>>(
 
   let is_window_transparent = window_builder.inner.window.transparent;
   #[cfg(feature = "menu")]
-  let menu_items = window_builder.menu_items;
+  let menu_items = {
+    let mut menu_items = HashMap::new();
+    let menu = to_wry_menu(&mut menu_items, window_builder.menu);
+    window_builder.inner = window_builder.inner.with_menu(menu);
+    menu_items
+  };
   let window = window_builder.inner.build(event_loop).unwrap();
   if window_builder.center {
     let _ = center_window(&window);

+ 38 - 7
core/tauri-runtime-wry/src/menu.rs

@@ -4,8 +4,8 @@
 
 pub use tauri_runtime::{
   menu::{
-    CustomMenuItem, Menu, MenuEntry, MenuItem, MenuUpdate, SystemTrayMenu, SystemTrayMenuEntry,
-    SystemTrayMenuItem, TrayHandle,
+    CustomMenuItem, Menu, MenuEntry, MenuItem, MenuUpdate, Submenu, SystemTrayMenu,
+    SystemTrayMenuEntry, SystemTrayMenuItem, TrayHandle,
   },
   window::MenuEvent,
   Icon, MenuId, SystemTrayEvent,
@@ -190,22 +190,53 @@ impl From<SystemTrayMenuItem> for MenuItemWrapper {
 }
 
 #[cfg(feature = "menu")]
-pub fn to_wry_menu<I: MenuId>(
+pub fn convert_menu_id<I: MenuId>(mut new_menu: Menu<u16>, menu: Menu<I>) -> Menu<u16> {
+  for item in menu.items {
+    match item {
+      MenuEntry::CustomItem(c) => {
+        let mut item = CustomMenuItem::new(c.id_value(), c.title);
+        #[cfg(target_os = "macos")]
+        if let Some(native_image) = c.native_image {
+          item = item.native_image(native_image);
+        }
+        if !c.enabled {
+          item = item.disabled();
+        }
+        if c.selected {
+          item = item.selected();
+        }
+        new_menu = new_menu.add_item(item);
+      }
+      MenuEntry::NativeItem(i) => {
+        new_menu = new_menu.add_native_item(i);
+      }
+      MenuEntry::Submenu(submenu) => {
+        let new_submenu = convert_menu_id(Menu::new(), submenu.inner);
+        new_menu = new_menu.add_submenu(Submenu::new(submenu.title, new_submenu));
+      }
+    }
+  }
+  new_menu
+}
+
+#[cfg(feature = "menu")]
+pub fn to_wry_menu(
   custom_menu_items: &mut HashMap<u16, WryCustomMenuItem>,
-  menu: Menu<I>,
+  menu: Menu<u16>,
 ) -> MenuBar {
   let mut wry_menu = MenuBar::new();
   for item in menu.items {
     match item {
       MenuEntry::CustomItem(c) => {
+        let mut attributes = MenuItemAttributesWrapper::from(&c).0;
+        attributes = attributes.with_id(WryMenuId(c.id));
         #[allow(unused_mut)]
-        let mut item = wry_menu.add_item(MenuItemAttributesWrapper::from(&c).0);
-        let id = c.id_value();
+        let mut item = wry_menu.add_item(attributes);
         #[cfg(target_os = "macos")]
         if let Some(native_image) = c.native_image {
           item.set_native_image(NativeImageWrapper::from(native_image).0);
         }
-        custom_menu_items.insert(id, item);
+        custom_menu_items.insert(c.id, item);
       }
       MenuEntry::NativeItem(i) => {
         wry_menu.add_native_item(MenuItemWrapper::from(i).0);