win_fix_multi_tab: send monitor ready on clipboard is ready
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
a9602f95ed
commit
c87e7f1e28
60
libs/clipboard/src/context_send.rs
Normal file
60
libs/clipboard/src/context_send.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use crate::cliprdr::*;
|
||||
use hbb_common::log;
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[cfg(windows)]
|
||||
lazy_static::lazy_static! {
|
||||
static ref CONTEXT_SEND: ContextSend = ContextSend{addr: Mutex::new(0)};
|
||||
}
|
||||
|
||||
pub struct ContextSend {
|
||||
addr: Mutex<u64>,
|
||||
}
|
||||
|
||||
impl ContextSend {
|
||||
pub fn is_enabled() -> bool {
|
||||
*CONTEXT_SEND.addr.lock().unwrap() != 0
|
||||
}
|
||||
|
||||
pub fn enable(enabled: bool) {
|
||||
let mut lock = CONTEXT_SEND.addr.lock().unwrap();
|
||||
if enabled {
|
||||
if *lock == 0 {
|
||||
match crate::create_cliprdr_context(true, false, crate::ProcessSide::ClientSide) {
|
||||
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 CliprdrClientContext);
|
||||
}
|
||||
log::info!("clipboard context for file transfer destroyed.");
|
||||
*lock = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn proc<F: FnOnce(&mut Box<CliprdrClientContext>) -> u32>(f: F) -> u32 {
|
||||
let mut lock = CONTEXT_SEND.addr.lock().unwrap();
|
||||
if *lock != 0 {
|
||||
unsafe {
|
||||
let mut context = Box::from_raw(*lock as *mut CliprdrClientContext);
|
||||
let res = f(&mut context);
|
||||
*lock = Box::into_raw(context) as _;
|
||||
res
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,8 @@ use std::{
|
||||
};
|
||||
|
||||
pub mod cliprdr;
|
||||
pub mod context_send;
|
||||
pub use context_send::*;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
|
@ -6,6 +6,9 @@ use crate::common;
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::common::{check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL};
|
||||
|
||||
#[cfg(windows)]
|
||||
use clipboard::{cliprdr::CliprdrClientContext, ContextSend};
|
||||
|
||||
use crate::ui_session_interface::{InvokeUiSession, Session};
|
||||
use crate::{client::Data, client::Interface};
|
||||
|
||||
@ -33,11 +36,6 @@ use std::collections::HashMap;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[cfg(windows)]
|
||||
lazy_static::lazy_static! {
|
||||
static ref CLIPBOARD_FILE_CONTEXT: Mutex<u64> = Mutex::new(0);
|
||||
}
|
||||
|
||||
pub struct Remote<T: InvokeUiSession> {
|
||||
handler: Session<T>,
|
||||
video_sender: MediaSender,
|
||||
@ -58,37 +56,6 @@ pub struct Remote<T: InvokeUiSession> {
|
||||
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, clipboard::ProcessSide::ClientSide)
|
||||
{
|
||||
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>,
|
||||
@ -1202,23 +1169,19 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
fn check_clipboard_file_context(&self) {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
check_clipboard_file_context(self.handler.lc.read().unwrap().enable_file_transfer);
|
||||
let enabled = SERVER_FILE_TRANSFER_ENABLED.load(Ordering::SeqCst)
|
||||
&& self.handler.lc.read().unwrap().enable_file_transfer;
|
||||
ContextSend::enable(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
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);
|
||||
}
|
||||
*lock = Box::into_raw(context) as _;
|
||||
}
|
||||
if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) {
|
||||
ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 {
|
||||
clipboard::server_clip_file(context, self.client_conn_id, clip)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,11 +53,8 @@ fn check_connect_status(
|
||||
) {
|
||||
let status = Arc::new(Mutex::new((0, false, 0, "".to_owned())));
|
||||
let options = Arc::new(Mutex::new(Config::get_options()));
|
||||
let cloned = status.clone();
|
||||
let cloned_options = options.clone();
|
||||
let (tx, rx) = mpsc::unbounded_channel::<ipc::Data>();
|
||||
let password = Arc::new(Mutex::new(String::default()));
|
||||
let cloned_password = password.clone();
|
||||
std::thread::spawn(move || crate::ui_interface::check_connect_status_(reconnect, rx));
|
||||
(status, options, tx, password)
|
||||
}
|
||||
|
@ -11,9 +11,7 @@ use std::{
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
use clipboard::empty_clipboard;
|
||||
#[cfg(windows)]
|
||||
use hbb_common::chrono::Duration;
|
||||
use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, ContextSend};
|
||||
use serde_derive::Serialize;
|
||||
|
||||
use crate::ipc::{self, new_listener, Connection, Data};
|
||||
@ -56,7 +54,6 @@ pub struct Client {
|
||||
struct IpcTaskRunner<T: InvokeUiCM> {
|
||||
stream: Connection,
|
||||
cm: ConnectionManager<T>,
|
||||
tx_file: mpsc::UnboundedSender<ClipboardFileData>,
|
||||
tx: mpsc::UnboundedSender<Data>,
|
||||
rx: mpsc::UnboundedReceiver<Data>,
|
||||
conn_id: i32,
|
||||
@ -233,14 +230,31 @@ pub fn get_clients_length() -> usize {
|
||||
clients.len()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ClipboardFileData {
|
||||
#[cfg(windows)]
|
||||
Clip((i32, ipc::ClipbaordFile)),
|
||||
Enable((i32, bool)),
|
||||
}
|
||||
|
||||
impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
||||
#[cfg(windows)]
|
||||
async fn enable_cliprdr_file_context(&mut self, conn_id: i32, enabled: bool) {
|
||||
if conn_id == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let pre_enabled = ContextSend::is_enabled();
|
||||
ContextSend::enable(enabled);
|
||||
if !pre_enabled && ContextSend::is_enabled() {
|
||||
allow_err!(
|
||||
self.stream
|
||||
.send(&Data::ClipbaordFile(clipboard::ClipbaordFile::MonitorReady))
|
||||
.await
|
||||
);
|
||||
}
|
||||
clipboard::set_conn_enabled(conn_id, enabled);
|
||||
if !enabled {
|
||||
ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 {
|
||||
clipboard::empty_clipboard(context, conn_id);
|
||||
0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(&mut self) {
|
||||
use hbb_common::config::LocalConfig;
|
||||
|
||||
@ -251,10 +265,8 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
||||
|
||||
#[cfg(windows)]
|
||||
if self.conn_id > 0 {
|
||||
allow_err!(self.tx_file.send(ClipboardFileData::Enable((
|
||||
self.conn_id,
|
||||
self.file_transfer_enabled
|
||||
))));
|
||||
self.enable_cliprdr_file_context(self.conn_id, self.file_transfer_enabled)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@ -297,13 +309,15 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
||||
break;
|
||||
}
|
||||
Data::Close => {
|
||||
allow_err!(self.tx_file.send(ClipboardFileData::Enable((self.conn_id, false))));
|
||||
#[cfg(windows)]
|
||||
self.enable_cliprdr_file_context(self.conn_id, false).await;
|
||||
log::info!("cm ipc connection closed from connection request");
|
||||
break;
|
||||
}
|
||||
Data::Disconnected => {
|
||||
close = false;
|
||||
allow_err!(self.tx_file.send(ClipboardFileData::Enable((self.conn_id, false))));
|
||||
#[cfg(windows)]
|
||||
self.enable_cliprdr_file_context(self.conn_id, false).await;
|
||||
log::info!("cm ipc connection disconnect");
|
||||
break;
|
||||
}
|
||||
@ -320,13 +334,20 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
||||
Data::FS(fs) => {
|
||||
handle_fs(fs, &mut write_jobs, &self.tx).await;
|
||||
}
|
||||
#[cfg(windows)]
|
||||
Data::ClipbaordFile(_clip) => {
|
||||
allow_err!(self.tx_file.send(ClipboardFileData::Clip((self.conn_id, _clip))));
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let conn_id = self.conn_id;
|
||||
|
||||
ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 {
|
||||
clipboard::server_clip_file(context, conn_id, _clip)
|
||||
});
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
Data::ClipboardFileEnabled(enabled) => {
|
||||
allow_err!(self.tx_file.send(ClipboardFileData::Enable((self.conn_id, enabled))));
|
||||
Data::ClipboardFileEnabled(_enabled) => {
|
||||
#[cfg(windows)]
|
||||
self.enable_cliprdr_file_context(self.conn_id, _enabled).await;
|
||||
}
|
||||
Data::Theme(dark) => {
|
||||
self.cm.change_theme(dark);
|
||||
@ -364,16 +385,11 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn ipc_task(
|
||||
stream: Connection,
|
||||
cm: ConnectionManager<T>,
|
||||
tx_file: mpsc::UnboundedSender<ClipboardFileData>,
|
||||
) {
|
||||
async fn ipc_task(stream: Connection, cm: ConnectionManager<T>) {
|
||||
let (tx, rx) = mpsc::unbounded_channel::<Data>();
|
||||
let mut task_runner = Self {
|
||||
stream,
|
||||
cm,
|
||||
tx_file,
|
||||
tx,
|
||||
rx,
|
||||
conn_id: 0,
|
||||
@ -391,13 +407,6 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
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>();
|
||||
#[cfg(windows)]
|
||||
std::thread::spawn(move || start_clipboard_file(_rx_file));
|
||||
|
||||
#[cfg(windows)]
|
||||
std::thread::spawn(move || {
|
||||
log::info!("try create privacy mode window");
|
||||
@ -422,7 +431,6 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
|
||||
tokio::spawn(IpcTaskRunner::<T>::ipc_task(
|
||||
Connection::new(stream),
|
||||
cm.clone(),
|
||||
tx_file.clone(),
|
||||
));
|
||||
}
|
||||
Err(err) => {
|
||||
@ -723,47 +731,3 @@ fn send_raw(msg: Message, tx: &UnboundedSender<Data>) {
|
||||
err => allow_err!(err),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
pub async fn start_clipboard_file(mut rx: mpsc::UnboundedReceiver<ClipboardFileData>) {
|
||||
let mut cliprdr_context = None;
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
server_msg = rx.recv() => match server_msg {
|
||||
Some(ClipboardFileData::Clip((conn_id, clip))) => {
|
||||
if let Some(ctx) = cliprdr_context.as_mut() {
|
||||
clipboard::server_clip_file(ctx, conn_id, clip);
|
||||
}
|
||||
}
|
||||
Some(ClipboardFileData::Enable((id, enabled))) => {
|
||||
if enabled && cliprdr_context.is_none() {
|
||||
cliprdr_context = Some(match clipboard::create_cliprdr_context(true, false, clipboard::ProcessSide::ServerSide) {
|
||||
Ok(context) => {
|
||||
log::info!("clipboard context for file transfer created.");
|
||||
context
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!(
|
||||
"Create clipboard context for file transfer: {}",
|
||||
err.to_string()
|
||||
);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
clipboard::set_conn_enabled(id, enabled);
|
||||
if !enabled {
|
||||
if let Some(ctx) = cliprdr_context.as_mut() {
|
||||
clipboard::empty_clipboard(ctx, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use crate::client::{
|
||||
load_config, send_mouse, start_video_audio_threads, FileManager, Key, LoginConfigHandler,
|
||||
QualityStatus, KEY_MAP, SERVER_KEYBOARD_ENABLED,
|
||||
};
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::common::IS_X11;
|
||||
use crate::{client::Data, client::Interface};
|
||||
use async_trait::async_trait;
|
||||
@ -812,6 +813,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
let keycode: u32 = keycode as u32;
|
||||
let scancode: u32 = scancode as u32;
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let key = rdev::key_from_scancode(scancode) as RdevKey;
|
||||
// Windows requires special handling
|
||||
#[cfg(target_os = "windows")]
|
||||
|
Loading…
x
Reference in New Issue
Block a user