From 8a4d4b69577b880e64d6db0a073320d6d6680119 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 21 Jan 2025 09:24:19 -0800 Subject: [PATCH] Have `icon_for_app_id` run in a background thread This should probably be faster, but it's good for things like this to not block the UI thread regardless. We could probably also cache for multiple apps with the same ID. Not sure if there's a good way to detect changes to the icon for an app id (Not really needed, probably?) --- src/desktop_info.rs | 18 +++++++++++------- src/main.rs | 28 +++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/desktop_info.rs b/src/desktop_info.rs index 382cc0f..70607ac 100644 --- a/src/desktop_info.rs +++ b/src/desktop_info.rs @@ -5,13 +5,17 @@ use freedesktop_desktop_entry::DesktopEntry; use itertools::Itertools; use std::path::PathBuf; -pub fn icon_for_app_id(app_id: String) -> Option { - Some( - desktop_info_for_app_ids(vec![app_id]) - .into_iter() - .next()? - .icon, - ) +pub async fn icon_for_app_id(app_id: String) -> Option { + tokio::task::spawn_blocking(|| { + Some( + desktop_info_for_app_ids(vec![app_id]) + .into_iter() + .next()? + .icon, + ) + }) + .await + .unwrap() } #[allow(dead_code)] diff --git a/src/main.rs b/src/main.rs index 506873c..faa683c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -149,6 +149,7 @@ enum Msg { CompConfig(Box), Config(CosmicWorkspacesConfig), BgConfig(cosmic_bg_config::state::State), + UpdateToplevelIcon(String, Option), Ignore, } @@ -445,8 +446,14 @@ impl Application for App { } backend::Event::NewToplevel(handle, info) => { log::debug!("New toplevel: {info:?}"); + let app_id = info.app_id.clone(); + let icon_task = iced::Task::perform( + desktop_info::icon_for_app_id(app_id.clone()), + move |path| Msg::UpdateToplevelIcon(app_id.clone(), path), + ) + .map(cosmic::app::Message::App); self.toplevels.push(Toplevel { - icon: desktop_info::icon_for_app_id(info.app_id.clone()), + icon: None, handle, info, img: None, @@ -454,17 +461,25 @@ impl Application for App { // Close workspaces view if a window spawns while open #[cfg(not(feature = "mock-backend"))] if self.visible { - return self.hide(); + return Task::batch([icon_task, self.hide()]); } + return icon_task; } backend::Event::UpdateToplevel(handle, info) => { if let Some(toplevel) = self.toplevels.iter_mut().find(|x| x.handle == handle) { + let mut task = Task::none(); if toplevel.info.app_id != info.app_id { - toplevel.icon = desktop_info::icon_for_app_id(info.app_id.clone()); + let app_id = info.app_id.clone(); + task = iced::Task::perform( + desktop_info::icon_for_app_id(app_id.clone()), + move |path| Msg::UpdateToplevelIcon(app_id.clone(), path), + ) + .map(cosmic::app::Message::App); } toplevel.info = info; + return task; } } backend::Event::CloseToplevel(handle) => { @@ -558,6 +573,13 @@ impl Application for App { Msg::BgConfig(c) => { self.conf.bg = c; } + Msg::UpdateToplevelIcon(app_id, path) => { + for toplevel in self.toplevels.iter_mut() { + if toplevel.info.app_id == app_id { + toplevel.icon = path.clone(); + } + } + } Msg::Ignore => {} }