use freedesktop instead of gtk

This commit is contained in:
galister
2025-12-27 15:28:16 +09:00
parent 64c8f03dae
commit 43037a6a41
10 changed files with 180 additions and 590 deletions

View File

@@ -117,7 +117,6 @@ impl TabApps {
extra: Default::default(),
};
gtk::init()?;
let entries = util::desktop_finder::find_entries()?;
let frontend_tasks = frontend.tasks.clone();

View File

@@ -1,5 +1,4 @@
use gio::prelude::{AppInfoExt, IconExt};
use gtk::traits::IconThemeExt;
use freedesktop::{ApplicationEntry, IconTheme};
use serde::{Deserialize, Serialize};
// compatibility with wayvr-ipc
@@ -31,6 +30,8 @@ pub struct EntrySearchCell {
pub categories: Vec<String>,
}
const ICON_SIZE: u32 = 128;
const CMD_BLACKLIST: [&str; 1] = [
"lsp-plugins", // LSP Plugins collection. They clutter the application list a lot
];
@@ -38,45 +39,32 @@ const CMD_BLACKLIST: [&str; 1] = [
const CATEGORY_TYPE_BLACKLIST: [&str; 5] = ["GTK", "Qt", "X-XFCE", "X-Bluetooth", "ConsoleOnly"];
pub fn find_entries() -> anyhow::Result<Vec<DesktopEntry>> {
let Some(icon_theme) = gtk::IconTheme::default() else {
anyhow::bail!("Failed to get current icon theme information");
};
let mut res = Vec::<DesktopEntry>::new();
let theme = IconTheme::current();
let info = gio::AppInfo::all();
log::debug!("app entry count {}", info.len());
'outer: for app_entry in info {
'outer: for app_entry in ApplicationEntry::all() {
let Some(app_entry_id) = app_entry.id() else {
log::warn!(
"failed to get desktop entry ID for application named \"{}\"",
app_entry.name()
"No desktop entry id for application \"{}\"",
app_entry.name().as_deref().unwrap_or("")
);
continue;
};
let Some(desktop_app) = gio::DesktopAppInfo::new(&app_entry_id) else {
log::warn!(
"failed to find desktop app file from application named \"{}\"",
app_entry.name()
);
let Some(name) = app_entry.name() else {
log::warn!("No Name on desktop entry {}", app_entry_id);
continue;
};
if desktop_app.is_nodisplay() || desktop_app.is_hidden() {
let Some(exec) = app_entry.exec() else {
log::warn!("No Exec on desktop entry {}", app_entry_id);
continue;
};
if app_entry.no_display() || app_entry.is_hidden() || app_entry.terminal() {
continue;
}
let Some(cmd) = desktop_app.commandline() else {
continue;
};
let name = String::from(desktop_app.name());
let exec = String::from(cmd.to_string_lossy());
for blacklisted in CMD_BLACKLIST {
if exec.contains(blacklisted) {
continue 'outer;
@@ -95,37 +83,17 @@ pub fn find_entries() -> anyhow::Result<Vec<DesktopEntry>> {
None => (exec, Vec::new()),
};
let icon_path = match desktop_app.icon() {
Some(icon) => {
if let Some(icon_str) = icon.to_string() {
if let Some(s_icon) = icon_theme.lookup_icon(&icon_str, 128, gtk::IconLookupFlags::GENERIC_FALLBACK) {
s_icon.filename().map(|p| String::from(p.to_string_lossy()))
} else {
None
}
} else {
None
}
}
None => None,
};
let icon_path = app_entry
.icon()
.and_then(|icon_name| theme.get_with_size(&icon_name, ICON_SIZE))
.and_then(|path_buf| path_buf.into_os_string().into_string().ok());
let categories: Vec<String> = match desktop_app.categories() {
Some(categories) => categories
.split(";")
.filter(|s| !s.is_empty())
.filter(|s| {
for b in CATEGORY_TYPE_BLACKLIST {
if *s == b {
return false;
}
}
true
})
.map(String::from)
.collect(),
None => Vec::new(),
};
let categories = app_entry.categories().map_or_else(Vec::default, |inner| {
inner
.into_iter()
.filter(|s| !(s.is_empty() || CATEGORY_TYPE_BLACKLIST.contains(&s.as_str())))
.collect()
});
let entry = DesktopEntry {
app_name: name,