win_fix_multi_tab: refactor clipboard on windows, mid commit3
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
		
							parent
							
								
									a49552d28b
								
							
						
					
					
						commit
						007cdb1020
					
				| @ -22,13 +22,22 @@ use hbb_common::tokio::{ | ||||
|     sync::mpsc, | ||||
|     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 std::collections::HashMap; | ||||
| 
 | ||||
| use std::sync::atomic::{AtomicUsize, Ordering}; | ||||
| 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> { | ||||
|     handler: Session<T>, | ||||
|     video_sender: MediaSender, | ||||
| @ -43,14 +52,42 @@ pub struct Remote<T: InvokeUiSession> { | ||||
|     last_update_jobs_status: (Instant, HashMap<i32, u64>), | ||||
|     first_frame: bool, | ||||
|     #[cfg(windows)] | ||||
|     clipboard_file_context: Option<Box<clipboard::cliprdr::CliprdrClientContext>>, | ||||
|     #[cfg(windows)] | ||||
|     client_conn_id: i32, // used for clipboard
 | ||||
|     data_count: Arc<AtomicUsize>, | ||||
|     frame_count: Arc<AtomicUsize>, | ||||
|     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> { | ||||
|     pub fn new( | ||||
|         handler: Session<T>, | ||||
| @ -74,8 +111,6 @@ impl<T: InvokeUiSession> Remote<T> { | ||||
|             last_update_jobs_status: (Instant::now(), Default::default()), | ||||
|             first_frame: false, | ||||
|             #[cfg(windows)] | ||||
|             clipboard_file_context: None, | ||||
|             #[cfg(windows)] | ||||
|             client_conn_id: 0, | ||||
|             data_count: Arc::new(AtomicUsize::new(0)), | ||||
|             frame_count, | ||||
| @ -789,13 +824,7 @@ impl<T: InvokeUiSession> Remote<T> { | ||||
|                 } | ||||
|                 #[cfg(windows)] | ||||
|                 Some(message::Union::Cliprdr(clip)) => { | ||||
|                     if !self.handler.lc.read().unwrap().disable_clipboard { | ||||
|                         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); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     self.handle_cliprdr_msg(clip); | ||||
|                 } | ||||
|                 Some(message::Union::FileResponse(fr)) => { | ||||
|                     match fr.union { | ||||
| @ -1169,30 +1198,25 @@ impl<T: InvokeUiSession> Remote<T> { | ||||
|         true | ||||
|     } | ||||
| 
 | ||||
|     fn check_clipboard_file_context(&mut self) { | ||||
|     fn check_clipboard_file_context(&self) { | ||||
|         #[cfg(windows)] | ||||
|         { | ||||
|             let enabled = SERVER_FILE_TRANSFER_ENABLED.load(Ordering::SeqCst) | ||||
|                 && 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) { | ||||
|                         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 | ||||
|                         } | ||||
|             check_clipboard_file_context(self.handler.lc.read().unwrap().enable_file_transfer); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn handle_cliprdr_msg(&self, clip: message_proto::Cliprdr) { | ||||
|         if !self.handler.lc.read().unwrap().disable_clipboard { | ||||
|             let mut lock = CLIPBOARD_FILE_CONTEXT.lock().unwrap(); | ||||
|             if *lock != 0 { | ||||
|                 unsafe { | ||||
|                     let mut context = | ||||
|                         Box::from_raw(*lock as *mut clipboard::cliprdr::CliprdrClientContext); | ||||
|                     if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) { | ||||
|                         clipboard::server_clip_file(&mut context, self.client_conn_id, clip); | ||||
|                     } | ||||
|                 } else { | ||||
|                     log::info!("clipboard context for file transfer destroyed."); | ||||
|                     None | ||||
|                 }; | ||||
|                     *lock = Box::into_raw(context) as _; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -220,7 +220,7 @@ pub fn get_clients_length() -> usize { | ||||
| #[derive(Debug)] | ||||
| pub enum ClipboardFileData { | ||||
|     #[cfg(windows)] | ||||
|     Clip(ipc::ClipbaordFile), | ||||
|     Clip((i32, ipc::ClipbaordFile)), | ||||
|     Enable((i32, bool)), | ||||
| } | ||||
| 
 | ||||
| @ -267,30 +267,10 @@ async fn cm_ipc_task_wait_login<T: InvokeUiCM>( | ||||
|     (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>( | ||||
|     mut stream: Connection, | ||||
|     cm: ConnectionManager<T>, | ||||
|     tx_file: mpsc::UnboundedSender<ClipboardFileData>, | ||||
|     tx: mpsc::UnboundedSender<Data>, | ||||
|     mut rx: mpsc::UnboundedReceiver<Data>, | ||||
|     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 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)] | ||||
|     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 { | ||||
|         tokio::select! { | ||||
|             res = stream.next() => { | ||||
| @ -347,7 +327,7 @@ async fn cm_ipc_task_loop<T: InvokeUiCM>( | ||||
|                             } | ||||
|                             #[cfg(windows)] | ||||
|                             Data::ClipbaordFile(_clip) => { | ||||
|                                 allow_err!(tx_file.send(ClipboardFileData::Clip(_clip))); | ||||
|                                 allow_err!(tx_file.send(ClipboardFileData::Clip((conn_id, _clip)))); | ||||
|                             } | ||||
|                             #[cfg(windows)] | ||||
|                             Data::ClipboardFileEnabled(enabled) => { | ||||
| @ -373,6 +353,14 @@ async fn cm_ipc_task_loop<T: InvokeUiCM>( | ||||
|                     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 { | ||||
| @ -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 (stream, cm, wait_res) = cm_ipc_task_wait_login(stream, cm, tx.clone()).await; | ||||
|     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)] | ||||
|     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)] | ||||
|     std::thread::spawn(move || { | ||||
|         log::info!("try create privacy mode window"); | ||||
| @ -415,7 +410,11 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) { | ||||
|                 match result { | ||||
|                     Ok(stream) => { | ||||
|                         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) => { | ||||
|                         log::error!("Couldn't get cm client: {:?}", err); | ||||
| @ -718,29 +717,13 @@ fn send_raw(msg: Message, tx: &UnboundedSender<Data>) { | ||||
| 
 | ||||
| #[cfg(windows)] | ||||
| #[tokio::main(flavor = "current_thread")] | ||||
| pub async fn start_clipboard_file( | ||||
|     conn_id: i32, | ||||
|     mut rx: mpsc::UnboundedReceiver<ClipboardFileData>, | ||||
| ) { | ||||
| pub async fn start_clipboard_file(mut rx: mpsc::UnboundedReceiver<ClipboardFileData>) { | ||||
|     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 { | ||||
|         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 { | ||||
|                 Some(ClipboardFileData::Clip(clip)) => { | ||||
|                 Some(ClipboardFileData::Clip((conn_id, clip))) => { | ||||
|                     if let Some(ctx) = cliprdr_context.as_mut() { | ||||
|                         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())); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user