1use crate::core::clipboard::Kind;
4use std::sync::Arc;
5use winit::window::{Window, WindowId};
6
7pub struct Clipboard {
10 state: State,
11}
12
13enum State {
14 Connected {
15 clipboard: window_clipboard::Clipboard,
16 #[allow(dead_code)]
21 window: Arc<Window>,
22 },
23 Unavailable,
24}
25
26impl Clipboard {
27 pub fn connect(window: Arc<Window>) -> Clipboard {
29 #[allow(unsafe_code)]
34 let clipboard = unsafe { window_clipboard::Clipboard::connect(&window) };
35
36 let state = match clipboard {
37 Ok(clipboard) => State::Connected { clipboard, window },
38 Err(_) => State::Unavailable,
39 };
40
41 Clipboard { state }
42 }
43
44 pub fn unconnected() -> Clipboard {
47 Clipboard {
48 state: State::Unavailable,
49 }
50 }
51
52 pub fn read(&self, kind: Kind) -> Option<String> {
54 match &self.state {
55 State::Connected { clipboard, .. } => match kind {
56 Kind::Standard => clipboard.read().ok(),
57 Kind::Primary => clipboard.read_primary().and_then(Result::ok),
58 },
59 State::Unavailable => None,
60 }
61 }
62
63 pub fn write(&mut self, kind: Kind, contents: String) {
65 match &mut self.state {
66 State::Connected { clipboard, .. } => {
67 let result = match kind {
68 Kind::Standard => clipboard.write(contents),
69 Kind::Primary => clipboard.write_primary(contents).unwrap_or(Ok(())),
70 };
71
72 match result {
73 Ok(()) => {}
74 Err(error) => {
75 log::warn!("error writing to clipboard: {error}");
76 }
77 }
78 }
79 State::Unavailable => {}
80 }
81 }
82
83 pub fn window_id(&self) -> Option<WindowId> {
85 match &self.state {
86 State::Connected { window, .. } => Some(window.id()),
87 State::Unavailable => None,
88 }
89 }
90}
91
92impl crate::core::Clipboard for Clipboard {
93 fn read(&self, kind: Kind) -> Option<String> {
94 self.read(kind)
95 }
96
97 fn write(&mut self, kind: Kind, contents: String) {
98 self.write(kind, contents);
99 }
100}