mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-11 23:31:03 +03:00
Fix/clipboard retry if is occupied (#9293)
* fix: clipboard, retry if is occupied Signed-off-by: fufesou <linlong1266@gmail.com> * fix: clipboard service, hold runtime to cm ipc Signed-off-by: fufesou <linlong1266@gmail.com> * update arboard Signed-off-by: fufesou <linlong1266@gmail.com> * refact: log Signed-off-by: fufesou <linlong1266@gmail.com> * fix: get formats, return only not Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -11,6 +11,8 @@ use std::{
|
||||
sync::mpsc::{channel, RecvTimeoutError, Sender},
|
||||
time::Duration,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
struct Handler {
|
||||
sp: EmptyExtraFieldService,
|
||||
@@ -18,6 +20,8 @@ struct Handler {
|
||||
tx_cb_result: Sender<CallbackResult>,
|
||||
#[cfg(target_os = "windows")]
|
||||
stream: Option<ipc::ConnectionTmpl<parity_tokio_ipc::ConnectionClient>>,
|
||||
#[cfg(target_os = "windows")]
|
||||
rt: Option<Runtime>,
|
||||
}
|
||||
|
||||
pub fn new() -> GenericService {
|
||||
@@ -34,6 +38,8 @@ fn run(sp: EmptyExtraFieldService) -> ResultType<()> {
|
||||
tx_cb_result,
|
||||
#[cfg(target_os = "windows")]
|
||||
stream: None,
|
||||
#[cfg(target_os = "windows")]
|
||||
rt: None,
|
||||
};
|
||||
|
||||
let (tx_start_res, rx_start_res) = channel();
|
||||
@@ -129,29 +135,41 @@ impl Handler {
|
||||
// 1. the clipboard is not used frequently.
|
||||
// 2. the clipboard handle is sync and will not block the main thread.
|
||||
#[cfg(windows)]
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn read_clipboard_from_cm_ipc(&mut self) -> ResultType<Vec<ClipboardNonFile>> {
|
||||
fn read_clipboard_from_cm_ipc(&mut self) -> ResultType<Vec<ClipboardNonFile>> {
|
||||
if self.rt.is_none() {
|
||||
self.rt = Some(Runtime::new()?);
|
||||
}
|
||||
let Some(rt) = &self.rt else {
|
||||
// unreachable!
|
||||
bail!("failed to get tokio runtime");
|
||||
};
|
||||
let mut is_sent = false;
|
||||
if let Some(stream) = &mut self.stream {
|
||||
// If previous stream is still alive, reuse it.
|
||||
// If the previous stream is dead, `is_sent` will trigger reconnect.
|
||||
is_sent = stream.send(&Data::ClipboardNonFile(None)).await.is_ok();
|
||||
is_sent = match rt.block_on(stream.send(&Data::ClipboardNonFile(None))) {
|
||||
Ok(_) => true,
|
||||
Err(e) => {
|
||||
log::debug!("Failed to send to cm: {}", e);
|
||||
false
|
||||
}
|
||||
};
|
||||
}
|
||||
if !is_sent {
|
||||
let mut stream = crate::ipc::connect(100, "_cm").await?;
|
||||
stream.send(&Data::ClipboardNonFile(None)).await?;
|
||||
let mut stream = rt.block_on(crate::ipc::connect(100, "_cm"))?;
|
||||
rt.block_on(stream.send(&Data::ClipboardNonFile(None)))?;
|
||||
self.stream = Some(stream);
|
||||
}
|
||||
|
||||
if let Some(stream) = &mut self.stream {
|
||||
loop {
|
||||
match stream.next_timeout(800).await? {
|
||||
match rt.block_on(stream.next_timeout(800))? {
|
||||
Some(Data::ClipboardNonFile(Some((err, mut contents)))) => {
|
||||
if !err.is_empty() {
|
||||
bail!("{}", err);
|
||||
} else {
|
||||
if contents.iter().any(|c| c.next_raw) {
|
||||
match timeout(1000, stream.next_raw()).await {
|
||||
match rt.block_on(timeout(1000, stream.next_raw())) {
|
||||
Ok(Ok(mut data)) => {
|
||||
for c in &mut contents {
|
||||
if c.next_raw {
|
||||
@@ -168,7 +186,7 @@ impl Handler {
|
||||
Err(e) => {
|
||||
// Reconnect to avoid the next raw data remaining in the buffer.
|
||||
self.stream = None;
|
||||
log::debug!("failed to get raw clipboard data: {}", e);
|
||||
log::debug!("Failed to get raw clipboard data: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user