refactor!: remove clipboard impl (#797)

This commit is contained in:
Amr Bashir
2023-10-05 00:44:32 +03:00
committed by GitHub
parent 0101ed656b
commit 71d744cf90
13 changed files with 6 additions and 400 deletions

5
.changes/clipboard.md Normal file
View File

@@ -0,0 +1,5 @@
---
"tao": "minor"
---
**Breaking change**: Removed clipboard implementation. Use `arboard` crate instead.

View File

@@ -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<str>) {
self.0.write_text(s);
}
/// The content in the clipboard as plain text.
///
/// ## Platform-specific
///
/// - **Android / iOS:** Unsupported
pub fn read_text(&self) -> Option<String> {
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<u8>,
}
// 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<Vec<u8>>) -> Self {
let data = data.into();
ClipboardFormat { identifier, data }
}
}
impl From<String> 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()
}
}

View File

@@ -165,7 +165,6 @@ extern crate bitflags;
#[macro_use]
extern crate objc;
pub mod clipboard;
pub mod dpi;
#[macro_use]
pub mod error;

View File

@@ -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<str>) {}
pub(crate) fn read_text(&self) -> Option<String> {
None
}
}

View File

@@ -28,8 +28,6 @@ use std::{
time::{Duration, Instant},
};
mod clipboard;
pub use clipboard::Clipboard;
pub mod ndk_glue;
use ndk_glue::{Event, Rect};

View File

@@ -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<str>) {}
pub(crate) fn read_text(&self) -> Option<String> {
None
}
}

View File

@@ -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},

View File

@@ -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<str>) {
let string = string.as_ref().to_string();
let display = gdk::Display::default().unwrap();
let clipboard = gtk::Clipboard::default(&display).unwrap();
let targets: Vec<TargetEntry> = 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<String> {
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
}
}

View File

@@ -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;

View File

@@ -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<str>) {
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<String> {
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())
}
}
}
}

View File

@@ -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},

View File

@@ -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<str>) {
let s = s.as_ref();
let format: ClipboardFormat = s.into();
self.put_formats(&[format])
}
pub(crate) fn read_text(&self) -> Option<String> {
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<u32> {
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<u32> {
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<u16> = s.encode_wide().chain(Some(0)).collect();
let handle = GlobalAlloc(GMEM_MOVEABLE, wstr.len() * std::mem::size_of::<u16>()).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::<u8>()).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<V>(f: impl FnOnce() -> V) -> Option<V> {
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"),
];

View File

@@ -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;