Explorar o código

refactor(core): add clipboard Cargo feature, enhancing binary size (#3957)

Lucas Fernandes Nogueira %!s(int64=3) %!d(string=hai) anos
pai
achega
24e4ff208e

+ 7 - 0
.changes/clipboard-feature.md

@@ -0,0 +1,7 @@
+---
+"tauri": patch
+"tauri-runtime": minor
+"tauri-runtime-wry": minor
+---
+
+**Breaking change::* Added the `clipboard` Cargo feature.

+ 1 - 0
core/tauri-runtime-wry/Cargo.toml

@@ -42,3 +42,4 @@ objc-exception = [ "wry/objc-exception" ]
 gtk-tray = [ "wry/gtk-tray" ]
 ayatana-tray = [ "wry/ayatana-tray" ]
 global-shortcut = [ "tauri-runtime/global-shortcut" ]
+clipboard = [ "tauri-runtime/clipboard" ]

+ 62 - 0
core/tauri-runtime-wry/src/clipboard.rs

@@ -0,0 +1,62 @@
+// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-License-Identifier: MIT
+
+//! Clipboard implementation.
+
+use crate::{getter, Context, Message};
+
+use std::sync::{
+  mpsc::{channel, Sender},
+  Arc, Mutex,
+};
+
+use tauri_runtime::{ClipboardManager, Result, UserEvent};
+pub use wry::application::clipboard::Clipboard;
+
+#[derive(Debug, Clone)]
+pub enum ClipboardMessage {
+  WriteText(String, Sender<()>),
+  ReadText(Sender<Option<String>>),
+}
+
+#[derive(Debug, Clone)]
+pub struct ClipboardManagerWrapper<T: UserEvent> {
+  pub context: Context<T>,
+}
+
+// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
+#[allow(clippy::non_send_fields_in_send_ty)]
+unsafe impl<T: UserEvent> Sync for ClipboardManagerWrapper<T> {}
+
+impl<T: UserEvent> ClipboardManager for ClipboardManagerWrapper<T> {
+  fn read_text(&self) -> Result<Option<String>> {
+    let (tx, rx) = channel();
+    getter!(self, rx, Message::Clipboard(ClipboardMessage::ReadText(tx)))
+  }
+
+  fn write_text<V: Into<String>>(&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<Mutex<Clipboard>>,
+) {
+  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(),
+  }
+}

+ 54 - 49
core/tauri-runtime-wry/src/lib.rs

@@ -16,8 +16,8 @@ use tauri_runtime::{
     dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
     CursorIcon, DetachedWindow, FileDropEvent, JsEventListenerKey, PendingWindow, WindowEvent,
   },
-  ClipboardManager, Dispatch, Error, EventLoopProxy, ExitRequestedEventAction, Result, RunEvent,
-  RunIteration, Runtime, RuntimeHandle, UserAttentionType, UserEvent, WindowIcon,
+  Dispatch, Error, EventLoopProxy, ExitRequestedEventAction, Result, RunEvent, RunIteration,
+  Runtime, RuntimeHandle, UserAttentionType, UserEvent, WindowIcon,
 };
 
 use tauri_runtime::window::MenuEvent;
