FabianLars 7 months ago
parent 6112867735
commit edbb8234be
No known key found for this signature in database

@ -0,0 +1,6 @@
---
clipboard-manager: patch
clipboard-manager-js: patch
---
Explicitly drop `arboard::Clipboard` on exit. Add recommendation to not use read methods on the mainthread.

@ -14,7 +14,7 @@ pub fn init<R: Runtime, C: DeserializeOwned>(
) -> crate::Result<Clipboard<R>> {
Ok(Clipboard {
app: app.clone(),
clipboard: arboard::Clipboard::new().map(Mutex::new),
clipboard: arboard::Clipboard::new().map(|c| Mutex::new(Some(c))),
})
}
@ -22,13 +22,21 @@ pub fn init<R: Runtime, C: DeserializeOwned>(
pub struct Clipboard<R: Runtime> {
#[allow(dead_code)]
app: AppHandle<R>,
clipboard: Result<Mutex<arboard::Clipboard>, arboard::Error>,
// According to arboard docs the clipboard must be dropped before exit.
// Since tauri doesn't call drop on exit we'll use an Option to take() on RunEvent::Exit.
clipboard: Result<Mutex<Option<arboard::Clipboard>>, arboard::Error>,
}
impl<R: Runtime> Clipboard<R> {
pub fn write_text<'a, T: Into<Cow<'a, str>>>(&self, text: T) -> crate::Result<()> {
match &self.clipboard {
Ok(clipboard) => clipboard.lock().unwrap().set_text(text).map_err(Into::into),
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.set_text(text)
.map_err(Into::into),
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
@ -38,6 +46,8 @@ impl<R: Runtime> Clipboard<R> {
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.set_image(ImageData {
bytes: Cow::Borrowed(image.rgba()),
width: image.width() as usize,
@ -48,10 +58,11 @@ impl<R: Runtime> Clipboard<R> {
}
}
/// Warning: This method should not be used on the main thread! Otherwise the underlying libraries may deadlock on Linux, freezing the whole app.
pub fn read_text(&self) -> crate::Result<String> {
match &self.clipboard {
Ok(clipboard) => {
let text = clipboard.lock().unwrap().get_text()?;
let text = clipboard.lock().unwrap().as_mut().unwrap().get_text()?;
Ok(text)
}
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
@ -67,6 +78,8 @@ impl<R: Runtime> Clipboard<R> {
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.set_html(html, alt_text)
.map_err(Into::into),
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
@ -75,15 +88,22 @@ impl<R: Runtime> Clipboard<R> {
pub fn clear(&self) -> crate::Result<()> {
match &self.clipboard {
Ok(clipboard) => clipboard.lock().unwrap().clear().map_err(Into::into),
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.clear()
.map_err(Into::into),
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
/// Warning: This method should not be used on the main thread! Otherwise the underlying libraries may deadlock on Linux, freezing the whole app.
pub fn read_image(&self) -> crate::Result<Image<'_>> {
match &self.clipboard {
Ok(clipboard) => {
let image = clipboard.lock().unwrap().get_image()?;
let image = clipboard.lock().unwrap().as_mut().unwrap().get_image()?;
let image = Image::new_owned(
image.bytes.to_vec(),
image.width as u32,
@ -94,4 +114,10 @@ impl<R: Runtime> Clipboard<R> {
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
pub(crate) fn cleanup(&self) {
if let Ok(clipboard) = &self.clipboard {
clipboard.lock().unwrap().take();
}
}
}

@ -11,7 +11,7 @@
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
Manager, RunEvent, Runtime,
};
#[cfg(desktop)]
@ -59,5 +59,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
app.manage(clipboard);
Ok(())
})
.on_event(|_app, _event| {
#[cfg(desktop)]
if let RunEvent::Exit = _event {
_app.clipboard().cleanup();
}
})
.build()
}

Loading…
Cancel
Save