mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-19 19:21:13 +03:00
feat: android clipboard, multi-formats (#9950)
* feat: android clipboard, multi-formats Signed-off-by: fufesou <linlong1266@gmail.com> * Chore Signed-off-by: fufesou <linlong1266@gmail.com> * Remove unused code Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -71,8 +71,10 @@ use crate::{
|
||||
ui_session_interface::{InvokeUiSession, Session},
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
use crate::clipboard::CLIPBOARD_INTERVAL;
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::clipboard::{check_clipboard, ClipboardSide, CLIPBOARD_INTERVAL};
|
||||
use crate::clipboard::{check_clipboard, ClipboardSide};
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::ui_session_interface::SessionPermissionConfig;
|
||||
@@ -131,7 +133,7 @@ pub(crate) struct ClientClipboardContext {
|
||||
/// Client of the remote desktop.
|
||||
pub struct Client;
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
struct TextClipboardState {
|
||||
is_required: bool,
|
||||
running: bool,
|
||||
@@ -144,6 +146,10 @@ lazy_static::lazy_static! {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
lazy_static::lazy_static! {
|
||||
static ref ENIGO: Arc<Mutex<enigo::Enigo>> = Arc::new(Mutex::new(enigo::Enigo::new()));
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
lazy_static::lazy_static! {
|
||||
static ref TEXT_CLIPBOARD_STATE: Arc<Mutex<TextClipboardState>> = Arc::new(Mutex::new(TextClipboardState::new()));
|
||||
}
|
||||
|
||||
@@ -648,12 +654,12 @@ impl Client {
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(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")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
fn try_stop_clipboard() {
|
||||
// There's a bug here.
|
||||
// If session is closed by the peer, `has_sessions_running()` will always return true.
|
||||
@@ -748,9 +754,41 @@ impl Client {
|
||||
|
||||
Some(rx_started)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
fn try_start_clipboard(_p: Option<()>) -> Option<UnboundedReceiver<()>> {
|
||||
let mut clipboard_lock = TEXT_CLIPBOARD_STATE.lock().unwrap();
|
||||
if clipboard_lock.running {
|
||||
return None;
|
||||
}
|
||||
clipboard_lock.running = true;
|
||||
|
||||
log::info!("Start text clipboard loop");
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
if !TEXT_CLIPBOARD_STATE.lock().unwrap().running {
|
||||
break;
|
||||
}
|
||||
if !TEXT_CLIPBOARD_STATE.lock().unwrap().is_required {
|
||||
std::thread::sleep(Duration::from_millis(CLIPBOARD_INTERVAL));
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(msg) = crate::clipboard::get_clipboards_msg(true) {
|
||||
crate::flutter::send_text_clipboard_msg(msg);
|
||||
}
|
||||
|
||||
std::thread::sleep(Duration::from_millis(CLIPBOARD_INTERVAL));
|
||||
}
|
||||
log::info!("Stop text clipboard loop");
|
||||
TEXT_CLIPBOARD_STATE.lock().unwrap().running = false;
|
||||
});
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
impl TextClipboardState {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -8,9 +8,9 @@ use std::{
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::clipboard::{update_clipboard, ClipboardSide, CLIPBOARD_INTERVAL};
|
||||
use crate::clipboard::{update_clipboard, ClipboardSide};
|
||||
#[cfg(not(any(target_os = "ios")))]
|
||||
use crate::{audio_service, ConnInner, CLIENT_SERVER};
|
||||
use crate::{audio_service, clipboard::CLIPBOARD_INTERVAL, ConnInner, CLIENT_SERVER};
|
||||
use crate::{
|
||||
client::{
|
||||
self, new_voice_call_request, Client, Data, Interface, MediaData, MediaSender,
|
||||
@@ -302,7 +302,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
.unwrap()
|
||||
.set_disconnected(round);
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
if _set_disconnected_ok {
|
||||
Client::try_stop_clipboard();
|
||||
}
|
||||
@@ -1177,7 +1177,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
self.check_clipboard_file_context();
|
||||
if !(self.handler.is_file_transfer() || self.handler.is_port_forward()) {
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
let rx = Client::try_start_clipboard(None);
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
@@ -1188,7 +1188,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
},
|
||||
));
|
||||
// To make sure current text clipboard data is updated.
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
if let Some(mut rx) = rx {
|
||||
timeout(CLIPBOARD_INTERVAL, rx.recv()).await.ok();
|
||||
}
|
||||
@@ -1209,6 +1209,11 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
});
|
||||
}
|
||||
}
|
||||
// to-do: Android, is `sync_init_clipboard` really needed?
|
||||
// https://github.com/rustdesk/rustdesk/discussions/9010
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
crate::flutter::update_text_clipboard_required();
|
||||
|
||||
// on connection established client
|
||||
#[cfg(all(feature = "flutter", feature = "plugin_framework"))]
|
||||
@@ -1240,7 +1245,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
if !self.handler.lc.read().unwrap().disable_clipboard.v {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
update_clipboard(vec![cb], ClipboardSide::Client);
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
#[cfg(target_os = "ios")]
|
||||
{
|
||||
let content = if cb.compress {
|
||||
hbb_common::compress::decompress(&cb.content)
|
||||
@@ -1251,12 +1256,16 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
self.handler.clipboard(content);
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "android")]
|
||||
crate::clipboard::handle_msg_clipboard(cb);
|
||||
}
|
||||
}
|
||||
Some(message::Union::MultiClipboards(_mcb)) => {
|
||||
if !self.handler.lc.read().unwrap().disable_clipboard.v {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
update_clipboard(_mcb.clipboards, ClipboardSide::Client);
|
||||
#[cfg(target_os = "android")]
|
||||
crate::clipboard::handle_msg_multi_clipboards(_mcb);
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||
@@ -1421,14 +1430,14 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
Ok(Permission::Keyboard) => {
|
||||
*self.handler.server_keyboard_enabled.write().unwrap() = p.enabled;
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
crate::flutter::update_text_clipboard_required();
|
||||
self.handler.set_permission("keyboard", p.enabled);
|
||||
}
|
||||
Ok(Permission::Clipboard) => {
|
||||
*self.handler.server_clipboard_enabled.write().unwrap() = p.enabled;
|
||||
#[cfg(feature = "flutter")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
crate::flutter::update_text_clipboard_required();
|
||||
self.handler.set_permission("clipboard", p.enabled);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use arboard::{ClipboardData, ClipboardFormat};
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use clipboard_master::{ClipboardHandler, Master, Shutdown};
|
||||
use hbb_common::{bail, log, message_proto::*, ResultType};
|
||||
use std::{
|
||||
@@ -16,6 +18,7 @@ const RUSTDESK_CLIPBOARD_OWNER_FORMAT: &'static str = "dyn.com.rustdesk.owner";
|
||||
// Add special format for Excel XML Spreadsheet
|
||||
const CLIPBOARD_FORMAT_EXCEL_XML_SPREADSHEET: &'static str = "XML Spreadsheet";
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
lazy_static::lazy_static! {
|
||||
static ref ARBOARD_MTX: Arc<Mutex<()>> = Arc::new(Mutex::new(()));
|
||||
// cache the clipboard msg
|
||||
@@ -27,9 +30,12 @@ lazy_static::lazy_static! {
|
||||
static ref CLIPBOARD_CTX: Arc<Mutex<Option<ClipboardContext>>> = Arc::new(Mutex::new(None));
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
const CLIPBOARD_GET_MAX_RETRY: usize = 3;
|
||||
#[cfg(not(target_os = "android"))]
|
||||
const CLIPBOARD_GET_RETRY_INTERVAL_DUR: Duration = Duration::from_millis(33);
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
const SUPPORTED_FORMATS: &[ClipboardFormat] = &[
|
||||
ClipboardFormat::Text,
|
||||
ClipboardFormat::Html,
|
||||
@@ -146,6 +152,7 @@ impl ClipboardContext {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn check_clipboard(
|
||||
ctx: &mut Option<ClipboardContext>,
|
||||
side: ClipboardSide,
|
||||
@@ -194,6 +201,7 @@ pub fn check_clipboard_cm() -> ResultType<MultiClipboards> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn update_clipboard_(multi_clipboards: Vec<Clipboard>, side: ClipboardSide) {
|
||||
let mut to_update_data = proto::from_multi_clipbards(multi_clipboards);
|
||||
if to_update_data.is_empty() {
|
||||
@@ -224,17 +232,20 @@ fn update_clipboard_(multi_clipboards: Vec<Clipboard>, side: ClipboardSide) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn update_clipboard(multi_clipboards: Vec<Clipboard>, side: ClipboardSide) {
|
||||
std::thread::spawn(move || {
|
||||
update_clipboard_(multi_clipboards, side);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
#[cfg(not(any(all(target_os = "linux", feature = "unix-file-copy-paste"))))]
|
||||
pub struct ClipboardContext {
|
||||
inner: arboard::Clipboard,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
#[cfg(not(any(all(target_os = "linux", feature = "unix-file-copy-paste"))))]
|
||||
#[allow(unreachable_code)]
|
||||
impl ClipboardContext {
|
||||
@@ -337,10 +348,20 @@ impl ClipboardContext {
|
||||
|
||||
pub fn is_support_multi_clipboard(peer_version: &str, peer_platform: &str) -> bool {
|
||||
use hbb_common::get_version_number;
|
||||
get_version_number(peer_version) >= get_version_number("1.3.0")
|
||||
&& !["", "Android", &whoami::Platform::Ios.to_string()].contains(&peer_platform)
|
||||
if get_version_number(peer_version) < get_version_number("1.3.0") {
|
||||
return false;
|
||||
}
|
||||
if ["", &whoami::Platform::Ios.to_string()].contains(&peer_platform) {
|
||||
return false;
|
||||
}
|
||||
if "Android" == peer_platform && get_version_number(peer_version) < get_version_number("1.3.3")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn get_current_clipboard_msg(
|
||||
peer_version: &str,
|
||||
peer_platform: &str,
|
||||
@@ -406,6 +427,7 @@ impl std::fmt::Display for ClipboardSide {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn start_clipbard_master_thread(
|
||||
handler: impl ClipboardHandler + Send + 'static,
|
||||
tx_start_res: Sender<(Option<Shutdown>, String)>,
|
||||
@@ -437,6 +459,7 @@ pub fn start_clipbard_master_thread(
|
||||
|
||||
pub use proto::get_msg_if_not_support_multi_clip;
|
||||
mod proto {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use arboard::ClipboardData;
|
||||
use hbb_common::{
|
||||
compress::{compress as compress_func, decompress},
|
||||
@@ -459,6 +482,7 @@ mod proto {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn image_to_proto(a: arboard::ImageData) -> Clipboard {
|
||||
match &a {
|
||||
arboard::ImageData::Rgba(rgba) => {
|
||||
@@ -519,6 +543,7 @@ mod proto {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn clipboard_data_to_proto(data: ClipboardData) -> Option<Clipboard> {
|
||||
let d = match data {
|
||||
ClipboardData::Text(s) => plain_to_proto(s, ClipboardFormat::Text),
|
||||
@@ -531,6 +556,7 @@ mod proto {
|
||||
Some(d)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn create_multi_clipboards(vec_data: Vec<ClipboardData>) -> MultiClipboards {
|
||||
MultiClipboards {
|
||||
clipboards: vec_data
|
||||
@@ -541,6 +567,7 @@ mod proto {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn from_clipboard(clipboard: Clipboard) -> Option<ClipboardData> {
|
||||
let data = if clipboard.compress {
|
||||
decompress(&clipboard.content)
|
||||
@@ -569,6 +596,7 @@ mod proto {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn from_multi_clipbards(multi_clipboards: Vec<Clipboard>) -> Vec<ClipboardData> {
|
||||
multi_clipboards
|
||||
.into_iter()
|
||||
@@ -597,3 +625,49 @@ mod proto {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn handle_msg_clipboard(mut cb: Clipboard) {
|
||||
use hbb_common::protobuf::Message;
|
||||
|
||||
if cb.compress {
|
||||
cb.content = bytes::Bytes::from(hbb_common::compress::decompress(&cb.content));
|
||||
}
|
||||
let multi_clips = MultiClipboards {
|
||||
clipboards: vec![cb],
|
||||
..Default::default()
|
||||
};
|
||||
if let Ok(bytes) = multi_clips.write_to_bytes() {
|
||||
let _ = scrap::android::ffi::call_clipboard_manager_update_clipboard(&bytes);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn handle_msg_multi_clipboards(mut mcb: MultiClipboards) {
|
||||
use hbb_common::protobuf::Message;
|
||||
|
||||
for cb in mcb.clipboards.iter_mut() {
|
||||
if cb.compress {
|
||||
cb.content = bytes::Bytes::from(hbb_common::compress::decompress(&cb.content));
|
||||
}
|
||||
}
|
||||
if let Ok(bytes) = mcb.write_to_bytes() {
|
||||
let _ = scrap::android::ffi::call_clipboard_manager_update_clipboard(&bytes);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn get_clipboards_msg(client: bool) -> Option<Message> {
|
||||
let mut clipboards = scrap::android::ffi::get_clipboards(client)?;
|
||||
let mut msg = Message::new();
|
||||
for c in &mut clipboards.clipboards {
|
||||
let compressed = hbb_common::compress::compress(&c.content);
|
||||
let compress = compressed.len() < c.content.len();
|
||||
if compress {
|
||||
c.content = compressed.into();
|
||||
}
|
||||
c.compress = compress;
|
||||
}
|
||||
msg.set_multi_clipboards(clipboards);
|
||||
Some(msg)
|
||||
}
|
||||
|
||||
@@ -1250,15 +1250,17 @@ fn try_send_close_event(event_stream: &Option<StreamSink<EventToUI>>) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
pub fn update_text_clipboard_required() {
|
||||
let is_required = sessions::get_sessions()
|
||||
.iter()
|
||||
.any(|s| s.is_text_clipboard_required());
|
||||
#[cfg(target_os = "android")]
|
||||
let _ = scrap::android::ffi::call_clipboard_manager_enable_client_clipboard(is_required);
|
||||
Client::set_is_text_clipboard_required(is_required);
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
pub fn send_text_clipboard_msg(msg: Message) {
|
||||
for s in sessions::get_sessions() {
|
||||
if s.is_text_clipboard_required() {
|
||||
@@ -2051,7 +2053,7 @@ pub mod sessions {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
pub fn has_sessions_running(conn_type: ConnType) -> bool {
|
||||
SESSIONS.read().unwrap().iter().any(|((_, r#type), s)| {
|
||||
*r#type == conn_type && s.session_handlers.read().unwrap().len() != 0
|
||||
|
||||
@@ -274,7 +274,7 @@ pub fn session_toggle_option(session_id: SessionID, value: String) {
|
||||
session.toggle_option(value.clone());
|
||||
try_sync_peer_option(&session, &session_id, &value, None);
|
||||
}
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
if sessions::get_session_by_session_id(&session_id).is_some() && value == "disable-clipboard" {
|
||||
crate::flutter::update_text_clipboard_required();
|
||||
}
|
||||
@@ -817,6 +817,17 @@ pub fn main_show_option(_key: String) -> SyncReturn<bool> {
|
||||
SyncReturn(false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_os = "android")]
|
||||
fn enable_server_clipboard(keyboard_enabled: &str, clip_enabled: &str) {
|
||||
use scrap::android::ffi::call_clipboard_manager_enable_service_clipboard;
|
||||
let keyboard_enabled =
|
||||
config::option2bool(config::keys::OPTION_ENABLE_KEYBOARD, &keyboard_enabled);
|
||||
let clip_enabled = config::option2bool(config::keys::OPTION_ENABLE_CLIPBOARD, &clip_enabled);
|
||||
crate::ui_cm_interface::switch_permission_all("clipboard".to_owned(), clip_enabled);
|
||||
let _ = call_clipboard_manager_enable_service_clipboard(keyboard_enabled && clip_enabled);
|
||||
}
|
||||
|
||||
pub fn main_set_option(key: String, value: String) {
|
||||
#[cfg(target_os = "android")]
|
||||
if key.eq(config::keys::OPTION_ENABLE_KEYBOARD) {
|
||||
@@ -824,6 +835,11 @@ pub fn main_set_option(key: String, value: String) {
|
||||
config::keys::OPTION_ENABLE_KEYBOARD,
|
||||
&value,
|
||||
));
|
||||
enable_server_clipboard(&value, &get_option(config::keys::OPTION_ENABLE_CLIPBOARD));
|
||||
}
|
||||
#[cfg(target_os = "android")]
|
||||
if key.eq(config::keys::OPTION_ENABLE_CLIPBOARD) {
|
||||
enable_server_clipboard(&get_option(config::keys::OPTION_ENABLE_KEYBOARD), &value);
|
||||
}
|
||||
if key.eq("custom-rendezvous-server") {
|
||||
set_option(key, value.clone());
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "上传文件夹"),
|
||||
("Upload files", "上传文件"),
|
||||
("Clipboard is synchronized", "剪贴板已同步"),
|
||||
("Update client clipboard", "更新客户端的粘贴板"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "Ordner hochladen"),
|
||||
("Upload files", "Dateien hochladen"),
|
||||
("Clipboard is synchronized", "Zwischenablage ist synchronisiert"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "Subir carpeta"),
|
||||
("Upload files", "Subir archivos"),
|
||||
("Clipboard is synchronized", "Portapapeles sincronizado"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "Mappa feltöltése"),
|
||||
("Upload files", "Fájlok feltöltése"),
|
||||
("Clipboard is synchronized", "A vágólap szinkronizálva van"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "Cartella upload"),
|
||||
("Upload files", "File upload"),
|
||||
("Clipboard is synchronized", "Gli appunti sono sincronizzati"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "폴더 업로드"),
|
||||
("Upload files", "파일 업로드"),
|
||||
("Clipboard is synchronized", "클립보드가 동기화됨"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "Augšupielādēt mapi"),
|
||||
("Upload files", "Augšupielādēt failus"),
|
||||
("Clipboard is synchronized", "Starpliktuve ir sinhronizēta"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "Map uploaden"),
|
||||
("Upload files", "Bestanden uploaden"),
|
||||
("Clipboard is synchronized", "Klembord is gesynchroniseerd"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "Wyślij folder"),
|
||||
("Upload files", "Wyślij pliki"),
|
||||
("Clipboard is synchronized", "Schowek jest zsynchronizowany"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "Загрузить папку"),
|
||||
("Upload files", "Загрузить файлы"),
|
||||
("Clipboard is synchronized", "Буфер обмена синхронизирован"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", "上傳資料夾"),
|
||||
("Upload files", "上傳檔案"),
|
||||
("Clipboard is synchronized", "剪貼簿已同步"),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -653,5 +653,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload folder", ""),
|
||||
("Upload files", ""),
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ mod custom_server;
|
||||
mod lang;
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
mod port_forward;
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
mod clipboard;
|
||||
|
||||
#[cfg(all(feature = "flutter", feature = "plugin_framework"))]
|
||||
|
||||
@@ -32,7 +32,7 @@ use crate::ipc::Data;
|
||||
|
||||
pub mod audio_service;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(any(target_os = "android", target_os = "ios")))] {
|
||||
if #[cfg(not(target_os = "ios"))] {
|
||||
mod clipboard_service;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) mod wayland;
|
||||
@@ -42,17 +42,20 @@ pub mod uinput;
|
||||
pub mod rdp_input;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod dbus;
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub mod input_service;
|
||||
} else {
|
||||
mod clipboard_service {
|
||||
pub const NAME: &'static str = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
pub mod input_service {
|
||||
pub const NAME_CURSOR: &'static str = "";
|
||||
pub const NAME_POS: &'static str = "";
|
||||
pub const NAME_WINDOW_FOCUS: &'static str = "";
|
||||
}
|
||||
}
|
||||
pub const NAME_CURSOR: &'static str = "";
|
||||
pub const NAME_POS: &'static str = "";
|
||||
pub const NAME_WINDOW_FOCUS: &'static str = "";
|
||||
}
|
||||
|
||||
mod connection;
|
||||
@@ -99,10 +102,12 @@ pub fn new() -> ServerPtr {
|
||||
};
|
||||
server.add_service(Box::new(audio_service::new()));
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
server.add_service(Box::new(display_service::new()));
|
||||
{
|
||||
server.add_service(Box::new(display_service::new()));
|
||||
server.add_service(Box::new(clipboard_service::new()));
|
||||
}
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
server.add_service(Box::new(clipboard_service::new()));
|
||||
if !display_service::capture_cursor_embedded() {
|
||||
server.add_service(Box::new(input_service::new_cursor()));
|
||||
server.add_service(Box::new(input_service::new_pos()));
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
use super::*;
|
||||
pub use crate::clipboard::{
|
||||
check_clipboard, ClipboardContext, ClipboardSide, CLIPBOARD_INTERVAL as INTERVAL,
|
||||
CLIPBOARD_NAME as NAME,
|
||||
};
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub use crate::clipboard::{check_clipboard, ClipboardContext, ClipboardSide};
|
||||
pub use crate::clipboard::{CLIPBOARD_INTERVAL as INTERVAL, CLIPBOARD_NAME as NAME};
|
||||
#[cfg(windows)]
|
||||
use crate::ipc::{self, ClipboardFile, ClipboardNonFile, Data};
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use clipboard_master::{CallbackResult, ClipboardHandler};
|
||||
#[cfg(target_os = "android")]
|
||||
use hbb_common::config::{keys, option2bool};
|
||||
#[cfg(target_os = "android")]
|
||||
use scrap::android::ffi::call_clipboard_manager_enable_service_clipboard;
|
||||
use std::{
|
||||
io,
|
||||
sync::mpsc::{channel, RecvTimeoutError, Sender},
|
||||
@@ -14,6 +18,7 @@ use std::{
|
||||
#[cfg(windows)]
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
struct Handler {
|
||||
sp: EmptyExtraFieldService,
|
||||
ctx: Option<ClipboardContext>,
|
||||
@@ -25,11 +30,12 @@ struct Handler {
|
||||
}
|
||||
|
||||
pub fn new() -> GenericService {
|
||||
let svc = EmptyExtraFieldService::new(NAME.to_owned(), true);
|
||||
let svc = EmptyExtraFieldService::new(NAME.to_owned(), false);
|
||||
GenericService::run(&svc.clone(), run);
|
||||
svc.sp
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn run(sp: EmptyExtraFieldService) -> ResultType<()> {
|
||||
let (tx_cb_result, rx_cb_result) = channel();
|
||||
let handler = Handler {
|
||||
@@ -73,9 +79,9 @@ fn run(sp: EmptyExtraFieldService) -> ResultType<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
impl ClipboardHandler for Handler {
|
||||
fn on_clipboard_change(&mut self) -> CallbackResult {
|
||||
self.sp.snapshot(|_sps| Ok(())).ok();
|
||||
if self.sp.ok() {
|
||||
if let Some(msg) = self.get_clipboard_msg() {
|
||||
self.sp.send(msg);
|
||||
@@ -92,6 +98,7 @@ impl ClipboardHandler for Handler {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
impl Handler {
|
||||
fn get_clipboard_msg(&mut self) -> Option<Message> {
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -216,3 +223,25 @@ impl Handler {
|
||||
bail!("failed to get clipboard data from cm");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
fn is_clipboard_enabled() -> bool {
|
||||
let keyboard_enabled = crate::ui_interface::get_option(keys::OPTION_ENABLE_KEYBOARD);
|
||||
let keyboard_enabled = option2bool(keys::OPTION_ENABLE_KEYBOARD, &keyboard_enabled);
|
||||
let clip_enabled = crate::ui_interface::get_option(keys::OPTION_ENABLE_CLIPBOARD);
|
||||
let clip_enabled = option2bool(keys::OPTION_ENABLE_CLIPBOARD, &clip_enabled);
|
||||
keyboard_enabled && clip_enabled
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
fn run(sp: EmptyExtraFieldService) -> ResultType<()> {
|
||||
let _res = call_clipboard_manager_enable_service_clipboard(is_clipboard_enabled());
|
||||
while sp.ok() {
|
||||
if let Some(msg) = crate::clipboard::get_clipboards_msg(false) {
|
||||
sp.send(msg);
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis(INTERVAL));
|
||||
}
|
||||
let _res = call_clipboard_manager_enable_service_clipboard(false);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -690,7 +690,7 @@ impl Connection {
|
||||
}
|
||||
}
|
||||
Some(message::Union::MultiClipboards(_multi_clipboards)) => {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
if let Some(msg_out) = crate::clipboard::get_msg_if_not_support_multi_clip(&conn.lr.version, &conn.lr.my_platform, _multi_clipboards) {
|
||||
if let Err(err) = conn.stream.send(&msg_out).await {
|
||||
conn.on_close(&err.to_string(), false).await;
|
||||
@@ -2074,7 +2074,9 @@ impl Connection {
|
||||
if self.clipboard {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
update_clipboard(vec![cb], ClipboardSide::Host);
|
||||
#[cfg(all(feature = "flutter", target_os = "android"))]
|
||||
// ios as the controlled side is actually not supported for now.
|
||||
// The following code is only used to preserve the logic of handling text clipboard on mobile.
|
||||
#[cfg(target_os = "ios")]
|
||||
{
|
||||
let content = if cb.compress {
|
||||
hbb_common::compress::decompress(&cb.content)
|
||||
@@ -2092,14 +2094,17 @@ impl Connection {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "android")]
|
||||
crate::clipboard::handle_msg_clipboard(cb);
|
||||
}
|
||||
}
|
||||
Some(message::Union::MultiClipboards(_mcb)) =>
|
||||
{
|
||||
Some(message::Union::MultiClipboards(_mcb)) => {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
if self.clipboard {
|
||||
update_clipboard(_mcb.clipboards, ClipboardSide::Host);
|
||||
}
|
||||
#[cfg(target_os = "android")]
|
||||
crate::clipboard::handle_msg_multi_clipboards(_mcb);
|
||||
}
|
||||
Some(message::Union::Cliprdr(_clip)) =>
|
||||
{
|
||||
|
||||
@@ -312,6 +312,17 @@ pub fn switch_permission(id: i32, name: String, enabled: bool) {
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn switch_permission_all(name: String, enabled: bool) {
|
||||
for (_, client) in CLIENTS.read().unwrap().iter() {
|
||||
allow_err!(client.tx.send(Data::SwitchPermission {
|
||||
name: name.clone(),
|
||||
enabled
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
#[inline]
|
||||
pub fn get_clients_state() -> String {
|
||||
|
||||
@@ -354,7 +354,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.lc.read().unwrap().is_privacy_mode_supported()
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
pub fn is_text_clipboard_required(&self) -> bool {
|
||||
*self.server_clipboard_enabled.read().unwrap()
|
||||
&& *self.server_keyboard_enabled.read().unwrap()
|
||||
@@ -526,10 +526,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn is_xfce(&self) -> bool {
|
||||
#[cfg(not(any(target_os = "ios")))]
|
||||
return crate::platform::is_xfce();
|
||||
#[cfg(any(target_os = "ios"))]
|
||||
false
|
||||
crate::platform::is_xfce()
|
||||
}
|
||||
|
||||
pub fn remove_port_forward(&self, port: i32) {
|
||||
|
||||
Reference in New Issue
Block a user