From a39c45b50b4989788c16e728001370eade4c2cd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fausto=20N=C3=BA=C3=B1ez=20Alberro?= Date: Sat, 26 Jun 2021 01:04:26 +0200 Subject: [PATCH 1/9] feat(linux): implement set_menu for system tray --- src/platform_impl/linux/system_tray.rs | 12 ++++++++++++ src/system_tray.rs | 11 ++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/platform_impl/linux/system_tray.rs b/src/platform_impl/linux/system_tray.rs index 2d5b1576d..04d01424d 100644 --- a/src/platform_impl/linux/system_tray.rs +++ b/src/platform_impl/linux/system_tray.rs @@ -69,4 +69,16 @@ impl SystemTray { .set_icon_theme_path(&path.to_string_lossy()); self.app_indicator.set_icon(&icon.to_string_lossy()) } + + pub fn set_menu( + &mut self, + tray_menu: Menu, + window_target: &EventLoopWindowTarget, + ) { + let tx_ = window_target.p.window_requests_tx.clone(); + let menu = &mut tray_menu.into_gtkmenu(&tx_, &AccelGroup::new(), WindowId::dummy()); + + self.app_indicator.set_menu(menu); + menu.show_all(); + } } diff --git a/src/system_tray.rs b/src/system_tray.rs index 060487b8c..24a9ab230 100644 --- a/src/system_tray.rs +++ b/src/system_tray.rs @@ -35,7 +35,8 @@ use crate::{ event_loop::EventLoopWindowTarget, menu::ContextMenu, platform_impl::{ - SystemTray as SystemTrayPlatform, SystemTrayBuilder as SystemTrayBuilderPlatform, + Menu as MenuPlatform, SystemTray as SystemTrayPlatform, + SystemTrayBuilder as SystemTrayBuilderPlatform, }, }; /// Object that allows you to build SystemTray instance. @@ -113,4 +114,12 @@ impl SystemTray { pub fn set_icon(&mut self, icon: PathBuf) { self.0.set_icon(icon) } + + pub fn set_menu( + &mut self, + tray_menu: MenuPlatform, + _window_target: &EventLoopWindowTarget, + ) { + self.0.set_menu(tray_menu, _window_target) + } } From dcf23d5ab1e6c175e09cf63ad4dd866a45bc4cb5 Mon Sep 17 00:00:00 2001 From: amrbashir <48618675+amrbashir@users.noreply.github.com> Date: Thu, 1 Jul 2021 20:26:26 +0200 Subject: [PATCH 2/9] add windows impl --- src/platform_impl/linux/system_tray.rs | 6 +- src/platform_impl/macos/system_tray.rs | 8 ++ src/platform_impl/windows/menu.rs | 2 +- src/platform_impl/windows/system_tray.rs | 168 ++++++++++++----------- src/system_tray.rs | 10 +- 5 files changed, 105 insertions(+), 89 deletions(-) diff --git a/src/platform_impl/linux/system_tray.rs b/src/platform_impl/linux/system_tray.rs index 04d01424d..5680c606d 100644 --- a/src/platform_impl/linux/system_tray.rs +++ b/src/platform_impl/linux/system_tray.rs @@ -72,13 +72,13 @@ impl SystemTray { pub fn set_menu( &mut self, - tray_menu: Menu, + tray_menu: &Menu, window_target: &EventLoopWindowTarget, ) { let tx_ = window_target.p.window_requests_tx.clone(); - let menu = &mut tray_menu.into_gtkmenu(&tx_, &AccelGroup::new(), WindowId::dummy()); + let mut menu = tray_menu.clone().into_gtkmenu(&tx_, &AccelGroup::new(), WindowId::dummy()); - self.app_indicator.set_menu(menu); + self.app_indicator.set_menu(&mut menu); menu.show_all(); } } diff --git a/src/platform_impl/macos/system_tray.rs b/src/platform_impl/macos/system_tray.rs index b54b56021..4f047761c 100644 --- a/src/platform_impl/macos/system_tray.rs +++ b/src/platform_impl/macos/system_tray.rs @@ -113,6 +113,14 @@ impl SystemTray { self.create_button_with_icon(); } + pub fn set_menu( + &mut self, + tray_menu: &Menu, + _window_target: &EventLoopWindowTarget, + ) { + + } + fn create_button_with_icon(&self) { const ICON_WIDTH: f64 = 18.0; const ICON_HEIGHT: f64 = 18.0; diff --git a/src/platform_impl/windows/menu.rs b/src/platform_impl/windows/menu.rs index 6d2bcda93..914a88e01 100644 --- a/src/platform_impl/windows/menu.rs +++ b/src/platform_impl/windows/menu.rs @@ -125,7 +125,7 @@ impl MenuItemAttributes { #[derive(Debug, Clone)] pub struct Menu { - hmenu: windef::HMENU, + pub(crate) hmenu: windef::HMENU, accels: HashMap, } diff --git a/src/platform_impl/windows/system_tray.rs b/src/platform_impl/windows/system_tray.rs index 473e5a1a2..4e68bb0a0 100644 --- a/src/platform_impl/windows/system_tray.rs +++ b/src/platform_impl/windows/system_tray.rs @@ -1,6 +1,8 @@ // Copyright 2019-2021 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 +use std::cell::RefCell; + use super::{ dpi::{dpi_to_scale_factor, hwnd_dpi}, menu::{subclass_proc, to_wstring, Menu, MenuHandler}, @@ -11,12 +13,11 @@ use crate::{ error::OsError as RootOsError, event::{Event, Rectangle, TrayEvent}, event_loop::EventLoopWindowTarget, - menu::MenuType, + menu::{ContextMenu, MenuType}, system_tray::SystemTray as RootSystemTray, }; use winapi::{ shared::{ - basetsd::LONG_PTR, minwindef::{LPARAM, LRESULT, UINT, WPARAM}, windef::{HICON, HMENU, HWND, POINT, RECT}, }, @@ -30,6 +31,7 @@ use winapi::{ const WM_USER_TRAYICON: u32 = 0x400 + 1111; const WM_USER_TRAYICON_UID: u32 = 0x855 + 1111; +thread_local!(static SYSTEM_TRAY_STASH: RefCell> = RefCell::new(None)); pub struct SystemTrayBuilder { pub(crate) icon: Vec, @@ -81,29 +83,6 @@ impl SystemTrayBuilder { ))); } - // system tray handler - let event_loop_runner = window_target.p.runner_shared.clone(); - let menu_handler = MenuHandler::new( - Box::new(move |event| { - if let Ok(e) = event.map_nonuser_event() { - event_loop_runner.send_event(e) - } - }), - MenuType::ContextMenu, - None, - ); - - let app_system_tray = SystemTray { - // dummy hwnd, will populate it later - hwnd: std::ptr::null::() as _, - hmenu, - }; - - let data = Box::into_raw(Box::new(WindowsLoopData { - system_tray: app_system_tray, - sender: menu_handler, - })); - let hwnd = winuser::CreateWindowExW( 0, class_name.as_ptr(), @@ -116,7 +95,7 @@ impl SystemTrayBuilder { 0 as _, 0 as _, hinstance as _, - data as _, + std::ptr::null_mut(), ); if hwnd == std::ptr::null_mut() { @@ -142,6 +121,26 @@ impl SystemTrayBuilder { let app_system_tray = SystemTray { hwnd, hmenu }; app_system_tray.set_icon_from_buffer(&self.icon, 32, 32); + // system tray handler + let event_loop_runner = window_target.p.runner_shared.clone(); + let menu_handler = MenuHandler::new( + Box::new(move |event| { + if let Ok(e) = event.map_nonuser_event() { + event_loop_runner.send_event(e) + } + }), + MenuType::ContextMenu, + None, + ); + + SYSTEM_TRAY_STASH.with(|stash| { + let data = WindowsLoopData { + system_tray: SystemTray { hwnd, hmenu }, + sender: menu_handler, + }; + (*stash.borrow_mut()) = Some(data); + }); + // create the handler for tray menu events let event_loop_runner = window_target.p.runner_shared.clone(); let menu_handler = MenuHandler::new( @@ -157,7 +156,7 @@ impl SystemTrayBuilder { let sender: *mut MenuHandler = Box::into_raw(Box::new(menu_handler)); SetWindowSubclass(hwnd as _, Some(subclass_proc), 0, sender as _); - return Ok(RootSystemTray(SystemTray { hwnd, hmenu })); + return Ok(RootSystemTray(app_system_tray)); } } } @@ -212,6 +211,20 @@ impl SystemTray { } } } + + pub fn set_menu( + &mut self, + tray_menu: &Menu, + _window_target: &EventLoopWindowTarget, + ) { + let new_menu = Some(tray_menu.hmenu); + self.hmenu = new_menu; + SYSTEM_TRAY_STASH.with(|stash| { + if let Some(ref mut data) = *stash.borrow_mut() { + data.system_tray.hmenu = new_menu; + } + }); + } } unsafe extern "system" fn window_proc( @@ -220,17 +233,9 @@ unsafe extern "system" fn window_proc( wparam: WPARAM, lparam: LPARAM, ) -> LRESULT { - let mut userdata = winuser::GetWindowLongPtrW(hwnd, winuser::GWL_USERDATA); - if userdata == 0 && msg == winuser::WM_NCCREATE { - let createstruct = &*(lparam as *const winuser::CREATESTRUCTW); - userdata = createstruct.lpCreateParams as LONG_PTR; - (*(userdata as *mut WindowsLoopData)).system_tray.hwnd = hwnd; - winuser::SetWindowLongPtrW(hwnd, winuser::GWL_USERDATA, userdata); - } - let userdata_ptr = userdata as *mut WindowsLoopData; - if msg == winuser::WM_DESTROY { winuser::PostQuitMessage(0); + return 0; } // click on the icon @@ -250,54 +255,57 @@ unsafe extern "system" fn window_proc( let mut cursor = POINT { x: 0, y: 0 }; winuser::GetCursorPos(&mut cursor as _); + SYSTEM_TRAY_STASH.with(|stash| { + if let Some(ref data) = *stash.borrow() { + match lparam as u32 { + // Left click tray icon + winuser::WM_LBUTTONUP => { + data.sender.send_event(Event::TrayEvent { + event: TrayEvent::LeftClick, + position: LogicalPosition::new(cursor.x, cursor.y).to_physical(scale_factor), + bounds: Rectangle { + position: LogicalPosition::new(rect.left, rect.top).to_physical(scale_factor), + size: LogicalSize::new(rect.right - rect.left, rect.bottom - rect.top) + .to_physical(scale_factor), + }, + }); + } - match lparam as u32 { - // Left click tray icon - winuser::WM_LBUTTONUP => { - (*userdata_ptr).sender.send_event(Event::TrayEvent { - event: TrayEvent::LeftClick, - position: LogicalPosition::new(cursor.x, cursor.y).to_physical(scale_factor), - bounds: Rectangle { - position: LogicalPosition::new(rect.left, rect.top).to_physical(scale_factor), - size: LogicalSize::new(rect.right - rect.left, rect.bottom - rect.top) - .to_physical(scale_factor), - }, - }); - } + // Right click tray icon + winuser::WM_RBUTTONUP => { + data.sender.send_event(Event::TrayEvent { + event: TrayEvent::RightClick, + position: LogicalPosition::new(cursor.x, cursor.y).to_physical(scale_factor), + bounds: Rectangle { + position: LogicalPosition::new(rect.left, rect.top).to_physical(scale_factor), + size: LogicalSize::new(rect.right - rect.left, rect.bottom - rect.top) + .to_physical(scale_factor), + }, + }); + + // show menu on right click + if let Some(menu) = data.system_tray.hmenu { + show_tray_menu(hwnd, menu, cursor.x, cursor.y); + } + } - // Right click tray icon - winuser::WM_RBUTTONUP => { - (*userdata_ptr).sender.send_event(Event::TrayEvent { - event: TrayEvent::RightClick, - position: LogicalPosition::new(cursor.x, cursor.y).to_physical(scale_factor), - bounds: Rectangle { - position: LogicalPosition::new(rect.left, rect.top).to_physical(scale_factor), - size: LogicalSize::new(rect.right - rect.left, rect.bottom - rect.top) - .to_physical(scale_factor), - }, - }); - - // show menu on right click - if let Some(menu) = (*userdata_ptr).system_tray.hmenu { - show_tray_menu(hwnd, menu, cursor.x, cursor.y); - } - } + // Double click tray icon + winuser::WM_LBUTTONDBLCLK => { + data.sender.send_event(Event::TrayEvent { + event: TrayEvent::DoubleClick, + position: LogicalPosition::new(cursor.x, cursor.y).to_physical(scale_factor), + bounds: Rectangle { + position: LogicalPosition::new(rect.left, rect.top).to_physical(scale_factor), + size: LogicalSize::new(rect.right - rect.left, rect.bottom - rect.top) + .to_physical(scale_factor), + }, + }); + } - // Double click tray icon - winuser::WM_LBUTTONDBLCLK => { - (*userdata_ptr).sender.send_event(Event::TrayEvent { - event: TrayEvent::DoubleClick, - position: LogicalPosition::new(cursor.x, cursor.y).to_physical(scale_factor), - bounds: Rectangle { - position: LogicalPosition::new(rect.left, rect.top).to_physical(scale_factor), - size: LogicalSize::new(rect.right - rect.left, rect.bottom - rect.top) - .to_physical(scale_factor), - }, - }); + _ => {} + } } - - _ => {} - } + }); } return winuser::DefWindowProcW(hwnd, msg, wparam, lparam); diff --git a/src/system_tray.rs b/src/system_tray.rs index 24a9ab230..82447a5d1 100644 --- a/src/system_tray.rs +++ b/src/system_tray.rs @@ -35,8 +35,7 @@ use crate::{ event_loop::EventLoopWindowTarget, menu::ContextMenu, platform_impl::{ - Menu as MenuPlatform, SystemTray as SystemTrayPlatform, - SystemTrayBuilder as SystemTrayBuilderPlatform, + SystemTray as SystemTrayPlatform, SystemTrayBuilder as SystemTrayBuilderPlatform, }, }; /// Object that allows you to build SystemTray instance. @@ -115,11 +114,12 @@ impl SystemTray { self.0.set_icon(icon) } + /// Set new tray menu. pub fn set_menu( &mut self, - tray_menu: MenuPlatform, - _window_target: &EventLoopWindowTarget, + tray_menu: &ContextMenu, + window_target: &EventLoopWindowTarget, ) { - self.0.set_menu(tray_menu, _window_target) + self.0.set_menu(&tray_menu.0.menu_platform, window_target) } } From 8f7dcf3f7d0082d1306ccf604fc59a1c4b94c72d Mon Sep 17 00:00:00 2001 From: David Lemarier Date: Fri, 2 Jul 2021 07:51:13 -0400 Subject: [PATCH 3/9] add macos impl --- examples/system_tray.rs | 9 +++++++++ src/platform_impl/linux/system_tray.rs | 4 +++- src/platform_impl/macos/system_tray.rs | 4 +++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/examples/system_tray.rs b/examples/system_tray.rs index fc5ded871..b6ec972f4 100644 --- a/examples/system_tray.rs +++ b/examples/system_tray.rs @@ -43,6 +43,8 @@ fn main() { let mut focus_all_window = tray_menu.add_item(MenuItemAttributes::new("Focus window").with_enabled(false)); + let change_menu = tray_menu.add_item(MenuItemAttributes::new("Change menu")); + // inject submenu into tray_menu tray_menu.add_submenu("Sub menu", true, submenu); @@ -156,6 +158,13 @@ fn main() { // tell our app to close at the end of the loop. *control_flow = ControlFlow::Exit; } + + if menu_id == change_menu.clone().id() { + let mut tray_menu = Menu::new(); + tray_menu.add_item(MenuItemAttributes::new("Quit")); + system_tray.set_menu(&tray_menu, &event_loop); + } + println!("Clicked on {:?}", menu_id); } _ => (), diff --git a/src/platform_impl/linux/system_tray.rs b/src/platform_impl/linux/system_tray.rs index 5680c606d..481baf108 100644 --- a/src/platform_impl/linux/system_tray.rs +++ b/src/platform_impl/linux/system_tray.rs @@ -76,7 +76,9 @@ impl SystemTray { window_target: &EventLoopWindowTarget, ) { let tx_ = window_target.p.window_requests_tx.clone(); - let mut menu = tray_menu.clone().into_gtkmenu(&tx_, &AccelGroup::new(), WindowId::dummy()); + let mut menu = tray_menu + .clone() + .into_gtkmenu(&tx_, &AccelGroup::new(), WindowId::dummy()); self.app_indicator.set_menu(&mut menu); menu.show_all(); diff --git a/src/platform_impl/macos/system_tray.rs b/src/platform_impl/macos/system_tray.rs index 4f047761c..bf91536d1 100644 --- a/src/platform_impl/macos/system_tray.rs +++ b/src/platform_impl/macos/system_tray.rs @@ -118,7 +118,9 @@ impl SystemTray { tray_menu: &Menu, _window_target: &EventLoopWindowTarget, ) { - + unsafe { + self.ns_status_bar.setMenu_(tray_menu.menu); + } } fn create_button_with_icon(&self) { From 540602d5176eebdb8aea1a9b1065fe94db670759 Mon Sep 17 00:00:00 2001 From: David Lemarier Date: Fri, 2 Jul 2021 08:20:19 -0400 Subject: [PATCH 4/9] clean linux and remove --- examples/system_tray.rs | 2 +- src/platform_impl/linux/system_tray.rs | 47 +++++++++++------------- src/platform_impl/macos/system_tray.rs | 6 +-- src/platform_impl/windows/system_tray.rs | 6 +-- src/system_tray.rs | 8 +--- 5 files changed, 27 insertions(+), 42 deletions(-) diff --git a/examples/system_tray.rs b/examples/system_tray.rs index b6ec972f4..1344b9e5f 100644 --- a/examples/system_tray.rs +++ b/examples/system_tray.rs @@ -162,7 +162,7 @@ fn main() { if menu_id == change_menu.clone().id() { let mut tray_menu = Menu::new(); tray_menu.add_item(MenuItemAttributes::new("Quit")); - system_tray.set_menu(&tray_menu, &event_loop); + system_tray.set_menu(&tray_menu); } println!("Clicked on {:?}", menu_id); diff --git a/src/platform_impl/linux/system_tray.rs b/src/platform_impl/linux/system_tray.rs index 481baf108..6d66988ed 100644 --- a/src/platform_impl/linux/system_tray.rs +++ b/src/platform_impl/linux/system_tray.rs @@ -5,15 +5,17 @@ use crate::{ error::OsError, event_loop::EventLoopWindowTarget, system_tray::SystemTray as RootSystemTray, }; +use glib::Sender; use std::path::PathBuf; use gtk::{AccelGroup, WidgetExt}; use libappindicator::{AppIndicator, AppIndicatorStatus}; -use super::{menu::Menu, WindowId}; +use super::{menu::Menu, window::WindowRequest, WindowId}; pub struct SystemTrayBuilder { - pub(crate) system_tray: SystemTray, + tray_menu: Option, + app_indicator: AppIndicator, } impl SystemTrayBuilder { @@ -25,11 +27,10 @@ impl SystemTrayBuilder { &icon.to_string_lossy(), &path.to_string_lossy(), ); + Self { - system_tray: SystemTray { - tray_menu, - app_indicator, - }, + tray_menu, + app_indicator, } } @@ -38,27 +39,27 @@ impl SystemTrayBuilder { mut self, window_target: &EventLoopWindowTarget, ) -> Result { - let tx_ = window_target.p.window_requests_tx.clone(); + let sender = window_target.p.window_requests_tx.clone(); - if let Some(tray_menu) = self.system_tray.tray_menu.clone() { - let menu = &mut tray_menu.into_gtkmenu(&tx_, &AccelGroup::new(), WindowId::dummy()); + if let Some(tray_menu) = self.tray_menu.clone() { + let menu = &mut tray_menu.into_gtkmenu(&sender, &AccelGroup::new(), WindowId::dummy()); - self.system_tray.app_indicator.set_menu(menu); + self.app_indicator.set_menu(menu); menu.show_all(); } - self - .system_tray - .app_indicator - .set_status(AppIndicatorStatus::Active); + self.app_indicator.set_status(AppIndicatorStatus::Active); - Ok(RootSystemTray(self.system_tray)) + Ok(RootSystemTray(SystemTray { + app_indicator: self.app_indicator, + sender, + })) } } pub struct SystemTray { - tray_menu: Option, app_indicator: AppIndicator, + sender: Sender<(WindowId, WindowRequest)>, } impl SystemTray { @@ -70,15 +71,11 @@ impl SystemTray { self.app_indicator.set_icon(&icon.to_string_lossy()) } - pub fn set_menu( - &mut self, - tray_menu: &Menu, - window_target: &EventLoopWindowTarget, - ) { - let tx_ = window_target.p.window_requests_tx.clone(); - let mut menu = tray_menu - .clone() - .into_gtkmenu(&tx_, &AccelGroup::new(), WindowId::dummy()); + pub fn set_menu(&mut self, tray_menu: &Menu) { + let mut menu = + tray_menu + .clone() + .into_gtkmenu(&self.sender, &AccelGroup::new(), WindowId::dummy()); self.app_indicator.set_menu(&mut menu); menu.show_all(); diff --git a/src/platform_impl/macos/system_tray.rs b/src/platform_impl/macos/system_tray.rs index bf91536d1..4d71bd9b6 100644 --- a/src/platform_impl/macos/system_tray.rs +++ b/src/platform_impl/macos/system_tray.rs @@ -113,11 +113,7 @@ impl SystemTray { self.create_button_with_icon(); } - pub fn set_menu( - &mut self, - tray_menu: &Menu, - _window_target: &EventLoopWindowTarget, - ) { + pub fn set_menu(&mut self, tray_menu: &Menu) { unsafe { self.ns_status_bar.setMenu_(tray_menu.menu); } diff --git a/src/platform_impl/windows/system_tray.rs b/src/platform_impl/windows/system_tray.rs index 4e68bb0a0..9e04387d3 100644 --- a/src/platform_impl/windows/system_tray.rs +++ b/src/platform_impl/windows/system_tray.rs @@ -212,11 +212,7 @@ impl SystemTray { } } - pub fn set_menu( - &mut self, - tray_menu: &Menu, - _window_target: &EventLoopWindowTarget, - ) { + pub fn set_menu(&mut self, tray_menu: &Menu) { let new_menu = Some(tray_menu.hmenu); self.hmenu = new_menu; SYSTEM_TRAY_STASH.with(|stash| { diff --git a/src/system_tray.rs b/src/system_tray.rs index 82447a5d1..38fc57341 100644 --- a/src/system_tray.rs +++ b/src/system_tray.rs @@ -115,11 +115,7 @@ impl SystemTray { } /// Set new tray menu. - pub fn set_menu( - &mut self, - tray_menu: &ContextMenu, - window_target: &EventLoopWindowTarget, - ) { - self.0.set_menu(&tray_menu.0.menu_platform, window_target) + pub fn set_menu(&mut self, tray_menu: &ContextMenu) { + self.0.set_menu(&tray_menu.0.menu_platform) } } From 444e5b783dabf5e285451619d4112842c4a78c13 Mon Sep 17 00:00:00 2001 From: David Lemarier Date: Wed, 14 Jul 2021 07:40:18 -0400 Subject: [PATCH 5/9] cleanup and add `FIXME` --- src/platform_impl/windows/menu.rs | 2 +- src/platform_impl/windows/system_tray.rs | 4 +++- src/platform_impl/windows/window.rs | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/platform_impl/windows/menu.rs b/src/platform_impl/windows/menu.rs index 914a88e01..5b1a43fca 100644 --- a/src/platform_impl/windows/menu.rs +++ b/src/platform_impl/windows/menu.rs @@ -157,7 +157,7 @@ impl Menu { } } - pub fn new_popup_menu() -> Menu { + pub fn new_popup_menu() -> Self { unsafe { let hmenu = winuser::CreatePopupMenu(); Menu { diff --git a/src/platform_impl/windows/system_tray.rs b/src/platform_impl/windows/system_tray.rs index 9e04387d3..b5edbf43d 100644 --- a/src/platform_impl/windows/system_tray.rs +++ b/src/platform_impl/windows/system_tray.rs @@ -13,7 +13,7 @@ use crate::{ error::OsError as RootOsError, event::{Event, Rectangle, TrayEvent}, event_loop::EventLoopWindowTarget, - menu::{ContextMenu, MenuType}, + menu::MenuType, system_tray::SystemTray as RootSystemTray, }; use winapi::{ @@ -212,6 +212,8 @@ impl SystemTray { } } + // FIXME: Doing this, drop the menu as we do not keep a reference to it + // dropped by the `impl Drop for Menu` pub fn set_menu(&mut self, tray_menu: &Menu) { let new_menu = Some(tray_menu.hmenu); self.hmenu = new_menu; diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index bcbfd9053..8b310cb12 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -22,14 +22,14 @@ use winapi::{ windef::{self, HWND, POINT, POINTS, RECT}, }, um::{ - combaseapi::{self, CoCreateInstance, CLSCTX_SERVER}, + combaseapi, dwmapi, imm::{CFS_POINT, COMPOSITIONFORM}, libloaderapi, objbase::COINIT_APARTMENTTHREADED, ole2, oleidl::LPDROPTARGET, - shobjidl_core::{CLSID_TaskbarList, ITaskbarList, ITaskbarList2}, + shobjidl_core::{CLSID_TaskbarList, ITaskbarList2}, wingdi::{CreateRectRgn, DeleteObject}, winnt::{LPCWSTR, SHORT}, winuser, From 38bc9599bcf3ec350a3b0a59c15764f6ca978131 Mon Sep 17 00:00:00 2001 From: David Lemarier Date: Wed, 14 Jul 2021 11:57:50 -0400 Subject: [PATCH 6/9] disable `set_menu` on Windows --- src/platform_impl/windows/system_tray.rs | 28 ++++++++++++++++-------- src/system_tray.rs | 4 ++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/platform_impl/windows/system_tray.rs b/src/platform_impl/windows/system_tray.rs index b5edbf43d..d106729d0 100644 --- a/src/platform_impl/windows/system_tray.rs +++ b/src/platform_impl/windows/system_tray.rs @@ -212,16 +212,26 @@ impl SystemTray { } } - // FIXME: Doing this, drop the menu as we do not keep a reference to it - // dropped by the `impl Drop for Menu` pub fn set_menu(&mut self, tray_menu: &Menu) { - let new_menu = Some(tray_menu.hmenu); - self.hmenu = new_menu; - SYSTEM_TRAY_STASH.with(|stash| { - if let Some(ref mut data) = *stash.borrow_mut() { - data.system_tray.hmenu = new_menu; - } - }); + /* + FIXME: Doing this, drop the menu as we do not keep a reference to it + dropped by the `impl Drop for Menu` + + To prevent release of tao 0.4 we disable the set_menu on the system tray + for now. + + To be continued in; + https://github.com/tauri-apps/tao/pull/93 + + let new_menu = Some(tray_menu.hmenu); + self.hmenu = new_menu; + SYSTEM_TRAY_STASH.with(|stash| { + if let Some(ref mut data) = *stash.borrow_mut() { + data.system_tray.hmenu = new_menu; + } + }); + */ + debug!("`set_menu` is unimplemented on Windows."); } } diff --git a/src/system_tray.rs b/src/system_tray.rs index 38fc57341..b3c130061 100644 --- a/src/system_tray.rs +++ b/src/system_tray.rs @@ -115,6 +115,10 @@ impl SystemTray { } /// Set new tray menu. + /// + /// ## Platform-specific + /// + /// - **Windows:**: Unsupported (menu is not updated, you should update the items manually) pub fn set_menu(&mut self, tray_menu: &ContextMenu) { self.0.set_menu(&tray_menu.0.menu_platform) } From 3a8d90971f5ff5c0df1b5a21186b9f81a7417c21 Mon Sep 17 00:00:00 2001 From: David Lemarier Date: Wed, 14 Jul 2021 12:06:26 -0400 Subject: [PATCH 7/9] fix fmt and add changefile --- .changes/tray-set-menu.md | 5 +++++ src/platform_impl/windows/system_tray.rs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changes/tray-set-menu.md diff --git a/.changes/tray-set-menu.md b/.changes/tray-set-menu.md new file mode 100644 index 000000000..2531b6367 --- /dev/null +++ b/.changes/tray-set-menu.md @@ -0,0 +1,5 @@ +--- +"tao": minor +--- + +macOS and Linux now allow `set_menu` on `SystemTray`. (Windows coming soon) diff --git a/src/platform_impl/windows/system_tray.rs b/src/platform_impl/windows/system_tray.rs index d106729d0..582f39376 100644 --- a/src/platform_impl/windows/system_tray.rs +++ b/src/platform_impl/windows/system_tray.rs @@ -212,7 +212,7 @@ impl SystemTray { } } - pub fn set_menu(&mut self, tray_menu: &Menu) { + pub fn set_menu(&mut self, _tray_menu: &Menu) { /* FIXME: Doing this, drop the menu as we do not keep a reference to it dropped by the `impl Drop for Menu` From 203e249b1a5f4eb8ae1139a63da5601ca7afea00 Mon Sep 17 00:00:00 2001 From: David Lemarier Date: Wed, 14 Jul 2021 12:22:44 -0400 Subject: [PATCH 8/9] re-add windows --- .changes/tray-set-menu.md | 2 +- examples/system_tray.rs | 8 +++++--- src/platform_impl/windows/system_tray.rs | 26 +++++++----------------- src/system_tray.rs | 4 ---- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/.changes/tray-set-menu.md b/.changes/tray-set-menu.md index 2531b6367..019227377 100644 --- a/.changes/tray-set-menu.md +++ b/.changes/tray-set-menu.md @@ -2,4 +2,4 @@ "tao": minor --- -macOS and Linux now allow `set_menu` on `SystemTray`. (Windows coming soon) +`SystemTray` expose `set_menu` to update the system tray menu once created. diff --git a/examples/system_tray.rs b/examples/system_tray.rs index 359f4001a..960b934ce 100644 --- a/examples/system_tray.rs +++ b/examples/system_tray.rs @@ -51,6 +51,10 @@ fn main() { // add quit button let quit_element = tray_menu.add_item(MenuItemAttributes::new("Quit")); + // second menu (lifetime is important, specially on Windows) + let mut new_tray_menu = Menu::new(); + new_tray_menu.add_item(MenuItemAttributes::new("Quit")); + // Windows require Vec ICO file #[cfg(target_os = "windows")] let icon = include_bytes!("icon.ico").to_vec(); @@ -162,9 +166,7 @@ fn main() { } if menu_id == change_menu.clone().id() { - let mut tray_menu = Menu::new(); - tray_menu.add_item(MenuItemAttributes::new("Quit")); - system_tray.set_menu(&tray_menu); + system_tray.set_menu(&new_tray_menu); } println!("Clicked on {:?}", menu_id); diff --git a/src/platform_impl/windows/system_tray.rs b/src/platform_impl/windows/system_tray.rs index 582f39376..e63006b87 100644 --- a/src/platform_impl/windows/system_tray.rs +++ b/src/platform_impl/windows/system_tray.rs @@ -213,25 +213,13 @@ impl SystemTray { } pub fn set_menu(&mut self, _tray_menu: &Menu) { - /* - FIXME: Doing this, drop the menu as we do not keep a reference to it - dropped by the `impl Drop for Menu` - - To prevent release of tao 0.4 we disable the set_menu on the system tray - for now. - - To be continued in; - https://github.com/tauri-apps/tao/pull/93 - - let new_menu = Some(tray_menu.hmenu); - self.hmenu = new_menu; - SYSTEM_TRAY_STASH.with(|stash| { - if let Some(ref mut data) = *stash.borrow_mut() { - data.system_tray.hmenu = new_menu; - } - }); - */ - debug!("`set_menu` is unimplemented on Windows."); + let new_menu = Some(tray_menu.hmenu); + self.hmenu = new_menu; + SYSTEM_TRAY_STASH.with(|stash| { + if let Some(ref mut data) = *stash.borrow_mut() { + data.system_tray.hmenu = new_menu; + } + }); } } diff --git a/src/system_tray.rs b/src/system_tray.rs index b3c130061..38fc57341 100644 --- a/src/system_tray.rs +++ b/src/system_tray.rs @@ -115,10 +115,6 @@ impl SystemTray { } /// Set new tray menu. - /// - /// ## Platform-specific - /// - /// - **Windows:**: Unsupported (menu is not updated, you should update the items manually) pub fn set_menu(&mut self, tray_menu: &ContextMenu) { self.0.set_menu(&tray_menu.0.menu_platform) } From 45b5c4b841a52441e7af7e169205619604b8dfa0 Mon Sep 17 00:00:00 2001 From: David Lemarier Date: Wed, 14 Jul 2021 12:28:38 -0400 Subject: [PATCH 9/9] fix variable name, remove drop on Windows and revert examples --- examples/system_tray.rs | 8 +++----- src/platform_impl/windows/menu.rs | 24 ++++++++++++++++-------- src/platform_impl/windows/system_tray.rs | 2 +- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/examples/system_tray.rs b/examples/system_tray.rs index 960b934ce..359f4001a 100644 --- a/examples/system_tray.rs +++ b/examples/system_tray.rs @@ -51,10 +51,6 @@ fn main() { // add quit button let quit_element = tray_menu.add_item(MenuItemAttributes::new("Quit")); - // second menu (lifetime is important, specially on Windows) - let mut new_tray_menu = Menu::new(); - new_tray_menu.add_item(MenuItemAttributes::new("Quit")); - // Windows require Vec ICO file #[cfg(target_os = "windows")] let icon = include_bytes!("icon.ico").to_vec(); @@ -166,7 +162,9 @@ fn main() { } if menu_id == change_menu.clone().id() { - system_tray.set_menu(&new_tray_menu); + let mut tray_menu = Menu::new(); + tray_menu.add_item(MenuItemAttributes::new("Quit")); + system_tray.set_menu(&tray_menu); } println!("Clicked on {:?}", menu_id); diff --git a/src/platform_impl/windows/menu.rs b/src/platform_impl/windows/menu.rs index 5b1a43fca..faca68be7 100644 --- a/src/platform_impl/windows/menu.rs +++ b/src/platform_impl/windows/menu.rs @@ -129,14 +129,6 @@ pub struct Menu { accels: HashMap, } -impl Drop for Menu { - fn drop(&mut self) { - unsafe { - winuser::DestroyMenu(self.hmenu); - } - } -} - unsafe impl Send for Menu {} unsafe impl Sync for Menu {} @@ -319,6 +311,22 @@ impl Menu { } } +/* + Disabled as menu's seems to be linked to the app + so they are dropped when the app closes. + see discussion here; + + https://github.com/tauri-apps/tao/pull/106#issuecomment-880034210 + + impl Drop for Menu { + fn drop(&mut self) { + unsafe { + winuser::DestroyMenu(self.hmenu); + } + } + } +*/ + pub fn initialize( menu_builder: Menu, window_handle: RawWindowHandle, diff --git a/src/platform_impl/windows/system_tray.rs b/src/platform_impl/windows/system_tray.rs index e63006b87..b22440a0c 100644 --- a/src/platform_impl/windows/system_tray.rs +++ b/src/platform_impl/windows/system_tray.rs @@ -212,7 +212,7 @@ impl SystemTray { } } - pub fn set_menu(&mut self, _tray_menu: &Menu) { + pub fn set_menu(&mut self, tray_menu: &Menu) { let new_menu = Some(tray_menu.hmenu); self.hmenu = new_menu; SYSTEM_TRAY_STASH.with(|stash| {