From 96651dccd2f81229a6a7d8a0fc8ffb122c099b30 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 22 Jun 2021 11:22:27 -0400 Subject: [PATCH] feat(menu): Add `window_id` to `MenuEvent` (#89) --- .changes/menu-windowid.md | 5 ++++ examples/custom_menu.rs | 7 +++++ examples/system_tray.rs | 1 + src/event.rs | 33 +++++++++++++++++++++--- src/platform_impl/linux/event_loop.rs | 2 ++ src/platform_impl/macos/menu.rs | 16 +++++++++++- src/platform_impl/windows/event_loop.rs | 1 + src/platform_impl/windows/menu.rs | 9 ++++++- src/platform_impl/windows/system_tray.rs | 2 ++ src/platform_impl/windows/window.rs | 7 +++-- 10 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 .changes/menu-windowid.md diff --git a/.changes/menu-windowid.md b/.changes/menu-windowid.md new file mode 100644 index 000000000..44da4a2dd --- /dev/null +++ b/.changes/menu-windowid.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +Add `window_id` to `MenuEvent`. diff --git a/examples/custom_menu.rs b/examples/custom_menu.rs index 5c9466868..68cc0ec40 100644 --- a/examples/custom_menu.rs +++ b/examples/custom_menu.rs @@ -83,10 +83,14 @@ fn main() { window.request_redraw(); } Event::MenuEvent { + window_id, menu_id, origin: MenuType::MenuBar, } if menu_id == test_menu_item.clone().id() => { println!("Clicked on `Disable menu`"); + if window_id == Some(window.id()) { + println!("Window ID match!"); + } // this allow us to get access to the menu and make changes // without re-rendering the whole menu test_menu_item.set_enabled(false); @@ -98,6 +102,7 @@ fn main() { Event::MenuEvent { menu_id, origin: MenuType::MenuBar, + .. } if menu_id == change_menu.clone().id() => { println!("Clicked on `Change menu`"); // set new menu @@ -110,12 +115,14 @@ fn main() { Event::MenuEvent { menu_id, origin: MenuType::MenuBar, + .. } if menu_id == custom_insert_clipboard.clone().id() => { cliboard.write_text("This is injected from tao!!!") } Event::MenuEvent { menu_id, origin: MenuType::MenuBar, + .. } if menu_id == custom_read_clipboard.clone().id() => { println!("Clipboard content: {:?}", cliboard.read_text()); } diff --git a/examples/system_tray.rs b/examples/system_tray.rs index 50c57fb54..fc5ded871 100644 --- a/examples/system_tray.rs +++ b/examples/system_tray.rs @@ -138,6 +138,7 @@ fn main() { menu_id, // specify only context menu's origin: MenuType::ContextMenu, + .. } => { // Click on Open new window or focus item if menu_id == open_new_window_element.clone().id() diff --git a/src/event.rs b/src/event.rs index 6608037e1..44a71744a 100644 --- a/src/event.rs +++ b/src/event.rs @@ -78,7 +78,11 @@ pub enum Event<'a, T: 'static> { /// Emitted when a menu has been clicked. There are two types of menu event. One comes from the /// menu bar, the other comes from the status bar. - MenuEvent { menu_id: MenuId, origin: MenuType }, + MenuEvent { + window_id: Option, + menu_id: MenuId, + origin: MenuType, + }, /// Emitted when tray has been clicked. /// @@ -166,7 +170,12 @@ impl Clone for Event<'static, T> { LoopDestroyed => LoopDestroyed, Suspended => Suspended, Resumed => Resumed, - MenuEvent { menu_id, origin } => MenuEvent { + MenuEvent { + window_id, + menu_id, + origin, + } => MenuEvent { + window_id: *window_id, menu_id: *menu_id, origin: *origin, }, @@ -198,7 +207,15 @@ impl<'a, T> Event<'a, T> { LoopDestroyed => Ok(LoopDestroyed), Suspended => Ok(Suspended), Resumed => Ok(Resumed), - MenuEvent { menu_id, origin } => Ok(MenuEvent { menu_id, origin }), + MenuEvent { + window_id, + menu_id, + origin, + } => Ok(MenuEvent { + window_id, + menu_id, + origin, + }), TrayEvent { bounds, event, @@ -229,7 +246,15 @@ impl<'a, T> Event<'a, T> { LoopDestroyed => Some(LoopDestroyed), Suspended => Some(Suspended), Resumed => Some(Resumed), - MenuEvent { menu_id, origin } => Some(MenuEvent { menu_id, origin }), + MenuEvent { + window_id, + menu_id, + origin, + } => Some(MenuEvent { + window_id, + menu_id, + origin, + }), TrayEvent { bounds, event, diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 1cf3b813f..cd6c74af7 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -483,6 +483,7 @@ impl EventLoop { WindowRequest::Menu(m) => match m { (None, Some(menu_id)) => { if let Err(e) = event_tx.send(Event::MenuEvent { + window_id: Some(RootWindowId(id)), menu_id, origin: MenuType::MenuBar, }) { @@ -643,6 +644,7 @@ impl EventLoop { } WindowRequest::Menu((None, Some(menu_id))) => { if let Err(e) = event_tx.send(Event::MenuEvent { + window_id: None, menu_id, origin: MenuType::ContextMenu, }) { diff --git a/src/platform_impl/macos/menu.rs b/src/platform_impl/macos/menu.rs index c3209e40e..9ac4d3730 100644 --- a/src/platform_impl/macos/menu.rs +++ b/src/platform_impl/macos/menu.rs @@ -18,9 +18,10 @@ use crate::{ keyboard::{KeyCode, ModifiersState}, menu::{CustomMenuItem, MenuId, MenuItem, MenuType}, platform::macos::NativeImage, + window::WindowId, }; -use super::{app_state::AppState, event::EventWrapper}; +use super::{app_state::AppState, event::EventWrapper, window::get_window_id}; static BLOCK_PTR: &str = "taoMenuItemBlockPtr"; @@ -429,7 +430,20 @@ fn send_event(this: &Object, origin: MenuType) { let obj = ptr as *const Action; &*obj }; + + // active window + let window_id = match origin { + MenuType::MenuBar => unsafe { + let app: id = msg_send![class!(NSApplication), sharedApplication]; + let window_id: id = msg_send![app, mainWindow]; + Some(WindowId(get_window_id(window_id))) + }, + // system tray do not send WindowId + MenuType::ContextMenu => None, + }; + let event = Event::MenuEvent { + window_id, menu_id: MenuId(*menu_id.0), origin, }; diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index c95ef5354..886b61f13 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -1099,6 +1099,7 @@ unsafe fn public_window_callback_inner( winuser::WM_COMMAND => { let menu_id = LOWORD(wparam as u32) as u16; subclass_input.send_event(Event::MenuEvent { + window_id: Some(RootWindowId(WindowId(window))), menu_id: MenuId(menu_id as u16), // todo fix menutype origin: MenuType::MenuBar, diff --git a/src/platform_impl/windows/menu.rs b/src/platform_impl/windows/menu.rs index ef3a7aae8..99dcbe7ae 100644 --- a/src/platform_impl/windows/menu.rs +++ b/src/platform_impl/windows/menu.rs @@ -40,13 +40,19 @@ lazy_static! { } pub struct MenuHandler { + window_id: Option, menu_type: MenuType, send_event: Box)>, } impl MenuHandler { - pub fn new(send_event: Box)>, menu_type: MenuType) -> MenuHandler { + pub fn new( + send_event: Box)>, + menu_type: MenuType, + window_id: Option, + ) -> MenuHandler { MenuHandler { + window_id, send_event, menu_type, } @@ -55,6 +61,7 @@ impl MenuHandler { (self.send_event)(Event::MenuEvent { menu_id: MenuId(menu_id), origin: self.menu_type, + window_id: self.window_id, }); } diff --git a/src/platform_impl/windows/system_tray.rs b/src/platform_impl/windows/system_tray.rs index b9133ccde..473e5a1a2 100644 --- a/src/platform_impl/windows/system_tray.rs +++ b/src/platform_impl/windows/system_tray.rs @@ -90,6 +90,7 @@ impl SystemTrayBuilder { } }), MenuType::ContextMenu, + None, ); let app_system_tray = SystemTray { @@ -150,6 +151,7 @@ impl SystemTrayBuilder { } }), MenuType::ContextMenu, + None, ); let sender: *mut MenuHandler = Box::into_raw(Box::new(menu_handler)); diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index ef3e3e57d..7e0a38dc8 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -53,7 +53,9 @@ use crate::{ window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState}, OsError, Parent, PlatformSpecificWindowBuilderAttributes, WindowId, }, - window::{CursorIcon, Fullscreen, Theme, UserAttentionType, WindowAttributes}, + window::{ + CursorIcon, Fullscreen, Theme, UserAttentionType, WindowAttributes, WindowId as RootWindowId, + }, }; struct HMenuWrapper(windef::HMENU); @@ -953,7 +955,7 @@ unsafe fn init( if let Some(window_menu) = attributes.window_menu { let event_loop_runner = event_loop.runner_shared.clone(); let window_handle = win.raw_window_handle(); - + let window_id = RootWindowId(win.id().clone()); let menu_handler = menu::MenuHandler::new( Box::new(move |event| { if let Ok(e) = event.map_nonuser_event() { @@ -961,6 +963,7 @@ unsafe fn init( } }), MenuType::MenuBar, + Some(window_id), ); win.menu = menu::initialize(window_menu, window_handle, menu_handler).map(|m| HMenuWrapper(m));