win_fix_multi_tab: refactor clipboard on windows, mid commit3

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2022-10-26 10:28:06 +08:00
parent a49552d28b
commit 007cdb1020
2 changed files with 89 additions and 96 deletions

View File

@ -22,13 +22,22 @@ use hbb_common::tokio::{
sync::mpsc, sync::mpsc,
time::{self, Duration, Instant, Interval}, time::{self, Duration, Instant, Interval},
}; };
use hbb_common::{allow_err, message_proto::*, sleep}; use hbb_common::{
allow_err,
message_proto::{self, *},
sleep,
};
use hbb_common::{fs, log, Stream}; use hbb_common::{fs, log, Stream};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
lazy_static::lazy_static! {
#[cfg(windows)]
static ref CLIPBOARD_FILE_CONTEXT: Mutex<u64> = Mutex::new(0);
}
pub struct Remote<T: InvokeUiSession> { pub struct Remote<T: InvokeUiSession> {
handler: Session<T>, handler: Session<T>,
video_sender: MediaSender, video_sender: MediaSender,
@ -43,14 +52,42 @@ pub struct Remote<T: InvokeUiSession> {
last_update_jobs_status: (Instant, HashMap<i32, u64>), last_update_jobs_status: (Instant, HashMap<i32, u64>),
first_frame: bool, first_frame: bool,
#[cfg(windows)] #[cfg(windows)]
clipboard_file_context: Option<Box<clipboard::cliprdr::CliprdrClientContext>>,
#[cfg(windows)]
client_conn_id: i32, // used for clipboard client_conn_id: i32, // used for clipboard
data_count: Arc<AtomicUsize>, data_count: Arc<AtomicUsize>,
frame_count: Arc<AtomicUsize>, frame_count: Arc<AtomicUsize>,
video_format: CodecFormat, video_format: CodecFormat,
} }
#[cfg(windows)]
fn check_clipboard_file_context(enable_file_transfer: bool) {
let enabled = SERVER_FILE_TRANSFER_ENABLED.load(Ordering::SeqCst) && enable_file_transfer;
let mut lock = CLIPBOARD_FILE_CONTEXT.lock().unwrap();
if enabled {
if *lock == 0 {
match clipboard::create_cliprdr_context(true, false) {
Ok(context) => {
log::info!("clipboard context for file transfer created.");
*lock = Box::into_raw(context) as _;
}
Err(err) => {
log::error!(
"Create clipboard context for file transfer: {}",
err.to_string()
);
}
}
}
} else {
if *lock != 0 {
unsafe {
let _ = Box::from_raw(*lock as *mut clipboard::cliprdr::CliprdrClientContext);
}
log::info!("clipboard context for file transfer destroyed.");
*lock = 0;
}
}
}
impl<T: InvokeUiSession> Remote<T> { impl<T: InvokeUiSession> Remote<T> {
pub fn new( pub fn new(
handler: Session<T>, handler: Session<T>,
@ -74,8 +111,6 @@ impl<T: InvokeUiSession> Remote<T> {
last_update_jobs_status: (Instant::now(), Default::default()), last_update_jobs_status: (Instant::now(), Default::default()),
first_frame: false, first_frame: false,
#[cfg(windows)] #[cfg(windows)]
clipboard_file_context: None,
#[cfg(windows)]
client_conn_id: 0, client_conn_id: 0,
data_count: Arc::new(AtomicUsize::new(0)), data_count: Arc::new(AtomicUsize::new(0)),
frame_count, frame_count,
@ -789,13 +824,7 @@ impl<T: InvokeUiSession> Remote<T> {
} }
#[cfg(windows)] #[cfg(windows)]
Some(message::Union::Cliprdr(clip)) => { Some(message::Union::Cliprdr(clip)) => {
if !self.handler.lc.read().unwrap().disable_clipboard { self.handle_cliprdr_msg(clip);
if let Some(context) = &mut self.clipboard_file_context {
if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) {
clipboard::server_clip_file(context, self.client_conn_id, clip);
}
}
}
} }
Some(message::Union::FileResponse(fr)) => { Some(message::Union::FileResponse(fr)) => {
match fr.union { match fr.union {
@ -1169,30 +1198,25 @@ impl<T: InvokeUiSession> Remote<T> {
true true
} }
fn check_clipboard_file_context(&mut self) { fn check_clipboard_file_context(&self) {
#[cfg(windows)] #[cfg(windows)]
{ {
let enabled = SERVER_FILE_TRANSFER_ENABLED.load(Ordering::SeqCst) check_clipboard_file_context(self.handler.lc.read().unwrap().enable_file_transfer);
&& self.handler.lc.read().unwrap().enable_file_transfer; }
if enabled == self.clipboard_file_context.is_none() { }
self.clipboard_file_context = if enabled {
match clipboard::create_cliprdr_context(true, false) { fn handle_cliprdr_msg(&self, clip: message_proto::Cliprdr) {
Ok(context) => { if !self.handler.lc.read().unwrap().disable_clipboard {
log::info!("clipboard context for file transfer created."); let mut lock = CLIPBOARD_FILE_CONTEXT.lock().unwrap();
Some(context) if *lock != 0 {
} unsafe {
Err(err) => { let mut context =
log::error!( Box::from_raw(*lock as *mut clipboard::cliprdr::CliprdrClientContext);
"Create clipboard context for file transfer: {}", if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) {
err.to_string() clipboard::server_clip_file(&mut context, self.client_conn_id, clip);
);
None
}
} }
} else { *lock = Box::into_raw(context) as _;
log::info!("clipboard context for file transfer destroyed."); }
None
};
} }
} }
} }

View File

@ -220,7 +220,7 @@ pub fn get_clients_length() -> usize {
#[derive(Debug)] #[derive(Debug)]
pub enum ClipboardFileData { pub enum ClipboardFileData {
#[cfg(windows)] #[cfg(windows)]
Clip(ipc::ClipbaordFile), Clip((i32, ipc::ClipbaordFile)),
Enable((i32, bool)), Enable((i32, bool)),
} }
@ -267,30 +267,10 @@ async fn cm_ipc_task_wait_login<T: InvokeUiCM>(
(stream, cm, ret) (stream, cm, ret)
} }
#[cfg(windows)]
fn create_cliprdr_context_(enabled: bool) -> Option<Box<clipboard::cliprdr::CliprdrClientContext>> {
if enabled {
match clipboard::create_cliprdr_context(true, false) {
Ok(context) => {
log::info!("clipboard context for file transfer created.");
Some(context)
}
Err(err) => {
log::error!(
"Create clipboard context for file transfer: {}",
err.to_string()
);
None
}
}
} else {
None
}
}
async fn cm_ipc_task_loop<T: InvokeUiCM>( async fn cm_ipc_task_loop<T: InvokeUiCM>(
mut stream: Connection, mut stream: Connection,
cm: ConnectionManager<T>, cm: ConnectionManager<T>,
tx_file: mpsc::UnboundedSender<ClipboardFileData>,
tx: mpsc::UnboundedSender<Data>, tx: mpsc::UnboundedSender<Data>,
mut rx: mpsc::UnboundedReceiver<Data>, mut rx: mpsc::UnboundedReceiver<Data>,
mut conn_id: i32, mut conn_id: i32,
@ -303,14 +283,14 @@ async fn cm_ipc_task_loop<T: InvokeUiCM>(
let mut write_jobs: Vec<fs::TransferJob> = Vec::new(); let mut write_jobs: Vec<fs::TransferJob> = Vec::new();
let mut close = true; let mut close = true;
let (tx_file, _rx_file) = mpsc::unbounded_channel::<ClipboardFileData>();
#[cfg(windows)]
std::thread::spawn(move || {
start_clipboard_file(conn_id, _rx_file);
});
#[cfg(windows)] #[cfg(windows)]
allow_err!(tx_file.send(ClipboardFileData::Enable((conn_id, file_transfer_enabled)))); allow_err!(tx_file.send(ClipboardFileData::Enable((conn_id, file_transfer_enabled))));
#[cfg(windows)]
let rx_clip_client1 = clipboard::get_rx_cliprdr_server(conn_id);
#[cfg(windows)]
let mut rx_clip_client = rx_clip_client1.lock().await;
loop { loop {
tokio::select! { tokio::select! {
res = stream.next() => { res = stream.next() => {
@ -347,7 +327,7 @@ async fn cm_ipc_task_loop<T: InvokeUiCM>(
} }
#[cfg(windows)] #[cfg(windows)]
Data::ClipbaordFile(_clip) => { Data::ClipbaordFile(_clip) => {
allow_err!(tx_file.send(ClipboardFileData::Clip(_clip))); allow_err!(tx_file.send(ClipboardFileData::Clip((conn_id, _clip))));
} }
#[cfg(windows)] #[cfg(windows)]
Data::ClipboardFileEnabled(enabled) => { Data::ClipboardFileEnabled(enabled) => {
@ -373,6 +353,14 @@ async fn cm_ipc_task_loop<T: InvokeUiCM>(
break; break;
} }
} }
clip_file = rx_clip_client.recv() => match clip_file {
Some(clip) => {
allow_err!(tx.send(Data::ClipbaordFile(clip)));
}
None => {
//
}
},
} }
} }
if conn_id != conn_id_tmp { if conn_id != conn_id_tmp {
@ -380,11 +368,15 @@ async fn cm_ipc_task_loop<T: InvokeUiCM>(
} }
} }
async fn cm_ipc_task<T: InvokeUiCM>(stream: Connection, cm: ConnectionManager<T>) { async fn cm_ipc_task<T: InvokeUiCM>(
stream: Connection,
cm: ConnectionManager<T>,
tx_file: mpsc::UnboundedSender<ClipboardFileData>,
) {
let (tx, rx) = mpsc::unbounded_channel::<Data>(); let (tx, rx) = mpsc::unbounded_channel::<Data>();
let (stream, cm, wait_res) = cm_ipc_task_wait_login(stream, cm, tx.clone()).await; let (stream, cm, wait_res) = cm_ipc_task_wait_login(stream, cm, tx.clone()).await;
if let Some((conn_id, file_transfer_enabled)) = wait_res { if let Some((conn_id, file_transfer_enabled)) = wait_res {
cm_ipc_task_loop(stream, cm, tx, rx, conn_id, file_transfer_enabled).await; cm_ipc_task_loop(stream, cm, tx_file, tx, rx, conn_id, file_transfer_enabled).await;
} }
} }
@ -394,6 +386,9 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
#[cfg(windows)] #[cfg(windows)]
let cm_clip = cm.clone(); let cm_clip = cm.clone();
let (tx_file, _rx_file) = mpsc::unbounded_channel::<ClipboardFileData>();
std::thread::spawn(move || start_clipboard_file(_rx_file));
#[cfg(windows)] #[cfg(windows)]
std::thread::spawn(move || { std::thread::spawn(move || {
log::info!("try create privacy mode window"); log::info!("try create privacy mode window");
@ -415,7 +410,11 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
match result { match result {
Ok(stream) => { Ok(stream) => {
log::debug!("Got new connection"); log::debug!("Got new connection");
tokio::spawn(cm_ipc_task(Connection::new(stream), cm.clone())); tokio::spawn(cm_ipc_task(
Connection::new(stream),
cm.clone(),
tx_file.clone(),
));
} }
Err(err) => { Err(err) => {
log::error!("Couldn't get cm client: {:?}", err); log::error!("Couldn't get cm client: {:?}", err);
@ -718,29 +717,13 @@ fn send_raw(msg: Message, tx: &UnboundedSender<Data>) {
#[cfg(windows)] #[cfg(windows)]
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
pub async fn start_clipboard_file( pub async fn start_clipboard_file(mut rx: mpsc::UnboundedReceiver<ClipboardFileData>) {
conn_id: i32,
mut rx: mpsc::UnboundedReceiver<ClipboardFileData>,
) {
let mut cliprdr_context = None; let mut cliprdr_context = None;
let rx_clip_client1 = clipboard::get_rx_cliprdr_server(conn_id);
let mut rx_clip_client = rx_clip_client1.lock().await;
loop { loop {
tokio::select! { tokio::select! {
clip_file = rx_clip_client.recv() => match clip_file {
Some(clip) => {
cmd_inner_send(
conn_id,
Data::ClipbaordFile(clip)
);
}
None => {
//
}
},
server_msg = rx.recv() => match server_msg { server_msg = rx.recv() => match server_msg {
Some(ClipboardFileData::Clip(clip)) => { Some(ClipboardFileData::Clip((conn_id, clip))) => {
if let Some(ctx) = cliprdr_context.as_mut() { if let Some(ctx) = cliprdr_context.as_mut() {
clipboard::server_clip_file(ctx, conn_id, clip); clipboard::server_clip_file(ctx, conn_id, clip);
} }
@ -775,17 +758,3 @@ pub async fn start_clipboard_file(
} }
} }
} }
#[cfg(windows)]
fn cmd_inner_send(id: i32, data: Data) {
let lock = CLIENTS.read().unwrap();
if id != 0 {
if let Some(s) = lock.get(&id) {
allow_err!(s.tx.send(data));
}
} else {
for s in lock.values() {
allow_err!(s.tx.send(data.clone()));
}
}
}