clipboard_win/lib.rs
1#![cfg(windows)]
2//! This crate provide simple means to operate with Windows clipboard.
3//!
4//!# Note keeping Clipboard around:
5//!
6//! In Windows [Clipboard](struct.Clipboard.html) opens globally and only one application can set data onto format at the time.
7//!
8//! Therefore as soon as operations are finished, user is advised to close [Clipboard](struct.Clipboard.html).
9//!
10//!# Features
11//!
12//! - `std` - Enables usage of `std`, including `std::error::Error` trait.
13//! - `monitor` - Enables code related to clipboard monitoring.
14//!
15//!# Clipboard
16//!
17//! All read and write access to Windows clipboard requires user to open it.
18//!
19//!# Usage
20//!
21//!## Getter
22//!
23//! Library provides various extractors from clipboard to particular format using [Getter](trait.Getter.html):
24//!
25//! - [RawData](formats/struct.RawData.html) - Reads raw bytes from specified format.
26//! - [Unicode](formats/struct.Unicode.html) - Reads unicode string from clipboard.
27//! - [Bitmap](formats/struct.Bitmap.html) - Reads RGB data of image on clipboard.
28//! - [FileList](formats/struct.FileList.html) - Reads list of files from clipboard.
29//!
30//! Depending on format, getter can extract data into various data types.
31//!
32//!## Setter
33//!
34//! Library provides various setters onto clipboard by using [Setter](trait.Setter.html):
35//!
36//! - [RawData](formats/struct.RawData.html) - Writes raw bytes onto specified format.
37//! - [Unicode](formats/struct.Unicode.html) - Writes unicode string onto clipboard.
38//! - [Bitmap](formats/struct.Bitmap.html) - Writes RGB data of image on clipboard.
39//!
40//! Default setters are generic over type allowing anything that can be referenced as byte slice or
41//! `str`
42//!
43//!## Manually lock clipboard
44//!
45//!```
46//!use clipboard_win::{Clipboard, formats, Getter, Setter};
47//!
48//!const SAMPLE: &str = "MY loli sample ^^";
49//!
50//!let _clip = Clipboard::new_attempts(10).expect("Open clipboard");
51//!formats::Unicode.write_clipboard(&SAMPLE).expect("Write sample");
52//!
53//!let mut output = String::new();
54//!
55//!assert_eq!(formats::Unicode.read_clipboard(&mut output).expect("Read sample"), SAMPLE.len());
56//!assert_eq!(output, SAMPLE);
57//!
58//!//Efficiently re-use buffer ;)
59//!output.clear();
60//!assert_eq!(formats::Unicode.read_clipboard(&mut output).expect("Read sample"), SAMPLE.len());
61//!assert_eq!(output, SAMPLE);
62//!
63//!//Or take the same string twice?
64//!assert_eq!(formats::Unicode.read_clipboard(&mut output).expect("Read sample"), SAMPLE.len());
65//!assert_eq!(format!("{0}{0}", SAMPLE), output);
66//!
67//!```
68//!
69//!## Simplified API
70//!
71//!```
72//!use clipboard_win::{formats, get_clipboard, set_clipboard};
73//!
74//!let text = "my sample ><";
75//!
76//!set_clipboard(formats::Unicode, text).expect("To set clipboard");
77//!//Type is necessary as string can be stored in various storages
78//!let result: String = get_clipboard(formats::Unicode).expect("To set clipboard");
79//!assert_eq!(result, text)
80//!```
81
82#![no_std]
83#![warn(missing_docs)]
84#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
85
86#[cfg(feature = "std")]
87extern crate std;
88
89extern crate alloc;
90
91pub mod options;
92mod sys;
93pub mod types;
94pub mod formats;
95pub use formats::Format;
96mod html;
97pub mod raw;
98#[cfg(feature = "monitor")]
99pub mod monitor;
100#[cfg(feature = "monitor")]
101pub use monitor::Monitor;
102pub(crate) mod utils;
103
104pub use raw::{get_owner, empty, seq_num, size, is_format_avail, register_format, count_formats, EnumFormats};
105pub use formats::Unicode;
106
107pub use error_code::ErrorCode;
108///Alias to result used by this crate
109pub type SysResult<T> = Result<T, ErrorCode>;
110
111///Clipboard instance, which allows to perform clipboard ops.
112///
113///# Note:
114///
115///You can have only one such instance across your program.
116///
117///# Warning:
118///
119///In Windows Clipboard opens globally and only one application can set data
120///onto format at the time.
121///
122///Therefore as soon as operations are finished, user is advised to close Clipboard.
123pub struct Clipboard {
124 _dummy: ()
125}
126
127impl Clipboard {
128 #[inline(always)]
129 ///Attempts to open clipboard, returning clipboard instance on success.
130 pub fn new() -> SysResult<Self> {
131 raw::open().map(|_| Self { _dummy: () })
132 }
133
134 #[inline(always)]
135 ///Attempts to open clipboard, associating it with specified `owner` and returning clipboard instance on success.
136 pub fn new_for(owner: types::HWND) -> SysResult<Self> {
137 raw::open_for(owner).map(|_| Self { _dummy: () })
138 }
139
140 #[inline(always)]
141 ///Attempts to open clipboard, giving it `num` retries in case of failure.
142 pub fn new_attempts(num: usize) -> SysResult<Self> {
143 Self::new_attempts_for(core::ptr::null_mut(), num)
144 }
145
146 #[inline]
147 ///Attempts to open clipboard, giving it `num` retries in case of failure.
148 pub fn new_attempts_for(owner: types::HWND, mut num: usize) -> SysResult<Self> {
149 loop {
150 match Self::new_for(owner) {
151 Ok(this) => break Ok(this),
152 Err(err) => match num {
153 0 => break Err(err),
154 _ => num -= 1,
155 }
156 }
157
158 //0 causes to yield remaining time in scheduler, but remain to be scheduled once again.
159 unsafe { sys::Sleep(0) };
160 }
161 }
162}
163
164impl Drop for Clipboard {
165 fn drop(&mut self) {
166 let _ = raw::close();
167 }
168}
169
170///Describes format getter, specifying data type as type param
171///
172///Default implementations only perform write, without opening/closing clipboard
173pub trait Getter<Type> {
174 ///Reads content of clipboard into `out`, returning number of bytes read on success, or otherwise 0.
175 fn read_clipboard(&self, out: &mut Type) -> SysResult<usize>;
176}
177
178///Describes format setter, specifying data type as type param
179///
180///Default implementations only perform write, without opening/closing clipboard
181pub trait Setter<Type: ?Sized> {
182 ///Writes content of `data` onto clipboard, returning whether it was successful or not
183 fn write_clipboard(&self, data: &Type) -> SysResult<()>;
184}
185
186#[inline(always)]
187///Runs provided callable with open clipboard, returning whether clipboard was open successfully.
188///
189///If clipboard fails to open, callable is not invoked.
190pub fn with_clipboard<F: FnMut()>(mut cb: F) -> SysResult<()> {
191 let _clip = Clipboard::new()?;
192 cb();
193 Ok(())
194}
195
196#[inline(always)]
197///Runs provided callable with open clipboard, returning whether clipboard was open successfully.
198///
199///If clipboard fails to open, attempts `num` number of retries before giving up.
200///In which case closure is not called
201pub fn with_clipboard_attempts<F: FnMut()>(num: usize, mut cb: F) -> SysResult<()> {
202 let _clip = Clipboard::new_attempts(num)?;
203 cb();
204 Ok(())
205}
206
207#[inline(always)]
208///Retrieve data from clipboard.
209pub fn get<R: Default, T: Getter<R>>(format: T) -> SysResult<R> {
210 let mut result = R::default();
211 format.read_clipboard(&mut result).map(|_| result)
212}
213
214#[inline(always)]
215///Shortcut to retrieve data from clipboard.
216///
217///It opens clipboard and gets output, if possible.
218pub fn get_clipboard<R: Default, T: Getter<R>>(format: T) -> SysResult<R> {
219 let _clip = Clipboard::new_attempts(10)?;
220 get(format)
221}
222
223#[inline(always)]
224///Set data onto clipboard.
225pub fn set<R, T: Setter<R>>(format: T, data: R) -> SysResult<()> {
226 format.write_clipboard(&data)
227}
228
229#[inline(always)]
230///Shortcut to set data onto clipboard.
231///
232///It opens clipboard and attempts to set data.
233pub fn set_clipboard<R, T: Setter<R>>(format: T, data: R) -> SysResult<()> {
234 let _clip = Clipboard::new_attempts(10)?;
235 set(format, data)
236}
237
238///Shortcut to retrieve string from clipboard.
239///
240///It opens clipboard and gets string, if possible.
241#[inline(always)]
242pub fn get_clipboard_string() -> SysResult<alloc::string::String> {
243 get_clipboard(Unicode)
244}
245
246///Shortcut to set string onto clipboard.
247///
248///It opens clipboard and attempts to set string.
249#[inline(always)]
250pub fn set_clipboard_string(data: &str) -> SysResult<()> {
251 set_clipboard(Unicode, data)
252}