Merge pull request #3238 from fufesou/refact/text_clipboard
refact text clipboard
This commit is contained in:
commit
589ad940cd
105
src/client.rs
105
src/client.rs
@ -3,7 +3,7 @@ use std::{
|
|||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
ops::{Deref, Not},
|
ops::{Deref, Not},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::{atomic::AtomicBool, mpsc, Arc, Mutex, RwLock},
|
sync::{mpsc, Arc, Mutex, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use async_trait::async_trait;
|
pub use async_trait::async_trait;
|
||||||
@ -34,7 +34,7 @@ use hbb_common::{
|
|||||||
socket_client,
|
socket_client,
|
||||||
sodiumoxide::crypto::{box_, secretbox, sign},
|
sodiumoxide::crypto::{box_, secretbox, sign},
|
||||||
timeout,
|
timeout,
|
||||||
tokio::time::Duration,
|
tokio::{sync::mpsc::UnboundedSender, time::Duration},
|
||||||
AddrMangle, ResultType, Stream,
|
AddrMangle, ResultType, Stream,
|
||||||
};
|
};
|
||||||
pub use helper::LatencyController;
|
pub use helper::LatencyController;
|
||||||
@ -50,21 +50,30 @@ use crate::{
|
|||||||
server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED},
|
server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
use crate::{
|
||||||
|
common::{check_clipboard, ClipboardContext, CLIPBOARD_INTERVAL},
|
||||||
|
ui_session_interface::SessionPermissionConfig,
|
||||||
|
};
|
||||||
|
|
||||||
pub use super::lang::*;
|
pub use super::lang::*;
|
||||||
|
|
||||||
pub mod file_trait;
|
pub mod file_trait;
|
||||||
pub mod helper;
|
pub mod helper;
|
||||||
pub mod io_loop;
|
pub mod io_loop;
|
||||||
|
|
||||||
pub static SERVER_KEYBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
|
||||||
pub static SERVER_FILE_TRANSFER_ENABLED: AtomicBool = AtomicBool::new(true);
|
|
||||||
pub static SERVER_CLIPBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
|
||||||
pub const MILLI1: Duration = Duration::from_millis(1);
|
pub const MILLI1: Duration = Duration::from_millis(1);
|
||||||
pub const SEC30: Duration = Duration::from_secs(30);
|
pub const SEC30: Duration = Duration::from_secs(30);
|
||||||
|
|
||||||
/// Client of the remote desktop.
|
/// Client of the remote desktop.
|
||||||
pub struct Client;
|
pub struct Client;
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
struct TextClipboardState {
|
||||||
|
is_required: bool,
|
||||||
|
running: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
|
#[cfg(not(any(target_os = "android", target_os = "linux")))]
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref AUDIO_HOST: Host = cpal::default_host();
|
static ref AUDIO_HOST: Host = cpal::default_host();
|
||||||
@ -73,6 +82,8 @@ lazy_static::lazy_static! {
|
|||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref ENIGO: Arc<Mutex<enigo::Enigo>> = Arc::new(Mutex::new(enigo::Enigo::new()));
|
static ref ENIGO: Arc<Mutex<enigo::Enigo>> = Arc::new(Mutex::new(enigo::Enigo::new()));
|
||||||
|
static ref OLD_CLIPBOARD_TEXT: Arc<Mutex<String>> = Default::default();
|
||||||
|
static ref TEXT_CLIPBOARD_STATE: Arc<Mutex<TextClipboardState>> = Arc::new(Mutex::new(TextClipboardState::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
@ -598,6 +609,86 @@ impl Client {
|
|||||||
conn.send(&msg_out).await?;
|
conn.send(&msg_out).await?;
|
||||||
Ok(conn)
|
Ok(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
pub fn set_is_text_clipboard_required(b: bool) {
|
||||||
|
TEXT_CLIPBOARD_STATE.lock().unwrap().is_required = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
fn try_stop_clipboard(_self_id: &str) {
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
if crate::flutter::other_sessions_running(_self_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TEXT_CLIPBOARD_STATE.lock().unwrap().running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
fn try_start_clipboard(_conf_tx: Option<(SessionPermissionConfig, UnboundedSender<Data>)>) {
|
||||||
|
let mut clipboard_lock = TEXT_CLIPBOARD_STATE.lock().unwrap();
|
||||||
|
if clipboard_lock.running {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match ClipboardContext::new() {
|
||||||
|
Ok(mut ctx) => {
|
||||||
|
clipboard_lock.running = true;
|
||||||
|
// ignore clipboard update before service start
|
||||||
|
check_clipboard(&mut ctx, Some(&OLD_CLIPBOARD_TEXT));
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
log::info!("Start text clipboard loop");
|
||||||
|
loop {
|
||||||
|
std::thread::sleep(Duration::from_millis(CLIPBOARD_INTERVAL));
|
||||||
|
if !TEXT_CLIPBOARD_STATE.lock().unwrap().running {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !TEXT_CLIPBOARD_STATE.lock().unwrap().is_required {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(msg) = check_clipboard(&mut ctx, Some(&OLD_CLIPBOARD_TEXT)) {
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
crate::flutter::send_text_clipboard_msg(msg);
|
||||||
|
#[cfg(not(feature = "flutter"))]
|
||||||
|
if let Some((cfg, tx)) = &_conf_tx {
|
||||||
|
if cfg.is_text_clipboard_required() {
|
||||||
|
let _ = tx.send(Data::Message(msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log::info!("Stop text clipboard loop");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("Failed to start clipboard service of client: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
fn get_current_text_clipboard_msg() -> Option<Message> {
|
||||||
|
let txt = &*OLD_CLIPBOARD_TEXT.lock().unwrap();
|
||||||
|
if txt.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(crate::create_clipboard_msg(txt.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
impl TextClipboardState {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
is_required: true,
|
||||||
|
running: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Audio handler for the [`Client`].
|
/// Audio handler for the [`Client`].
|
||||||
@ -1148,6 +1239,10 @@ impl LoginConfigHandler {
|
|||||||
if !name.contains("block-input") {
|
if !name.contains("block-input") {
|
||||||
self.save_config(config);
|
self.save_config(config);
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
if name == "disable-clipboard" {
|
||||||
|
crate::flutter::update_text_clipboard_required();
|
||||||
|
}
|
||||||
let mut misc = Misc::new();
|
let mut misc = Misc::new();
|
||||||
misc.set_option(option);
|
misc.set_option(option);
|
||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
|
@ -26,10 +26,10 @@ use hbb_common::{fs, log, Stream};
|
|||||||
|
|
||||||
use crate::client::{
|
use crate::client::{
|
||||||
new_voice_call_request, Client, CodecFormat, MediaData, MediaSender, QualityStatus, MILLI1,
|
new_voice_call_request, Client, CodecFormat, MediaData, MediaSender, QualityStatus, MILLI1,
|
||||||
SEC30, SERVER_CLIPBOARD_ENABLED, SERVER_FILE_TRANSFER_ENABLED, SERVER_KEYBOARD_ENABLED,
|
SEC30,
|
||||||
};
|
};
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
use crate::common::{check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL};
|
use crate::common::update_clipboard;
|
||||||
use crate::common::{get_default_sound_input, set_sound_input};
|
use crate::common::{get_default_sound_input, set_sound_input};
|
||||||
use crate::ui_session_interface::{InvokeUiSession, Session};
|
use crate::ui_session_interface::{InvokeUiSession, Session};
|
||||||
use crate::{audio_service, common, ConnInner, CLIENT_SERVER};
|
use crate::{audio_service, common, ConnInner, CLIENT_SERVER};
|
||||||
@ -91,7 +91,6 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn io_loop(&mut self, key: &str, token: &str) {
|
pub async fn io_loop(&mut self, key: &str, token: &str) {
|
||||||
let stop_clipboard = self.start_clipboard();
|
|
||||||
let mut last_recv_time = Instant::now();
|
let mut last_recv_time = Instant::now();
|
||||||
let mut received = false;
|
let mut received = false;
|
||||||
let conn_type = if self.handler.is_file_transfer() {
|
let conn_type = if self.handler.is_file_transfer() {
|
||||||
@ -110,9 +109,6 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok((mut peer, direct)) => {
|
Ok((mut peer, direct)) => {
|
||||||
SERVER_KEYBOARD_ENABLED.store(true, Ordering::SeqCst);
|
|
||||||
SERVER_CLIPBOARD_ENABLED.store(true, Ordering::SeqCst);
|
|
||||||
SERVER_FILE_TRANSFER_ENABLED.store(true, Ordering::SeqCst);
|
|
||||||
self.handler.set_connection_type(peer.is_secured(), direct); // flutter -> connection_ready
|
self.handler.set_connection_type(peer.is_secured(), direct); // flutter -> connection_ready
|
||||||
self.handler.set_connection_info(direct, false);
|
self.handler.set_connection_info(direct, false);
|
||||||
|
|
||||||
@ -237,12 +233,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
.msgbox("error", "Connection Error", &err.to_string(), "");
|
.msgbox("error", "Connection Error", &err.to_string(), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(stop) = stop_clipboard {
|
Client::try_stop_clipboard(&self.handler.id);
|
||||||
stop.send(()).ok();
|
|
||||||
}
|
|
||||||
SERVER_KEYBOARD_ENABLED.store(false, Ordering::SeqCst);
|
|
||||||
SERVER_CLIPBOARD_ENABLED.store(false, Ordering::SeqCst);
|
|
||||||
SERVER_FILE_TRANSFER_ENABLED.store(false, Ordering::SeqCst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_job_status(&mut self, id: i32, file_num: i32, err: Option<String>) {
|
fn handle_job_status(&mut self, id: i32, file_num: i32, err: Option<String>) {
|
||||||
@ -347,46 +338,6 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
Some(tx)
|
Some(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_clipboard(&mut self) -> Option<std::sync::mpsc::Sender<()>> {
|
|
||||||
if self.handler.is_file_transfer() || self.handler.is_port_forward() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let (tx, rx) = std::sync::mpsc::channel();
|
|
||||||
let old_clipboard = self.old_clipboard.clone();
|
|
||||||
let tx_protobuf = self.sender.clone();
|
|
||||||
let lc = self.handler.lc.clone();
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
|
||||||
match ClipboardContext::new() {
|
|
||||||
Ok(mut ctx) => {
|
|
||||||
// ignore clipboard update before service start
|
|
||||||
check_clipboard(&mut ctx, Some(&old_clipboard));
|
|
||||||
std::thread::spawn(move || loop {
|
|
||||||
std::thread::sleep(Duration::from_millis(CLIPBOARD_INTERVAL));
|
|
||||||
match rx.try_recv() {
|
|
||||||
Ok(_) | Err(std::sync::mpsc::TryRecvError::Disconnected) => {
|
|
||||||
log::debug!("Exit clipboard service of client");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
if !SERVER_CLIPBOARD_ENABLED.load(Ordering::SeqCst)
|
|
||||||
|| !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst)
|
|
||||||
|| lc.read().unwrap().disable_clipboard.v
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if let Some(msg) = check_clipboard(&mut ctx, Some(&old_clipboard)) {
|
|
||||||
tx_protobuf.send(Data::Message(msg)).ok();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
log::error!("Failed to start clipboard service of client: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_msg_from_ui(&mut self, data: Data, peer: &mut Stream) -> bool {
|
async fn handle_msg_from_ui(&mut self, data: Data, peer: &mut Stream) -> bool {
|
||||||
match data {
|
match data {
|
||||||
Data::Close => {
|
Data::Close => {
|
||||||
@ -885,23 +836,29 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
Some(login_response::Union::PeerInfo(pi)) => {
|
Some(login_response::Union::PeerInfo(pi)) => {
|
||||||
self.handler.handle_peer_info(pi);
|
self.handler.handle_peer_info(pi);
|
||||||
self.check_clipboard_file_context();
|
self.check_clipboard_file_context();
|
||||||
if !(self.handler.is_file_transfer()
|
if !(self.handler.is_file_transfer() || self.handler.is_port_forward()) {
|
||||||
|| self.handler.is_port_forward()
|
|
||||||
|| !SERVER_CLIPBOARD_ENABLED.load(Ordering::SeqCst)
|
|
||||||
|| !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst)
|
|
||||||
|| self.handler.lc.read().unwrap().disable_clipboard.v)
|
|
||||||
{
|
|
||||||
let txt = self.old_clipboard.lock().unwrap().clone();
|
|
||||||
if !txt.is_empty() {
|
|
||||||
let msg_out = crate::create_clipboard_msg(txt);
|
|
||||||
let sender = self.sender.clone();
|
let sender = self.sender.clone();
|
||||||
|
let permission_config = self.handler.get_permission_config();
|
||||||
|
|
||||||
|
#[cfg(feature = "flutter")]
|
||||||
|
Client::try_start_clipboard(None);
|
||||||
|
#[cfg(not(feature = "flutter"))]
|
||||||
|
Client::try_start_clipboard(Some((
|
||||||
|
permission_config.clone(),
|
||||||
|
sender.clone(),
|
||||||
|
)));
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
// due to clipboard service interval time
|
// due to clipboard service interval time
|
||||||
sleep(common::CLIPBOARD_INTERVAL as f32 / 1_000.).await;
|
sleep(common::CLIPBOARD_INTERVAL as f32 / 1_000.).await;
|
||||||
|
if permission_config.is_text_clipboard_required() {
|
||||||
|
if let Some(msg_out) = Client::get_current_text_clipboard_msg()
|
||||||
|
{
|
||||||
sender.send(Data::Message(msg_out)).ok();
|
sender.send(Data::Message(msg_out)).ok();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if self.handler.is_file_transfer() {
|
if self.handler.is_file_transfer() {
|
||||||
self.handler.load_last_jobs();
|
self.handler.load_last_jobs();
|
||||||
@ -1092,18 +1049,23 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
log::info!("Change permission {:?} -> {}", p.permission, p.enabled);
|
log::info!("Change permission {:?} -> {}", p.permission, p.enabled);
|
||||||
match p.permission.enum_value_or_default() {
|
match p.permission.enum_value_or_default() {
|
||||||
Permission::Keyboard => {
|
Permission::Keyboard => {
|
||||||
SERVER_KEYBOARD_ENABLED.store(p.enabled, Ordering::SeqCst);
|
#[cfg(feature = "flutter")]
|
||||||
|
crate::flutter::update_text_clipboard_required();
|
||||||
|
*self.handler.server_keyboard_enabled.write().unwrap() = p.enabled;
|
||||||
self.handler.set_permission("keyboard", p.enabled);
|
self.handler.set_permission("keyboard", p.enabled);
|
||||||
}
|
}
|
||||||
Permission::Clipboard => {
|
Permission::Clipboard => {
|
||||||
SERVER_CLIPBOARD_ENABLED.store(p.enabled, Ordering::SeqCst);
|
#[cfg(feature = "flutter")]
|
||||||
|
crate::flutter::update_text_clipboard_required();
|
||||||
|
*self.handler.server_clipboard_enabled.write().unwrap() = p.enabled;
|
||||||
self.handler.set_permission("clipboard", p.enabled);
|
self.handler.set_permission("clipboard", p.enabled);
|
||||||
}
|
}
|
||||||
Permission::Audio => {
|
Permission::Audio => {
|
||||||
self.handler.set_permission("audio", p.enabled);
|
self.handler.set_permission("audio", p.enabled);
|
||||||
}
|
}
|
||||||
Permission::File => {
|
Permission::File => {
|
||||||
SERVER_FILE_TRANSFER_ENABLED.store(p.enabled, Ordering::SeqCst);
|
*self.handler.server_file_transfer_enabled.write().unwrap() =
|
||||||
|
p.enabled;
|
||||||
if !p.enabled && self.handler.is_file_transfer() {
|
if !p.enabled && self.handler.is_file_transfer() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1416,7 +1378,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
fn check_clipboard_file_context(&self) {
|
fn check_clipboard_file_context(&self) {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
let enabled = SERVER_FILE_TRANSFER_ENABLED.load(Ordering::SeqCst)
|
let enabled = *self.handler.server_file_transfer_enabled.read().unwrap()
|
||||||
&& self.handler.lc.read().unwrap().enable_file_transfer.v;
|
&& self.handler.lc.read().unwrap().enable_file_transfer.v;
|
||||||
ContextSend::enable(enabled);
|
ContextSend::enable(enabled);
|
||||||
}
|
}
|
||||||
|
@ -464,6 +464,9 @@ pub fn session_add(
|
|||||||
|
|
||||||
let session: Session<FlutterHandler> = Session {
|
let session: Session<FlutterHandler> = Session {
|
||||||
id: session_id.clone(),
|
id: session_id.clone(),
|
||||||
|
server_keyboard_enabled: Arc::new(RwLock::new(true)),
|
||||||
|
server_file_transfer_enabled: Arc::new(RwLock::new(true)),
|
||||||
|
server_clipboard_enabled: Arc::new(RwLock::new(true)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -514,6 +517,31 @@ pub fn session_start_(id: &str, event_stream: StreamSink<EventToUI>) -> ResultTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
pub fn update_text_clipboard_required() {
|
||||||
|
let is_required = SESSIONS
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.any(|(_id, session)| session.is_text_clipboard_required());
|
||||||
|
Client::set_is_text_clipboard_required(is_required);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
pub fn other_sessions_running(id: &str) -> bool {
|
||||||
|
SESSIONS.read().unwrap().keys().filter(|k| *k != id).count() != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
pub fn send_text_clipboard_msg(msg: Message) {
|
||||||
|
for (_id, session) in SESSIONS.read().unwrap().iter() {
|
||||||
|
if session.is_text_clipboard_required() {
|
||||||
|
session.send(Data::Message(msg.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Server Side
|
// Server Side
|
||||||
#[cfg(not(any(target_os = "ios")))]
|
#[cfg(not(any(target_os = "ios")))]
|
||||||
pub mod connection_manager {
|
pub mod connection_manager {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use sciter::{
|
use sciter::{
|
||||||
@ -454,6 +454,9 @@ impl SciterSession {
|
|||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
password: password.clone(),
|
password: password.clone(),
|
||||||
args,
|
args,
|
||||||
|
server_keyboard_enabled: Arc::new(RwLock::new(true)),
|
||||||
|
server_file_transfer_enabled: Arc::new(RwLock::new(true)),
|
||||||
|
server_clipboard_enabled: Arc::new(RwLock::new(true)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::{
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||||
use std::time::Duration;
|
Arc, Mutex, RwLock,
|
||||||
|
};
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
@ -37,9 +39,37 @@ pub struct Session<T: InvokeUiSession> {
|
|||||||
pub sender: Arc<RwLock<Option<mpsc::UnboundedSender<Data>>>>,
|
pub sender: Arc<RwLock<Option<mpsc::UnboundedSender<Data>>>>,
|
||||||
pub thread: Arc<Mutex<Option<std::thread::JoinHandle<()>>>>,
|
pub thread: Arc<Mutex<Option<std::thread::JoinHandle<()>>>>,
|
||||||
pub ui_handler: T,
|
pub ui_handler: T,
|
||||||
|
pub server_keyboard_enabled: Arc<RwLock<bool>>,
|
||||||
|
pub server_file_transfer_enabled: Arc<RwLock<bool>>,
|
||||||
|
pub server_clipboard_enabled: Arc<RwLock<bool>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SessionPermissionConfig {
|
||||||
|
pub lc: Arc<RwLock<LoginConfigHandler>>,
|
||||||
|
pub server_keyboard_enabled: Arc<RwLock<bool>>,
|
||||||
|
pub server_file_transfer_enabled: Arc<RwLock<bool>>,
|
||||||
|
pub server_clipboard_enabled: Arc<RwLock<bool>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SessionPermissionConfig {
|
||||||
|
pub fn is_text_clipboard_required(&self) -> bool {
|
||||||
|
*self.server_clipboard_enabled.read().unwrap()
|
||||||
|
&& *self.server_keyboard_enabled.read().unwrap()
|
||||||
|
&& !self.lc.read().unwrap().disable_clipboard.v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: InvokeUiSession> Session<T> {
|
impl<T: InvokeUiSession> Session<T> {
|
||||||
|
pub fn get_permission_config(&self) -> SessionPermissionConfig {
|
||||||
|
SessionPermissionConfig {
|
||||||
|
lc: self.lc.clone(),
|
||||||
|
server_keyboard_enabled: self.server_keyboard_enabled.clone(),
|
||||||
|
server_file_transfer_enabled: self.server_file_transfer_enabled.clone(),
|
||||||
|
server_clipboard_enabled: self.server_clipboard_enabled.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_file_transfer(&self) -> bool {
|
pub fn is_file_transfer(&self) -> bool {
|
||||||
self.lc
|
self.lc
|
||||||
.read()
|
.read()
|
||||||
@ -128,6 +158,12 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
self.lc.read().unwrap().is_privacy_mode_supported()
|
self.lc.read().unwrap().is_privacy_mode_supported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_text_clipboard_required(&self) -> bool {
|
||||||
|
*self.server_clipboard_enabled.read().unwrap()
|
||||||
|
&& *self.server_keyboard_enabled.read().unwrap()
|
||||||
|
&& !self.lc.read().unwrap().disable_clipboard.v
|
||||||
|
}
|
||||||
|
|
||||||
pub fn refresh_video(&self) {
|
pub fn refresh_video(&self) {
|
||||||
self.send(Data::Message(LoginConfigHandler::refresh()));
|
self.send(Data::Message(LoginConfigHandler::refresh()));
|
||||||
}
|
}
|
||||||
@ -445,7 +481,7 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
KeyRelease(key)
|
KeyRelease(key)
|
||||||
};
|
};
|
||||||
let event = Event {
|
let event = Event {
|
||||||
time: std::time::SystemTime::now(),
|
time: SystemTime::now(),
|
||||||
unicode: None,
|
unicode: None,
|
||||||
code: keycode as _,
|
code: keycode as _,
|
||||||
scan_code: scancode as _,
|
scan_code: scancode as _,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user