This commit is contained in:
s1korrrr 2026-04-20 20:53:13 +02:00 committed by GitHub
commit 3447739837
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 108 additions and 16 deletions

View file

@ -353,7 +353,10 @@ class FfiModel with ChangeNotifier {
} else if (name == 'cursor_position') {
await parent.target?.cursorModel.updateCursorPosition(evt, peerId);
} else if (name == 'clipboard') {
Clipboard.setData(ClipboardData(text: evt['content']));
final content = evt['content'];
if (content is String) {
await Clipboard.setData(ClipboardData(text: content));
}
} else if (name == 'permission') {
updatePermission(evt, peerId);
} else if (name == 'chat_client_mode') {

View file

@ -1431,12 +1431,7 @@ impl<T: InvokeUiSession> Remote<T> {
update_clipboard(vec![cb], ClipboardSide::Client);
#[cfg(target_os = "ios")]
{
let content = if cb.compress {
hbb_common::compress::decompress(&cb.content)
} else {
cb.content.into()
};
if let Ok(content) = String::from_utf8(content) {
if let Some(content) = crate::clipboard::decode_text_clipboard(&cb) {
self.handler.clipboard(content);
}
}
@ -1448,6 +1443,14 @@ impl<T: InvokeUiSession> Remote<T> {
if !self.handler.lc.read().unwrap().disable_clipboard.v {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
update_clipboard(_mcb.clipboards, ClipboardSide::Client);
#[cfg(target_os = "ios")]
{
if let Some(content) =
crate::clipboard::decode_multi_clipboards_text(&_mcb)
{
self.handler.clipboard(content);
}
}
#[cfg(target_os = "android")]
crate::clipboard::handle_msg_multi_clipboards(_mcb);
}

View file

@ -466,6 +466,35 @@ pub fn is_support_multi_clipboard(peer_version: &str, peer_platform: &str) -> bo
true
}
/// Returns the first plain-text clipboard entry from a multi-clipboard payload.
pub fn get_first_text_clipboard(multi_clipboards: &MultiClipboards) -> Option<Clipboard> {
multi_clipboards
.clipboards
.iter()
.find(|c| c.format.enum_value() == Ok(hbb_common::message_proto::ClipboardFormat::Text))
.cloned()
}
/// Decodes a plain-text clipboard entry, including RustDesk's compressed payloads.
pub fn decode_text_clipboard(clipboard: &Clipboard) -> Option<String> {
if clipboard.format.enum_value() != Ok(hbb_common::message_proto::ClipboardFormat::Text) {
return None;
}
let content = if clipboard.compress {
hbb_common::compress::decompress(&clipboard.content)
} else {
clipboard.content.to_vec()
};
String::from_utf8(content).ok()
}
/// Extracts and decodes the first plain-text entry from a multi-clipboard payload.
pub fn decode_multi_clipboards_text(multi_clipboards: &MultiClipboards) -> Option<String> {
get_first_text_clipboard(multi_clipboards)
.as_ref()
.and_then(decode_text_clipboard)
}
#[cfg(not(target_os = "android"))]
pub fn get_current_clipboard_msg(
peer_version: &str,
@ -689,15 +718,72 @@ mod proto {
}
// Find the first text clipboard and send it.
multi_clipboards
.clipboards
.iter()
.find(|c| c.format.enum_value() == Ok(ClipboardFormat::Text))
.map(|c| {
let mut msg = Message::new();
msg.set_clipboard(c.clone());
msg
})
crate::clipboard::get_first_text_clipboard(multi_clipboards).map(|clipboard| {
let mut msg = Message::new();
msg.set_clipboard(clipboard);
msg
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::Bytes;
fn make_clipboard(
format: hbb_common::message_proto::ClipboardFormat,
content: &[u8],
compress: bool,
) -> Clipboard {
let mut clipboard = Clipboard::new();
clipboard.format = format.into();
clipboard.content = if compress {
Bytes::from(hbb_common::compress::compress(content))
} else {
Bytes::copy_from_slice(content)
};
clipboard.compress = compress;
clipboard
}
#[test]
fn selects_first_text_clipboard() {
let multi = MultiClipboards {
clipboards: vec![
make_clipboard(
hbb_common::message_proto::ClipboardFormat::Html,
b"<b>hello</b>",
false,
),
make_clipboard(
hbb_common::message_proto::ClipboardFormat::Text,
b"hello",
false,
),
],
..Default::default()
};
let clipboard = get_first_text_clipboard(&multi).expect("text clipboard");
assert_eq!(decode_text_clipboard(&clipboard).as_deref(), Some("hello"));
}
#[test]
fn decodes_compressed_text_from_multi_clipboards() {
let multi = MultiClipboards {
clipboards: vec![make_clipboard(
hbb_common::message_proto::ClipboardFormat::Text,
b"hello from windows",
true,
)],
..Default::default()
};
assert_eq!(
decode_multi_clipboards_text(&multi).as_deref(),
Some("hello from windows")
);
}
}