Files
rklip/rklipd/src/ws/wayland.rs
2026-05-21 09:39:12 +02:00

103 lines
3.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::models::{ClipboardData, ClipboardEntry, Image};
use std::collections::hash_map::DefaultHasher;
use std::error::Error;
use std::hash::{Hash, Hasher};
use std::sync::mpsc;
use std::time::SystemTime;
use uuid::Uuid;
use wayland_clipboard_listener::{WlClipboardPasteStream, WlListenType};
const MAX_IMAGE_PIXELS: usize = 3840 * 2160;
fn hash_bytes(data: &[u8]) -> u64 {
let mut hasher = DefaultHasher::new();
data.hash(&mut hasher);
hasher.finish()
}
pub fn start(
tx: mpsc::Sender<ClipboardEntry>,
_clipboard: arboard::Clipboard,
) -> Result<(), Box<dyn Error>> {
let mut stream = WlClipboardPasteStream::init(WlListenType::ListenOnCopy)
.map_err(|e| format!("Impossible d'initialiser Wayland : {e}"))?;
println!("Écoute du presse-papier Wayland...");
let mut last_text: Option<String> = None;
let mut last_image_hash: Option<u64> = None;
for msg in stream.paste_stream().flatten() {
let data: &[u8] = msg.context.context.as_slice();
if data.is_empty() {
continue;
}
let entry = if let Ok(text) = String::from_utf8(data.to_vec()) {
let text = text.trim_end_matches('\n').to_string();
if text.is_empty() || Some(&text) == last_text.as_ref() {
continue;
}
last_text = Some(text.clone());
last_image_hash = None;
println!("Clipboard update (texte)");
ClipboardEntry {
content: ClipboardData::Text(text),
timestamp: SystemTime::now(),
}
} else {
let hash = hash_bytes(data);
if Some(hash) == last_image_hash {
continue;
}
match image::load_from_memory(data) {
Ok(img) => {
let (width, height) = (img.width(), img.height());
if (width as usize) * (height as usize) > MAX_IMAGE_PIXELS {
eprintln!(
"Image Wayland ignorée : {}×{} ({} Mpx > limite {}×{})",
width,
height,
(width as usize * height as usize) / 1_000_000,
3840,
2160
);
last_image_hash = Some(hash);
last_text = None;
continue;
}
last_image_hash = Some(hash);
last_text = None;
println!("Clipboard update (image)");
let rgba = img.into_rgba8();
ClipboardEntry {
content: ClipboardData::Image(Image {
raw_pixels: Some(rgba.into_raw()),
width,
height,
id: Uuid::new_v4(),
}),
timestamp: SystemTime::now(),
}
}
Err(e) => {
eprintln!("Clipboard ignoré (format inconnu) : {e}");
continue;
}
}
};
if tx.send(entry).is_err() {
eprintln!("Wayland : writer thread disparu, arrêt");
break;
}
}
Ok(())
}