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?)
This commit is contained in:
Ian Douglas Scott 2025-01-21 09:24:19 -08:00
parent 0c9cabd21a
commit 8a4d4b6957
2 changed files with 36 additions and 10 deletions

View file

@ -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<PathBuf> {
Some(
desktop_info_for_app_ids(vec![app_id])
.into_iter()
.next()?
.icon,
)
pub async fn icon_for_app_id(app_id: String) -> Option<PathBuf> {
tokio::task::spawn_blocking(|| {
Some(
desktop_info_for_app_ids(vec![app_id])
.into_iter()
.next()?
.icon,
)
})
.await
.unwrap()
}
#[allow(dead_code)]

View file

@ -149,6 +149,7 @@ enum Msg {
CompConfig(Box<CosmicCompConfig>),
Config(CosmicWorkspacesConfig),
BgConfig(cosmic_bg_config::state::State),
UpdateToplevelIcon(String, Option<PathBuf>),
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 => {}
}