signal json clipboard writing
This commit is contained in:
119
rklipd/Cargo.lock
generated
119
rklipd/Cargo.lock
generated
@ -160,6 +160,15 @@ dependencies = [
|
||||
"core2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "built"
|
||||
version = "0.8.0"
|
||||
@ -202,6 +211,19 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-master"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c324ebf93a69bed78df929206f4475e7287fff609bebdfce199ea9dde4ce4e3d"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-app-kit",
|
||||
"windows-win",
|
||||
"x11-clipboard",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "5.4.1"
|
||||
@ -672,8 +694,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-text",
|
||||
"objc2-core-video",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
@ -701,6 +754,41 @@ dependencies = [
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-video"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
@ -729,6 +817,17 @@ dependencies = [
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
@ -982,6 +1081,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"base64",
|
||||
"clipboard-master",
|
||||
"image",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -1261,6 +1361,15 @@ dependencies = [
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-win"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58e23e33622b3b52f948049acbec9bcc34bf6e26d74176b88941f213c75cf2dc"
|
||||
dependencies = [
|
||||
"error-code",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.1"
|
||||
@ -1315,6 +1424,16 @@ version = "0.51.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||
|
||||
[[package]]
|
||||
name = "x11-clipboard"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11rb"
|
||||
version = "0.13.2"
|
||||
|
||||
@ -10,3 +10,8 @@ serde = {version = "1.0.228", features = ["derive"]}
|
||||
serde_json = "1.0.149"
|
||||
serde_millis = "0.1.1"
|
||||
base64 = "0.22.1"
|
||||
clipboard-master = "4.0.0"
|
||||
|
||||
[features]
|
||||
x11 = []
|
||||
wayland = []
|
||||
|
||||
@ -3,25 +3,43 @@ use image::codecs::png::PngEncoder;
|
||||
use image::{ExtendedColorType, ImageEncoder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::{self, File};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::result::Result;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::{error::Error, time::SystemTime};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ClipboardEntry {
|
||||
pub content: ClipboardData,
|
||||
#[serde(with = "serde_millis")]
|
||||
pub timestamp: SystemTime,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum ClipboardData {
|
||||
Text(String),
|
||||
#[serde(with = "base64_vec")]
|
||||
Image(Vec<u8>),
|
||||
}
|
||||
|
||||
// X11
|
||||
use clipboard_master::{CallbackResult, ClipboardHandler};
|
||||
|
||||
pub struct Handler {
|
||||
pub clipboard_tx: Sender<()>,
|
||||
}
|
||||
|
||||
impl ClipboardHandler for Handler {
|
||||
fn on_clipboard_change(&mut self) -> CallbackResult {
|
||||
if let Err(e) = self.clipboard_tx.send(()) {
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
CallbackResult::Next
|
||||
}
|
||||
}
|
||||
|
||||
// X11 end
|
||||
|
||||
mod base64_vec {
|
||||
use base64::{Engine as _, engine::general_purpose::STANDARD};
|
||||
use serde::{Deserialize, Deserializer, Serializer};
|
||||
@ -98,16 +116,46 @@ impl ClipboardEntry {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub fn write_entry_json(&self, path: &str) -> Result<(), Box<dyn Error>> {
|
||||
let json = serde_json::to_string_pretty(self)?;
|
||||
let mut file = File::create(path)?;
|
||||
file.write_all(json.as_bytes())?;
|
||||
|
||||
pub fn append_json(&self, path: &str) -> Result<(), Box<dyn Error>> {
|
||||
let mut entries: Vec<ClipboardEntry> = if Path::new(path).exists() {
|
||||
let data = fs::read_to_string(path)?;
|
||||
if data.trim().is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
serde_json::from_str(&data)?
|
||||
}
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
entries.push(self.clone());
|
||||
let json = serde_json::to_string_pretty(&entries)?;
|
||||
fs::write(path, json)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_entry_json(path: &str) -> Result<Self, Box<dyn Error>> {
|
||||
pub fn read_json(path: &str) -> Result<Vec<ClipboardEntry>, Box<dyn Error>> {
|
||||
if !Path::new(path).exists() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let data = fs::read_to_string(path)?;
|
||||
let entry: ClipboardEntry = serde_json::from_str(&data)?;
|
||||
Ok(entry)
|
||||
if data.trim().is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let entries: Vec<ClipboardEntry> = serde_json::from_str(&data)?;
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
// pub fn write_json(&self, path: &str) -> Result<(), Box<dyn Error>> {
|
||||
// let json = serde_json::to_string_pretty(self)?;
|
||||
// let mut file = File::create(path)?;
|
||||
// file.write_all(json.as_bytes())?;
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// pub fn read_json(path: &str) -> Result<Self, Box<dyn Error>> {
|
||||
// let data = fs::read_to_string(path)?;
|
||||
// let entry: ClipboardEntry = serde_json::from_str(&data)?;
|
||||
// Ok(entry)
|
||||
// }
|
||||
}
|
||||
|
||||
@ -1,17 +1,38 @@
|
||||
use arboard::Clipboard;
|
||||
use rklipd::ClipboardEntry;
|
||||
use clipboard_master::Master;
|
||||
use rklipd::{ClipboardEntry, Handler};
|
||||
use std::error::Error;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
// X11
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut clipboard = Clipboard::new()?;
|
||||
let entry = ClipboardEntry::new(&mut clipboard)?;
|
||||
let path = "clipboard.json";
|
||||
match ClipboardEntry::new_json(path) {
|
||||
Ok(_) => println!("JSON file created {}", path),
|
||||
Err(e) => println!("{}", e),
|
||||
ClipboardEntry::new_json(path).unwrap_or(());
|
||||
|
||||
let (tx, rx) = channel();
|
||||
|
||||
let mut master = Master::new(Handler { clipboard_tx: tx })?;
|
||||
// let shutdown = master.shutdown_channel();
|
||||
std::thread::spawn(move || {
|
||||
if let Err(e) = master.run() {
|
||||
eprintln!("Clipboard monitor error : {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
println!("Monitoring clipboard X11...");
|
||||
|
||||
for _ in rx {
|
||||
println!("Clipboard changed!");
|
||||
if let Ok(entry) = ClipboardEntry::new(&mut clipboard) {
|
||||
if let Err(e) = entry.append_json(path) {
|
||||
eprintln!("JSON writing error: {}", e);
|
||||
} else {
|
||||
println!("JSON edited!");
|
||||
}
|
||||
}
|
||||
}
|
||||
entry.write_entry_json(path)?;
|
||||
let loaded_entry = ClipboardEntry::read_entry_json(path)?;
|
||||
println!("{:#?}", loaded_entry);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// X11
|
||||
|
||||
Reference in New Issue
Block a user