diff --git a/.changes/clipboard.md b/.changes/clipboard.md new file mode 100644 index 000000000..80fd9accf --- /dev/null +++ b/.changes/clipboard.md @@ -0,0 +1,5 @@ +--- +"tao": "minor" +--- + +**Breaking change**: Removed clipboard implementation. Use `arboard` crate instead. diff --git a/src/clipboard.rs b/src/clipboard.rs deleted file mode 100644 index e45e9fdc5..000000000 --- a/src/clipboard.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2014-2021 The winit contributors -// Copyright 2021-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 - -//! The `Clipboard` struct and associated types. -//! -//! ## Platform-specific -//! -//! - **Android / iOS:** Unsupported -//! -//! ```rust,ignore -//! let mut cliboard = Clipboard::new(); -//! cliboard.write_text("This is injected from tao!!!") -//! let content = cliboard.read_text(); -//! ``` -//! - -use crate::platform_impl::Clipboard as ClipboardPlatform; - -#[derive(Debug, Clone, Default)] -/// Object that allows you to access the `Clipboard` instance. -pub struct Clipboard(ClipboardPlatform); - -impl Clipboard { - /// Creates a new `Clipboard` instance. - /// - /// ## Platform-specific - /// - /// - **Android / iOS:** Unsupported - pub fn new() -> Self { - Self::default() - } - - /// Writes the text into the clipboard as plain text. - /// - /// ## Platform-specific - /// - /// - **Android / iOS:** Unsupported - pub fn write_text(&mut self, s: impl AsRef) { - self.0.write_text(s); - } - - /// The content in the clipboard as plain text. - /// - /// ## Platform-specific - /// - /// - **Android / iOS:** Unsupported - pub fn read_text(&self) -> Option { - self.0.read_text() - } -} - -/// Identifier of a clipboard format. -pub(crate) type FormatId = &'static str; - -/// Object that allows you to access the `ClipboardFormat`. -#[derive(Debug, Clone)] -#[allow(dead_code)] -pub(crate) struct ClipboardFormat { - pub(crate) identifier: FormatId, - pub(crate) data: Vec, -} - -// todo add more formats -impl ClipboardFormat { - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub const TEXT: &'static str = "public.utf8-plain-text"; - #[cfg(any(target_os = "windows", target_os = "android"))] - pub const TEXT: &'static str = "text/plain"; - #[cfg(any( - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd" - ))] - pub const TEXT: &'static str = "UTF8_STRING"; -} - -impl ClipboardFormat { - pub fn new(identifier: FormatId, data: impl Into>) -> Self { - let data = data.into(); - ClipboardFormat { identifier, data } - } -} - -impl From for ClipboardFormat { - fn from(src: String) -> ClipboardFormat { - let data = src.into_bytes(); - ClipboardFormat::new(ClipboardFormat::TEXT, data) - } -} - -impl From<&str> for ClipboardFormat { - fn from(src: &str) -> ClipboardFormat { - src.to_string().into() - } -} diff --git a/src/lib.rs b/src/lib.rs index 9da97b748..dfa702d3d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,7 +165,6 @@ extern crate bitflags; #[macro_use] extern crate objc; -pub mod clipboard; pub mod dpi; #[macro_use] pub mod error; diff --git a/src/platform_impl/android/clipboard.rs b/src/platform_impl/android/clipboard.rs deleted file mode 100644 index 6dde41922..000000000 --- a/src/platform_impl/android/clipboard.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2014-2021 The winit contributors -// Copyright 2021-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 - -#[derive(Debug, Clone, Default)] -pub struct Clipboard; -impl Clipboard { - pub(crate) fn write_text(&mut self, _s: impl AsRef) {} - pub(crate) fn read_text(&self) -> Option { - None - } -} diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 9e264ee22..6bd64dc67 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -28,8 +28,6 @@ use std::{ time::{Duration, Instant}, }; -mod clipboard; -pub use clipboard::Clipboard; pub mod ndk_glue; use ndk_glue::{Event, Rect}; diff --git a/src/platform_impl/ios/clipboard.rs b/src/platform_impl/ios/clipboard.rs deleted file mode 100644 index 6dde41922..000000000 --- a/src/platform_impl/ios/clipboard.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2014-2021 The winit contributors -// Copyright 2021-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 - -#[derive(Debug, Clone, Default)] -pub struct Clipboard; -impl Clipboard { - pub(crate) fn write_text(&mut self, _s: impl AsRef) {} - pub(crate) fn read_text(&self) -> Option { - None - } -} diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index 93820ca59..1e5565a2b 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -74,7 +74,6 @@ macro_rules! assert_main_thread { } mod app_state; -mod clipboard; mod event_loop; mod ffi; mod keycode; @@ -86,7 +85,6 @@ use std::fmt; pub(crate) use self::event_loop::PlatformSpecificEventLoopAttributes; pub use self::{ - clipboard::Clipboard, event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}, keycode::{keycode_from_scancode, keycode_to_scancode}, monitor::{MonitorHandle, VideoMode}, diff --git a/src/platform_impl/linux/clipboard.rs b/src/platform_impl/linux/clipboard.rs deleted file mode 100644 index f55e0865b..000000000 --- a/src/platform_impl/linux/clipboard.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2014-2021 The winit contributors -// Copyright 2021-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 - -use gdk::Atom; -use gtk::{TargetEntry, TargetFlags}; - -#[derive(Debug, Clone, Default)] -pub struct Clipboard; - -const CLIPBOARD_TARGETS: [&str; 5] = [ - "UTF8_STRING", - "TEXT", - "STRING", - "text/plain;charset=utf-8", - "text/plain", -]; - -impl Clipboard { - pub(crate) fn write_text(&mut self, string: impl AsRef) { - let string = string.as_ref().to_string(); - - let display = gdk::Display::default().unwrap(); - let clipboard = gtk::Clipboard::default(&display).unwrap(); - - let targets: Vec = CLIPBOARD_TARGETS - .iter() - .enumerate() - .map(|(i, target)| TargetEntry::new(target, TargetFlags::all(), i as u32)) - .collect(); - - clipboard.set_with_data(&targets, move |_, selection, _| { - selection.set(&selection.target(), 8i32, string.as_bytes()); - }); - } - - pub(crate) fn read_text(&self) -> Option { - let display = gdk::Display::default().unwrap(); - let clipboard = gtk::Clipboard::default(&display).unwrap(); - - for target in &CLIPBOARD_TARGETS { - let atom = Atom::intern(target); - if let Some(selection) = clipboard.wait_for_contents(&atom) { - return String::from_utf8(selection.data()).ok(); - } - } - - None - } -} diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 850c74b14..da3b2e386 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -10,7 +10,6 @@ target_os = "openbsd" ))] -mod clipboard; mod device; mod event_loop; mod icon; @@ -23,10 +22,7 @@ mod window; pub mod taskbar; pub mod x11; -pub use self::{ - clipboard::Clipboard, - keycode::{keycode_from_scancode, keycode_to_scancode}, -}; +pub use self::keycode::{keycode_from_scancode, keycode_to_scancode}; pub(crate) use event_loop::PlatformSpecificEventLoopAttributes; pub use event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}; pub use icon::PlatformIcon; diff --git a/src/platform_impl/macos/clipboard.rs b/src/platform_impl/macos/clipboard.rs deleted file mode 100644 index 967b91edb..000000000 --- a/src/platform_impl/macos/clipboard.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014-2021 The winit contributors -// Copyright 2021-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 - -use cocoa::{ - appkit::NSPasteboardTypeString, - base::{id, nil, BOOL, YES}, - foundation::{NSInteger, NSString}, -}; -use objc::{class, msg_send, sel, sel_impl}; - -#[derive(Debug, Clone, Default)] -pub struct Clipboard; - -impl Clipboard { - pub(crate) fn write_text(&mut self, s: impl AsRef) { - let s = s.as_ref(); - unsafe { - let nsstring = NSString::alloc(nil).init_str(s); - let pasteboard: id = msg_send![class!(NSPasteboard), generalPasteboard]; - let _: NSInteger = msg_send![pasteboard, clearContents]; - let result: BOOL = msg_send![pasteboard, setString: nsstring forType: NSPasteboardTypeString]; - if result != YES { - #[cfg(debug_assertions)] - println!("failed to set clipboard"); - } - } - } - - pub(crate) fn read_text(&self) -> Option { - unsafe { - let pasteboard: id = msg_send![class!(NSPasteboard), generalPasteboard]; - let contents: id = msg_send![pasteboard, stringForType: NSPasteboardTypeString]; - if contents.is_null() { - None - } else { - let slice = std::slice::from_raw_parts(contents.UTF8String() as *const _, contents.len()); - let result = std::str::from_utf8_unchecked(slice); - Some(result.to_string()) - } - } - } -} diff --git a/src/platform_impl/macos/mod.rs b/src/platform_impl/macos/mod.rs index 2637324a6..5eada728d 100644 --- a/src/platform_impl/macos/mod.rs +++ b/src/platform_impl/macos/mod.rs @@ -7,7 +7,6 @@ mod app; mod app_delegate; mod app_state; -mod clipboard; mod event; mod event_loop; mod ffi; @@ -26,7 +25,6 @@ use std::{fmt, ops::Deref, sync::Arc}; pub(crate) use self::event_loop::PlatformSpecificEventLoopAttributes; pub use self::{ app_delegate::{get_aux_state_mut, AuxDelegateState}, - clipboard::Clipboard, event::KeyEventExtra, event_loop::{EventLoop, EventLoopWindowTarget, Proxy as EventLoopProxy}, keycode::{keycode_from_scancode, keycode_to_scancode}, diff --git a/src/platform_impl/windows/clipboard.rs b/src/platform_impl/windows/clipboard.rs deleted file mode 100644 index 7b1295211..000000000 --- a/src/platform_impl/windows/clipboard.rs +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2014-2021 The winit contributors -// Copyright 2021-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 - -use super::util; -use crate::clipboard::{ClipboardFormat, FormatId}; -use std::{ffi::OsStr, os::windows::ffi::OsStrExt, ptr}; -use windows::{ - core::{PCWSTR, PWSTR}, - Win32::{ - Foundation::{HANDLE, HGLOBAL, HWND}, - System::{ - DataExchange::{ - CloseClipboard, EmptyClipboard, GetClipboardData, OpenClipboard, RegisterClipboardFormatW, - SetClipboardData, - }, - Memory::{GlobalAlloc, GlobalLock, GlobalUnlock, GMEM_MOVEABLE}, - Ole::CF_UNICODETEXT, - }, - }, -}; - -#[derive(Debug, Clone, Default)] -pub struct Clipboard; - -impl Clipboard { - pub fn write_text(&mut self, s: impl AsRef) { - let s = s.as_ref(); - let format: ClipboardFormat = s.into(); - self.put_formats(&[format]) - } - - pub(crate) fn read_text(&self) -> Option { - with_clipboard(|| unsafe { - let handle = GetClipboardData(CF_UNICODETEXT.0 as _).unwrap_or_default(); - if handle.is_invalid() { - None - } else { - let unic_str = PWSTR::from_raw(GlobalLock(HGLOBAL(handle.0)) as *mut _); - let mut len = 0; - while *unic_str.0.offset(len) != 0 { - len += 1; - } - let utf16_slice = std::slice::from_raw_parts(unic_str.0, len as usize); - let result = String::from_utf16(utf16_slice); - if let Ok(result) = result { - GlobalUnlock(HGLOBAL(handle.0)); - return Some(result); - } - - None - } - }) - .flatten() - } - - pub(crate) fn put_formats(&mut self, formats: &[ClipboardFormat]) { - with_clipboard(|| unsafe { - EmptyClipboard(); - - for format in formats { - let handle = make_handle(format); - let format_id = match get_format_id(format.identifier) { - Some(id) => id, - None => { - #[cfg(debug_assertions)] - println!("failed to register clipboard format {}", &format.identifier); - continue; - } - }; - if let Err(err) = SetClipboardData(format_id, handle) { - #[cfg(debug_assertions)] - println!( - "failed to set clipboard for fmt {}, error: {}", - &format.identifier, err - ); - } - } - }); - } -} - -fn get_format_id(format: FormatId) -> Option { - if let Some((id, _)) = STANDARD_FORMATS.iter().find(|(_, s)| s == &format) { - return Some(*id); - } - match format { - ClipboardFormat::TEXT => Some(CF_UNICODETEXT.0 as _), - other => register_identifier(other), - } -} - -fn register_identifier(ident: &str) -> Option { - unsafe { - let clipboard_format = util::encode_wide(ident); - - let pb_format = RegisterClipboardFormatW(PCWSTR::from_raw(clipboard_format.as_ptr())); - if pb_format == 0 { - #[cfg(debug_assertions)] - println!( - "failed to register clipboard format '{}'; error {}.", - ident, - windows::core::Error::from_win32().code().0 - ); - return None; - } - Some(pb_format) - } -} - -unsafe fn make_handle(format: &ClipboardFormat) -> HANDLE { - HANDLE(if format.identifier == ClipboardFormat::TEXT { - let s: &OsStr = std::str::from_utf8_unchecked(&format.data).as_ref(); - let wstr: Vec = s.encode_wide().chain(Some(0)).collect(); - let handle = GlobalAlloc(GMEM_MOVEABLE, wstr.len() * std::mem::size_of::()).unwrap(); - let locked = GlobalLock(HGLOBAL(handle.0)) as *mut _; - ptr::copy_nonoverlapping(wstr.as_ptr(), locked, wstr.len()); - GlobalUnlock(handle); - handle.0 - } else { - let handle = GlobalAlloc(GMEM_MOVEABLE, format.data.len() * std::mem::size_of::()).unwrap(); - let locked = GlobalLock(HGLOBAL(handle.0)) as *mut _; - ptr::copy_nonoverlapping(format.data.as_ptr(), locked, format.data.len()); - GlobalUnlock(HGLOBAL(handle.0)); - handle.0 - }) -} - -fn with_clipboard(f: impl FnOnce() -> V) -> Option { - unsafe { - if !OpenClipboard(HWND::default()).as_bool() { - return None; - } - - let result = f(); - - CloseClipboard(); - - Some(result) - } -} - -// https://docs.microsoft.com/en-ca/windows/win32/dataxchg/standard-clipboard-formats -static STANDARD_FORMATS: &[(u32, &str)] = &[ - (1, "CF_TEXT"), - (2, "CF_BITMAP"), - (3, "CF_METAFILEPICT"), - (4, "CF_SYLK"), - (5, "CF_DIF"), - (6, "CF_TIFF"), - (7, "CF_OEMTEXT"), - (8, "CF_DIB"), - (9, "CF_PALETTE"), - (10, "CF_PENDATA"), - (11, "CF_RIFF"), - (12, "CF_WAVE"), - (13, "CF_UNICODETEXT"), - (14, "CF_ENHMETAFILE"), - (15, "CF_HDROP"), - (16, "CF_LOCALE"), - (17, "CF_DIBV5"), - (0x0080, "CF_OWNERDISPLAY"), - (0x0081, "CF_DSPTEXT"), - (0x0082, "CF_DSPBITMAP"), - (0x0083, "CF_DSPMETAFILEPICT"), - (0x008E, "CF_DSPENHMETAFILE"), - (0x0200, "CF_PRIVATEFIRST"), - (0x02FF, "CF_PRIVATELAST"), - (0x0300, "CF_GDIOBJFIRST"), - (0x03FF, "CF_GDIOBJLAST"), -]; diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index b2b7c500a..695f4672f 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -10,7 +10,6 @@ use windows::Win32::{ }; pub(crate) use self::{ - clipboard::Clipboard, event_loop::{ EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, }, @@ -138,7 +137,6 @@ impl WindowId { #[macro_use] mod util; -mod clipboard; mod dark_mode; mod dpi; mod drop_handler;