@@ -43,7 +43,6 @@ use tauri_utils::{config::WindowConfig, Theme};
 use uuid::Uuid;
 use wry::{
   application::{
-    clipboard::Clipboard,
     dpi::{
       LogicalPosition as WryLogicalPosition, LogicalSize as WryLogicalSize,
       PhysicalPosition as WryPhysicalPosition, PhysicalSize as WryPhysicalSize,
@@ -111,6 +110,11 @@ mod global_shortcut;
 #[cfg(feature = "global-shortcut")]
 use global_shortcut::*;
 
+#[cfg(feature = "clipboard")]
+mod clipboard;
+#[cfg(feature = "clipboard")]
+use clipboard::*;
+
 type WebContextStore = Arc<Mutex<HashMap<Option<PathBuf>, WebContext>>>;
 // window
 type WindowEventHandler = Box<dyn Fn(&WindowEvent) + Send>;
@@ -138,7 +142,7 @@ impl WebviewIdStore {
 macro_rules! getter {
   ($self: ident, $rx: expr, $message: expr) => {{
     crate::send_user_message(&$self.context, $message)?;
-    $rx.recv().map_err(|_| Error::FailedToReceiveMessage)
+    $rx.recv().map_err(|_| crate::Error::FailedToReceiveMessage)
   }};
 }
 
@@ -159,6 +163,7 @@ fn send_user_message<T: UserEvent>(context: &Context<T>, message: Message<T>) ->
         window_event_listeners: &context.window_event_listeners,
         #[cfg(feature = "global-shortcut")]
         global_shortcut_manager: context.main_thread.global_shortcut_manager.clone(),
+        #[cfg(feature = "clipboard")]
         clipboard_manager: context.main_thread.clipboard_manager.clone(),
         menu_event_listeners: &context.menu_event_listeners,
         windows: context.main_thread.windows.clone(),
@@ -240,6 +245,7 @@ struct DispatcherMainThreadContext<T: UserEvent> {
   web_context: WebContextStore,
   #[cfg(feature = "global-shortcut")]
   global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
+  #[cfg(feature = "clipboard")]
   clipboard_manager: Arc<Mutex<Clipboard>>,
   windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
   #[cfg(feature = "system-tray")]
@@ -464,32 +470,6 @@ impl From<NativeImage> for NativeImageWrapper {
   }
 }
 
-#[derive(Debug, Clone)]
-pub struct ClipboardManagerWrapper<T: UserEvent> {
-  context: Context<T>,
-}
-
-// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
-#[allow(clippy::non_send_fields_in_send_ty)]
-unsafe impl<T: UserEvent> Sync for ClipboardManagerWrapper<T> {}
-
-impl<T: UserEvent> ClipboardManager for ClipboardManagerWrapper<T> {
-  fn read_text(&self) -> Result<Option<String>> {
-    let (tx, rx) = channel();
-    getter!(self, rx, Message::Clipboard(ClipboardMessage::ReadText(tx)))
-  }
-
-  fn write_text<V: Into<String>>(&mut self, text: V) -> Result<()> {
-    let (tx, rx) = channel();
-    getter!(
-      self,
-      rx,
-      Message::Clipboard(ClipboardMessage::WriteText(text.into(), tx))
-    )?;
-    Ok(())
-  }
-}
-
 /// Wrapper around a [`wry::application::window::Icon`] that can be created from an [`WindowIcon`].
 pub struct WryIcon(WryWindowIcon);
 
@@ -1078,12 +1058,6 @@ pub enum TrayMessage {
   Close,
 }
 
-#[derive(Debug, Clone)]
-pub enum ClipboardMessage {
-  WriteText(String, Sender<()>),
-  ReadText(Sender<Option<String>>),
-}
-
 pub type CreateWebviewClosure<T> = Box<
   dyn FnOnce(&EventLoopWindowTarget<Message<T>>, &WebContextStore) -> Result<WindowWrapper> + Send,
 >;
@@ -1102,6 +1076,7 @@ pub enum Message<T: 'static> {
   ),
   #[cfg(feature = "global-shortcut")]
   GlobalShortcut(GlobalShortcutMessage),
+  #[cfg(feature = "clipboard")]
   Clipboard(ClipboardMessage),
   UserEvent(T),
 }
@@ -1115,6 +1090,7 @@ impl<T: UserEvent> Clone for Message<T> {
       Self::Tray(m) => Self::Tray(m.clone()),
       #[cfg(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!(),
@@ -1590,12 +1566,17 @@ impl<T: UserEvent> EventLoopProxy<T> for EventProxy<T> {
 /// A Tauri [`Runtime`] wrapper around wry.
 pub struct Wry<T: UserEvent> {
   main_thread_id: ThreadId,
+
   #[cfg(feature = "global-shortcut")]
   global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
   #[cfg(feature = "global-shortcut")]
   global_shortcut_manager_handle: GlobalShortcutManagerHandle<T>,
+
+  #[cfg(feature = "clipboard")]
   clipboard_manager: Arc<Mutex<Clipboard>>,
+  #[cfg(feature = "clipboard")]
   clipboard_manager_handle: ClipboardManagerWrapper<T>,
+
   event_loop: EventLoop<Message<T>>,
   windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
   webview_id_map: WebviewIdStore,
@@ -1610,19 +1591,24 @@ impl<T: UserEvent> fmt::Debug for Wry<T> {
   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     let mut d = f.debug_struct("Wry");
     d.field("main_thread_id", &self.main_thread_id)
-      .field("clipboard_manager", &self.clipboard_manager)
-      .field("clipboard_manager_handle", &self.clipboard_manager_handle)
       .field("event_loop", &self.event_loop)
       .field("windows", &self.windows)
       .field("web_context", &self.web_context);
+
     #[cfg(feature = "system-tray")]
     d.field("tray_context", &self.tray_context);
+
     #[cfg(feature = "global-shortcut")]
     d.field("global_shortcut_manager", &self.global_shortcut_manager)
       .field(
         "global_shortcut_manager_handle",
         &self.global_shortcut_manager_handle,
       );
+
+    #[cfg(feature = "clipboard")]
+    d.field("clipboard_manager", &self.clipboard_manager)
+      .field("clipboard_manager_handle", &self.clipboard_manager_handle);
+
     d.finish()
   }
 }
@@ -1703,14 +1689,15 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
 
 impl<T: UserEvent> Wry<T> {
   fn init(event_loop: EventLoop<Message<T>>) -> Result<Self> {
-    let proxy = event_loop.create_proxy();
     let main_thread_id = current_thread().id();
     let web_context = WebContextStore::default();
 
     #[cfg(feature = "global-shortcut")]
     let global_shortcut_manager = Arc::new(Mutex::new(WryShortcutManager::new(&event_loop)));
 
+    #[cfg(feature = "clipboard")]
     let clipboard_manager = Arc::new(Mutex::new(Clipboard::new()));
+
     let windows = Arc::new(Mutex::new(HashMap::default()));
     let webview_id_map = WebviewIdStore::default();
     let window_event_listeners = WindowEventListeners::default();
@@ -1719,10 +1706,11 @@ impl<T: UserEvent> Wry<T> {
     #[cfg(feature = "system-tray")]
     let tray_context = TrayContext::default();
 
+    #[allow(unused_variables)]
     let event_loop_context = Context {
       webview_id_map: webview_id_map.clone(),
       main_thread_id,
-      proxy,
+      proxy: event_loop.create_proxy(),
       window_event_listeners: window_event_listeners.clone(),
       menu_event_listeners: menu_event_listeners.clone(),
       main_thread: DispatcherMainThreadContext {
@@ -1730,6 +1718,7 @@ impl<T: UserEvent> Wry<T> {
         web_context: web_context.clone(),
         #[cfg(feature = "global-shortcut")]
         global_shortcut_manager: global_shortcut_manager.clone(),
+        #[cfg(feature = "clipboard")]
         clipboard_manager: clipboard_manager.clone(),
         windows: windows.clone(),
         #[cfg(feature = "system-tray")]
@@ -1740,6 +1729,7 @@ impl<T: UserEvent> Wry<T> {
     #[cfg(feature = "global-shortcut")]
     let global_shortcut_listeners = GlobalShortcutListeners::default();
 
+    #[cfg(feature = "clipboard")]
     #[allow(clippy::redundant_clone)]
     let clipboard_manager_handle = ClipboardManagerWrapper {
       context: event_loop_context.clone(),
@@ -1747,6 +1737,7 @@ impl<T: UserEvent> Wry<T> {
 
     Ok(Self {
       main_thread_id,
+
       #[cfg(feature = "global-shortcut")]
       global_shortcut_manager,
       #[cfg(feature = "global-shortcut")]
@@ -1755,8 +1746,12 @@ impl<T: UserEvent> Wry<T> {
         shortcuts: Default::default(),
         listeners: global_shortcut_listeners,
       },
+
+      #[cfg(feature = "clipboard")]
       clipboard_manager,
+      #[cfg(feature = "clipboard")]
       clipboard_manager_handle,
+
       event_loop,
       windows,
       webview_id_map,
@@ -1772,11 +1767,16 @@ impl<T: UserEvent> Wry<T> {
 impl<T: UserEvent> Runtime<T> for Wry<T> {
   type Dispatcher = WryDispatcher<T>;
   type Handle = WryHandle<T>;
+
   #[cfg(feature = "global-shortcut")]
   type GlobalShortcutManager = GlobalShortcutManagerHandle<T>;
+
+  #[cfg(feature = "clipboard")]
   type ClipboardManager = ClipboardManagerWrapper<T>;
+
   #[cfg(feature = "system-tray")]
   type TrayHandler = SystemTrayHandle<T>;
+
   type EventLoopProxy = EventProxy<T>;
 
   fn new() -> Result<Self> {
@@ -1811,6 +1811,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
           web_context: self.web_context.clone(),
           #[cfg(feature = "global-shortcut")]
           global_shortcut_manager: self.global_shortcut_manager.clone(),
+          #[cfg(feature = "clipboard")]
           clipboard_manager: self.clipboard_manager.clone(),
           windows: self.windows.clone(),
           #[cfg(feature = "system-tray")]
@@ -1825,6 +1826,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
     self.global_shortcut_manager_handle.clone()
   }
 
+  #[cfg(feature = "clipboard")]
   fn clipboard_manager(&self) -> Self::ClipboardManager {
     self.clipboard_manager_handle.clone()
   }
@@ -1847,6 +1849,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
         web_context: self.web_context.clone(),
         #[cfg(feature = "global-shortcut")]
         global_shortcut_manager: self.global_shortcut_manager.clone(),
+        #[cfg(feature = "clipboard")]
         clipboard_manager: self.clipboard_manager.clone(),
         windows: self.windows.clone(),
         #[cfg(feature = "system-tray")]
@@ -1953,6 +1956,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
     #[cfg(feature = "global-shortcut")]
     let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone();
 
+    #[cfg(feature = "clipboard")]
     let clipboard_manager = self.clipboard_manager.clone();
     let mut iteration = RunIteration::default();
 
@@ -1977,6 +1981,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
             global_shortcut_manager: global_shortcut_manager.clone(),
             #[cfg(feature = "global-shortcut")]
             global_shortcut_manager_handle: &global_shortcut_manager_handle,
+            #[cfg(feature = "clipboard")]
             clipboard_manager: clipboard_manager.clone(),
             menu_event_listeners: &menu_event_listeners,
             #[cfg(feature = "system-tray")]
@@ -2004,6 +2009,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
     #[cfg(feature = "global-shortcut")]
     let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone();
 
+    #[cfg(feature = "clipboard")]
     let clipboard_manager = self.clipboard_manager.clone();
 
     self.event_loop.run(move |event, event_loop, control_flow| {
@@ -2020,6 +2026,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
           global_shortcut_manager: global_shortcut_manager.clone(),
           #[cfg(feature = "global-shortcut")]
           global_shortcut_manager_handle: &global_shortcut_manager_handle,
+          #[cfg(feature = "clipboard")]
           clipboard_manager: clipboard_manager.clone(),
           menu_event_listeners: &menu_event_listeners,
           #[cfg(feature = "system-tray")]
@@ -2040,6 +2047,7 @@ pub struct EventLoopIterationContext<'a, T: UserEvent> {
   global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
   #[cfg(feature = "global-shortcut")]
   global_shortcut_manager_handle: &'a GlobalShortcutManagerHandle<T>,
+  #[cfg(feature = "clipboard")]
   clipboard_manager: Arc<Mutex<Clipboard>>,
   menu_event_listeners: &'a MenuEventListeners,
   #[cfg(feature = "system-tray")]
@@ -2051,6 +2059,7 @@ struct UserMessageContext<'a> {
   window_event_listeners: &'a WindowEventListeners,
   #[cfg(feature = "global-shortcut")]
   global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
+  #[cfg(feature = "clipboard")]
   clipboard_manager: Arc<Mutex<Clipboard>>,
   menu_event_listeners: &'a MenuEventListeners,
   windows: Arc<Mutex<HashMap<WebviewId, WindowWrapper>>>,
@@ -2070,6 +2079,7 @@ fn handle_user_message<T: UserEvent>(
     menu_event_listeners,
     #[cfg(feature = "global-shortcut")]
     global_shortcut_manager,
+    #[cfg(feature = "clipboard")]
     clipboard_manager,
     windows,
     #[cfg(feature = "system-tray")]
@@ -2374,15 +2384,8 @@ fn handle_user_message<T: UserEvent>(
     Message::GlobalShortcut(message) => {
       handle_global_shortcut_message(message, &global_shortcut_manager)
     }
-    Message::Clipboard(message) => 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(),
-    },
+    #[cfg(feature = "clipboard")]
+    Message::Clipboard(message) => handle_clipboard_message(message, &clipboard_manager),
     Message::UserEvent(_) => (),
   }
 
@@ -2408,6 +2411,7 @@ fn handle_event_loop<T: UserEvent>(
     global_shortcut_manager,
     #[cfg(feature = "global-shortcut")]
     global_shortcut_manager_handle,
+    #[cfg(feature = "clipboard")]
     clipboard_manager,
     menu_event_listeners,
     #[cfg(feature = "system-tray")]
@@ -2615,6 +2619,7 @@ fn handle_event_loop<T: UserEvent>(
             window_event_listeners,
             #[cfg(feature = "global-shortcut")]
             global_shortcut_manager,
+            #[cfg(feature = "clipboard")]
             clipboard_manager,
             menu_event_listeners,
             windows,

+ 1 - 0
core/tauri-runtime/Cargo.toml

@@ -47,3 +47,4 @@ devtools = [ ]
 system-tray = [ ]
 macos-private-api = [ ]
 global-shortcut = [ ]
+clipboard = [ ]

+ 3 - 0
core/tauri-runtime/src/lib.rs

@@ -311,6 +311,7 @@ pub trait GlobalShortcutManager: Debug + Clone + Send + Sync {
 }
 
 /// Clipboard manager.
+#[cfg(feature = "clipboard")]
 pub trait ClipboardManager: Debug + Clone + Send + Sync {
   /// Writes the text into the clipboard as plain text.
   fn write_text<T: Into<String>>(&mut self, text: T) -> Result<()>;
@@ -332,6 +333,7 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
   #[cfg(feature = "global-shortcut")]
   type GlobalShortcutManager: GlobalShortcutManager;
   /// The clipboard manager type.
+  #[cfg(feature = "clipboard")]
   type ClipboardManager: ClipboardManager;
   /// The tray handler type.
   #[cfg(feature = "system-tray")]
@@ -358,6 +360,7 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
   fn global_shortcut_manager(&self) -> Self::GlobalShortcutManager;
 
   /// Gets the clipboard manager.
+  #[cfg(feature = "clipboard")]
   fn clipboard_manager(&self) -> Self::ClipboardManager;
 
   /// Create a new webview window.

+ 3 - 2
core/tauri/Cargo.toml

@@ -142,6 +142,7 @@ fs-extract-api = [ "zip" ]
 reqwest-client = [ "reqwest", "bytes" ]
 process-command-api = [ "shared_child", "os_pipe" ]
 global-shortcut = [ "tauri-runtime/global-shortcut", "tauri-runtime-wry/global-shortcut" ]
+clipboard = [ "tauri-runtime/clipboard", "tauri-runtime-wry/clipboard" ]
 dialog = [ "rfd" ]
 notification = [ "notify-rust" ]
 cli = [ "clap" ]
@@ -168,8 +169,8 @@ api-all = [
   "window-all"
 ]
 clipboard-all = [ "clipboard-write-text", "clipboard-read-text" ]
-clipboard-read-text = [ ]
-clipboard-write-text = [ ]
+clipboard-read-text = [ "clipboard" ]
+clipboard-write-text = [ "clipboard" ]
 dialog-all = [ "dialog-open", "dialog-save", "dialog-message", "dialog-ask" ]
 dialog-ask = [ "dialog" ]
 dialog-confirm = [ "dialog" ]

+ 8 - 0
core/tauri/src/app.rs

@@ -289,6 +289,7 @@ pub struct AppHandle<R: Runtime> {
   manager: WindowManager<R>,
   #[cfg(feature = "global-shortcut")]
   global_shortcut_manager: R::GlobalShortcutManager,
+  #[cfg(feature = "clipboard")]
   clipboard_manager: R::ClipboardManager,
   #[cfg(feature = "system-tray")]
   tray_handle: Option<tray::SystemTrayHandle<R>>,
@@ -340,6 +341,7 @@ impl<R: Runtime> Clone for AppHandle<R> {
       manager: self.manager.clone(),
       #[cfg(feature = "global-shortcut")]
       global_shortcut_manager: self.global_shortcut_manager.clone(),
+      #[cfg(feature = "clipboard")]
       clipboard_manager: self.clipboard_manager.clone(),
       #[cfg(feature = "system-tray")]
       tray_handle: self.tray_handle.clone(),
@@ -446,6 +448,7 @@ pub struct App<R: Runtime> {
   manager: WindowManager<R>,
   #[cfg(feature = "global-shortcut")]
   global_shortcut_manager: R::GlobalShortcutManager,
+  #[cfg(feature = "clipboard")]
   clipboard_manager: R::ClipboardManager,
   #[cfg(feature = "system-tray")]
   tray_handle: Option<tray::SystemTrayHandle<R>>,
@@ -520,6 +523,8 @@ macro_rules! shared_app_impl {
       }
 
       /// Gets a copy of the clipboard manager instance.
+      #[cfg(feature = "clipboard")]
+      #[cfg_attr(doc_cfg, doc(cfg(feature = "clipboard")))]
       pub fn clipboard_manager(&self) -> R::ClipboardManager {
         self.clipboard_manager.clone()
       }
@@ -1242,6 +1247,7 @@ impl<R: Runtime> Builder<R> {
     #[cfg(feature = "global-shortcut")]
     let global_shortcut_manager = runtime.global_shortcut_manager();
 
+    #[cfg(feature = "clipboard")]
     let clipboard_manager = runtime.clipboard_manager();
 
     let mut app = App {
@@ -1249,6 +1255,7 @@ impl<R: Runtime> Builder<R> {
       manager: manager.clone(),
       #[cfg(feature = "global-shortcut")]
       global_shortcut_manager: global_shortcut_manager.clone(),
+      #[cfg(feature = "clipboard")]
       clipboard_manager: clipboard_manager.clone(),
       #[cfg(feature = "system-tray")]
       tray_handle: None,
@@ -1257,6 +1264,7 @@ impl<R: Runtime> Builder<R> {
         manager,
         #[cfg(feature = "global-shortcut")]
         global_shortcut_manager,
+        #[cfg(feature = "clipboard")]
         clipboard_manager,
         #[cfg(feature = "system-tray")]
         tray_handle: None,

+ 2 - 1
core/tauri/src/lib.rs

@@ -24,6 +24,7 @@
 //! - **reqwest-client**: Uses `reqwest` as HTTP client on the `http` APIs. Improves performance, but increases the bundle size.
 //! - **process-command-api**: Enables the [`api::process::Command`] APIs.
 //! - **global-shortcut**: Enables the global shortcut APIs.
+//! - **clipboard**: Enables the clipboard APIs.
 //! - **process-relaunch-dangerous-allow-symlink-macos**: Allows the [`api::process::current_binary`] function to allow symlinks on macOS (this is dangerous, see the Security section in the documentation website).
 //! - **dialog**: Enables the [`api::dialog`] module.
 //! - **notification**: Enables the [`api::notification`] module.
@@ -233,7 +234,7 @@ pub use {
       dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
       CursorIcon, FileDropEvent,
     },
-    ClipboardManager, RunIteration, TrayIcon, UserAttentionType,
+    RunIteration, TrayIcon, UserAttentionType,
   },
   self::state::{State, StateManager},
   self::utils::{

+ 9 - 3
core/tauri/src/test/mock_runtime.rs

@@ -12,8 +12,8 @@ use tauri_runtime::{
     dpi::{PhysicalPosition, PhysicalSize, Position, Size},
     CursorIcon, DetachedWindow, MenuEvent, PendingWindow, WindowEvent,
   },
-  ClipboardManager, Dispatch, EventLoopProxy, Result, RunEvent, Runtime, RuntimeHandle,
-  UserAttentionType, UserEvent, WindowIcon,
+  Dispatch, EventLoopProxy, Result, RunEvent, Runtime, RuntimeHandle, UserAttentionType, UserEvent,
+  WindowIcon,
 };
 #[cfg(feature = "system-tray")]
 use tauri_runtime::{
@@ -132,12 +132,14 @@ impl tauri_runtime::GlobalShortcutManager for MockGlobalShortcutManager {
   }
 }
 
+#[cfg(feature = "clipboard")]
 #[derive(Debug, Clone)]
 pub struct MockClipboardManager {
   context: RuntimeContext,
 }
 
-impl ClipboardManager for MockClipboardManager {
+#[cfg(feature = "clipboard")]
+impl tauri_runtime::ClipboardManager for MockClipboardManager {
   fn write_text<T: Into<String>>(&mut self, text: T) -> Result<()> {
     self.context.clipboard.lock().unwrap().replace(text.into());
     Ok(())
@@ -547,6 +549,7 @@ pub struct MockRuntime {
   pub context: RuntimeContext,
   #[cfg(feature = "global-shortcut")]
   global_shortcut_manager: MockGlobalShortcutManager,
+  #[cfg(feature = "clipboard")]
   clipboard_manager: MockClipboardManager,
   #[cfg(feature = "system-tray")]
   tray_handler: MockTrayHandler,
@@ -563,6 +566,7 @@ impl MockRuntime {
       global_shortcut_manager: MockGlobalShortcutManager {
         context: context.clone(),
       },
+      #[cfg(feature = "clipboard")]
       clipboard_manager: MockClipboardManager {
         context: context.clone(),
       },
@@ -580,6 +584,7 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
   type Handle = MockRuntimeHandle;
   #[cfg(feature = "global-shortcut")]
   type GlobalShortcutManager = MockGlobalShortcutManager;
+  #[cfg(feature = "clipboard")]
   type ClipboardManager = MockClipboardManager;
   #[cfg(feature = "system-tray")]
   type TrayHandler = MockTrayHandler;
@@ -609,6 +614,7 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
     self.global_shortcut_manager.clone()
   }
 
+  #[cfg(feature = "clipboard")]
   fn clipboard_manager(&self) -> Self::ClipboardManager {
     self.clipboard_manager.clone()
   }