Merge pull request #4795 from dignow/refact/win_cliprd_wait_timeout

Refact/win cliprd wait timeout
This commit is contained in:
RustDesk 2023-06-29 22:50:45 +08:00 committed by GitHub
commit c01dfc9af3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 223 additions and 37 deletions

View File

@ -998,6 +998,26 @@ Widget msgboxIcon(String type) {
// title should be null
Widget msgboxContent(String type, String title, String text) {
String translateText(String text) {
if (text.indexOf('Failed') == 0 && text.indexOf(': ') > 0) {
List<String> words = text.split(': ');
for (var i = 0; i < words.length; ++i) {
words[i] = translate(words[i]);
}
text = words.join(': ');
} else {
List<String> words = text.split(' ');
if (words.length > 1 && words[0].endsWith('_tip')) {
words[0] = translate(words[0]);
final rest = text.substring(words[0].length + 1);
text = '${words[0]} ${translate(rest)}';
} else {
text = translate(text);
}
}
return text;
}
return Row(
children: [
msgboxIcon(type),
@ -1009,7 +1029,7 @@ Widget msgboxContent(String type, String title, String text) {
translate(title),
style: TextStyle(fontSize: 21),
).marginOnly(bottom: 10),
Text(translate(text), style: const TextStyle(fontSize: 15)),
Text(translateText(text), style: const TextStyle(fontSize: 15)),
],
),
),

View File

@ -150,6 +150,15 @@ extern "C"
typedef struct _cliprdr_client_context CliprdrClientContext;
struct _NOTIFICATION_MESSAGE
{
// 0 - info, 1 - warning, 2 - error
UINT32 type;
char *msg;
char *details;
};
typedef struct _NOTIFICATION_MESSAGE NOTIFICATION_MESSAGE;
typedef UINT (*pcCliprdrServerCapabilities)(CliprdrClientContext *context,
const CLIPRDR_CAPABILITIES *capabilities);
typedef UINT (*pcCliprdrClientCapabilities)(CliprdrClientContext *context,
@ -158,6 +167,9 @@ extern "C"
const CLIPRDR_MONITOR_READY *monitorReady);
typedef UINT (*pcCliprdrTempDirectory)(CliprdrClientContext *context,
const CLIPRDR_TEMP_DIRECTORY *tempDirectory);
typedef UINT (*pcNotifyClipboardMsg)(UINT32 connID, const NOTIFICATION_MESSAGE *msg);
typedef UINT (*pcCliprdrClientFormatList)(CliprdrClientContext *context,
const CLIPRDR_FORMAT_LIST *formatList);
typedef UINT (*pcCliprdrServerFormatList)(CliprdrClientContext *context,
@ -199,10 +211,12 @@ extern "C"
BOOL EnableOthers;
BOOL IsStopped;
UINT32 ResponseWaitTimeoutSecs;
pcCliprdrServerCapabilities ServerCapabilities;
pcCliprdrClientCapabilities ClientCapabilities;
pcCliprdrMonitorReady MonitorReady;
pcCliprdrTempDirectory TempDirectory;
pcNotifyClipboardMsg NotifyClipboardMsg;
pcCliprdrClientFormatList ClientFormatList;
pcCliprdrServerFormatList ServerFormatList;
pcCliprdrClientFormatListResponse ClientFormatListResponse;
@ -228,4 +242,3 @@ extern "C"
#endif
#endif // WF_CLIPRDR_H__

View File

@ -324,6 +324,14 @@ pub struct _CLIPRDR_FILE_CONTENTS_RESPONSE {
}
pub type CLIPRDR_FILE_CONTENTS_RESPONSE = _CLIPRDR_FILE_CONTENTS_RESPONSE;
pub type CliprdrClientContext = _cliprdr_client_context;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _NOTIFICATION_MESSAGE {
pub r#type: UINT32, // 0 - info, 1 - warning, 2 - error
pub msg: *const BYTE,
pub details: *const BYTE,
}
pub type NOTIFICATION_MESSAGE = _NOTIFICATION_MESSAGE;
pub type pcCliprdrServerCapabilities = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
@ -348,6 +356,8 @@ pub type pcCliprdrTempDirectory = ::std::option::Option<
tempDirectory: *const CLIPRDR_TEMP_DIRECTORY,
) -> UINT,
>;
pub type pcNotifyClipboardMsg =
::std::option::Option<unsafe extern "C" fn(connID: UINT32, msg: *const NOTIFICATION_MESSAGE) -> UINT>;
pub type pcCliprdrClientFormatList = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
@ -453,10 +463,12 @@ pub struct _cliprdr_client_context {
pub EnableFiles: BOOL,
pub EnableOthers: BOOL,
pub IsStopped: BOOL,
pub ResponseWaitTimeoutSecs: UINT32,
pub ServerCapabilities: pcCliprdrServerCapabilities,
pub ClientCapabilities: pcCliprdrClientCapabilities,
pub MonitorReady: pcCliprdrMonitorReady,
pub TempDirectory: pcCliprdrTempDirectory,
pub NotifyClipboardMsg: pcNotifyClipboardMsg,
pub ClientFormatList: pcCliprdrClientFormatList,
pub ServerFormatList: pcCliprdrServerFormatList,
pub ClientFormatListResponse: pcCliprdrClientFormatListResponse,
@ -498,6 +510,8 @@ impl CliprdrClientContext {
pub fn create(
enable_files: bool,
enable_others: bool,
response_wait_timeout_secs: u32,
notify_callback: pcNotifyClipboardMsg,
client_format_list: pcCliprdrClientFormatList,
client_format_list_response: pcCliprdrClientFormatListResponse,
client_format_data_request: pcCliprdrClientFormatDataRequest,
@ -510,10 +524,12 @@ impl CliprdrClientContext {
EnableFiles: if enable_files { TRUE } else { FALSE },
EnableOthers: if enable_others { TRUE } else { FALSE },
IsStopped: FALSE,
ResponseWaitTimeoutSecs: response_wait_timeout_secs,
ServerCapabilities: None,
ClientCapabilities: None,
MonitorReady: None,
TempDirectory: None,
NotifyClipboardMsg: notify_callback,
ClientFormatList: client_format_list,
ServerFormatList: None,
ClientFormatListResponse: client_format_list_response,

View File

@ -2,6 +2,8 @@ use crate::cliprdr::*;
use hbb_common::log;
use std::sync::Mutex;
const CLIPBOARD_RESPONSE_WAIT_TIMEOUT_SECS: u32 = 30;
lazy_static::lazy_static! {
static ref CONTEXT_SEND: ContextSend = ContextSend{addr: Mutex::new(0)};
}
@ -27,7 +29,11 @@ impl ContextSend {
let mut lock = CONTEXT_SEND.addr.lock().unwrap();
if enabled {
if *lock == 0 {
match crate::create_cliprdr_context(true, false) {
match crate::create_cliprdr_context(
true,
false,
CLIPBOARD_RESPONSE_WAIT_TIMEOUT_SECS,
) {
Ok(context) => {
log::info!("clipboard context for file transfer created.");
*lock = Box::into_raw(context) as _;

View File

@ -1,6 +1,6 @@
use cliprdr::*;
use hbb_common::{
allow_err, log,
allow_err, lazy_static, log,
tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex,
@ -19,10 +19,16 @@ pub mod context_send;
pub use context_send::*;
const ERR_CODE_SERVER_FUNCTION_NONE: u32 = 0x00000001;
const ERR_CODE_INVALID_PARAMETER: u32 = 0x00000002;
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "t", content = "c")]
pub enum ClipboardFile {
NotifyCallback {
r#type: String,
title: String,
text: String,
},
MonitorReady,
FormatList {
format_list: Vec<(i32, String)>,
@ -167,41 +173,40 @@ pub fn server_clip_file(
conn_id: i32,
msg: ClipboardFile,
) -> u32 {
let mut ret = 0;
match msg {
ClipboardFile::NotifyCallback { .. } => {
// unreachable
}
ClipboardFile::MonitorReady => {
log::debug!("server_monitor_ready called");
let ret = server_monitor_ready(context, conn_id);
ret = server_monitor_ready(context, conn_id);
log::debug!("server_monitor_ready called, return {}", ret);
ret
}
ClipboardFile::FormatList { format_list } => {
log::debug!("server_format_list called");
let ret = server_format_list(context, conn_id, format_list);
ret = server_format_list(context, conn_id, format_list);
log::debug!("server_format_list called, return {}", ret);
ret
}
ClipboardFile::FormatListResponse { msg_flags } => {
log::debug!("format_list_response called");
let ret = server_format_list_response(context, conn_id, msg_flags);
ret = server_format_list_response(context, conn_id, msg_flags);
log::debug!("server_format_list_response called, return {}", ret);
ret
}
ClipboardFile::FormatDataRequest {
requested_format_id,
} => {
log::debug!("format_data_request called");
let ret = server_format_data_request(context, conn_id, requested_format_id);
ret = server_format_data_request(context, conn_id, requested_format_id);
log::debug!("server_format_data_request called, return {}", ret);
ret
}
ClipboardFile::FormatDataResponse {
msg_flags,
format_data,
} => {
log::debug!("format_data_response called");
let ret = server_format_data_response(context, conn_id, msg_flags, format_data);
ret = server_format_data_response(context, conn_id, msg_flags, format_data);
log::debug!("server_format_data_response called, return {}", ret);
ret
}
ClipboardFile::FileContentsRequest {
stream_id,
@ -214,7 +219,7 @@ pub fn server_clip_file(
clip_data_id,
} => {
log::debug!("file_contents_request called");
let ret = server_file_contents_request(
ret = server_file_contents_request(
context,
conn_id,
stream_id,
@ -227,7 +232,6 @@ pub fn server_clip_file(
clip_data_id,
);
log::debug!("server_file_contents_request called, return {}", ret);
ret
}
ClipboardFile::FileContentsResponse {
msg_flags,
@ -235,7 +239,7 @@ pub fn server_clip_file(
requested_data,
} => {
log::debug!("file_contents_response called");
let ret = server_file_contents_response(
ret = server_file_contents_response(
context,
conn_id,
msg_flags,
@ -243,9 +247,9 @@ pub fn server_clip_file(
requested_data,
);
log::debug!("server_file_contents_response called, return {}", ret);
ret
}
}
ret
}
pub fn server_monitor_ready(context: &mut Box<CliprdrClientContext>, conn_id: i32) -> u32 {
@ -446,10 +450,13 @@ pub fn server_file_contents_response(
pub fn create_cliprdr_context(
enable_files: bool,
enable_others: bool,
response_wait_timeout_secs: u32,
) -> ResultType<Box<CliprdrClientContext>> {
Ok(CliprdrClientContext::create(
enable_files,
enable_others,
response_wait_timeout_secs,
Some(notify_callback),
Some(client_format_list),
Some(client_format_list_response),
Some(client_format_data_request),
@ -459,6 +466,51 @@ pub fn create_cliprdr_context(
)?)
}
extern "C" fn notify_callback(conn_id: UINT32, msg: *const NOTIFICATION_MESSAGE) -> UINT {
log::debug!("notify_callback called");
let data = unsafe {
let msg = &*msg;
let details = if msg.details.is_null() {
Ok("")
} else {
CStr::from_ptr(msg.details as _).to_str()
};
match (CStr::from_ptr(msg.msg as _).to_str(), details) {
(Ok(m), Ok(d)) => {
let msgtype = format!(
"custom-{}-nocancel-nook-hasclose",
if msg.r#type == 0 {
"info"
} else if msg.r#type == 1 {
"warn"
} else {
"error"
}
);
let title = "Clipboard";
let text = if d.is_empty() {
m.to_string()
} else {
format!("{} {}", m, d)
};
ClipboardFile::NotifyCallback {
r#type: msgtype,
title: title.to_string(),
text,
}
}
_ => {
log::error!("notify_callback: failed to convert msg");
return ERR_CODE_INVALID_PARAMETER;
}
}
};
// no need to handle result here
send_data(conn_id as _, data);
0
}
extern "C" fn client_format_list(
_context: *mut CliprdrClientContext,
clip_format_list: *const CLIPRDR_FORMAT_LIST,

View File

@ -1449,14 +1449,16 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID)
return rc;
}
UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void **data)
UINT wait_response_event(UINT32 connID, wfClipboard *clipboard, HANDLE event, void **data)
{
UINT rc = ERROR_SUCCESS;
clipboard->context->IsStopped = FALSE;
// with default 3min timeout
for (int i = 0; i < 20 * 60 * 3; i++)
DWORD waitOnceTimeoutMillis = 50;
int waitCount = 1000 * clipboard->context->ResponseWaitTimeoutSecs / waitOnceTimeoutMillis;
int i = 0;
for (; i < waitCount; i++)
{
DWORD waitRes = WaitForSingleObject(event, 50);
DWORD waitRes = WaitForSingleObject(event, waitOnceTimeoutMillis);
if (waitRes == WAIT_TIMEOUT && clipboard->context->IsStopped == FALSE)
{
continue;
@ -1487,7 +1489,21 @@ UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void **data)
return rc;
}
if ((*data) != NULL)
if (i == waitCount)
{
NOTIFICATION_MESSAGE msg;
msg.type = 2;
msg.msg = "clipboard_wait_response_timeout_tip";
msg.details = NULL;
clipboard->context->NotifyClipboardMsg(connID, &msg);
rc = ERROR_INTERNAL_ERROR;
if (!ResetEvent(event))
{
// NOTE: critical error here, crash may be better
}
}
else if ((*data) != NULL)
{
if (!ResetEvent(event))
{
@ -1519,7 +1535,7 @@ static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UIN
return rc;
}
wait_response_event(clipboard, clipboard->response_data_event, &clipboard->hmem);
wait_response_event(connID, clipboard, clipboard->response_data_event, &clipboard->hmem);
}
UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, const void *streamid, ULONG index,
@ -1547,7 +1563,7 @@ UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, co
return rc;
}
return wait_response_event(clipboard, clipboard->req_fevent, (void **)&clipboard->req_fdata);
return wait_response_event(connID, clipboard, clipboard->req_fevent, (void **)&clipboard->req_fdata);
}
static UINT cliprdr_send_response_filecontents(

View File

@ -206,16 +206,21 @@ impl<T: InvokeUiSession> Remote<T> {
_msg = rx_clip_client.recv() => {
#[cfg(windows)]
match _msg {
Some(clip) => {
let is_stopping_allowed = clip.is_stopping_allowed();
let server_file_transfer_enabled = *self.handler.server_file_transfer_enabled.read().unwrap();
let file_transfer_enabled = self.handler.lc.read().unwrap().enable_file_transfer.v;
let stop = is_stopping_allowed && !(server_file_transfer_enabled && file_transfer_enabled);
log::debug!("Process clipboard message from system, stop: {}, is_stopping_allowed: {}, server_file_transfer_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, server_file_transfer_enabled, file_transfer_enabled);
if stop {
ContextSend::set_is_stopped();
} else {
allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await);
Some(clip) => match clip {
clipboard::ClipboardFile::NotifyCallback{r#type, title, text} => {
self.handler.msgbox(&r#type, &title, &text, "");
}
_ => {
let is_stopping_allowed = clip.is_stopping_allowed();
let server_file_transfer_enabled = *self.handler.server_file_transfer_enabled.read().unwrap();
let file_transfer_enabled = self.handler.lc.read().unwrap().enable_file_transfer.v;
let stop = is_stopping_allowed && !(server_file_transfer_enabled && file_transfer_enabled);
log::debug!("Process clipboard message from system, stop: {}, is_stopping_allowed: {}, server_file_transfer_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, server_file_transfer_enabled, file_transfer_enabled);
if stop {
ContextSend::set_is_stopped();
} else {
allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await);
}
}
}
None => {

View File

@ -3,6 +3,20 @@ use hbb_common::message_proto::*;
pub fn clip_2_msg(clip: ClipboardFile) -> Message {
match clip {
ClipboardFile::NotifyCallback {
r#type,
title,
text,
} => Message {
union: Some(message::Union::MessageBox(MessageBox {
msgtype: r#type,
title,
text,
link: "".to_string(),
..Default::default()
})),
..Default::default()
},
ClipboardFile::MonitorReady => Message {
union: Some(message::Union::Cliprdr(Cliprdr {
union: Some(cliprdr::Union::Ready(CliprdrMonitorReady {

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "折叠工具栏"),
("Accept and Elevate", "接受并提权"),
("accept_and_elevate_btn_tooltip", "接受连接并提升 UAC 权限"),
("clipboard_wait_response_timeout_tip", "等待拷贝响应超时"),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "Symbolleiste einklappen"),
("Accept and Elevate", "Akzeptieren und Rechte erhöhen"),
("accept_and_elevate_btn_tooltip", "Akzeptieren Sie die Verbindung und erhöhen Sie die UAC-Berechtigungen."),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -70,5 +70,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("resolution_fit_local_tip", "Fit local resolution"),
("resolution_custom_tip", "Custom resolution"),
("accept_and_elevate_btn_tooltip", "Accept the connection and elevate UAC permissions."),
("clipboard_wait_response_timeout_tip", "Timed out waiting for copy response."),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "Contraer barra de herramientas"),
("Accept and Elevate", "Aceptar y Elevar"),
("accept_and_elevate_btn_tooltip", "Aceptar la conexión y elevar permisos UAC."),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "جمع کردن نوار ابزار"),
("Accept and Elevate", "بپذیرید و افزایش دهید"),
("accept_and_elevate_btn_tooltip", "را افزایش دهید UAC اتصال را بپذیرید و مجوزهای."),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "Comprimi barra strumenti"),
("Accept and Elevate", "Accetta ed eleva"),
("accept_and_elevate_btn_tooltip", "Accetta la connessione ed eleva le autorizzazioni UAC."),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "Werkbalk samenvouwen"),
("Accept and Elevate", "Accepteren en Verheffen"),
("accept_and_elevate_btn_tooltip", "Accepteer de verbinding en verhoog de UAC-machtigingen."),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "Zwiń pasek narzędzi"),
("Accept and Elevate", "Akceptuj i Podnieś uprawnienia"),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "Свернуть панель инструментов"),
("Accept and Elevate", "Принять и повысить"),
("accept_and_elevate_btn_tooltip", "Разрешить подключение и повысить права UAC."),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", ""),
("Accept and Elevate", ""),
("accept_and_elevate_btn_tooltip", ""),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -511,5 +511,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Collapse toolbar", "Thu nhỏ thanh công cụ"),
("Accept and Elevate", "Chấp nhận và Cấp Quyền"),
("accept_and_elevate_btn_tooltip", "Chấp nhận kết nối và cấp các quyền UAC."),
("clipboard_wait_response_timeout_tip", ""),
].iter().cloned().collect();
}

View File

@ -987,7 +987,7 @@ fn try_get_displays() -> ResultType<Vec<Display>> {
}
#[inline]
#[cfg(windows)]
#[cfg(all(windows, feature = "virtual_display_driver"))]
fn no_displays(displays: &Vec<Display>) -> bool {
let display_len = displays.len();
if display_len == 0 {

View File

@ -5,6 +5,15 @@ function translate_text(text) {
fds[i] = translate(fds[i]);
}
text = fds.join(': ');
} else {
var fds = text.split(' ');
if (fds.length > 1 && fds[0].slice(-4) === '_tip') {
fds[0] = translate(fds[0]);
var rest = text.substring(fds[0].length + 1);
text = fds[0] + ' ' + translate(rest);
} else {
text = translate(text);
}
}
return text;
}

View File

@ -423,7 +423,7 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
Data::ClipboardFileEnabled(_enabled) => {
#[cfg(windows)]
{
self.file_transfer_enabled_peer =_enabled;
self.file_transfer_enabled_peer = _enabled;
}
}
Data::Theme(dark) => {