#[cfg(all(unix, not(target_os = "macos")))]
mod desktop_file;
mod exec;
#[cfg(all(unix, not(target_os = "macos")))]
mod gio;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(all(unix, not(target_os = "macos")))]
mod mime;
#[cfg(all(unix, not(target_os = "macos")))]
mod scan;
use std::path::Path;
use super::super::state::OpenWithApp;
use crate::core::Entry;
pub(super) fn discover_open_with_apps_for_entry(entry: &Entry) -> Vec<OpenWithApp> {
discover_open_with_apps_inner(&entry.path, Some(entry.name.as_str()))
}
fn discover_open_with_apps_inner(path: &Path, display_name: Option<&str>) -> Vec<OpenWithApp> {
#[cfg(target_os = "macos")]
{
let _ = display_name;
macos::discover_via_nsworkspace(path)
}
#[cfg(all(unix, not(target_os = "macos")))]
{
discover_xdg(path, display_name)
}
#[cfg(not(any(target_os = "macos", all(unix, not(target_os = "macos")))))]
{
let _ = path;
let _ = display_name;
vec![]
}
}
#[cfg(all(unix, not(target_os = "macos")))]
pub(super) fn xdg_data_dirs() -> Vec<std::path::PathBuf> {
let mut dirs = Vec::new();
let data_home = std::env::var("XDG_DATA_HOME")
.map(std::path::PathBuf::from)
.unwrap_or_else(|_| {
dirs::home_dir()
.map(|h| h.join(".local/share"))
.unwrap_or_default()
});
if !data_home.as_os_str().is_empty() {
dirs.push(data_home);
}
for entry in std::env::var("XDG_DATA_DIRS")
.unwrap_or_else(|_| "/usr/local/share:/usr/share".to_string())
.split(':')
.filter(|s| !s.is_empty())
{
dirs.push(std::path::PathBuf::from(entry));
}
dirs
}
#[cfg(all(unix, not(target_os = "macos")))]
pub(super) fn current_desktops() -> Vec<String> {
std::env::var("XDG_CURRENT_DESKTOP")
.unwrap_or_default()
.split(':')
.filter(|s| !s.is_empty())
.map(str::to_string)
.collect()
}
#[cfg(all(unix, not(target_os = "macos")))]
fn discover_xdg(path: &Path, display_name: Option<&str>) -> Vec<OpenWithApp> {
use std::time::{Duration, Instant};
let deadline = Instant::now() + Duration::from_millis(3000);
let canceled = || Instant::now() > deadline;
let Some(mime_type) = mime::detect_mime_type_with_name(path, display_name, &canceled) else {
return vec![];
};
if let Some(apps) = gio::discover_via_gio(&mime_type, path, &canceled)
&& !apps.is_empty()
{
return apps;
}
scan::discover_via_desktop_scan(&mime_type, path)
}