term_model/
clipboard.rs

1// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "fuchsia")))]
16use std::ffi::c_void;
17
18#[cfg(not(target_os = "fuchsia"))]
19use log::{debug, warn};
20
21#[cfg(not(target_os = "fuchsia"))]
22use copypasta::nop_clipboard::NopClipboardContext;
23#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "fuchsia")))]
24use copypasta::wayland_clipboard;
25#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "fuchsia")))]
26use copypasta::x11_clipboard::{Primary as X11SelectionClipboard, X11ClipboardContext};
27#[cfg(not(target_os = "fuchsia"))]
28use copypasta::{ClipboardContext, ClipboardProvider};
29
30pub struct Clipboard {
31    #[cfg(not(target_os = "fuchsia"))]
32    clipboard: Box<dyn ClipboardProvider>,
33    #[cfg(not(target_os = "fuchsia"))]
34    selection: Option<Box<dyn ClipboardProvider>>,
35}
36
37impl Clipboard {
38    #[cfg(any(target_os = "macos", target_os = "windows", target_os = "fuchsia"))]
39    pub fn new() -> Self {
40        Self::default()
41    }
42
43    #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "fuchsia")))]
44    pub fn new(display: Option<*mut c_void>) -> Self {
45        if let Some(display) = display {
46            let (selection, clipboard) =
47                unsafe { wayland_clipboard::create_clipboards_from_external(display) };
48            return Self { clipboard: Box::new(clipboard), selection: Some(Box::new(selection)) };
49        }
50
51        Self {
52            clipboard: Box::new(ClipboardContext::new().unwrap()),
53            selection: Some(Box::new(X11ClipboardContext::<X11SelectionClipboard>::new().unwrap())),
54        }
55     }
56
57    // Use for tests and ref-tests
58    #[cfg(not(target_os = "fuchsia"))]
59    pub fn new_nop() -> Self {
60        Self { clipboard: Box::new(NopClipboardContext::new().unwrap()), selection: None }
61    }
62
63    #[cfg(target_os = "fuchsia")]
64    pub fn new_nop() -> Self {
65        Self {}
66    }
67}
68
69impl Default for Clipboard {
70    #[cfg(not(target_os = "fuchsia"))]
71    fn default() -> Self {
72        Self { clipboard: Box::new(ClipboardContext::new().unwrap()), selection: None }
73    }
74
75    #[cfg(target_os = "fuchsia")]
76    fn default() -> Self {
77        Self {}
78    }
79}
80
81#[derive(Debug)]
82pub enum ClipboardType {
83    Clipboard,
84    Selection,
85}
86
87//
88// Fuchsia does not currently support clipboards but the Clipboard struct
89// is required for the terminal. For now, we will leave the struct empty until
90// we support this functionality.
91//
92
93impl Clipboard {
94    #[cfg(not(target_os = "fuchsia"))]
95    pub fn store(&mut self, ty: ClipboardType, text: impl Into<String>) {
96        let clipboard = match (ty, &mut self.selection) {
97            (ClipboardType::Selection, Some(provider)) => provider,
98            (ClipboardType::Selection, None) => return,
99            _ => &mut self.clipboard,
100        };
101        clipboard.set_contents(text.into()).unwrap_or_else(|err| {
102            warn!("Unable to store text in clipboard: {}", err);
103        });
104    }
105
106    #[cfg(target_os = "fuchsia")]
107    pub fn store(&mut self, _ty: ClipboardType, _text: impl Into<String>) {
108        // Intentionally blank
109    }
110
111    #[cfg(not(target_os = "fuchsia"))]
112    pub fn load(&mut self, ty: ClipboardType) -> String {
113        let clipboard = match (ty, &mut self.selection) {
114            (ClipboardType::Selection, Some(provider)) => provider,
115            _ => &mut self.clipboard,
116        };
117
118        match clipboard.get_contents() {
119            Err(err) => {
120                debug!("Unable to load text from clipboard: {}", err);
121                String::new()
122            },
123            Ok(text) => text,
124        }
125    }
126
127    #[cfg(target_os = "fuchsia")]
128    pub fn load(&mut self, _ty: ClipboardType) -> String {
129        String::new()
130    }
131}