mirror of
https://github.com/Noratrieb/clippyboard.git
synced 2026-01-14 09:55:04 +01:00
try try try
This commit is contained in:
parent
ea487d598c
commit
0df0d40f7c
3 changed files with 234 additions and 28 deletions
140
Cargo.lock
generated
140
Cargo.lock
generated
|
|
@ -108,6 +108,15 @@ dependencies = [
|
|||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
|
|
@ -270,7 +279,7 @@ dependencies = [
|
|||
"futures-lite",
|
||||
"parking",
|
||||
"polling",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"slab",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
|
@ -301,7 +310,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"event-listener",
|
||||
"futures-lite",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -327,7 +336,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"windows-sys 0.60.2",
|
||||
|
|
@ -412,6 +421,21 @@ version = "1.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.8.0"
|
||||
|
|
@ -618,7 +642,9 @@ dependencies = [
|
|||
"eframe",
|
||||
"egui_extras",
|
||||
"eyre",
|
||||
"rustix 1.1.2",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"wayland-client",
|
||||
|
|
@ -1242,7 +1268,7 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55"
|
||||
dependencies = [
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
|
|
@ -1269,6 +1295,12 @@ dependencies = [
|
|||
"wasi 0.14.4+wasi-0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "gl_generator"
|
||||
version = "0.14.0"
|
||||
|
|
@ -1590,6 +1622,17 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.21.1"
|
||||
|
|
@ -1696,9 +1739,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
|||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.4"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
||||
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
|
|
@ -1819,6 +1862,17 @@ dependencies = [
|
|||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moxcms"
|
||||
version = "0.7.5"
|
||||
|
|
@ -2243,6 +2297,15 @@ dependencies = [
|
|||
"objc2-foundation 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
|
|
@ -2469,7 +2532,7 @@ dependencies = [
|
|||
"concurrent-queue",
|
||||
"hermit-abi",
|
||||
"pin-project-lite",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
|
|
@ -2646,6 +2709,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
|
|
@ -2673,14 +2742,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.8"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
||||
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"linux-raw-sys 0.11.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
|
|
@ -2857,6 +2926,16 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv"
|
||||
version = "0.3.0+sdk-1.3.268.0"
|
||||
|
|
@ -2937,7 +3016,7 @@ dependencies = [
|
|||
"fastrand",
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
|
|
@ -3048,6 +3127,37 @@ dependencies = [
|
|||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.47.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"io-uring",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.11"
|
||||
|
|
@ -3323,7 +3433,7 @@ checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35"
|
|||
dependencies = [
|
||||
"cc",
|
||||
"downcast-rs",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"scoped-tls",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
|
|
@ -3336,7 +3446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"wayland-backend",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
|
@ -3358,7 +3468,7 @@ version = "0.31.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29"
|
||||
dependencies = [
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"wayland-client",
|
||||
"xcursor",
|
||||
]
|
||||
|
|
@ -4155,7 +4265,7 @@ dependencies = [
|
|||
"libc",
|
||||
"libloading",
|
||||
"once_cell",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"x11rb-protocol",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ dirs = "6.0.0"
|
|||
eframe = "0.32.2"
|
||||
egui_extras = { version = "0.32.2", features = ["image"] }
|
||||
eyre = "0.6.12"
|
||||
rustix = "1.1.2"
|
||||
serde = "1.0.219"
|
||||
tokio = { version = "1.47.1", features = ["full", "sync"] }
|
||||
tracing = { version = "0.1.41", features = ["attributes"] }
|
||||
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
|
||||
wayland-client = "0.31.11"
|
||||
|
|
|
|||
120
src/daemon.rs
120
src/daemon.rs
|
|
@ -3,7 +3,11 @@ use super::MAX_ENTRY_SIZE;
|
|||
use eframe::egui::ahash::HashSet;
|
||||
use eyre::Context;
|
||||
use eyre::bail;
|
||||
use rustix::fs::OFlags;
|
||||
use rustix::fs::fcntl_setfl;
|
||||
use rustix::io::FdFlags;
|
||||
use std::collections::HashMap;
|
||||
use std::future::poll_fn;
|
||||
use std::io::{BufReader, BufWriter, PipeWriter, Read, Write};
|
||||
use std::os::fd::AsFd;
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
|
|
@ -11,12 +15,15 @@ use std::path::PathBuf;
|
|||
use std::sync::{Arc, Mutex, OnceLock, atomic::AtomicU64};
|
||||
use std::time::Duration;
|
||||
use std::time::SystemTime;
|
||||
use tracing::error;
|
||||
use tracing::info;
|
||||
use tracing::warn;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use wayland_client::{Dispatch, Proxy, QueueHandle, backend::ObjectId, event_created_child};
|
||||
use wayland_client::protocol::wl_callback::WlCallback;
|
||||
use wayland_client::protocol::wl_display::WlDisplay;
|
||||
use wayland_client::protocol::wl_registry::WlRegistry;
|
||||
use wayland_client::protocol::wl_seat::WlSeat;
|
||||
use wayland_client::{Dispatch, Proxy, QueueHandle, backend::ObjectId, event_created_child};
|
||||
use wayland_protocols::ext::data_control::v1::client::ext_data_control_device_v1;
|
||||
use wayland_protocols::ext::data_control::v1::client::ext_data_control_device_v1::{
|
||||
EVT_DATA_OFFER_OPCODE, ExtDataControlDeviceV1,
|
||||
|
|
@ -32,10 +39,12 @@ struct SharedState {
|
|||
// for deduplication because the event stream will tell us that we just copied something :)
|
||||
last_copied_item_id: AtomicU64,
|
||||
items: Mutex<Vec<HistoryItem>>,
|
||||
select_history_send: tokio::sync::mpsc::Sender<HistoryItem>,
|
||||
|
||||
data_control_manager: OnceLock<ExtDataControlManagerV1>,
|
||||
data_control_devices: Mutex<HashMap</*seat global name */ u32, ExtDataControlDeviceV1>>,
|
||||
qh: QueueHandle<WlState>,
|
||||
d: WlDisplay,
|
||||
}
|
||||
|
||||
struct InProgressOffer {
|
||||
|
|
@ -61,6 +70,19 @@ struct WlState {
|
|||
current_selection: Option<CurrentSelection>,
|
||||
}
|
||||
|
||||
impl Dispatch<WlCallback, String> for WlState {
|
||||
fn event(
|
||||
_state: &mut Self,
|
||||
_proxy: &WlCallback,
|
||||
_event: <WlCallback as Proxy>::Event,
|
||||
data: &String,
|
||||
_conn: &wayland_client::Connection,
|
||||
_qhandle: &QueueHandle<Self>,
|
||||
) {
|
||||
info!("Received sync back {data}");
|
||||
}
|
||||
}
|
||||
|
||||
impl Dispatch<WlRegistry, ()> for WlState {
|
||||
fn event(
|
||||
state: &mut Self,
|
||||
|
|
@ -199,7 +221,7 @@ impl Dispatch<ExtDataControlDeviceV1, ()> for WlState {
|
|||
|
||||
state.current_selection = new_offer;
|
||||
|
||||
if let Some(offer) = &state.current_selection {
|
||||
if let Some(offer) = state.current_selection.take() {
|
||||
let Some(mime) = ["text/plain", "image/png"]
|
||||
.iter()
|
||||
.find(|mime| offer.mime_types.contains(**mime))
|
||||
|
|
@ -223,6 +245,8 @@ impl Dispatch<ExtDataControlDeviceV1, ()> for WlState {
|
|||
if let Err(err) = result {
|
||||
warn!("Failed to read clipboard: {:?}", err)
|
||||
}
|
||||
|
||||
offer.offer.destroy();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -333,16 +357,30 @@ pub fn main(socket_path: &PathBuf) -> eyre::Result<()> {
|
|||
let conn =
|
||||
wayland_client::Connection::connect_to_env().wrap_err("connecting to the compositor")?;
|
||||
|
||||
rustix::fs::fcntl_setfl(conn.as_fd(), OFlags::NONBLOCK).expect("TODO");
|
||||
|
||||
let mut queue = conn.new_event_queue::<WlState>();
|
||||
|
||||
let (select_history_send, mut select_history_recv) =
|
||||
tokio::sync::mpsc::channel::<HistoryItem>(1);
|
||||
|
||||
let shared_state = Arc::new(SharedState {
|
||||
next_item_id: AtomicU64::new(0),
|
||||
last_copied_item_id: AtomicU64::new(u64::MAX),
|
||||
items: Mutex::new(Vec::<HistoryItem>::new()),
|
||||
select_history_send,
|
||||
|
||||
data_control_manager: OnceLock::new(),
|
||||
data_control_devices: Mutex::new(HashMap::new()),
|
||||
qh: queue.handle(),
|
||||
d: conn.display(),
|
||||
});
|
||||
|
||||
shared_state.items.lock().unwrap().push(HistoryItem {
|
||||
id: 3548235782,
|
||||
mime: "text/plain".into(),
|
||||
data: b"meow".to_vec().into(),
|
||||
created_time: 0,
|
||||
});
|
||||
|
||||
let history_state2 = shared_state.clone();
|
||||
|
|
@ -372,14 +410,50 @@ pub fn main(socket_path: &PathBuf) -> eyre::Result<()> {
|
|||
}
|
||||
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
let result = queue
|
||||
.blocking_dispatch(&mut wl_state)
|
||||
.wrap_err("handling wayland");
|
||||
if let Err(err) = result {
|
||||
warn!("Received error from Wayland: {:?}", err);
|
||||
}
|
||||
}
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
loop {
|
||||
info!("about to cook");
|
||||
|
||||
queue.dispatch_pending(&mut wl_state).expect("todo");
|
||||
|
||||
let read_guard = queue.prepare_read().expect("todo");
|
||||
|
||||
let fd =
|
||||
tokio::io::unix::AsyncFd::new(read_guard.connection_fd()).expect("todo");
|
||||
|
||||
info!("gonna wait, maybe forever");
|
||||
|
||||
tokio::select! {
|
||||
result = fd.readable() => {
|
||||
info!("we are ready to read!");
|
||||
if let Err(err) = result {
|
||||
error!("Received error from Wayland: {:?}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
drop(fd);
|
||||
|
||||
read_guard.read().expect("todo");
|
||||
}
|
||||
item = select_history_recv.recv() => {
|
||||
info!("received thing from channel");
|
||||
match item {
|
||||
None => {
|
||||
error!("IPC socket thread hung up");
|
||||
std::process::exit(1);
|
||||
}
|
||||
Some(item) => {
|
||||
do_copy_into_clipboard(item, &wl_state.shared_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
info!("Listening on {}", socket_path.display());
|
||||
|
|
@ -437,16 +511,28 @@ fn handle_copy(mut peer: UnixStream, shared_state: &SharedState) -> Result<(), e
|
|||
};
|
||||
let entry = items.remove(idx);
|
||||
items.push(entry.clone());
|
||||
shared_state.select_history_send.try_send(entry)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
drop(items);
|
||||
|
||||
fn do_copy_into_clipboard(
|
||||
entry: HistoryItem,
|
||||
shared_state: &SharedState,
|
||||
) -> Result<(), eyre::Error> {
|
||||
for device in &*shared_state.data_control_devices.lock().unwrap() {
|
||||
shared_state
|
||||
.d
|
||||
.sync(&shared_state.qh, "before create_data_source".into());
|
||||
let data_source = shared_state
|
||||
.data_control_manager
|
||||
.get()
|
||||
.expect("data manger not found")
|
||||
.create_data_source(&shared_state.qh, OfferData(entry.data.clone()));
|
||||
|
||||
shared_state
|
||||
.d
|
||||
.sync(&shared_state.qh, "after create_data_source".into());
|
||||
|
||||
if entry.mime == "text/plain" {
|
||||
// Just like wl_clipboard_rs, we also offer some extra mimes for text.
|
||||
let text_mimes = [
|
||||
|
|
@ -459,13 +545,21 @@ fn handle_copy(mut peer: UnixStream, shared_state: &SharedState) -> Result<(), e
|
|||
for mime in text_mimes {
|
||||
data_source.offer(mime.to_string());
|
||||
}
|
||||
} else {
|
||||
data_source.offer(entry.mime.clone());
|
||||
}
|
||||
|
||||
data_source.offer(entry.mime.clone());
|
||||
shared_state
|
||||
.d
|
||||
.sync(&shared_state.qh, "before set_selection".into());
|
||||
|
||||
info!("setting the selection");
|
||||
|
||||
device.1.set_selection(Some(&data_source));
|
||||
|
||||
shared_state
|
||||
.d
|
||||
.sync(&shared_state.qh, "setting the selection".into());
|
||||
}
|
||||
|
||||
shared_state
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue