Hi,
I want to create a tray icon app with iced settings window.
I’m using tao, tray-icon and iced.
At first there is an eventloop by tao. There the tray menu events are handled. This works very well.
Then I want to open an iced window. The window opens and I can close it. But after then the eventloop stops working.
I assume iced somehow stops the loop.
Is there a way to continue the loop after the window was closed?
Example:
use iced::{widget::text, Element};
use tao::event_loop::{ControlFlow, EventLoop};
use tokio::runtime::Runtime;
use tray_icon::{
menu::{Menu, MenuEvent, MenuItem},
TrayIconBuilder, TrayIconEvent,
};
fn main() {
let runtime = Runtime::new().expect("Tokio Runtime konnte nicht erstellt werden");
let event_loop = EventLoop::new();
let item_update = MenuItem::new("update", true, None);
let item_config = MenuItem::new("settings", true, None);
let item_exit = MenuItem::new("quit", true, None);
let menu = Menu::new();
let _ = menu.append_items(&[&item_update, &item_config, &item_exit]);
let mut tray_icon = None;
let mut iced_window = None;
let menu_channel = MenuEvent::receiver();
let tray_channel = TrayIconEvent::receiver();
event_loop.run(move |event, _, control_flow| {
println!("event start");
*control_flow = ControlFlow::WaitUntil(
std::time::Instant::now() + std::time::Duration::from_millis(16),
);
if let tao::event::Event::NewEvents(tao::event::StartCause::Init) = event {
println!("Building tray icon");
tray_icon = Some(
TrayIconBuilder::new()
.with_menu(Box::new(menu.clone()))
.with_tooltip("tao - awesome windowing lib")
.build()
.unwrap(),
);
}
if let Ok(event) = menu_channel.try_recv() {
println!("menu event: {event:?}");
if event.id == item_exit.id() {
println!("Exiting...");
tray_icon.take();
*control_flow = ControlFlow::Exit;
} else if event.id == item_config.id() {
if iced_window.is_none() {
println!("Starting window");
iced_window = Some(
iced::application(
SettingsWindow::title,
SettingsWindow::update,
SettingsWindow::view,
)
.run()
.expect("Error running window"),
);
println!("Window closed");
}
} else if event.id == item_update.id() {
println!("Updating...");
runtime.spawn(async {
let _ = perform_web_request().await;
println!("Web-Request done");
});
}
}
if let Ok(event) = tray_channel.try_recv() {
println!("tray event: {event:?}");
}
//println!("event loop exit");
});
}
async fn perform_web_request() -> Result<String, ()> {
Ok("test".into())
}
#[derive(Debug, Clone, Copy)]
enum Message {}
#[derive(Default)]
struct SettingsWindow;
impl SettingsWindow {
fn title(&self) -> String {
"Einstellungen".to_string()
}
fn update(&mut self, message: Message) {}
fn view(&self) -> Element<Message> {
text("Hier können die Einstellungen vorgenommen werden.").into()
}
}
cargo.toml:
[package]
name = "iced-tray-icon"
version = "0.1.0"
edition = "2021"
[dependencies]
tao = "0.30.8"
iced = "0.13.1"
tray-icon = "0.19.0"
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] }