1use super::canonicalize;
30use std::path::Path;
31
32#[cfg(all(unix, not(any(target_vendor = "apple", target_os = "android"))))]
33fn attempt_dbus_call(path: &Path) -> bool {
34 use std::ffi::OsString;
35 use zbus::{blocking::Connection, dbus_proxy, Result};
36 #[dbus_proxy(
37 default_service = "org.freedesktop.FileManager1",
38 interface = "org.freedesktop.FileManager1",
39 default_path = "/org/freedesktop/FileManager1"
40 )]
41 trait FileManager {
42 fn show_folders(&self, uris: &[&str], startup_id: &str) -> Result<()>;
43 fn show_items(&self, uris: &[&str], startup_id: &str) -> Result<()>;
44 }
45 let con = match Connection::session() {
46 Ok(v) => v,
47 Err(_) => return false,
48 };
49 let proxy = match FileManagerProxyBlocking::new(&con) {
50 Ok(v) => v,
51 Err(_) => return false,
52 };
53 let mut uri = OsString::from("file://");
54 let f = match canonicalize(path.as_os_str()) {
55 Ok(v) => v,
56 Err(_) => return false,
57 };
58 uri.push(f);
59 let res = match path.is_dir() {
60 true => proxy.show_folders(&[&uri.to_string_lossy()], "test"),
61 false => proxy.show_items(&[&uri.to_string_lossy()], "test"),
62 };
63 res.is_ok()
64}
65
66#[cfg(all(unix, not(any(target_vendor = "apple", target_os = "android"))))]
67fn attempt_xdg_open(path: &Path) -> bool {
68 use std::ffi::OsString;
69 use std::process::Command;
70 let mut uri = OsString::from("file://");
71 let f = match canonicalize(path.as_os_str()) {
72 Ok(v) => v,
73 Err(_) => return false,
74 };
75 uri.push(f);
76 let res = Command::new("xdg-open")
77 .args([&*uri.to_string_lossy()])
78 .output();
79 res.is_ok()
80}
81
82#[cfg(target_os = "macos")]
84#[link(name = "AppKit", kind = "framework")]
85extern "C" {}
86
87#[allow(unused_variables)] pub fn open<T: AsRef<Path>>(path: T) -> bool {
92 let path = path.as_ref();
93 cfg_if::cfg_if! {
94 if #[cfg(windows)] {
95 unsafe {
96 use std::os::windows::ffi::OsStrExt;
97 use windows_sys::Win32::UI::Shell::ShellExecuteW;
98 use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOW;
99 use windows_sys::Win32::Foundation::PWSTR;
100 let operation = ['o' as u16, 'p' as u16, 'e' as u16, 'n' as u16, 0x0000];
101 let mut file: Vec<u16> = path.as_os_str().encode_wide().collect();
102 file.push(0x0000);
103 let file: PWSTR = std::mem::transmute(file.as_ptr());
106 let operation: PWSTR = std::mem::transmute(operation.as_ptr());
107 let res = ShellExecuteW(0, operation, file, std::ptr::null_mut(), std::ptr::null_mut(), SW_SHOW as _);
108 res > 32
109 }
110 } else if #[cfg(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "android"))))] {
111 let mut flag = attempt_dbus_call(path);
112 if !flag {
113 flag = attempt_xdg_open(path);
114 }
115 flag
116 } else if #[cfg(target_os = "macos")] {
117 use std::os::unix::ffi::OsStrExt;
118 use std::os::raw::c_ulong;
119 use objc::class;
120 use objc::msg_send;
121 use objc::sel;
122 use objc::sel_impl;
123 use objc::runtime::Object;
124 const NS_UTF8_STRING_ENCODING: c_ulong = 4;
125 let f = match canonicalize(path.as_os_str()) {
126 Ok(v) => v,
127 Err(_) => return false
128 };
129 let isdir = path.is_dir();
130 unsafe {
131 let nsstring = class!(NSString);
132 let nsurl = class!(NSURL);
133 let nsarray = class!(NSArray);
134 let nsworkspace = class!(NSWorkspace);
135 let mut str: *mut Object = msg_send![nsstring, alloc];
136 str = msg_send![str,
137 initWithBytes: f.as_os_str().as_bytes().as_ptr()
138 length: f.as_os_str().len() as c_ulong
139 encoding: NS_UTF8_STRING_ENCODING
140 ];
141 let mut url: *mut Object = msg_send![nsurl, alloc];
142 url = msg_send![url,
143 initFileURLWithPath: str
144 isDirectory: isdir
145 ];
146 if isdir {
147 let workspace: *mut Object = msg_send![nsworkspace, sharedWorkspace];
148 let _: () = msg_send![workspace, openURL: url];
149 } else {
150 let arr: *mut Object = msg_send![nsarray, arrayWithObject: url];
151 let workspace: *mut Object = msg_send![nsworkspace, sharedWorkspace];
152 let _: () = msg_send![workspace, activateFileViewerSelectingURLs: arr];
153 }
154 let _: () = msg_send![url, release]; let _: () = msg_send![str, release]; true
159 }
160 } else {
161 false
162 }
163 }
164}