From 4009fd77e853f29808e1bca86482adf29c05ed37 Mon Sep 17 00:00:00 2001 From: dignow Date: Mon, 31 Jul 2023 21:40:55 +0800 Subject: [PATCH] init sync file clipboard, local to remote Signed-off-by: dignow --- libs/clipboard/src/lib.rs | 7 ++++ src/client/io_loop.rs | 76 ++++++++++++++++++++++++++----------- src/platform/mod.rs | 5 +++ src/ui_session_interface.rs | 2 +- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index 7a5941029..497ce54c8 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -70,6 +70,7 @@ struct MsgChannel { lazy_static::lazy_static! { static ref VEC_MSG_CHANNEL: RwLock> = Default::default(); static ref CLIENT_CONN_ID_COUNTER: Mutex = Mutex::new(0); + static ref LAST_FILE_FORMAT_LIST: Arc>> = Default::default(); } impl ClipboardFile { @@ -90,6 +91,11 @@ impl ClipboardFile { } } +#[inline] +pub fn get_last_file_format_list() -> Option { + LAST_FILE_FORMAT_LIST.lock().unwrap().clone() +} + pub fn get_client_conn_id(session_uuid: &SessionID) -> Option { VEC_MSG_CHANNEL .read() @@ -561,6 +567,7 @@ extern "C" fn client_format_list( } log::debug!("client_format_list called, client id: {}, format_list: {:?}", conn_id, &format_list); let data = ClipboardFile::FormatList { format_list }; + *LAST_FILE_FORMAT_LIST.lock().unwrap() = Some(data.clone()); // no need to handle result here if conn_id == 0 { // msg_channel is used for debug, VEC_MSG_CHANNEL cannot be inspected by the debugger. diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index bb79a2d5e..498d022f1 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -6,7 +6,9 @@ use std::sync::{ }; #[cfg(windows)] -use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, ContextSend}; +use clipboard::{ + cliprdr::CliprdrClientContext, empty_clipboard, get_last_file_format_list, ContextSend, +}; use crossbeam_queue::ArrayQueue; use hbb_common::config::{PeerConfig, TransferSerde}; use hbb_common::fs::{ @@ -56,6 +58,7 @@ pub struct Remote { remove_jobs: HashMap, timer: Interval, last_update_jobs_status: (Instant, HashMap), + is_connected: bool, first_frame: bool, #[cfg(windows)] client_conn_id: i32, // used for file clipboard @@ -90,6 +93,7 @@ impl Remote { remove_jobs: Default::default(), timer: time::interval(SEC30), last_update_jobs_status: (Instant::now(), Default::default()), + is_connected: false, first_frame: false, #[cfg(windows)] client_conn_id: 0, @@ -195,28 +199,7 @@ impl Remote { } _msg = rx_clip_client.recv() => { #[cfg(windows)] - match _msg { - Some(clip) => match clip { - clipboard::ClipboardFile::NotifyCallback{r#type, title, text} => { - self.handler.msgbox(&r#type, &title, &text, ""); - } - _ => { - let is_stopping_allowed = clip.is_stopping_allowed(); - let server_file_transfer_enabled = *self.handler.server_file_transfer_enabled.read().unwrap(); - let file_transfer_enabled = self.handler.lc.read().unwrap().enable_file_transfer.v; - let stop = is_stopping_allowed && (!self.first_frame || !(server_file_transfer_enabled && file_transfer_enabled)); - log::debug!("Process clipboard message from system, stop: {}, is_stopping_allowed: {}, server_file_transfer_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, server_file_transfer_enabled, file_transfer_enabled); - if stop { - ContextSend::set_is_stopped(); - } else { - allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); - } - } - } - None => { - // unreachable!() - } - } + self.handle_local_clipboard_msg(&mut peer, _msg).await; } _ = self.timer.tick() => { if last_recv_time.elapsed() >= SEC30 { @@ -277,6 +260,44 @@ impl Remote { } } + #[cfg(windows)] + async fn handle_local_clipboard_msg( + &self, + peer: &mut crate::client::FramedStream, + msg: Option, + ) { + match msg { + Some(clip) => match clip { + clipboard::ClipboardFile::NotifyCallback { + r#type, + title, + text, + } => { + self.handler.msgbox(&r#type, &title, &text, ""); + } + _ => { + let is_stopping_allowed = clip.is_stopping_allowed(); + let server_file_transfer_enabled = + *self.handler.server_file_transfer_enabled.read().unwrap(); + let file_transfer_enabled = + self.handler.lc.read().unwrap().enable_file_transfer.v; + let stop = is_stopping_allowed + && (!self.is_connected + || !(server_file_transfer_enabled && file_transfer_enabled)); + log::debug!("Process clipboard message from system, stop: {}, is_stopping_allowed: {}, server_file_transfer_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, server_file_transfer_enabled, file_transfer_enabled); + if stop { + ContextSend::set_is_stopped(); + } else { + allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); + } + } + }, + None => { + // unreachable!() + } + } + } + fn handle_job_status(&mut self, id: i32, file_num: i32, err: Option) { if let Some(job) = self.remove_jobs.get_mut(&id) { if job.no_confirm { @@ -1030,6 +1051,15 @@ impl Remote { if self.handler.is_file_transfer() { self.handler.load_last_jobs(); } + + self.is_connected = true; + #[cfg(target_os = "windows")] + if self.handler.peer_platform() == crate::platform::PLATFORM_WINDOWS { + if let Some(last_file_format_list) = get_last_file_format_list() { + self.handle_local_clipboard_msg(peer, Some(last_file_format_list)) + .await; + } + } } _ => {} }, diff --git a/src/platform/mod.rs b/src/platform/mod.rs index e962ef9d5..6492e5e25 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -26,6 +26,11 @@ use hbb_common::{message_proto::CursorData, ResultType}; #[cfg(not(any(target_os = "macos", target_os = "android", target_os = "ios")))] const SERVICE_INTERVAL: u64 = 300; +pub const PLATFORM_WINDOWS: &str = "Windows"; +pub const PLATFORM_LINUX: &str = "Linux"; +pub const PLATFORM_MACOS: &str = "Mac OS"; +pub const PLATFORM_ANDROID: &str = "Android"; + pub fn is_xfce() -> bool { #[cfg(target_os = "linux")] { diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index a88a02edb..be0185d30 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -412,7 +412,7 @@ impl Session { pub fn get_path_sep(&self, is_remote: bool) -> &'static str { let p = self.get_platform(is_remote); - if &p == "Windows" { + if &p == crate::platform::PLATFORM_WINDOWS { return "\\"; } else { return "/";