1use anyhow::Result;
2use arboard::{Clipboard, Error};
3use std::env;
4use std::process;
5use std::sync::{Arc, Mutex};
6
7#[cfg(target_os = "linux")]
8use arboard::SetExtLinux;
9
10use crate::DAEMONIZE_ARG;
11
12pub trait ClipboardTrait {
13 fn set_contents(&mut self, content: String) -> anyhow::Result<()>;
14 fn get_content(&self) -> anyhow::Result<String>;
15}
16
17pub struct EditorClipboard {
18 clipboard: Arc<Mutex<Clipboard>>,
19}
20
21impl EditorClipboard {
22 pub fn new() -> Result<EditorClipboard, Error> {
23 Clipboard::new().map(|c| EditorClipboard {
24 clipboard: Arc::new(Mutex::new(c)),
25 })
26 }
27
28 pub fn try_new() -> Option<EditorClipboard> {
29 Self::new().ok()
30 }
31
32 pub fn set_contents(&mut self, content: String) -> Result<(), Error> {
33 #[cfg(target_os = "linux")]
34 {
35 let is_wayland = std::env::var("WAYLAND_DISPLAY").is_ok()
36 || std::env::var("XDG_SESSION_TYPE")
37 .map(|v| v == "wayland")
38 .unwrap_or(false);
39
40 if is_wayland {
41 let mut clipboard = self
42 .clipboard
43 .lock()
44 .map_err(|_e| arboard::Error::ContentNotAvailable)?;
45
46 let result = clipboard.set().wait().text(content);
47 result
48 } else if env::args().nth(1).as_deref() == Some(DAEMONIZE_ARG) {
49 let mut clipboard = self
50 .clipboard
51 .lock()
52 .map_err(|_e| arboard::Error::ContentNotAvailable)?;
53 clipboard.set().wait().text(content)
54 } else {
55 if std::env::var("THOTH_DEBUG_CLIPBOARD").is_ok() {
56 return Err(arboard::Error::ContentNotAvailable);
57 }
58
59 process::Command::new(env::current_exe().unwrap())
60 .arg(DAEMONIZE_ARG)
61 .arg(content)
62 .stdin(process::Stdio::null())
63 .stdout(process::Stdio::null())
64 .stderr(process::Stdio::null())
65 .current_dir("/")
66 .spawn()
67 .map_err(|_e| arboard::Error::ContentNotAvailable)?;
68 Ok(())
69 }
70 }
71
72 #[cfg(not(target_os = "linux"))]
73 {
74 let mut clipboard = self
75 .clipboard
76 .lock()
77 .map_err(|_e| arboard::Error::ContentNotAvailable)?;
78 clipboard.set_text(content)
79 }
80 }
81
82 pub fn get_content(&mut self) -> Result<String, Error> {
83 let mut clipboard = self.clipboard.lock().unwrap();
84 clipboard.get_text()
85 }
86
87 #[cfg(target_os = "linux")]
88 pub fn handle_daemon_args() -> Result<(), Error> {
89 if let Some(content) = env::args().nth(2) {
90 if env::args().nth(1).as_deref() == Some(DAEMONIZE_ARG) {
91 let mut clipboard = Self::new()?;
92 clipboard.set_contents(content)?;
93 std::process::exit(0);
94 }
95 }
96 Ok(())
97 }
98}