glob-based icon discovery but very slow
This commit is contained in:
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -1429,6 +1429,7 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"freedesktop",
|
"freedesktop",
|
||||||
"glam",
|
"glam",
|
||||||
|
"glob",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"keyvalues-parser",
|
"keyvalues-parser",
|
||||||
@@ -1998,7 +1999,6 @@ source = "git+https://github.com/galister/freedesktop.git?rev=2c1e653#2c1e653afc
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"freedesktop-apps",
|
"freedesktop-apps",
|
||||||
"freedesktop-core",
|
"freedesktop-core",
|
||||||
"freedesktop-icon",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2019,15 +2019,6 @@ dependencies = [
|
|||||||
"dirs",
|
"dirs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "freedesktop-icon"
|
|
||||||
version = "0.0.3"
|
|
||||||
source = "git+https://github.com/galister/freedesktop.git?rev=2c1e653#2c1e653afcd025c3254a25dcdd5e8750e263eebf"
|
|
||||||
dependencies = [
|
|
||||||
"freedesktop-core",
|
|
||||||
"rust-ini",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ wgui = { path = "../wgui/" }
|
|||||||
wlx-common = { path = "../wlx-common" }
|
wlx-common = { path = "../wlx-common" }
|
||||||
|
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
freedesktop = { workspace = true, features = ["apps", "icon"] }
|
freedesktop = { workspace = true, features = ["apps"] }
|
||||||
glam = { workspace = true, features = ["mint", "serde"] }
|
glam = { workspace = true, features = ["mint", "serde"] }
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
rust-embed.workspace = true
|
rust-embed.workspace = true
|
||||||
serde.workspace = true
|
serde = { workspace = true, features = ["rc"] }
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
|
||||||
chrono = "0.4.42"
|
chrono = "0.4.42"
|
||||||
@@ -23,3 +23,4 @@ hyper = { version = "1.8.1", features = ["client", "http1", "http2"] }
|
|||||||
http-body-util = "0.1.3"
|
http-body-util = "0.1.3"
|
||||||
async-native-tls = "0.5.0"
|
async-native-tls = "0.5.0"
|
||||||
smol-hyper = "0.1.1"
|
smol-hyper = "0.1.1"
|
||||||
|
glob = "0.3.3"
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ use wlx_common::{dash_interface::BoxDashInterface, timestep::Timestep};
|
|||||||
use crate::{
|
use crate::{
|
||||||
assets, settings,
|
assets, settings,
|
||||||
tab::{
|
tab::{
|
||||||
Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses,
|
apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses, settings::TabSettings,
|
||||||
settings::TabSettings,
|
Tab, TabType,
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
|
desktop_finder::DesktopFinder,
|
||||||
popup_manager::{MountPopupParams, PopupManager, PopupManagerParams},
|
popup_manager::{MountPopupParams, PopupManager, PopupManagerParams},
|
||||||
toast_manager::ToastManager,
|
toast_manager::ToastManager,
|
||||||
various::AsyncExecutor,
|
various::AsyncExecutor,
|
||||||
@@ -63,6 +64,8 @@ pub struct Frontend {
|
|||||||
|
|
||||||
window_audio_settings: WguiWindow,
|
window_audio_settings: WguiWindow,
|
||||||
view_audio_settings: Option<views::audio_settings::View>,
|
view_audio_settings: Option<views::audio_settings::View>,
|
||||||
|
|
||||||
|
pub(crate) desktop_finder: DesktopFinder,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InitParams {
|
pub struct InitParams {
|
||||||
@@ -146,6 +149,7 @@ impl Frontend {
|
|||||||
window_audio_settings: WguiWindow::default(),
|
window_audio_settings: WguiWindow::default(),
|
||||||
view_audio_settings: None,
|
view_audio_settings: None,
|
||||||
executor: Rc::new(smol::LocalExecutor::new()),
|
executor: Rc::new(smol::LocalExecutor::new()),
|
||||||
|
desktop_finder: DesktopFinder::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// init some things first
|
// init some things first
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ use crate::{
|
|||||||
frontend::{Frontend, FrontendTask, FrontendTasks},
|
frontend::{Frontend, FrontendTask, FrontendTasks},
|
||||||
tab::{Tab, TabType},
|
tab::{Tab, TabType},
|
||||||
util::{
|
util::{
|
||||||
self,
|
|
||||||
desktop_finder::DesktopEntry,
|
desktop_finder::DesktopEntry,
|
||||||
popup_manager::{MountPopupParams, PopupHandle},
|
popup_manager::{MountPopupParams, PopupHandle},
|
||||||
},
|
},
|
||||||
@@ -117,7 +116,7 @@ impl TabApps {
|
|||||||
extra: Default::default(),
|
extra: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let entries = util::desktop_finder::find_entries()?;
|
let entries = frontend.desktop_finder.find_entries()?;
|
||||||
|
|
||||||
let frontend_tasks = frontend.tasks.clone();
|
let frontend_tasks = frontend.tasks.clone();
|
||||||
let globals = frontend.layout.state.globals.clone();
|
let globals = frontend.layout.state.globals.clone();
|
||||||
@@ -173,7 +172,7 @@ impl AppList {
|
|||||||
entry
|
entry
|
||||||
.icon_path
|
.icon_path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or_else(|| Rc::from(""), |icon_path| Rc::from(icon_path.as_str())),
|
.map_or_else(|| Rc::from(""), |icon_path| icon_path.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// entry fallback (question mark) icon
|
// entry fallback (question mark) icon
|
||||||
@@ -186,7 +185,7 @@ impl AppList {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
template_params.insert(Rc::from("name"), Rc::from(entry.app_name.as_str()));
|
template_params.insert(Rc::from("name"), entry.app_name.clone());
|
||||||
|
|
||||||
let data = parser_state.parse_template(
|
let data = parser_state.parse_template(
|
||||||
doc_params,
|
doc_params,
|
||||||
|
|||||||
@@ -1,48 +1,108 @@
|
|||||||
use freedesktop::{ApplicationEntry, IconTheme};
|
use std::{collections::HashMap, ffi::OsStr, rc::Rc};
|
||||||
|
|
||||||
|
use freedesktop::{xdg_data_dirs, xdg_data_home, ApplicationEntry};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// compatibility with wayvr-ipc
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
// TODO: remove this after we're done with the old wayvr-dashboard and use DesktopEntry instead
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
pub struct DesktopFile {
|
|
||||||
pub name: String,
|
|
||||||
pub icon: Option<String>,
|
|
||||||
pub exec_path: String,
|
|
||||||
pub exec_args: Vec<String>,
|
|
||||||
pub categories: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DesktopEntry {
|
pub struct DesktopEntry {
|
||||||
pub exec_path: String,
|
pub exec_path: Rc<str>,
|
||||||
pub exec_args: Vec<String>,
|
pub exec_args: Rc<str>,
|
||||||
pub app_name: String,
|
pub app_name: Rc<str>,
|
||||||
pub icon_path: Option<String>,
|
pub icon_path: Option<Rc<str>>,
|
||||||
pub categories: Vec<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)] // TODO: remove this
|
|
||||||
pub struct EntrySearchCell {
|
|
||||||
pub exec_path: String,
|
|
||||||
pub exec_args: Vec<String>,
|
|
||||||
pub app_name: String,
|
|
||||||
pub icon_name: Option<String>,
|
|
||||||
pub categories: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
const ICON_SIZE: u32 = 128;
|
|
||||||
|
|
||||||
const CMD_BLACKLIST: [&str; 1] = [
|
const CMD_BLACKLIST: [&str; 1] = [
|
||||||
"lsp-plugins", // LSP Plugins collection. They clutter the application list a lot
|
"lsp-plugins", // LSP Plugins collection. They clutter the application list a lot
|
||||||
];
|
];
|
||||||
|
|
||||||
const CATEGORY_TYPE_BLACKLIST: [&str; 5] = ["GTK", "Qt", "X-XFCE", "X-Bluetooth", "ConsoleOnly"];
|
const CATEGORY_TYPE_BLACKLIST: [&str; 5] = ["GTK", "Qt", "X-XFCE", "X-Bluetooth", "ConsoleOnly"];
|
||||||
|
|
||||||
pub fn find_entries() -> anyhow::Result<Vec<DesktopEntry>> {
|
pub struct DesktopFinder {
|
||||||
let mut res = Vec::<DesktopEntry>::new();
|
size_preferences: Vec<&'static OsStr>,
|
||||||
let theme = IconTheme::current();
|
icon_cache: HashMap<String, Rc<str>>,
|
||||||
|
icon_folders: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
'outer: for app_entry in ApplicationEntry::all() {
|
impl DesktopFinder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let data_home = xdg_data_home();
|
||||||
|
|
||||||
|
let mut icon_folders = vec![
|
||||||
|
// XDG_DATA_HOME takes priority
|
||||||
|
{
|
||||||
|
let mut data_home_flatpak = data_home.clone();
|
||||||
|
data_home_flatpak.push("flatpak/exports/share/icons");
|
||||||
|
data_home_flatpak.to_string_lossy().to_string()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
let mut data_home = data_home.clone();
|
||||||
|
data_home.push("icons");
|
||||||
|
data_home.to_string_lossy().to_string()
|
||||||
|
},
|
||||||
|
"/var/lib/flatpak/exports/share/icons".into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
let data_dirs = xdg_data_dirs();
|
||||||
|
for mut data_dir in data_dirs {
|
||||||
|
data_dir.push("icons");
|
||||||
|
icon_folders.push(data_dir.to_string_lossy().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let size_preferences = ["scalable", "128x128", "96x96", "72x72", "64x64", "48x48", "32x32"]
|
||||||
|
.into_iter()
|
||||||
|
.map(OsStr::new)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
icon_folders,
|
||||||
|
icon_cache: HashMap::new(),
|
||||||
|
size_preferences,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_icon(&mut self, icon_name: &str) -> Option<Rc<str>> {
|
||||||
|
if let Some(icon_path) = self.icon_cache.get(icon_name) {
|
||||||
|
return Some(icon_path.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for folder in &self.icon_folders {
|
||||||
|
let pattern = format!("{}/*/apps/*/{}.*", folder, icon_name);
|
||||||
|
|
||||||
|
let mut entries: Vec<_> = glob::glob(&pattern)
|
||||||
|
.expect("Bad glob pattern!")
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
log::warn!("Looking for '{pattern}' resulted in {} entries.", entries.len());
|
||||||
|
|
||||||
|
// sort by SIZE_PREFERENCES
|
||||||
|
entries.sort_by_key(|path| {
|
||||||
|
path
|
||||||
|
.components()
|
||||||
|
.rev()
|
||||||
|
.nth(1) // ← <THEME>/apps/<*SIZE*>/filename.ext
|
||||||
|
.map(|c| c.as_os_str())
|
||||||
|
.and_then(|size| {
|
||||||
|
log::warn!("looking for {size:?} in size preferences.");
|
||||||
|
self.size_preferences.iter().position(|&p| p == size)
|
||||||
|
})
|
||||||
|
.unwrap_or(usize::MAX)
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(first) = entries.into_iter().next() {
|
||||||
|
let rc: Rc<str> = first.to_string_lossy().into();
|
||||||
|
log::warn!("Found icon for {icon_name} at {rc}");
|
||||||
|
self.icon_cache.insert(icon_name.to_string(), rc.clone());
|
||||||
|
return Some(rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_entries(&mut self) -> anyhow::Result<Vec<DesktopEntry>> {
|
||||||
|
let mut res = Vec::<DesktopEntry>::new();
|
||||||
|
|
||||||
|
'app_entries: for app_entry in ApplicationEntry::all() {
|
||||||
let Some(app_entry_id) = app_entry.id() else {
|
let Some(app_entry_id) = app_entry.id() else {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"No desktop entry id for application \"{}\"",
|
"No desktop entry id for application \"{}\"",
|
||||||
@@ -67,37 +127,25 @@ pub fn find_entries() -> anyhow::Result<Vec<DesktopEntry>> {
|
|||||||
|
|
||||||
for blacklisted in CMD_BLACKLIST {
|
for blacklisted in CMD_BLACKLIST {
|
||||||
if exec.contains(blacklisted) {
|
if exec.contains(blacklisted) {
|
||||||
continue 'outer;
|
continue 'app_entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (exec_path, exec_args) = match exec.split_once(" ") {
|
let (exec_path, exec_args) = match exec.split_once(" ") {
|
||||||
Some((left, right)) => (
|
Some((left, right)) => (left.into(), right.into()),
|
||||||
String::from(left),
|
None => (exec.into(), "".into()),
|
||||||
right
|
|
||||||
.split(" ")
|
|
||||||
.filter(|arg| !arg.starts_with('%')) // exclude arguments like "%f"
|
|
||||||
.map(String::from)
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
None => (exec, Vec::new()),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let icon_path = app_entry
|
let icon_path = app_entry.icon().and_then(|icon_name| self.find_icon(&icon_name));
|
||||||
.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 = app_entry.categories().map_or_else(Vec::default, |inner| {
|
for cat in app_entry.categories().unwrap_or_default() {
|
||||||
inner
|
if CATEGORY_TYPE_BLACKLIST.contains(&cat.as_str()) {
|
||||||
.into_iter()
|
continue 'app_entries;
|
||||||
.filter(|s| !(s.is_empty() || CATEGORY_TYPE_BLACKLIST.contains(&s.as_str())))
|
}
|
||||||
.collect()
|
}
|
||||||
});
|
|
||||||
|
|
||||||
let entry = DesktopEntry {
|
let entry = DesktopEntry {
|
||||||
app_name: name,
|
app_name: name.into(),
|
||||||
categories,
|
|
||||||
exec_path,
|
exec_path,
|
||||||
exec_args,
|
exec_args,
|
||||||
icon_path,
|
icon_path,
|
||||||
@@ -107,16 +155,5 @@ pub fn find_entries() -> anyhow::Result<Vec<DesktopEntry>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
|
||||||
|
|
||||||
impl DesktopEntry {
|
|
||||||
pub fn to_desktop_file(&self) -> DesktopFile {
|
|
||||||
DesktopFile {
|
|
||||||
categories: self.categories.clone(),
|
|
||||||
exec_args: self.exec_args.clone(),
|
|
||||||
exec_path: self.exec_path.clone(),
|
|
||||||
icon: self.icon_path.clone(),
|
|
||||||
name: self.app_name.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ use crate::util::desktop_finder;
|
|||||||
|
|
||||||
// the compiler wants to scream
|
// the compiler wants to scream
|
||||||
#[allow(irrefutable_let_patterns)]
|
#[allow(irrefutable_let_patterns)]
|
||||||
pub fn get_desktop_file_icon_path(desktop_file: &desktop_finder::DesktopFile) -> AssetPathOwned {
|
pub fn get_desktop_file_icon_path(desktop_file: &desktop_finder::DesktopEntry) -> AssetPathOwned {
|
||||||
/*
|
/*
|
||||||
FIXME: why is the compiler complaining about trailing irrefutable patterns there?!?!
|
FIXME: why is the compiler complaining about trailing irrefutable patterns there?!?!
|
||||||
looking at the PathBuf::from_str implementation, it always returns Ok() and it's inline, maybe that's why.
|
looking at the PathBuf::from_str implementation, it always returns Ok() and it's inline, maybe that's why.
|
||||||
*/
|
*/
|
||||||
if let Some(icon) = &desktop_file.icon
|
if let Some(icon) = &desktop_file.icon_path
|
||||||
&& let Ok(path) = PathBuf::from_str(icon)
|
&& let Ok(path) = PathBuf::from_str(icon)
|
||||||
{
|
{
|
||||||
return AssetPathOwned::File(path);
|
return AssetPathOwned::File(path);
|
||||||
|
|||||||
@@ -85,12 +85,12 @@ impl View {
|
|||||||
|
|
||||||
label_exec.set_text_simple(
|
label_exec.set_text_simple(
|
||||||
&mut params.globals.get(),
|
&mut params.globals.get(),
|
||||||
Translation::from_raw_text_string(params.entry.app_name.clone()),
|
Translation::from_raw_text_rc(params.entry.app_name.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
label_args.set_text_simple(
|
label_args.set_text_simple(
|
||||||
&mut params.globals.get(),
|
&mut params.globals.get(),
|
||||||
Translation::from_raw_text_string(params.entry.exec_args.join(" ")),
|
Translation::from_raw_text_rc(params.entry.exec_args.clone()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ impl View {
|
|||||||
// app icon
|
// app icon
|
||||||
if let Some(icon_path) = ¶ms.entry.icon_path {
|
if let Some(icon_path) = ¶ms.entry.icon_path {
|
||||||
let mut template_params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
|
let mut template_params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
|
||||||
template_params.insert("path".into(), icon_path.as_str().into());
|
template_params.insert("path".into(), icon_path.clone());
|
||||||
state.instantiate_template(
|
state.instantiate_template(
|
||||||
doc_params,
|
doc_params,
|
||||||
"ApplicationIcon",
|
"ApplicationIcon",
|
||||||
@@ -225,27 +225,23 @@ impl View {
|
|||||||
env.push("ELECTRON_OZONE_PLATFORM_HINT=wayland".into());
|
env.push("ELECTRON_OZONE_PLATFORM_HINT=wayland".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: refactor this after we ditch old wayvr-dashboard completely
|
|
||||||
let desktop_file = params.application.to_desktop_file();
|
|
||||||
let mut userdata = HashMap::<String, String>::new();
|
|
||||||
userdata.insert("desktop_file".into(), serde_json::to_string(&desktop_file)?);
|
|
||||||
|
|
||||||
let exec_args_str = desktop_file.exec_args.join(" ");
|
|
||||||
|
|
||||||
let args = match params.run_mode {
|
let args = match params.run_mode {
|
||||||
RunMode::Cage => format!("-- {} {}", desktop_file.exec_path, exec_args_str),
|
RunMode::Cage => format!("-- {} {}", params.application.exec_path, params.application.exec_args),
|
||||||
RunMode::Wayland => exec_args_str,
|
RunMode::Wayland => params.application.exec_args.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let exec = match params.run_mode {
|
let exec = match params.run_mode {
|
||||||
RunMode::Cage => "cage",
|
RunMode::Cage => "cage".to_string(),
|
||||||
RunMode::Wayland => &desktop_file.name,
|
RunMode::Wayland => params.application.exec_path.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut userdata = HashMap::new();
|
||||||
|
userdata.insert("desktop-entry".to_string(), serde_json::to_string(params.application)?);
|
||||||
|
|
||||||
params.interface.process_launch(WvrProcessLaunchParams {
|
params.interface.process_launch(WvrProcessLaunchParams {
|
||||||
env,
|
env,
|
||||||
exec: String::from(exec),
|
exec,
|
||||||
name: desktop_file.name,
|
name: params.application.app_name.to_string(),
|
||||||
args,
|
args,
|
||||||
userdata,
|
userdata,
|
||||||
})?;
|
})?;
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ use wgui::{
|
|||||||
taffy::{self, prelude::length},
|
taffy::{self, prelude::length},
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
widget::{
|
widget::{
|
||||||
ConstructEssentials,
|
|
||||||
div::WidgetDiv,
|
div::WidgetDiv,
|
||||||
label::{WidgetLabel, WidgetLabelParams},
|
label::{WidgetLabel, WidgetLabelParams},
|
||||||
|
ConstructEssentials,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use wlx_common::dash_interface::BoxDashInterface;
|
use wlx_common::dash_interface::BoxDashInterface;
|
||||||
@@ -89,13 +89,13 @@ impl View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_desktop_file_from_process(process: &packet_server::WvrProcess) -> Option<desktop_finder::DesktopFile> {
|
fn get_desktop_entry_from_process(process: &packet_server::WvrProcess) -> Option<desktop_finder::DesktopEntry> {
|
||||||
// TODO: refactor this after we ditch old wayvr-dashboard completely
|
// TODO: refactor this after we ditch old wayvr-dashboard completely
|
||||||
let Some(dfile_str) = process.userdata.get("desktop_file") else {
|
let Some(dfile_str) = process.userdata.get("desktop-entry") else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(desktop_file) = serde_json::from_str::<desktop_finder::DesktopFile>(dfile_str) else {
|
let Ok(desktop_file) = serde_json::from_str::<desktop_finder::DesktopEntry>(dfile_str) else {
|
||||||
debug_assert!(false); // invalid json???
|
debug_assert!(false); // invalid json???
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
@@ -144,7 +144,7 @@ fn construct_process_entry(
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let Some(desktop_file) = get_desktop_file_from_process(process) {
|
if let Some(desktop_file) = get_desktop_entry_from_process(process) {
|
||||||
// desktop file icon and process name
|
// desktop file icon and process name
|
||||||
util::various::mount_simple_sprite_square(
|
util::various::mount_simple_sprite_square(
|
||||||
globals,
|
globals,
|
||||||
@@ -158,7 +158,7 @@ fn construct_process_entry(
|
|||||||
globals,
|
globals,
|
||||||
ess.layout,
|
ess.layout,
|
||||||
cell.id,
|
cell.id,
|
||||||
Translation::from_raw_text_string(desktop_file.name.clone()),
|
Translation::from_raw_text_rc(desktop_file.app_name.clone()),
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
// just show a process name
|
// just show a process name
|
||||||
|
|||||||
Reference in New Issue
Block a user