Install clipboard-rs via Cargo
masterTo use clipboard-rs in your Rust project, add it to your Cargo.toml dependencies file.
[dependencies]
clipboard-rs = "0.3.5"repository·master·Indexed 41 days ago
https://github.com/churchtao/clipboard-rsA cross-platform Rust library for interacting with system-level clipboards on Windows, macOS, and Linux. Version 0.3.5 supports reading and writing plain text, HTML, RTF, images, and file lists. It includes a ClipboardWatcher for monitoring clipboard changes and the RustImage trait for image processing and manipulation.
To use clipboard-rs in your Rust project, add it to your Cargo.toml dependencies file.
[dependencies]
clipboard-rs = "0.3.5"Use ctx.get_image() to retrieve clipboard images. The returned image type (likely RustImage) provides methods like save_to_path and thumbnail for processing.
use clipboard_rs::{common::RustImage, Clipboard, ClipboardContext};
const TMP_PATH: &str = "/tmp/";
fn main() {
let ctx = ClipboardContext::new().unwrap();
let img = ctx.get_image();
match img {
Ok(img) => {
img.save_to_path(format!("{}test.png", TMP_PATH).as_str())
.unwrap();
let resize_img = img.thumbnail(300, 300).unwrap();
resize_img
.save_to_path(format!("{}test_thumbnail.png", TMP_PATH).as_str())
.unwrap();
}
Err(err) => {
println!("err={}", err);
}
}
}You can use ClipboardContext to check for available formats and retrieve common content types like plain text, HTML, or Rich Text (RTF). Use ctx.has(ContentFormat) to check for existence before retrieving.
use clipboard_rs::{Clipboard, ClipboardContext, ContentFormat};
fn main() {
nlet ctx = ClipboardContext::new().unwrap();
let types = ctx.available_formats().unwrap();
println!("{:?}", types);
let has_rtf = ctx.has(ContentFormat::Rtf);
println!("has_rtf={}", has_rtf);
let rtf = ctx.get_rich_text().unwrap_or("".to_string());
println!("rtf={}", rtf);
let has_html = ctx.has(ContentFormat::Html);
println!("has_html={}", has_html);
let html = ctx.get_html().unwrap_or("".to_string());
let content = ctx.get_text().unwrap_or("".to_string());
println!("txt={}", content);
}To react to clipboard changes, implement the ClipboardHandler trait for your manager struct and use ClipboardWatcherContext to start watching. You can obtain a shutdown channel to stop the watcher programmatically.
use clipboard_rs::{
Clipboard,
ClipboardContext,
ClipboardHandler,
ClipboardWatcher,
ClipboardWatcherContext,
};
use std::{thread, time::Duration};
struct Manager {
ctx: ClipboardContext,
}
impl Manager {
pub fn new() -> Self {
let ctx = ClipboardContext::new().unwrap();
Manager { ctx }
}
}
impl ClipboardHandler for Manager {
fn on_clipboard_change(&mut self) {
println!(
"on_clipboard_change, txt = {}",
self.ctx.get_text().unwrap()
);
}
}
fn main() {
let manager = Manager::new();
let mut watcher = ClipboardWatcherContext::new().unwrap();
// Add handler and get shutdown channel
let watcher_shutdown = watcher.add_handler(manager).get_shutdown_channel();
thread::spawn(move || {
thread::sleep(Duration::from_secs(5));
println!("stop watch!");
watcher_shutdown.stop();
});
println!("start watch!");
watcher.start_watch();
}If a specific helper method doesn't exist, you can retrieve raw data for any supported type using ctx.get_buffer(type_identifier). This returns a byte buffer which you can then convert (e.g., to a UTF-8 string).
use clipboard_rs::{Clipboard, ClipboardContext};
fn main() {
let ctx = ClipboardContext::new().unwrap();
let types = ctx.available_formats().unwrap();
println!("{:?}", types);
// Use a specific type identifier like "public.html"
let buffer = ctx.get_buffer("public.html").unwrap();
let string = String::from_utf8(buffer).unwrap();
println!("{}", string);
}On Linux (X11), reading large data (like high-resolution images) might fail due to the default 500ms timeout. You can increase this timeout using ClipboardContext::new_with_options and providing ClipboardContextX11Options.
#[cfg(unix)]
fn setup_clipboard() -> ClipboardContext {
// Set read_timeout to None or a specific duration to prevent interruption
ClipboardContext::new_with_options(ClipboardContextX11Options { read_timeout: None }).unwrap()
}
#[cfg(not(unix))]
fn setup_clipboard(ctx: &mut ClipboardContext) -> ClipboardContext {
ClipboardContext::new().unwrap()
}The library supports various data formats across different operating systems. Note that Android support is currently under development (🚧).
| Type | Windows | macOS | Linux (X11) | iOS (Beta) | Android |
|---|---|---|---|---|---|
| Plain Text | ✅ | ✅ | ✅ | ✅ | 🚧 |
| HTML | ✅ | ✅ | ✅ | ✅ | 🚧 |
| RTF | ✅ | ✅ | ✅ | ✅ | 🚧 |
| Images | PNG/DIBV5 | PNG/TIFF | PNG | PNG | 🚧 |
| File Lists | ✅ | ✅ | ✅ | ❌ | 🚧 |
| Custom Types | ✅ | ✅ | ✅ | ✅ | 🚧 |
| Change Monitoring | ✅ | ✅ | ✅ | ✅ | 🚧 |
A RustImageBuffer is a wrapper around a Vec<u8> containing encoded image data (e.g., a complete PNG or JPEG file). It is the return type for all conversion methods in the RustImage trait.
Use get_bytes() to access the raw encoded byte slice or save_to_path(path) to write the buffer directly to a file.
#[cfg(feature = "image")]
impl RustImageBuffer {
pub fn get_bytes(&self) -> &[u8] {
&self.0
}
pub fn save_to_path(&self, path: &str) -> Result<()> {
std::fs::write(path, &self.0)?;
Ok(())
}
}If the image feature is enabled, you can use the RustImage trait to perform advanced image operations on clipboard image data. This trait works with the RustImageData struct.
Key capabilities:
from_path), byte slices (from_bytes), or DynamicImage objects (from_dynamic_image).thumbnail) or resize exactly to dimensions (resize).to_jpeg), PNG (to_png), or BMP (to_bitmap, Windows only) which return a RustImageBuffer.save_to_path).DynamicImage or convert to Rgba8 format.use clipboard_rs::RustImage;
// Example: Loading and resizing an image
let img = RustImageData::from_path("input.png")?;
let small_img = img.thumbnail(100, 100)?;
// Example: Converting to PNG bytes
let png_buffer = small_img.to_png()?;
let bytes = png_buffer.get_bytes();
// Example: Saving to disk
small_img.save_to_path("output.png")?;To react to clipboard updates, implement the ClipboardHandler trait. This is typically used in conjunction with a listener loop or event system provided by the library to trigger logic whenever the clipboard content changes.
pub trait ClipboardHandler {
fn on_clipboard_change(&mut self);
}The ClipboardContent enum represents the various types of data that can be stored in the clipboard. It supports text, RTF, HTML, images (requires image feature), file paths, and generic 'other' data.
By implementing the ContentData trait, you can interact with any ClipboardContent variant using a unified interface to retrieve its format, raw bytes, or string representation.
use clipboard_rs::ClipboardContent;
// Example of matching on content
match content {
ClipboardContent::Text(t) => println!("Text: {}", t),
ClipboardContent::Image(img) => println!("Image data available"),
_ => println!("Other content type"),
}
// Using ContentData methods
let format = content.get_format();
let bytes = content.as_bytes();
let text_result = content.as_str();The Clipboard trait provides the core interface for interacting with the system clipboard. It supports reading various data formats (plain text, rich text, HTML, images, and files) and writing them back to the clipboard.
Key Capabilities:
get_text(), get_rich_text(), get_html(), get_image() (requires image feature), or get_buffer(format: &str) for raw byte access.set_text(), set_rich_text(), set_html(), set_image() (requires image feature), or set_buffer(format: &str, buffer: Vec<u8>).available_formats() or check for a specific format with has(format: ContentFormat).clear() or set multiple contents at once using set(contents: &[ClipboardContent]).// Example: Reading and writing text
fn handle_clipboard(clipboard: &impl Clipboard) -> Result<()> {
// Read text
let text = clipboard.get_text()?;
println!("Clipboard contains: {}", text);
// Write text
clipboard.set_text("Hello from clipboard-rs!".to_string())?;
Ok(())
}