use super::canonicalize;
use std::path::Path;
#[cfg(all(unix, not(any(target_vendor = "apple", target_os = "android"))))]
fn attempt_dbus_call(path: &Path) -> bool {
use std::ffi::OsString;
use zbus::{blocking::Connection, dbus_proxy, Result};
#[dbus_proxy(
default_service = "org.freedesktop.FileManager1",
interface = "org.freedesktop.FileManager1",
default_path = "/org/freedesktop/FileManager1"
)]
trait FileManager {
fn show_folders(&self, uris: &[&str], startup_id: &str) -> Result<()>;
fn show_items(&self, uris: &[&str], startup_id: &str) -> Result<()>;
}
let con = match Connection::session() {
Ok(v) => v,
Err(_) => return false,
};
let proxy = match FileManagerProxyBlocking::new(&con) {
Ok(v) => v,
Err(_) => return false,
};
let mut uri = OsString::from("file://");
let f = match canonicalize(path.as_os_str()) {
Ok(v) => v,
Err(_) => return false,
};
uri.push(f);
let res = match path.is_dir() {
true => proxy.show_folders(&[&uri.to_string_lossy()], "test"),
false => proxy.show_items(&[&uri.to_string_lossy()], "test"),
};
res.is_ok()
}
#[cfg(all(unix, not(any(target_vendor = "apple", target_os = "android"))))]
fn attempt_xdg_open(path: &Path) -> bool {
use std::ffi::OsString;
use std::process::Command;
let mut uri = OsString::from("file://");
let f = match canonicalize(path.as_os_str()) {
Ok(v) => v,
Err(_) => return false,
};
uri.push(f);
let res = Command::new("xdg-open")
.args([&*uri.to_string_lossy()])
.output();
res.is_ok()
}
#[cfg(target_os = "macos")]
#[link(name = "AppKit", kind = "framework")]
extern "C" {}
#[allow(unused_variables)] pub fn open<T: AsRef<Path>>(path: T) -> bool {
let path = path.as_ref();
cfg_if::cfg_if! {
if #[cfg(windows)] {
unsafe {
use std::os::windows::ffi::OsStrExt;
use windows_sys::Win32::UI::Shell::ShellExecuteW;
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOW;
use windows_sys::Win32::Foundation::PWSTR;
let operation = ['o' as u16, 'p' as u16, 'e' as u16, 'n' as u16, 0x0000];
let mut file: Vec<u16> = path.as_os_str().encode_wide().collect();
file.push(0x0000);
let file: PWSTR = std::mem::transmute(file.as_ptr());
let operation: PWSTR = std::mem::transmute(operation.as_ptr());
let res = ShellExecuteW(0, operation, file, std::ptr::null_mut(), std::ptr::null_mut(), SW_SHOW as _);
res > 32
}
} else if #[cfg(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "android"))))] {
let mut flag = attempt_dbus_call(path);
if !flag {
flag = attempt_xdg_open(path);
}
flag
} else if #[cfg(target_os = "macos")] {
use std::os::unix::ffi::OsStrExt;
use std::os::raw::c_ulong;
use objc::class;
use objc::msg_send;
use objc::sel;
use objc::sel_impl;
use objc::runtime::Object;
const NS_UTF8_STRING_ENCODING: c_ulong = 4;
let f = match canonicalize(path.as_os_str()) {
Ok(v) => v,
Err(_) => return false
};
let isdir = path.is_dir();
unsafe {
let nsstring = class!(NSString);
let nsurl = class!(NSURL);
let nsarray = class!(NSArray);
let nsworkspace = class!(NSWorkspace);
let mut str: *mut Object = msg_send![nsstring, alloc];
str = msg_send![str,
initWithBytes: f.as_os_str().as_bytes().as_ptr()
length: f.as_os_str().len() as c_ulong
encoding: NS_UTF8_STRING_ENCODING
];
let mut url: *mut Object = msg_send![nsurl, alloc];
url = msg_send![url,
initFileURLWithPath: str
isDirectory: isdir
];
if isdir {
let workspace: *mut Object = msg_send![nsworkspace, sharedWorkspace];
let _: () = msg_send![workspace, openURL: url];
} else {
let arr: *mut Object = msg_send![nsarray, arrayWithObject: url];
let workspace: *mut Object = msg_send![nsworkspace, sharedWorkspace];
let _: () = msg_send![workspace, activateFileViewerSelectingURLs: arr];
}
let _: () = msg_send![url, release]; let _: () = msg_send![str, release]; true
}
} else {
false
}
}
}