mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-17 18:21:02 +03:00
Fix/arboard clipboard context timeout (#7217)
* Fix. Set custom timeout for arboard clipboard Signed-off-by: fufesou <shuanglongchen@yeah.net> * fix build Signed-off-by: fufesou <shuanglongchen@yeah.net> * Do not block tokio runtime Signed-off-by: fufesou <shuanglongchen@yeah.net> --------- Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
152
src/common.rs
152
src/common.rs
@@ -1,4 +1,5 @@
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
future::Future,
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
task::Poll,
|
||||
@@ -12,13 +13,6 @@ pub enum GrabState {
|
||||
Exit,
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
all(target_os = "linux", feature = "unix-file-copy-paste")
|
||||
)))]
|
||||
pub use arboard::Clipboard as ClipboardContext;
|
||||
|
||||
#[cfg(all(target_os = "linux", feature = "unix-file-copy-paste"))]
|
||||
static X11_CLIPBOARD: once_cell::sync::OnceCell<x11_clipboard::Clipboard> =
|
||||
once_cell::sync::OnceCell::new();
|
||||
@@ -290,14 +284,18 @@ pub fn create_clipboard_msg(content: String) -> Message {
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn check_clipboard(
|
||||
ctx: &mut ClipboardContext,
|
||||
ctx: &mut Option<ClipboardContext>,
|
||||
old: Option<&Arc<Mutex<String>>>,
|
||||
) -> Option<Message> {
|
||||
if ctx.is_none() {
|
||||
*ctx = ClipboardContext::new().ok();
|
||||
}
|
||||
let ctx2 = ctx.as_mut()?;
|
||||
let side = if old.is_none() { "host" } else { "client" };
|
||||
let old = if let Some(old) = old { old } else { &CONTENT };
|
||||
let content = {
|
||||
let _lock = ARBOARD_MTX.lock().unwrap();
|
||||
ctx.get_text()
|
||||
ctx2.get_text()
|
||||
};
|
||||
if let Ok(content) = content {
|
||||
if content.len() < 2_000_000 && !content.is_empty() {
|
||||
@@ -1374,9 +1372,7 @@ impl ThrottledInterval {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
Poll::Pending => {
|
||||
Poll::Pending
|
||||
},
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1388,6 +1384,78 @@ pub fn rustdesk_interval(i: Interval) -> ThrottledInterval {
|
||||
ThrottledInterval::new(i)
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
all(target_os = "linux", feature = "unix-file-copy-paste")
|
||||
)))]
|
||||
pub struct ClipboardContext(arboard::Clipboard);
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
all(target_os = "linux", feature = "unix-file-copy-paste")
|
||||
)))]
|
||||
impl ClipboardContext {
|
||||
#[inline]
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
pub fn new() -> ResultType<ClipboardContext> {
|
||||
Ok(ClipboardContext(arboard::Clipboard::new()?))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn new() -> ResultType<ClipboardContext> {
|
||||
let dur = arboard::Clipboard::get_x11_server_conn_timeout();
|
||||
let dur_bak = dur;
|
||||
let _restore_timeout_on_ret = SimpleCallOnReturn {
|
||||
b: true,
|
||||
f: Box::new(move || arboard::Clipboard::set_x11_server_conn_timeout(dur_bak)),
|
||||
};
|
||||
|
||||
for i in 1..4 {
|
||||
arboard::Clipboard::set_x11_server_conn_timeout(dur * i);
|
||||
match arboard::Clipboard::new() {
|
||||
Ok(c) => return Ok(ClipboardContext(c)),
|
||||
Err(arboard::Error::X11ServerConnTimeout) => continue,
|
||||
Err(err) => return Err(err.into()),
|
||||
}
|
||||
}
|
||||
bail!("Failed to create clipboard context, timeout");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
pub fn get_text(&mut self) -> ResultType<String> {
|
||||
Ok(self.0.get_text()?)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn get_text(&mut self) -> ResultType<String> {
|
||||
let dur = arboard::Clipboard::get_x11_server_conn_timeout();
|
||||
let dur_bak = dur;
|
||||
let _restore_timeout_on_ret = SimpleCallOnReturn {
|
||||
b: true,
|
||||
f: Box::new(move || arboard::Clipboard::set_x11_server_conn_timeout(dur_bak)),
|
||||
};
|
||||
|
||||
for i in 1..4 {
|
||||
arboard::Clipboard::set_x11_server_conn_timeout(dur * i);
|
||||
match self.0.get_text() {
|
||||
Ok(s) => return Ok(s),
|
||||
Err(arboard::Error::X11ServerConnTimeout) => continue,
|
||||
Err(err) => return Err(err.into()),
|
||||
}
|
||||
}
|
||||
bail!("Failed to get text, timeout");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_text<'a, T: Into<Cow<'a, str>>>(&mut self, text: T) -> ResultType<()> {
|
||||
self.0.set_text(text)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -1444,12 +1512,58 @@ mod tests {
|
||||
let dur = Duration::from_secs(1);
|
||||
|
||||
assert_eq!(dur * 2, Duration::from_secs(2));
|
||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.9), Duration::from_millis(900));
|
||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923), Duration::from_millis(923));
|
||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-3), Duration::from_micros(923));
|
||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-6), Duration::from_nanos(923));
|
||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-9), Duration::from_nanos(1));
|
||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.5 * 1e-9), Duration::from_nanos(1));
|
||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.499 * 1e-9), Duration::from_nanos(0));
|
||||
assert_eq!(
|
||||
Duration::from_secs_f64(dur.as_secs_f64() * 0.9),
|
||||
Duration::from_millis(900)
|
||||
);
|
||||
assert_eq!(
|
||||
Duration::from_secs_f64(dur.as_secs_f64() * 0.923),
|
||||
Duration::from_millis(923)
|
||||
);
|
||||
assert_eq!(
|
||||
Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-3),
|
||||
Duration::from_micros(923)
|
||||
);
|
||||
assert_eq!(
|
||||
Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-6),
|
||||
Duration::from_nanos(923)
|
||||
);
|
||||
assert_eq!(
|
||||
Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-9),
|
||||
Duration::from_nanos(1)
|
||||
);
|
||||
assert_eq!(
|
||||
Duration::from_secs_f64(dur.as_secs_f64() * 0.5 * 1e-9),
|
||||
Duration::from_nanos(1)
|
||||
);
|
||||
assert_eq!(
|
||||
Duration::from_secs_f64(dur.as_secs_f64() * 0.499 * 1e-9),
|
||||
Duration::from_nanos(0)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
all(target_os = "linux", feature = "unix-file-copy-paste")
|
||||
)))]
|
||||
async fn test_clipboard_context() {
|
||||
#[cfg(target_os = "linux")]
|
||||
let dur = {
|
||||
let dur = Duration::from_micros(500);
|
||||
arboard::Clipboard::set_x11_server_conn_timeout(dur);
|
||||
dur
|
||||
};
|
||||
|
||||
let _ctx = ClipboardContext::new();
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
assert_eq!(
|
||||
arboard::Clipboard::get_x11_server_conn_timeout(),
|
||||
dur,
|
||||
"Failed to restore x11 server conn timeout"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user