Skip to content

Commit

Permalink
Add support for explicit clipboard monitor excluding on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
complexspaces committed Nov 20, 2023
1 parent f801e67 commit b2b0809
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## Unreleased
- Add support for `ExcludeClipboardContentFromMonitorProcessing` on Windows platforms.

## 3.2.1 on 2023-28-11

### Fixed
Expand Down
50 changes: 46 additions & 4 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,13 +493,19 @@ impl<'clipboard> Get<'clipboard> {

pub(crate) struct Set<'clipboard> {
clipboard: Result<OpenClipboard<'clipboard>, Error>,
exclude_from_monitoring: bool,
exclude_from_cloud: bool,
exclude_from_history: bool,
}

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

pub(crate) fn text(self, data: Cow<'_, str>) -> Result<(), Error> {
Expand All @@ -509,7 +515,12 @@ impl<'clipboard> Set<'clipboard> {
description: "Could not place the specified text to the clipboard".into(),
})?;

add_clipboard_exclusions(open_clipboard, self.exclude_from_cloud, self.exclude_from_history)
add_clipboard_exclusions(
open_clipboard,
self.exclude_from_monitoring,
self.exclude_from_cloud,
self.exclude_from_history,
)
}

pub(crate) fn html(self, html: Cow<'_, str>, alt: Option<Cow<'_, str>>) -> Result<(), Error> {
Expand All @@ -529,7 +540,12 @@ impl<'clipboard> Set<'clipboard> {
.map_err(|e| Error::Unknown { description: e.to_string() })?;
}

add_clipboard_exclusions(open_clipboard, self.exclude_from_cloud, self.exclude_from_history)
add_clipboard_exclusions(
open_clipboard,
self.exclude_from_monitoring,
self.exclude_from_cloud,
self.exclude_from_history,
)
}

#[cfg(feature = "image-data")]
Expand All @@ -548,6 +564,7 @@ impl<'clipboard> Set<'clipboard> {

fn add_clipboard_exclusions(
_open_clipboard: OpenClipboard<'_>,
exclude_from_monitoring: bool,
exclude_from_cloud: bool,
exclude_from_history: bool,
) -> Result<(), Error> {
Expand All @@ -556,10 +573,24 @@ fn add_clipboard_exclusions(
/// See https://docs.microsoft.com/en-us/windows/win32/dataxchg/clipboard-formats#cloud-clipboard-and-clipboard-history-formats
const CLIPBOARD_EXCLUSION_DATA: &[u8] = &0u32.to_ne_bytes();

// Clipboard exclusions are applied retroactively to the item that is currently in the clipboard.
// Clipboard exclusions are applied retroactively (we still have the clipboard lock) to the item that is currently in the clipboard.
// See the MS docs on `CLIPBOARD_EXCLUSION_DATA` for specifics. Once the item is added to the clipboard,
// tell Windows to remove it from cloud syncing and history.

if exclude_from_monitoring {
if let Some(format) =
clipboard_win::register_format("ExcludeClipboardContentFromMonitorProcessing")
{
// The documentation states "place any data on the clipboard in this format to prevent...", and using the zero bytes
// like the others for consistency works.
clipboard_win::raw::set_without_clear(format.get(), CLIPBOARD_EXCLUSION_DATA).map_err(
|_| Error::Unknown {
description: "Failed to exclude data from clipboard monitoring".into(),
},
)?;
}
}

if exclude_from_cloud {
if let Some(format) = clipboard_win::register_format("CanUploadToCloudClipboard") {
// We believe that it would be a logic error if this call failed, since we've validated the format is supported,
Expand Down Expand Up @@ -589,6 +620,12 @@ fn add_clipboard_exclusions(

/// Windows-specific extensions to the [`Set`](crate::Set) builder.
pub trait SetExtWindows: private::Sealed {
/// Exclude the data which will be set on the clipboard from being processed
/// at all, either in the local clipboard history or getting uploaded to the cloud.
///
/// If this is set, it is not recommended to call [exclude_from_cloud](SetExtWindows::exclude_from_cloud) or [exclude_from_history](SetExtWindows::exclude_from_history).
fn exclude_from_monitoring(self) -> Self;

/// Excludes the data which will be set on the clipboard from being uploaded to
/// the Windows 10/11 [cloud clipboard].
///
Expand All @@ -603,6 +640,11 @@ pub trait SetExtWindows: private::Sealed {
}

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

fn exclude_from_cloud(mut self) -> Self {
self.platform.exclude_from_cloud = true;
self
Expand Down

0 comments on commit b2b0809

Please sign in to comment.