diff --git a/.changes/arboard.md b/.changes/arboard.md new file mode 100644 index 000000000..5a6aadb1f --- /dev/null +++ b/.changes/arboard.md @@ -0,0 +1,5 @@ +--- +"tauri-runtime-wry": patch:bug +--- + +Use `arboard` instead of `tao` clipboard implementation to prevent a crash. diff --git a/core/tauri-runtime-wry/Cargo.toml b/core/tauri-runtime-wry/Cargo.toml index f5601e432..98095a700 100644 --- a/core/tauri-runtime-wry/Cargo.toml +++ b/core/tauri-runtime-wry/Cargo.toml @@ -20,6 +20,7 @@ uuid = { version = "1", features = [ "v4" ] } rand = "0.8" raw-window-handle = "0.5" tracing = { version = "0.1", optional = true } +arboard = { version = "3", optional = true } [target."cfg(windows)".dependencies] webview2-com = "0.19.1" @@ -47,6 +48,6 @@ macos-private-api = [ ] objc-exception = [ "wry/objc-exception" ] global-shortcut = [ "tauri-runtime/global-shortcut" ] -clipboard = [ "tauri-runtime/clipboard" ] +clipboard = [ "tauri-runtime/clipboard", "arboard" ] linux-headers = [ "wry/linux-headers", "webkit2gtk/v2_36" ] tracing = [ "dep:tracing", "wry/tracing" ] diff --git a/core/tauri-runtime-wry/src/clipboard.rs b/core/tauri-runtime-wry/src/clipboard.rs index 428f1abb3..13f61c6f0 100644 --- a/core/tauri-runtime-wry/src/clipboard.rs +++ b/core/tauri-runtime-wry/src/clipboard.rs @@ -4,59 +4,36 @@ //! Clipboard implementation. -use crate::{getter, Context, Message}; - -use std::sync::{ - mpsc::{channel, Sender}, - Arc, Mutex, +use std::{ + fmt, + sync::{Arc, Mutex}, }; -use tauri_runtime::{ClipboardManager, Result, UserEvent}; -pub use wry::application::clipboard::Clipboard; +pub use arboard::Clipboard; +use tauri_runtime::{ClipboardManager, Result}; -#[derive(Debug, Clone)] -pub enum ClipboardMessage { - WriteText(String, Sender<()>), - ReadText(Sender>), +#[derive(Clone)] +pub struct ClipboardManagerWrapper { + pub clipboard: Arc>, } -#[derive(Debug, Clone)] -pub struct ClipboardManagerWrapper { - pub context: Context, +impl fmt::Debug for ClipboardManagerWrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ClipboardManagerWrapper").finish() + } } -// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`. -#[allow(clippy::non_send_fields_in_send_ty)] -unsafe impl Sync for ClipboardManagerWrapper {} - -impl ClipboardManager for ClipboardManagerWrapper { +impl ClipboardManager for ClipboardManagerWrapper { fn read_text(&self) -> Result> { - let (tx, rx) = channel(); - getter!(self, rx, Message::Clipboard(ClipboardMessage::ReadText(tx))) + Ok(self.clipboard.lock().unwrap().get_text().ok()) } fn write_text>(&mut self, text: V) -> Result<()> { - let (tx, rx) = channel(); - getter!( - self, - rx, - Message::Clipboard(ClipboardMessage::WriteText(text.into(), tx)) - )?; - Ok(()) - } -} - -pub fn handle_clipboard_message( - message: ClipboardMessage, - clipboard_manager: &Arc>, -) { - match message { - ClipboardMessage::WriteText(text, tx) => { - clipboard_manager.lock().unwrap().write_text(text); - tx.send(()).unwrap(); - } - ClipboardMessage::ReadText(tx) => tx - .send(clipboard_manager.lock().unwrap().read_text()) - .unwrap(), + self + .clipboard + .lock() + .unwrap() + .set_text(text.into()) + .map_err(|e| crate::Error::Clipboard(Box::new(e))) } } diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index 27f541838..e944917d4 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/core/tauri-runtime-wry/src/lib.rs @@ -175,8 +175,6 @@ pub(crate) fn send_user_message( webview_id_map: context.webview_id_map.clone(), #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager: context.main_thread.global_shortcut_manager.clone(), - #[cfg(feature = "clipboard")] - clipboard_manager: context.main_thread.clipboard_manager.clone(), windows: context.main_thread.windows.clone(), #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager: context.main_thread.system_tray_manager.clone(), @@ -276,8 +274,6 @@ pub struct DispatcherMainThreadContext { pub web_context: WebContextStore, #[cfg(all(desktop, feature = "global-shortcut"))] pub global_shortcut_manager: Rc>, - #[cfg(feature = "clipboard")] - pub clipboard_manager: Arc>, pub windows: Rc>>, #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager: SystemTrayManager, @@ -1213,8 +1209,6 @@ pub enum Message { ), #[cfg(all(desktop, feature = "global-shortcut"))] GlobalShortcut(GlobalShortcutMessage), - #[cfg(feature = "clipboard")] - Clipboard(ClipboardMessage), UserEvent(T), } @@ -1226,8 +1220,6 @@ impl Clone for Message { Self::Tray(i, m) => Self::Tray(*i, m.clone()), #[cfg(all(desktop, feature = "global-shortcut"))] Self::GlobalShortcut(m) => Self::GlobalShortcut(m.clone()), - #[cfg(feature = "clipboard")] - Self::Clipboard(m) => Self::Clipboard(m.clone()), Self::UserEvent(t) => Self::UserEvent(t.clone()), _ => unimplemented!(), } @@ -1829,7 +1821,7 @@ pub struct Wry { global_shortcut_manager_handle: GlobalShortcutManagerHandle, #[cfg(feature = "clipboard")] - clipboard_manager_handle: ClipboardManagerWrapper, + clipboard_manager_handle: ClipboardManagerWrapper, event_loop: EventLoop>, } @@ -1860,11 +1852,7 @@ impl fmt::Debug for Wry { ); #[cfg(feature = "clipboard")] - d.field( - "clipboard_manager", - &self.context.main_thread.clipboard_manager, - ) - .field("clipboard_manager_handle", &self.clipboard_manager_handle); + d.field("clipboard_manager_handle", &self.clipboard_manager_handle); d.finish() } @@ -1985,9 +1973,6 @@ impl Wry { #[cfg(all(desktop, feature = "global-shortcut"))] let global_shortcut_manager = Rc::new(Mutex::new(WryShortcutManager::new(&event_loop))); - #[cfg(feature = "clipboard")] - let clipboard_manager = Arc::new(Mutex::new(Clipboard::new())); - let windows = Rc::new(RefCell::new(HashMap::default())); let webview_id_map = WebviewIdStore::default(); @@ -2003,8 +1988,6 @@ impl Wry { web_context, #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager, - #[cfg(feature = "clipboard")] - clipboard_manager, windows, #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager, @@ -2023,7 +2006,7 @@ impl Wry { #[cfg(feature = "clipboard")] #[allow(clippy::redundant_clone)] let clipboard_manager_handle = ClipboardManagerWrapper { - context: context.clone(), + clipboard: Arc::new(Mutex::new(Clipboard::new().unwrap())), }; Ok(Self { @@ -2056,7 +2039,7 @@ impl Runtime for Wry { type GlobalShortcutManager = GlobalShortcutManagerHandle; #[cfg(feature = "clipboard")] - type ClipboardManager = ClipboardManagerWrapper; + type ClipboardManager = ClipboardManagerWrapper; #[cfg(all(desktop, feature = "system-tray"))] type TrayHandler = SystemTrayHandle; @@ -2221,8 +2204,6 @@ impl Runtime for Wry { #[cfg(all(desktop, feature = "global-shortcut"))] let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone(); - #[cfg(feature = "clipboard")] - let clipboard_manager = self.context.main_thread.clipboard_manager.clone(); let mut iteration = RunIteration::default(); let proxy = self.event_loop.create_proxy(); @@ -2249,8 +2230,6 @@ impl Runtime for Wry { global_shortcut_manager: global_shortcut_manager.clone(), #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager_handle: &global_shortcut_manager_handle, - #[cfg(feature = "clipboard")] - clipboard_manager: clipboard_manager.clone(), #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager: system_tray_manager.clone(), #[cfg(feature = "tracing")] @@ -2275,8 +2254,6 @@ impl Runtime for Wry { global_shortcut_manager: global_shortcut_manager.clone(), #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager_handle: &global_shortcut_manager_handle, - #[cfg(feature = "clipboard")] - clipboard_manager: clipboard_manager.clone(), #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager: system_tray_manager.clone(), #[cfg(feature = "tracing")] @@ -2306,9 +2283,6 @@ impl Runtime for Wry { #[cfg(all(desktop, feature = "global-shortcut"))] let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone(); - #[cfg(feature = "clipboard")] - let clipboard_manager = self.context.main_thread.clipboard_manager.clone(); - let proxy = self.event_loop.create_proxy(); self.event_loop.run(move |event, event_loop, control_flow| { @@ -2326,8 +2300,6 @@ impl Runtime for Wry { global_shortcut_manager: global_shortcut_manager.clone(), #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager_handle: &global_shortcut_manager_handle, - #[cfg(feature = "clipboard")] - clipboard_manager: clipboard_manager.clone(), #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager: system_tray_manager.clone(), #[cfg(feature = "tracing")] @@ -2351,8 +2323,6 @@ impl Runtime for Wry { global_shortcut_manager: global_shortcut_manager.clone(), #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager_handle: &global_shortcut_manager_handle, - #[cfg(feature = "clipboard")] - clipboard_manager: clipboard_manager.clone(), #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager: system_tray_manager.clone(), #[cfg(feature = "tracing")] @@ -2372,8 +2342,6 @@ pub struct EventLoopIterationContext<'a, T: UserEvent> { pub global_shortcut_manager: Rc>, #[cfg(all(desktop, feature = "global-shortcut"))] pub global_shortcut_manager_handle: &'a GlobalShortcutManagerHandle, - #[cfg(feature = "clipboard")] - pub clipboard_manager: Arc>, #[cfg(all(desktop, feature = "system-tray"))] pub system_tray_manager: SystemTrayManager, #[cfg(feature = "tracing")] @@ -2385,8 +2353,6 @@ struct UserMessageContext { webview_id_map: WebviewIdStore, #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager: Rc>, - #[cfg(feature = "clipboard")] - clipboard_manager: Arc>, #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager: SystemTrayManager, } @@ -2401,8 +2367,6 @@ fn handle_user_message( webview_id_map, #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager, - #[cfg(feature = "clipboard")] - clipboard_manager, windows, #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager, @@ -2805,8 +2769,6 @@ fn handle_user_message( Message::GlobalShortcut(message) => { handle_global_shortcut_message(message, &global_shortcut_manager) } - #[cfg(feature = "clipboard")] - Message::Clipboard(message) => handle_clipboard_message(message, &clipboard_manager), Message::UserEvent(_) => (), } @@ -2831,8 +2793,6 @@ fn handle_event_loop( global_shortcut_manager, #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager_handle, - #[cfg(feature = "clipboard")] - clipboard_manager, #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager, #[cfg(feature = "tracing")] @@ -3079,8 +3039,6 @@ fn handle_event_loop( webview_id_map, #[cfg(all(desktop, feature = "global-shortcut"))] global_shortcut_manager, - #[cfg(feature = "clipboard")] - clipboard_manager, windows, #[cfg(all(desktop, feature = "system-tray"))] system_tray_manager, diff --git a/core/tauri-runtime/src/lib.rs b/core/tauri-runtime/src/lib.rs index 0671fa253..9e961e863 100644 --- a/core/tauri-runtime/src/lib.rs +++ b/core/tauri-runtime/src/lib.rs @@ -252,6 +252,9 @@ pub enum Error { #[cfg(all(desktop, feature = "global-shortcut"))] #[error(transparent)] GlobalShortcut(Box), + #[cfg(all(desktop, feature = "clipboard"))] + #[error(transparent)] + Clipboard(Box), #[error("Invalid header name: {0}")] InvalidHeaderName(#[from] InvalidHeaderName), #[error("Invalid header value: {0}")] diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 813d8098d..e14d16c96 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -134,6 +134,25 @@ dependencies = [ "window-shadows", ] +[[package]] +name = "arboard" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafb29b107435aa276664c1db8954ac27a6e105cdad3c88287a199eb0e313c08" +dependencies = [ + "clipboard-win", + "core-graphics", + "image", + "log", + "objc", + "objc-foundation", + "objc_id", + "parking_lot", + "thiserror", + "winapi", + "x11rb", +] + [[package]] name = "ascii" version = "1.1.0" @@ -532,6 +551,17 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clipboard-win" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + [[package]] name = "cocoa" version = "0.24.1" @@ -939,6 +969,16 @@ dependencies = [ "libc", ] +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -1240,6 +1280,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -1700,6 +1750,8 @@ dependencies = [ "color_quant", "num-rational", "num-traits", + "png", + "tiff", ] [[package]] @@ -1835,6 +1887,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jpeg-decoder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" + [[package]] name = "js-sys" version = "0.3.64" @@ -3377,6 +3435,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + [[package]] name = "string_cache" version = "0.8.7" @@ -3555,7 +3619,7 @@ checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" [[package]] name = "tauri" -version = "1.5.2" +version = "1.5.3" dependencies = [ "anyhow", "base64 0.21.2", @@ -3660,7 +3724,7 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.1" +version = "1.4.2" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -3691,8 +3755,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.1" +version = "0.14.2" dependencies = [ + "arboard", "cocoa", "gtk", "percent-encoding", @@ -3709,7 +3774,7 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.5.0" +version = "1.5.1" dependencies = [ "aes-gcm", "brotli", @@ -3834,6 +3899,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiff" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "time" version = "0.3.22" @@ -4405,6 +4481,12 @@ dependencies = [ "windows-metadata", ] +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + [[package]] name = "win7-notifications" version = "0.4.0" @@ -4440,6 +4522,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4886,6 +4977,28 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "x11rb" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" +dependencies = [ + "gethostname", + "nix", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" +dependencies = [ + "nix", +] + [[package]] name = "xattr" version = "0.2.3"