82 lines
2.8 KiB
Rust
82 lines
2.8 KiB
Rust
use super::*;
|
|
unsafe extern "C" {
|
|
fn PasteboardSynchronize(pasteboard: Object) -> u32;
|
|
fn PasteboardGetItemIdentifier(pasteboard: Object, index: isize, item: *mut usize) -> i32;
|
|
fn PasteboardCopyItemFlavorData(
|
|
pasteboard: Object,
|
|
item: usize,
|
|
flavor: Object,
|
|
data: *mut Object,
|
|
) -> i32;
|
|
fn CFDataGetBytePtr(data: Object) -> *const u8;
|
|
fn CFDataGetLength(data: Object) -> isize;
|
|
}
|
|
#[test]
|
|
fn native_publication_preserves_plain_utf8_bytes_on_an_isolated_pasteboard() {
|
|
// A private pasteboard leaves the user's clipboard untouched.
|
|
let _pool = unsafe { AutoreleasePool(objc_autoreleasePoolPush()) };
|
|
let name = unsafe {
|
|
Owned::new(CFStringCreateWithCString(
|
|
ptr::null(),
|
|
c"vamp-native-clipboard-regression".as_ptr(),
|
|
0x0800_0100,
|
|
))
|
|
.unwrap()
|
|
};
|
|
let board = unsafe {
|
|
let mut board = ptr::null();
|
|
check(PasteboardCreate(name.0, &mut board)).unwrap();
|
|
Owned::new(board).unwrap()
|
|
};
|
|
let reader = unsafe {
|
|
let send: unsafe extern "C" fn(Object, Object, Object) -> Object =
|
|
std::mem::transmute(objc_msgSend as unsafe extern "C" fn());
|
|
send(
|
|
objc_getClass(c"NSPasteboard".as_ptr()),
|
|
sel_registerName(c"pasteboardWithName:".as_ptr()),
|
|
name.0,
|
|
)
|
|
};
|
|
for text in [
|
|
"",
|
|
"é e\u{301} 👨💻\n\0tail",
|
|
"{\\rtf1 plain text}",
|
|
"%!PS-Adobe-3.0\nplain",
|
|
] {
|
|
write_to(name.0, text).unwrap();
|
|
assert_eq!(read_from(reader).unwrap(), text);
|
|
unsafe {
|
|
PasteboardSynchronize(board.0);
|
|
let mut item = 0;
|
|
check(PasteboardGetItemIdentifier(board.0, 1, &mut item)).unwrap();
|
|
let flavor = Owned::new(CFStringCreateWithCString(
|
|
ptr::null(),
|
|
c"public.utf8-plain-text".as_ptr(),
|
|
0x0800_0100,
|
|
))
|
|
.unwrap();
|
|
let mut data = ptr::null();
|
|
check(PasteboardCopyItemFlavorData(
|
|
board.0, item, flavor.0, &mut data,
|
|
))
|
|
.unwrap();
|
|
let data = Owned::new(data).unwrap();
|
|
let length = CFDataGetLength(data.0) as usize;
|
|
let bytes = if length == 0 {
|
|
&[]
|
|
} else {
|
|
std::slice::from_raw_parts(CFDataGetBytePtr(data.0), length)
|
|
};
|
|
assert_eq!(bytes, text.as_bytes());
|
|
}
|
|
}
|
|
let maximum = "x".repeat(super::super::MAX_CLIPBOARD_BYTES);
|
|
write_to(name.0, &maximum).unwrap();
|
|
assert_eq!(read_from(reader).unwrap(), maximum);
|
|
write_to(name.0, &(maximum + "x")).unwrap();
|
|
assert_eq!(
|
|
read_from(reader).unwrap_err(),
|
|
"System clipboard text exceeds 4 MiB"
|
|
);
|
|
}
|