diff --git a/Cargo.lock b/Cargo.lock index 944389b..ca76b16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,15 +108,6 @@ 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" @@ -421,21 +412,6 @@ 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" @@ -644,7 +620,6 @@ dependencies = [ "eyre", "rustix 1.1.2", "serde", - "tokio", "tracing", "tracing-subscriber", "wayland-client", @@ -1295,12 +1270,6 @@ 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" @@ -1622,17 +1591,6 @@ 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" @@ -1862,17 +1820,6 @@ 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" @@ -2297,15 +2244,6 @@ 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" @@ -2709,12 +2647,6 @@ 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" @@ -2926,16 +2858,6 @@ 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" @@ -3127,37 +3049,6 @@ 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" diff --git a/Cargo.toml b/Cargo.toml index 7874f7d..205341e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ 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" diff --git a/src/daemon.rs b/src/daemon.rs index 498ba15..8671497 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -2,12 +2,16 @@ use super::HistoryItem; use super::MAX_ENTRY_SIZE; use eframe::egui::ahash::HashSet; use eyre::Context; +use eyre::ContextCompat; use eyre::bail; +use rustix::event::PollFd; +use rustix::event::PollFlags; 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::PipeReader; use std::io::{BufReader, BufWriter, PipeWriter, Read, Write}; use std::os::fd::AsFd; use std::os::unix::net::{UnixListener, UnixStream}; @@ -19,6 +23,7 @@ use tracing::error; use tracing::info; use tracing::warn; use tracing_subscriber::EnvFilter; +use wayland_client::EventQueue; use wayland_client::protocol::wl_callback::WlCallback; use wayland_client::protocol::wl_display::WlDisplay; use wayland_client::protocol::wl_registry::WlRegistry; @@ -39,7 +44,7 @@ struct SharedState { // for deduplication because the event stream will tell us that we just copied something :) last_copied_item_id: AtomicU64, items: Mutex>, - select_history_send: tokio::sync::mpsc::Sender, + notify_write_send: PipeWriter, data_control_manager: OnceLock, data_control_devices: Mutex>, @@ -172,12 +177,6 @@ impl Dispatch for WlState { } } impl Dispatch for WlState { - #[tracing::instrument( - skip(state, _proxy, event, _data, _conn, _qhandle), - level = "info", - ret, - target = "ExtDataControlDeviceV1::event" - )] fn event( state: &mut Self, _proxy: &ExtDataControlDeviceV1, @@ -303,12 +302,6 @@ impl Dispatch for WlState { } impl Dispatch for WlState { - #[tracing::instrument( - skip(_state, proxy, event, data, _conn, _qhandle), - level = "info", - ret, - target = "ExtDataControlSourceV1::event" - )] fn event( _state: &mut Self, proxy: &ExtDataControlSourceV1, @@ -357,18 +350,15 @@ 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::(); - let (select_history_send, mut select_history_recv) = - tokio::sync::mpsc::channel::(1); + let (notify_write_recv, notify_write_send) = std::io::pipe().expect("todo"); let shared_state = Arc::new(SharedState { next_item_id: AtomicU64::new(0), last_copied_item_id: AtomicU64::new(u64::MAX), items: Mutex::new(Vec::::new()), - select_history_send, + notify_write_send, data_control_manager: OnceLock::new(), data_control_devices: Mutex::new(HashMap::new()), @@ -403,57 +393,20 @@ pub fn main(socket_path: &PathBuf) -> eyre::Result<()> { if wl_state.shared_state.data_control_manager.get().is_none() { bail!( "{} not found, the ext-data-control-v1 Wayland extension is likely unsupported by your compositor.\n\ - check https://wayland.app/protocols/ext-data-control-v1#compositor-support + check https://wayland.app/protocols/ext-data-control-v1#compositor-support\ ", ExtDataControlManagerV1::interface().name ); } + rustix::fs::fcntl_setfl(notify_write_recv.as_fd(), OFlags::NONBLOCK).expect("todo"); + rustix::fs::fcntl_setfl(conn.as_fd(), OFlags::NONBLOCK).expect("TODO"); + std::thread::spawn(move || { - 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); - } - } - } - } - } - }); + if let Err(err) = dispatch_wayland(queue, wl_state, notify_write_recv) { + error!("error on Wayland thread: {err:?}"); + std::process::exit(1); + } }); info!("Listening on {}", socket_path.display()); @@ -478,6 +431,32 @@ pub fn main(socket_path: &PathBuf) -> eyre::Result<()> { Ok(()) } +fn dispatch_wayland( + mut queue: EventQueue, + mut wl_state: WlState, + notify_write_recv: PipeReader, +) -> eyre::Result<()> { + loop { + queue + .dispatch_pending(&mut wl_state) + .wrap_err("dispatching Wayland events")?; + + let read_guard = queue + .prepare_read() + .wrap_err("preparing read from Wayland socket")?; + let _ = queue.flush(); + + let pollfd1_read = PollFd::from_borrowed_fd(read_guard.connection_fd(), PollFlags::IN); + let pollfd_signal = PollFd::from_borrowed_fd(notify_write_recv.as_fd(), PollFlags::IN); + + let _ = rustix::event::poll(&mut [pollfd1_read, pollfd_signal], None); + + read_guard + .read_without_dispatch() + .wrap_err("reading from wayland socket")?; + } +} + #[tracing::instrument(skip(peer, shared_state), level = "info")] fn handle_peer(mut peer: UnixStream, shared_state: &SharedState) -> eyre::Result<()> { let mut request = [0; 1]; @@ -509,9 +488,17 @@ fn handle_copy(mut peer: UnixStream, shared_state: &SharedState) -> Result<(), e let Some(idx) = items.iter().position(|item| item.id == id) else { return Ok(()); }; - let entry = items.remove(idx); - items.push(entry.clone()); - shared_state.select_history_send.try_send(entry)?; + let item = items.remove(idx); + items.push(item.clone()); + + drop(items); + + do_copy_into_clipboard(item, &shared_state).wrap_err("doing copy")?; + + (&shared_state.notify_write_send) + .write_all(&[0]) + .wrap_err("notifying wayland thread")?; + Ok(()) }