Skip to content

Commit ac37b56

Browse files
authored
fix(core): menu id map not reflecting the current window menu (#2726)
1 parent b5ee03a commit ac37b56

File tree

8 files changed

+106
-105
lines changed

8 files changed

+106
-105
lines changed

.changes/fix-menu-ids.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Fixes the menu id mapping not reflecting the current window.

.changes/get-menu.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-runtime": minor
3+
"tauri-runtime-wry": minor
4+
---
5+
6+
Replace `WindowBuilder`'s `has_menu` with `get_menu`.

core/tauri-runtime-wry/src/lib.rs

Lines changed: 51 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use tauri_runtime::{
99
Request as HttpRequest, RequestParts as HttpRequestParts, Response as HttpResponse,
1010
ResponseParts as HttpResponseParts,
1111
},
12-
menu::{CustomMenuItem, Menu, MenuEntry, MenuHash, MenuItem, MenuUpdate, Submenu},
12+
menu::{CustomMenuItem, Menu, MenuEntry, MenuHash, MenuId, MenuItem, MenuUpdate},
1313
monitor::Monitor,
1414
webview::{
1515
FileDropEvent, FileDropHandler, RpcRequest, WebviewRpcHandler, WindowBuilder, WindowBuilderBase,
@@ -693,7 +693,7 @@ impl From<UserAttentionType> for UserAttentionTypeWrapper {
693693
pub struct WindowBuilderWrapper {
694694
inner: WryWindowBuilder,
695695
center: bool,
696-
menu: Menu,
696+
menu: Option<Menu>,
697697
}
698698

699699
// safe since `menu_items` are read only here
@@ -736,7 +736,7 @@ impl WindowBuilder for WindowBuilderWrapper {
736736
}
737737

738738
fn menu(mut self, menu: Menu) -> Self {
739-
self.menu = convert_menu_id(Menu::new(), menu);
739+
self.menu.replace(menu);
740740
self
741741
}
742742

@@ -857,8 +857,8 @@ impl WindowBuilder for WindowBuilderWrapper {
857857
self.inner.window.window_icon.is_some()
858858
}
859859

860-
fn has_menu(&self) -> bool {
861-
self.inner.window.window_menu.is_some()
860+
fn get_menu(&self) -> Option<&Menu> {
861+
self.menu.as_ref()
862862
}
863863
}
864864

@@ -1206,6 +1206,7 @@ impl Dispatch for WryDispatcher {
12061206
) -> Result<DetachedWindow<Self::Runtime>> {
12071207
let (tx, rx) = channel();
12081208
let label = pending.label.clone();
1209+
let menu_ids = pending.menu_ids.clone();
12091210
let context = self.context.clone();
12101211

12111212
send_user_message(
@@ -1223,7 +1224,11 @@ impl Dispatch for WryDispatcher {
12231224
window_id,
12241225
context: self.context.clone(),
12251226
};
1226-
Ok(DetachedWindow { label, dispatcher })
1227+
Ok(DetachedWindow {
1228+
label,
1229+
dispatcher,
1230+
menu_ids,
1231+
})
12271232
}
12281233

12291234
fn set_resizable(&self, resizable: bool) -> Result<()> {
@@ -1451,7 +1456,7 @@ impl WindowHandle {
14511456
pub struct WindowWrapper {
14521457
label: String,
14531458
inner: WindowHandle,
1454-
menu_items: HashMap<u16, WryCustomMenuItem>,
1459+
menu_items: Option<HashMap<u16, WryCustomMenuItem>>,
14551460
}
14561461

14571462
/// A Tauri [`Runtime`] wrapper around wry.
@@ -1509,6 +1514,7 @@ impl RuntimeHandle for WryHandle {
15091514
) -> Result<DetachedWindow<Self::Runtime>> {
15101515
let (tx, rx) = channel();
15111516
let label = pending.label.clone();
1517+
let menu_ids = pending.menu_ids.clone();
15121518
let context = self.context.clone();
15131519
send_user_message(
15141520
&self.context,
@@ -1525,7 +1531,11 @@ impl RuntimeHandle for WryHandle {
15251531
window_id,
15261532
context: self.context.clone(),
15271533
};
1528-
Ok(DetachedWindow { label, dispatcher })
1534+
Ok(DetachedWindow {
1535+
label,
1536+
dispatcher,
1537+
menu_ids,
1538+
})
15291539
}
15301540

15311541
fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
@@ -1632,6 +1642,7 @@ impl Runtime for Wry {
16321642

16331643
fn create_window(&self, pending: PendingWindow<Self>) -> Result<DetachedWindow<Self>> {
16341644
let label = pending.label.clone();
1645+
let menu_ids = pending.menu_ids.clone();
16351646
let proxy = self.event_loop.create_proxy();
16361647
let webview = create_webview(
16371648
&self.event_loop,
@@ -1717,7 +1728,11 @@ impl Runtime for Wry {
17171728
.unwrap()
17181729
.insert(webview.inner.window().id(), webview);
17191730

1720-
Ok(DetachedWindow { label, dispatcher })
1731+
Ok(DetachedWindow {
1732+
label,
1733+
dispatcher,
1734+
menu_ids,
1735+
})
17211736
}
17221737

17231738
#[cfg(feature = "system-tray")]
@@ -2006,17 +2021,16 @@ fn handle_user_message(
20062021
let _ = window.drag_window();
20072022
}
20082023
WindowMessage::UpdateMenuItem(id, update) => {
2009-
let item = webview
2010-
.menu_items
2011-
.get_mut(&id)
2012-
.expect("menu item not found");
2013-
match update {
2014-
MenuUpdate::SetEnabled(enabled) => item.set_enabled(enabled),
2015-
MenuUpdate::SetTitle(title) => item.set_title(&title),
2016-
MenuUpdate::SetSelected(selected) => item.set_selected(selected),
2017-
#[cfg(target_os = "macos")]
2018-
MenuUpdate::SetNativeImage(image) => {
2019-
item.set_native_image(NativeImageWrapper::from(image).0)
2024+
if let Some(menu_items) = webview.menu_items.as_mut() {
2025+
let item = menu_items.get_mut(&id).expect("menu item not found");
2026+
match update {
2027+
MenuUpdate::SetEnabled(enabled) => item.set_enabled(enabled),
2028+
MenuUpdate::SetTitle(title) => item.set_title(&title),
2029+
MenuUpdate::SetSelected(selected) => item.set_selected(selected),
2030+
#[cfg(target_os = "macos")]
2031+
MenuUpdate::SetNativeImage(image) => {
2032+
item.set_native_image(NativeImageWrapper::from(image).0)
2033+
}
20202034
}
20212035
}
20222036
}
@@ -2464,38 +2478,6 @@ fn center_window(window: &Window, window_size: WryPhysicalSize<u32>) -> Result<(
24642478
}
24652479
}
24662480

2467-
fn convert_menu_id(mut new_menu: Menu, menu: Menu) -> Menu {
2468-
for item in menu.items {
2469-
match item {
2470-
MenuEntry::CustomItem(c) => {
2471-
let mut item = CustomMenuItem::new(c.id_str, c.title);
2472-
#[cfg(target_os = "macos")]
2473-
if let Some(native_image) = c.native_image {
2474-
item = item.native_image(native_image);
2475-
}
2476-
if let Some(accelerator) = c.keyboard_accelerator {
2477-
item = item.accelerator(accelerator);
2478-
}
2479-
if !c.enabled {
2480-
item = item.disabled();
2481-
}
2482-
if c.selected {
2483-
item = item.selected();
2484-
}
2485-
new_menu = new_menu.add_item(item);
2486-
}
2487-
MenuEntry::NativeItem(i) => {
2488-
new_menu = new_menu.add_native_item(i);
2489-
}
2490-
MenuEntry::Submenu(submenu) => {
2491-
let new_submenu = convert_menu_id(Menu::new(), submenu.inner);
2492-
new_menu = new_menu.add_submenu(Submenu::new(submenu.title, new_submenu));
2493-
}
2494-
}
2495-
}
2496-
new_menu
2497-
}
2498-
24992481
fn to_wry_menu(
25002482
custom_menu_items: &mut HashMap<MenuHash, WryCustomMenuItem>,
25012483
menu: Menu,
@@ -2544,15 +2526,18 @@ fn create_webview(
25442526
file_drop_handler,
25452527
label,
25462528
url,
2529+
menu_ids,
25472530
..
25482531
} = pending;
25492532

25502533
let is_window_transparent = window_builder.inner.window.transparent;
2551-
let menu_items = {
2534+
let menu_items = if let Some(menu) = window_builder.menu {
25522535
let mut menu_items = HashMap::new();
2553-
let menu = to_wry_menu(&mut menu_items, window_builder.menu);
2536+
let menu = to_wry_menu(&mut menu_items, menu);
25542537
window_builder.inner = window_builder.inner.with_menu(menu);
2555-
menu_items
2538+
Some(menu_items)
2539+
} else {
2540+
None
25562541
};
25572542
let window = window_builder.inner.build(event_loop).unwrap();
25582543

@@ -2577,13 +2562,18 @@ fn create_webview(
25772562
.unwrap() // safe to unwrap because we validate the URL beforehand
25782563
.with_transparent(is_window_transparent);
25792564
if let Some(handler) = rpc_handler {
2580-
webview_builder =
2581-
webview_builder.with_rpc_handler(create_rpc_handler(context.clone(), label.clone(), handler));
2565+
webview_builder = webview_builder.with_rpc_handler(create_rpc_handler(
2566+
context.clone(),
2567+
label.clone(),
2568+
menu_ids.clone(),
2569+
handler,
2570+
));
25822571
}
25832572
if let Some(handler) = file_drop_handler {
25842573
webview_builder = webview_builder.with_file_drop_handler(create_file_drop_handler(
25852574
context,
25862575
label.clone(),
2576+
menu_ids,
25872577
handler,
25882578
));
25892579
}
@@ -2639,6 +2629,7 @@ fn create_webview(
26392629
fn create_rpc_handler(
26402630
context: Context,
26412631
label: String,
2632+
menu_ids: HashMap<MenuHash, MenuId>,
26422633
handler: WebviewRpcHandler<Wry>,
26432634
) -> Box<dyn Fn(&Window, WryRpcRequest) -> Option<RpcResponse> + 'static> {
26442635
Box::new(move |window, request| {
@@ -2649,6 +2640,7 @@ fn create_rpc_handler(
26492640
context: context.clone(),
26502641
},
26512642
label: label.clone(),
2643+
menu_ids: menu_ids.clone(),
26522644
},
26532645
RpcRequestWrapper(request).into(),
26542646
);
@@ -2660,6 +2652,7 @@ fn create_rpc_handler(
26602652
fn create_file_drop_handler(
26612653
context: Context,
26622654
label: String,
2655+
menu_ids: HashMap<MenuHash, MenuId>,
26632656
handler: FileDropHandler<Wry>,
26642657
) -> Box<dyn Fn(&Window, WryFileDropEvent) -> bool + 'static> {
26652658
Box::new(move |window, event| {
@@ -2671,6 +2664,7 @@ fn create_file_drop_handler(
26712664
context: context.clone(),
26722665
},
26732666
label: label.clone(),
2667+
menu_ids: menu_ids.clone(),
26742668
},
26752669
)
26762670
})

core/tauri-runtime/src/webview.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ pub trait WindowBuilder: WindowBuilderBase {
156156
/// Whether the icon was set or not.
157157
fn has_icon(&self) -> bool;
158158

159-
/// Whether the menu was set or not.
160-
fn has_menu(&self) -> bool;
159+
/// Gets the window menu.
160+
fn get_menu(&self) -> Option<&Menu>;
161161
}
162162

163163
/// Rpc request.

core/tauri-runtime/src/window.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
use crate::{
88
http::{Request as HttpRequest, Response as HttpResponse},
9+
menu::{Menu, MenuEntry, MenuHash, MenuId},
910
webview::{FileDropHandler, WebviewAttributes, WebviewRpcHandler},
1011
Dispatch, Runtime, WindowBuilder,
1112
};
@@ -61,6 +62,18 @@ pub struct MenuEvent {
6162
pub menu_item_id: u16,
6263
}
6364

65+
fn get_menu_ids(map: &mut HashMap<MenuHash, MenuId>, menu: &Menu) {
66+
for item in &menu.items {
67+
match item {
68+
MenuEntry::CustomItem(c) => {
69+
map.insert(c.id, c.id_str.clone());
70+
}
71+
MenuEntry::Submenu(s) => get_menu_ids(map, &s.inner),
72+
_ => {}
73+
}
74+
}
75+
}
76+
6477
/// A webview window that has yet to be built.
6578
pub struct PendingWindow<R: Runtime> {
6679
/// The label that the window will be named.
@@ -82,6 +95,9 @@ pub struct PendingWindow<R: Runtime> {
8295

8396
/// The resolved URL to load on the webview.
8497
pub url: String,
98+
99+
/// Maps runtime id to a string menu id.
100+
pub menu_ids: HashMap<MenuHash, MenuId>,
85101
}
86102

87103
impl<R: Runtime> PendingWindow<R> {
@@ -91,6 +107,10 @@ impl<R: Runtime> PendingWindow<R> {
91107
webview_attributes: WebviewAttributes,
92108
label: impl Into<String>,
93109
) -> Self {
110+
let mut menu_ids = HashMap::new();
111+
if let Some(menu) = window_builder.get_menu() {
112+
get_menu_ids(&mut menu_ids, menu);
113+
}
94114
Self {
95115
window_builder,
96116
webview_attributes,
@@ -99,6 +119,7 @@ impl<R: Runtime> PendingWindow<R> {
99119
rpc_handler: None,
100120
file_drop_handler: None,
101121
url: "tauri://localhost".to_string(),
122+
menu_ids,
102123
}
103124
}
104125

@@ -108,14 +129,20 @@ impl<R: Runtime> PendingWindow<R> {
108129
webview_attributes: WebviewAttributes,
109130
label: impl Into<String>,
110131
) -> Self {
132+
let window_builder = <<R::Dispatcher as Dispatch>::WindowBuilder>::with_config(window_config);
133+
let mut menu_ids = HashMap::new();
134+
if let Some(menu) = window_builder.get_menu() {
135+
get_menu_ids(&mut menu_ids, menu);
136+
}
111137
Self {
112-
window_builder: <<R::Dispatcher as Dispatch>::WindowBuilder>::with_config(window_config),
138+
window_builder,
113139
webview_attributes,
114140
uri_scheme_protocols: Default::default(),
115141
label: label.into(),
116142
rpc_handler: None,
117143
file_drop_handler: None,
118144
url: "tauri://localhost".to_string(),
145+
menu_ids,
119146
}
120147
}
121148

@@ -142,13 +169,17 @@ pub struct DetachedWindow<R: Runtime> {
142169

143170
/// The [`Dispatch`](crate::Dispatch) associated with the window.
144171
pub dispatcher: R::Dispatcher,
172+
173+
/// Maps runtime id to a string menu id.
174+
pub menu_ids: HashMap<MenuHash, MenuId>,
145175
}
146176

147177
impl<R: Runtime> Clone for DetachedWindow<R> {
148178
fn clone(&self) -> Self {
149179
Self {
150180
label: self.label.clone(),
151181
dispatcher: self.dispatcher.clone(),
182+
menu_ids: self.menu_ids.clone(),
152183
}
153184
}
154185
}

core/tauri/src/endpoints/window.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub enum WindowManagerCmd {
9090
#[serde(tag = "cmd", content = "data", rename_all = "camelCase")]
9191
pub enum Cmd {
9292
CreateWebview {
93-
options: WindowConfig,
93+
options: Box<WindowConfig>,
9494
},
9595
Manage {
9696
label: Option<String>,
@@ -123,7 +123,7 @@ impl Cmd {
123123
window
124124
.create_window(label.clone(), url, |_, webview_attributes| {
125125
(
126-
<<R::Dispatcher as Dispatch>::WindowBuilder>::with_config(options),
126+
<<R::Dispatcher as Dispatch>::WindowBuilder>::with_config(*options),
127127
webview_attributes,
128128
)
129129
})?

0 commit comments

Comments
 (0)