Files
SimpleRemoter/macos/ClipboardHandler.h

187 lines
6.0 KiB
Objective-C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#import <Cocoa/Cocoa.h>
#include <string>
#include <vector>
// macOS 剪贴板操作封装
// 使用 NSPasteboard API 实现
class ClipboardHandler
{
public:
// 检查剪贴板功能是否可用 (macOS 总是可用)
static bool IsAvailable()
{
return true;
}
// 获取剪贴板中的文件列表
// 返回文件的完整路径列表UTF-8失败返回空列表
static std::vector<std::string> GetFiles()
{
std::vector<std::string> files;
@autoreleasepool {
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
// 方法1: 尝试获取文件 URL 列表 (macOS 10.13+)
NSArray<NSURL*>* urls = [pasteboard readObjectsForClasses:@[[NSURL class]]
options:@{NSPasteboardURLReadingFileURLsOnlyKey: @YES}];
if (urls && urls.count > 0) {
for (NSURL* url in urls) {
if (url.isFileURL) {
NSString* path = url.path;
if (path) {
files.push_back([path UTF8String]);
}
}
}
return files;
}
// 方法2: 兼容旧版 API (NSFilenamesPboardType)
NSArray* filenames = [pasteboard propertyListForType:NSFilenamesPboardType];
if (filenames && [filenames isKindOfClass:[NSArray class]]) {
for (NSString* path in filenames) {
if ([path isKindOfClass:[NSString class]]) {
files.push_back([path UTF8String]);
}
}
}
}
return files;
}
// 获取剪贴板文本
// 返回 UTF-8 编码的文本,失败返回空字符串
static std::string GetText()
{
@autoreleasepool {
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
NSString* text = [pasteboard stringForType:NSPasteboardTypeString];
if (text) {
return [text UTF8String];
}
}
return "";
}
// 设置剪贴板文本
// text: UTF-8 编码的文本
// 返回是否成功
static bool SetText(const std::string& text)
{
if (text.empty()) return true;
@autoreleasepool {
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
[pasteboard clearContents];
NSString* nsText = [NSString stringWithUTF8String:text.c_str()];
if (nsText) {
return [pasteboard setString:nsText forType:NSPasteboardTypeString];
}
}
return false;
}
// 设置剪贴板文本(从原始字节)
// data: 文本数据(可能是 GBK 或 UTF-8
// len: 数据长度
static bool SetTextRaw(const char* data, size_t len)
{
if (!data || len == 0) return true;
// 服务端发来的文本可能是 GBK 编码,尝试转换为 UTF-8
std::string text = ConvertToUtf8(data, len);
return SetText(text);
}
// 设置剪贴板文件列表
// files: UTF-8 编码的文件路径列表
// 返回是否成功
static bool SetFiles(const std::vector<std::string>& files)
{
if (files.empty()) return true;
@autoreleasepool {
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
[pasteboard clearContents];
NSMutableArray<NSURL*>* urls = [NSMutableArray arrayWithCapacity:files.size()];
for (const auto& path : files) {
NSString* nsPath = [NSString stringWithUTF8String:path.c_str()];
if (nsPath) {
NSURL* url = [NSURL fileURLWithPath:nsPath];
if (url) {
[urls addObject:url];
}
}
}
if (urls.count > 0) {
return [pasteboard writeObjects:urls];
}
}
return false;
}
private:
// 检查是否是有效的 UTF-8 序列
static bool IsValidUtf8(const char* data, size_t len)
{
const unsigned char* bytes = (const unsigned char*)data;
size_t i = 0;
while (i < len) {
if (bytes[i] <= 0x7F) {
// ASCII
i++;
} else if ((bytes[i] & 0xE0) == 0xC0) {
// 2-byte sequence
if (i + 1 >= len || (bytes[i + 1] & 0xC0) != 0x80) return false;
i += 2;
} else if ((bytes[i] & 0xF0) == 0xE0) {
// 3-byte sequence
if (i + 2 >= len || (bytes[i + 1] & 0xC0) != 0x80 || (bytes[i + 2] & 0xC0) != 0x80) return false;
i += 3;
} else if ((bytes[i] & 0xF8) == 0xF0) {
// 4-byte sequence
if (i + 3 >= len || (bytes[i + 1] & 0xC0) != 0x80 ||
(bytes[i + 2] & 0xC0) != 0x80 || (bytes[i + 3] & 0xC0) != 0x80) return false;
i += 4;
} else {
return false;
}
}
return true;
}
// 尝试将 GBK 转换为 UTF-8
// 如果已经是 UTF-8直接返回
static std::string ConvertToUtf8(const char* data, size_t len)
{
// 检查是否已经是有效的 UTF-8
if (IsValidUtf8(data, len)) {
return std::string(data, len);
}
// 使用 NSString 进行编码转换 (GBK = CFStringEncodingGB_18030_2000)
@autoreleasepool {
// 尝试 GBK (GB18030) 编码
NSStringEncoding gbkEncoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSString* str = [[NSString alloc] initWithBytes:data length:len encoding:gbkEncoding];
if (str) {
const char* utf8 = [str UTF8String];
if (utf8) {
return std::string(utf8);
}
}
}
// 转换失败,返回原始数据
return std::string(data, len);
}
};