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,
|
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
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user