diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 2dbc569..fc5c892 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -154,9 +154,15 @@ impl<'clipboard> Set<'clipboard> { pub(crate) fn text(self, text: Cow<'_, str>) -> Result<(), Error> { match self.clipboard { - Clipboard::X11(clipboard) => { - clipboard.set_text(text, self.selection, self.wait, self.wait_until) - } + Clipboard::X11(clipboard) => clipboard.set_text( + text, + self.selection, + match (self.wait, self.wait_until) { + (_, Some(deadline)) => x11::WaitConfig::Until(deadline), + (true, None) => x11::WaitConfig::Forever, + (false, None) => x11::WaitConfig::None, + }, + ), #[cfg(feature = "wayland-data-control")] Clipboard::WlDataControl(clipboard) => clipboard.set_text(text, self.selection, self.wait), @@ -165,9 +171,16 @@ impl<'clipboard> Set<'clipboard> { pub(crate) fn html(self, html: Cow<'_, str>, alt: Option>) -> Result<(), Error> { match self.clipboard { - Clipboard::X11(clipboard) => { - clipboard.set_html(html, alt, self.selection, self.wait, self.wait_until) - } + Clipboard::X11(clipboard) => clipboard.set_html( + html, + alt, + self.selection, + match (self.wait, self.wait_until) { + (_, Some(deadline)) => x11::WaitConfig::Until(deadline), + (true, None) => x11::WaitConfig::Forever, + (false, None) => x11::WaitConfig::None, + }, + ), #[cfg(feature = "wayland-data-control")] Clipboard::WlDataControl(clipboard) => clipboard.set_html(html, alt, self.selection, self.wait), @@ -177,9 +190,15 @@ impl<'clipboard> Set<'clipboard> { #[cfg(feature = "image-data")] pub(crate) fn image(self, image: ImageData<'_>) -> Result<(), Error> { match self.clipboard { - Clipboard::X11(clipboard) => { - clipboard.set_image(image, self.selection, self.wait, self.wait_until) - } + Clipboard::X11(clipboard) => clipboard.set_image( + image, + self.selection, + match (self.wait, self.wait_until) { + (_, Some(deadline)) => x11::WaitConfig::Until(deadline), + (true, None) => x11::WaitConfig::Forever, + (false, None) => x11::WaitConfig::None, + }, + ), #[cfg(feature = "wayland-data-control")] Clipboard::WlDataControl(clipboard) => clipboard.set_image(image, self.selection, self.wait), @@ -241,13 +260,11 @@ pub trait SetExtLinux: private::Sealed { /// Whether or not to wait for the clipboard's content to be replaced after setting it. This waits until the /// `deadline` has exceeded. /// - /// This is useful for short-lived programs so that it doesn't block until new contents on the clipboard - /// were added and will exit as so. - /// - /// For X11, this will wait until it either had new contents available in the clipboard or if the - /// `deadline` was exceeded. This isn't available for Wayland and will not do anything. + /// This is useful for short-lived programs so it won't block until new contents on the clipboard + /// were added. /// - /// Note: this will call [`wait()`][SetExtLinux::wait] if it wasn't previously set. + /// Note: this is a superset of [`wait()`][SetExtLinux::wait] and will overwrite any state + /// that was previously set using it. fn wait_until(self, deadline: Instant) -> Self; } diff --git a/src/platform/linux/x11.rs b/src/platform/linux/x11.rs index e5c0654..68545bc 100644 --- a/src/platform/linux/x11.rs +++ b/src/platform/linux/x11.rs @@ -205,6 +205,20 @@ enum ReadSelNotifyResult { EventNotRecognized, } +/// Configuration on how long to wait for a new X11 copy event is emitted. +#[derive(Default)] +pub enum WaitConfig { + /// Waits until the given [`Instant`] has reached. + Until(Instant), + + /// Waits forever until a new event is reached. + Forever, + + /// It shouldn't wait. + #[default] + None, +} + impl Inner { fn new() -> Result { let server = XContext::new()?; @@ -227,8 +241,7 @@ impl Inner { &self, data: Vec, selection: LinuxClipboardKind, - wait: bool, - until: Option, + wait: WaitConfig, ) -> Result<()> { if self.serve_stopped.load(Ordering::Relaxed) { return Err(Error::Unknown { @@ -261,16 +274,16 @@ impl Inner { // It is important that the mutex is locked to prevent this notification getting lost. selection.data_changed.notify_all(); - if wait { - drop(data_guard); - - // Wait for the clipboard's content to be changed. - match until { - Some(deadline) => { - selection.data_changed.wait_until(&mut guard, deadline); - } + match wait { + WaitConfig::None => {} + WaitConfig::Forever => { + drop(data_guard); + selection.data_changed.wait(&mut guard); + } - None => selection.data_changed.wait(&mut guard), + WaitConfig::Until(deadline) => { + drop(data_guard); + selection.data_changed.wait_until(&mut guard, deadline); } } @@ -882,14 +895,13 @@ impl Clipboard { &self, message: Cow<'_, str>, selection: LinuxClipboardKind, - wait: bool, - until: Option, + wait: WaitConfig, ) -> Result<()> { let data = vec![ClipboardData { bytes: message.into_owned().into_bytes(), format: self.inner.atoms.UTF8_STRING, }]; - self.inner.write(data, selection, wait, until) + self.inner.write(data, selection, wait) } pub(crate) fn set_html( @@ -897,8 +909,7 @@ impl Clipboard { html: Cow<'_, str>, alt: Option>, selection: LinuxClipboardKind, - wait: bool, - until: Option, + wait: WaitConfig, ) -> Result<()> { let mut data = vec![]; if let Some(alt_text) = alt { @@ -911,7 +922,7 @@ impl Clipboard { bytes: html.into_owned().into_bytes(), format: self.inner.atoms.HTML, }); - self.inner.write(data, selection, wait, until) + self.inner.write(data, selection, wait) } #[cfg(feature = "image-data")] @@ -937,12 +948,11 @@ impl Clipboard { &self, image: ImageData, selection: LinuxClipboardKind, - wait: bool, - until: Option, + wait: WaitConfig, ) -> Result<()> { let encoded = encode_as_png(&image)?; let data = vec![ClipboardData { bytes: encoded, format: self.inner.atoms.PNG_MIME }]; - self.inner.write(data, selection, wait, until) + self.inner.write(data, selection, wait) } }