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:
parent
c690d5e940
commit
25afdda2b2
70
Cargo.lock
generated
70
Cargo.lock
generated
@ -271,12 +271,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arboard"
|
name = "arboard"
|
||||||
version = "3.3.0"
|
version = "3.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/fufesou/arboard?branch=feat/x11_set_conn_timeout#956b5f8693b4fc7fddd7b8cafbe1111a892b34b1"
|
||||||
checksum = "aafb29b107435aa276664c1db8954ac27a6e105cdad3c88287a199eb0e313c08"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clipboard-win",
|
"clipboard-win",
|
||||||
"core-graphics 0.22.3",
|
"core-graphics 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"image",
|
"image",
|
||||||
"log",
|
"log",
|
||||||
"objc",
|
"objc",
|
||||||
@ -284,9 +283,9 @@ dependencies = [
|
|||||||
"objc_id",
|
"objc_id",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"winapi 0.3.9",
|
"windows-sys 0.48.0",
|
||||||
"wl-clipboard-rs",
|
"wl-clipboard-rs",
|
||||||
"x11rb",
|
"x11rb 0.13.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -997,18 +996,16 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"utf16string",
|
"utf16string",
|
||||||
"x11-clipboard",
|
"x11-clipboard",
|
||||||
"x11rb",
|
"x11rb 0.12.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clipboard-win"
|
name = "clipboard-win"
|
||||||
version = "4.5.0"
|
version = "5.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362"
|
checksum = "3ec832972fefb8cf9313b45a0d1945e29c9c251f1d4c6eafc5fe2124c02d2e81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"error-code",
|
"error-code",
|
||||||
"str-buf",
|
|
||||||
"winapi 0.3.9",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1731,7 +1728,7 @@ version = "0.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
|
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libloading 0.8.1",
|
"libloading 0.7.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1980,13 +1977,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "error-code"
|
name = "error-code"
|
||||||
version = "2.3.1"
|
version = "3.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21"
|
checksum = "281e452d3bad4005426416cdba5ccfd4f5c1280e10099e21db27f7c1c28347fc"
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"str-buf",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "evdev"
|
name = "evdev"
|
||||||
@ -2467,6 +2460,16 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gethostname"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
@ -5501,7 +5504,7 @@ dependencies = [
|
|||||||
"winres",
|
"winres",
|
||||||
"wol-rs",
|
"wol-rs",
|
||||||
"x11-clipboard",
|
"x11-clipboard",
|
||||||
"x11rb",
|
"x11rb 0.12.0",
|
||||||
"zip",
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -5999,12 +6002,6 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "str-buf"
|
|
||||||
version = "1.0.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strength_reduce"
|
name = "strength_reduce"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
@ -7785,7 +7782,7 @@ name = "x11-clipboard"
|
|||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
source = "git+https://github.com/clslaid/x11-clipboard?branch=feat/store-batch#5fc2e73bc01ada3681159b34cf3ea8f0d14cd904"
|
source = "git+https://github.com/clslaid/x11-clipboard?branch=feat/store-batch#5fc2e73bc01ada3681159b34cf3ea8f0d14cd904"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"x11rb",
|
"x11rb 0.12.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -7805,11 +7802,22 @@ version = "0.12.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a"
|
checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gethostname",
|
"gethostname 0.3.0",
|
||||||
"nix 0.26.4",
|
"nix 0.26.4",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
"winapi-wsapoll",
|
"winapi-wsapoll",
|
||||||
"x11rb-protocol",
|
"x11rb-protocol 0.12.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x11rb"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a"
|
||||||
|
dependencies = [
|
||||||
|
"gethostname 0.4.3",
|
||||||
|
"rustix 0.38.21",
|
||||||
|
"x11rb-protocol 0.13.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -7821,6 +7829,12 @@ dependencies = [
|
|||||||
"nix 0.26.4",
|
"nix 0.26.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x11rb-protocol"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xdg-home"
|
name = "xdg-home"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -95,7 +95,7 @@ sys-locale = "0.3"
|
|||||||
enigo = { path = "libs/enigo", features = [ "with_serde" ] }
|
enigo = { path = "libs/enigo", features = [ "with_serde" ] }
|
||||||
clipboard = { path = "libs/clipboard" }
|
clipboard = { path = "libs/clipboard" }
|
||||||
ctrlc = "3.2"
|
ctrlc = "3.2"
|
||||||
arboard = { version = "3.2", features = ["wayland-data-control"] }
|
arboard = { git = "https://github.com/fufesou/arboard", branch = "feat/x11_set_conn_timeout", features = ["wayland-data-control"] }
|
||||||
system_shutdown = "4.0"
|
system_shutdown = "4.0"
|
||||||
qrcode-generator = "4.1"
|
qrcode-generator = "4.1"
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ use hbb_common::tokio;
|
|||||||
#[cfg(not(feature = "flutter"))]
|
#[cfg(not(feature = "flutter"))]
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
use hbb_common::tokio::sync::mpsc::UnboundedSender;
|
use hbb_common::tokio::sync::mpsc::UnboundedSender;
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
use hbb_common::tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
anyhow::{anyhow, Context},
|
anyhow::{anyhow, Context},
|
||||||
@ -65,7 +67,7 @@ use crate::{
|
|||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
use crate::ui_session_interface::SessionPermissionConfig;
|
use crate::ui_session_interface::SessionPermissionConfig;
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
use crate::{check_clipboard, ClipboardContext, CLIPBOARD_INTERVAL};
|
use crate::{check_clipboard, CLIPBOARD_INTERVAL};
|
||||||
|
|
||||||
pub use super::lang::*;
|
pub use super::lang::*;
|
||||||
|
|
||||||
@ -717,47 +719,48 @@ impl Client {
|
|||||||
//
|
//
|
||||||
// If clipboard update is detected, the text will be sent to all sessions by `send_text_clipboard_msg`.
|
// If clipboard update is detected, the text will be sent to all sessions by `send_text_clipboard_msg`.
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
fn try_start_clipboard(_ctx: Option<ClientClipboardContext>) {
|
fn try_start_clipboard(_ctx: Option<ClientClipboardContext>) -> Option<UnboundedReceiver<()>> {
|
||||||
let mut clipboard_lock = TEXT_CLIPBOARD_STATE.lock().unwrap();
|
let mut clipboard_lock = TEXT_CLIPBOARD_STATE.lock().unwrap();
|
||||||
if clipboard_lock.running {
|
if clipboard_lock.running {
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
clipboard_lock.running = true;
|
||||||
|
let (tx, rx) = unbounded_channel();
|
||||||
|
|
||||||
match ClipboardContext::new() {
|
log::info!("Start text clipboard loop");
|
||||||
Ok(mut ctx) => {
|
std::thread::spawn(move || {
|
||||||
clipboard_lock.running = true;
|
let mut is_sent = false;
|
||||||
// ignore clipboard update before service start
|
let mut ctx = None;
|
||||||
check_clipboard(&mut ctx, Some(&OLD_CLIPBOARD_TEXT));
|
loop {
|
||||||
std::thread::spawn(move || {
|
if !TEXT_CLIPBOARD_STATE.lock().unwrap().running {
|
||||||
log::info!("Start text clipboard loop");
|
break;
|
||||||
loop {
|
}
|
||||||
std::thread::sleep(Duration::from_millis(CLIPBOARD_INTERVAL));
|
if !TEXT_CLIPBOARD_STATE.lock().unwrap().is_required {
|
||||||
if !TEXT_CLIPBOARD_STATE.lock().unwrap().running {
|
continue;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !TEXT_CLIPBOARD_STATE.lock().unwrap().is_required {
|
if let Some(msg) = check_clipboard(&mut ctx, Some(&OLD_CLIPBOARD_TEXT)) {
|
||||||
continue;
|
#[cfg(feature = "flutter")]
|
||||||
}
|
crate::flutter::send_text_clipboard_msg(msg);
|
||||||
|
#[cfg(not(feature = "flutter"))]
|
||||||
if let Some(msg) = check_clipboard(&mut ctx, Some(&OLD_CLIPBOARD_TEXT)) {
|
if let Some(ctx) = &_ctx {
|
||||||
#[cfg(feature = "flutter")]
|
if ctx.cfg.is_text_clipboard_required() {
|
||||||
crate::flutter::send_text_clipboard_msg(msg);
|
let _ = ctx.tx.send(Data::Message(msg));
|
||||||
#[cfg(not(feature = "flutter"))]
|
|
||||||
if let Some(ctx) = &_ctx {
|
|
||||||
if ctx.cfg.is_text_clipboard_required() {
|
|
||||||
let _ = ctx.tx.send(Data::Message(msg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log::info!("Stop text clipboard loop");
|
}
|
||||||
});
|
|
||||||
|
if !is_sent {
|
||||||
|
is_sent = true;
|
||||||
|
tx.send(()).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread::sleep(Duration::from_millis(CLIPBOARD_INTERVAL));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
log::info!("Stop text clipboard loop");
|
||||||
log::error!("Failed to start clipboard service of client: {}", err);
|
});
|
||||||
}
|
|
||||||
}
|
Some(rx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1532,8 +1535,7 @@ impl LoginConfigHandler {
|
|||||||
n += 1;
|
n += 1;
|
||||||
} else if q == "custom" {
|
} else if q == "custom" {
|
||||||
let config = self.load_config();
|
let config = self.load_config();
|
||||||
let allow_more =
|
let allow_more = !crate::using_public_server() || self.direct == Some(true);
|
||||||
!crate::using_public_server() || self.direct == Some(true);
|
|
||||||
let quality = if config.custom_image_quality.is_empty() {
|
let quality = if config.custom_image_quality.is_empty() {
|
||||||
50
|
50
|
||||||
} else {
|
} else {
|
||||||
|
@ -17,16 +17,15 @@ use hbb_common::tokio::sync::mpsc::error::TryRecvError;
|
|||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
config::{PeerConfig, TransferSerde},
|
config::{PeerConfig, TransferSerde},
|
||||||
fs,
|
|
||||||
fs::{
|
fs::{
|
||||||
can_enable_overwrite_detection, get_job, get_string, new_send_confirm, DigestCheckResult,
|
self, can_enable_overwrite_detection, get_job, get_string, new_send_confirm,
|
||||||
RemoveJobMeta,
|
DigestCheckResult, RemoveJobMeta,
|
||||||
},
|
},
|
||||||
get_time, log,
|
get_time, log,
|
||||||
message_proto::permission_info::Permission,
|
message_proto::{permission_info::Permission, *},
|
||||||
message_proto::*,
|
|
||||||
protobuf::Message as _,
|
protobuf::Message as _,
|
||||||
rendezvous_proto::ConnType,
|
rendezvous_proto::ConnType,
|
||||||
|
timeout,
|
||||||
tokio::{
|
tokio::{
|
||||||
self,
|
self,
|
||||||
sync::mpsc,
|
sync::mpsc,
|
||||||
@ -170,7 +169,8 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
let mut rx_clip_client = rx_clip_client_lock.lock().await;
|
let mut rx_clip_client = rx_clip_client_lock.lock().await;
|
||||||
|
|
||||||
let mut status_timer = crate::rustdesk_interval(time::interval(Duration::new(1, 0)));
|
let mut status_timer =
|
||||||
|
crate::rustdesk_interval(time::interval(Duration::new(1, 0)));
|
||||||
let mut fps_instant = Instant::now();
|
let mut fps_instant = Instant::now();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -1099,15 +1099,20 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
if !(self.handler.is_file_transfer() || self.handler.is_port_forward()) {
|
if !(self.handler.is_file_transfer() || self.handler.is_port_forward()) {
|
||||||
#[cfg(feature = "flutter")]
|
#[cfg(feature = "flutter")]
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
Client::try_start_clipboard(None);
|
let rx = Client::try_start_clipboard(None);
|
||||||
#[cfg(not(feature = "flutter"))]
|
#[cfg(not(feature = "flutter"))]
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
Client::try_start_clipboard(Some(
|
let rx = Client::try_start_clipboard(Some(
|
||||||
crate::client::ClientClipboardContext {
|
crate::client::ClientClipboardContext {
|
||||||
cfg: self.handler.get_permission_config(),
|
cfg: self.handler.get_permission_config(),
|
||||||
tx: self.sender.clone(),
|
tx: self.sender.clone(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
// To make sure current text clipboard data is updated.
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
if let Some(mut rx) = rx {
|
||||||
|
timeout(common::CLIPBOARD_INTERVAL, rx.recv()).await.ok();
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
if let Some(msg_out) = Client::get_current_text_clipboard_msg() {
|
if let Some(msg_out) = Client::get_current_text_clipboard_msg() {
|
||||||
|
152
src/common.rs
152
src/common.rs
@ -1,4 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
future::Future,
|
future::Future,
|
||||||
sync::{Arc, Mutex, RwLock},
|
sync::{Arc, Mutex, RwLock},
|
||||||
task::Poll,
|
task::Poll,
|
||||||
@ -12,13 +13,6 @@ pub enum GrabState {
|
|||||||
Exit,
|
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"))]
|
#[cfg(all(target_os = "linux", feature = "unix-file-copy-paste"))]
|
||||||
static X11_CLIPBOARD: once_cell::sync::OnceCell<x11_clipboard::Clipboard> =
|
static X11_CLIPBOARD: once_cell::sync::OnceCell<x11_clipboard::Clipboard> =
|
||||||
once_cell::sync::OnceCell::new();
|
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")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
pub fn check_clipboard(
|
pub fn check_clipboard(
|
||||||
ctx: &mut ClipboardContext,
|
ctx: &mut Option<ClipboardContext>,
|
||||||
old: Option<&Arc<Mutex<String>>>,
|
old: Option<&Arc<Mutex<String>>>,
|
||||||
) -> Option<Message> {
|
) -> 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 side = if old.is_none() { "host" } else { "client" };
|
||||||
let old = if let Some(old) = old { old } else { &CONTENT };
|
let old = if let Some(old) = old { old } else { &CONTENT };
|
||||||
let content = {
|
let content = {
|
||||||
let _lock = ARBOARD_MTX.lock().unwrap();
|
let _lock = ARBOARD_MTX.lock().unwrap();
|
||||||
ctx.get_text()
|
ctx2.get_text()
|
||||||
};
|
};
|
||||||
if let Ok(content) = content {
|
if let Ok(content) = content {
|
||||||
if content.len() < 2_000_000 && !content.is_empty() {
|
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,
|
||||||
Poll::Pending
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1388,6 +1384,78 @@ pub fn rustdesk_interval(i: Interval) -> ThrottledInterval {
|
|||||||
ThrottledInterval::new(i)
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -1444,12 +1512,58 @@ mod tests {
|
|||||||
let dur = Duration::from_secs(1);
|
let dur = Duration::from_secs(1);
|
||||||
|
|
||||||
assert_eq!(dur * 2, Duration::from_secs(2));
|
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!(
|
||||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923), Duration::from_millis(923));
|
Duration::from_secs_f64(dur.as_secs_f64() * 0.9),
|
||||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.923 * 1e-3), Duration::from_micros(923));
|
Duration::from_millis(900)
|
||||||
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!(
|
||||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.5 * 1e-9), Duration::from_nanos(1));
|
Duration::from_secs_f64(dur.as_secs_f64() * 0.923),
|
||||||
assert_eq!(Duration::from_secs_f64(dur.as_secs_f64() * 0.499 * 1e-9), Duration::from_nanos(0));
|
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"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,18 +34,16 @@ pub fn new() -> GenericService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(sp: EmptyExtraFieldService, state: &mut State) -> ResultType<()> {
|
fn run(sp: EmptyExtraFieldService, state: &mut State) -> ResultType<()> {
|
||||||
if let Some(ctx) = state.ctx.as_mut() {
|
if let Some(msg) = check_clipboard(&mut state.ctx, None) {
|
||||||
if let Some(msg) = check_clipboard(ctx, None) {
|
sp.send(msg);
|
||||||
sp.send(msg);
|
|
||||||
}
|
|
||||||
sp.snapshot(|sps| {
|
|
||||||
let txt = crate::CONTENT.lock().unwrap().clone();
|
|
||||||
if !txt.is_empty() {
|
|
||||||
let msg_out = crate::create_clipboard_msg(txt);
|
|
||||||
sps.send_shared(Arc::new(msg_out));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
sp.snapshot(|sps| {
|
||||||
|
let txt = crate::CONTENT.lock().unwrap().clone();
|
||||||
|
if !txt.is_empty() {
|
||||||
|
let msg_out = crate::create_clipboard_msg(txt);
|
||||||
|
sps.send_shared(Arc::new(msg_out));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user