Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for excluding macos clipboard items from history #159

Merged
merged 4 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,6 @@ impl<F: FnOnce()> Drop for ScopeGuard<F> {

/// Common trait for sealing platform extension traits.
pub(crate) mod private {
// This is currently unused on macOS, so silence the warning which appears
// since there's no extension traits making use of this trait sealing structure.
#[cfg_attr(target_vendor = "apple", allow(unreachable_pub, dead_code))]
pub trait Sealed {}

impl Sealed for crate::Get<'_> {}
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub use platform::{ClearExtLinux, GetExtLinux, LinuxClipboardKind, SetExtLinux};
#[cfg(windows)]
pub use platform::SetExtWindows;

#[cfg(target_os = "macos")]
pub use platform::SetExtApple;

/// The OS independent struct for accessing the clipboard.
///
/// Any number of `Clipboard` instances are allowed to exist at a single point in time. Note however
Expand Down
2 changes: 1 addition & 1 deletion src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ pub use windows::*;
#[cfg(target_os = "macos")]
mod osx;
#[cfg(target_os = "macos")]
pub(crate) use osx::*;
pub use osx::*;
46 changes: 43 additions & 3 deletions src/platform/osx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ the Apache 2.0 or the MIT license at the licensee's choice. The terms
and conditions of the chosen license apply to this file.
*/

use crate::common::Error;
#[cfg(feature = "image-data")]
use crate::common::ImageData;
use crate::common::{private, Error};
use objc2::{
msg_send_id,
rc::{autoreleasepool, Id},
runtime::ProtocolObject,
ClassType,
};
use objc2_app_kit::{NSPasteboard, NSPasteboardTypeHTML, NSPasteboardTypeString};
use objc2_foundation::{NSArray, NSString};
use objc2_foundation::{ns_string, NSArray, NSString};
use std::{
borrow::Cow,
panic::{RefUnwindSafe, UnwindSafe},
Expand Down Expand Up @@ -235,11 +235,12 @@ impl<'clipboard> Get<'clipboard> {

pub(crate) struct Set<'clipboard> {
clipboard: &'clipboard mut Clipboard,
exclude_from_history: bool,
}

impl<'clipboard> Set<'clipboard> {
pub(crate) fn new(clipboard: &'clipboard mut Clipboard) -> Self {
Self { clipboard }
Self { clipboard, exclude_from_history: false }
}

pub(crate) fn text(self, data: Cow<'_, str>) -> Result<(), Error> {
Expand All @@ -248,6 +249,9 @@ impl<'clipboard> Set<'clipboard> {
let string_array =
NSArray::from_vec(vec![ProtocolObject::from_id(NSString::from_str(&data))]);
let success = unsafe { self.clipboard.pasteboard.writeObjects(&string_array) };

add_clipboard_exclusions(self.clipboard, self.exclude_from_history);

if success {
Ok(())
} else {
Expand Down Expand Up @@ -279,6 +283,9 @@ impl<'clipboard> Set<'clipboard> {
};
}
}

add_clipboard_exclusions(self.clipboard, self.exclude_from_history);

if success {
Ok(())
} else {
Expand All @@ -296,6 +303,9 @@ impl<'clipboard> Set<'clipboard> {

let image_array = NSArray::from_vec(vec![ProtocolObject::from_id(image)]);
let success = unsafe { self.clipboard.pasteboard.writeObjects(&image_array) };

add_clipboard_exclusions(self.clipboard, self.exclude_from_history);

if success {
Ok(())
} else {
Expand All @@ -322,3 +332,33 @@ impl<'clipboard> Clear<'clipboard> {
Ok(())
}
}

fn add_clipboard_exclusions(clipboard: &mut Clipboard, exclude_from_history: bool) {
// On Mac there isn't an official standard for excluding data from clipboard, however
// there is an unofficial standard which is to set `org.nspasteboard.ConcealedType`.
//
// See http://nspasteboard.org/ for details about the community standard.
if exclude_from_history {
unsafe {
clipboard
.pasteboard
.setString_forType(ns_string!(""), ns_string!("org.nspasteboard.ConcealedType"));
}
}
}

/// Apple-specific extensions to the [`Set`](crate::Set) builder.
pub trait SetExtApple: private::Sealed {
/// Excludes the data which will be set on the clipboard from being added to
/// third party clipboard history software.
///
/// See http://nspasteboard.org/ for details about the community standard.
fn exclude_from_history(self) -> Self;
}

impl SetExtApple for crate::Set<'_> {
fn exclude_from_history(mut self) -> Self {
self.platform.exclude_from_history = true;
self
}
}