diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 67091db7a..7827ee13c 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -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 words = text.split(': '); + for (var i = 0; i < words.length; ++i) { + words[i] = translate(words[i]); + } + text = words.join(': '); + } else { + List 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)), ], ), ), diff --git a/libs/clipboard/src/cliprdr.h b/libs/clipboard/src/cliprdr.h index 57cae5f8f..8b9cecef0 100644 --- a/libs/clipboard/src/cliprdr.h +++ b/libs/clipboard/src/cliprdr.h @@ -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__ - diff --git a/libs/clipboard/src/cliprdr.rs b/libs/clipboard/src/cliprdr.rs index e5bc3e7ef..c787d8ef6 100644 --- a/libs/clipboard/src/cliprdr.rs +++ b/libs/clipboard/src/cliprdr.rs @@ -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 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, diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index 16363250e..76f8e4d7a 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -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 _; diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index c63817415..84179621d 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -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, 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> { 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, diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index f7111c41b..801fa71f3 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -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( diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index d75b53888..ff1387dd0 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -206,16 +206,21 @@ impl Remote { _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 => { diff --git a/src/clipboard_file.rs b/src/clipboard_file.rs index f0fe41b8d..a4bfc1aef 100644 --- a/src/clipboard_file.rs +++ b/src/clipboard_file.rs @@ -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 { diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 11f7a877a..b5163f68e 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -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(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 2fe55a6bc..7fc27f687 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -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(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index cad262bea..5f279c7b9 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -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(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 229cd5661..aaa5acf0e 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -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(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index fede1f3ae..1325aac4f 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -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(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 06d52f10a..6eacba007 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -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(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index c8e4f3f9f..9d759ada4 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -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(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 281601109..e232cb582 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -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(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 57023178d..28d8832f0 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -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(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 3da21726e..10b49ee98 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -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(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 483ea8f44..e782e8dc0 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -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(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 46bf48dd9..d9b95eeb0 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -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(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index c88faaba3..27cdcf1f1 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -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(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 173bb843a..edc2eb9a8 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -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(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index b02cca143..5def2cfca 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -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(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 4a052e844..90040b964 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -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(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index efdb9718b..6bb1c7a95 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -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(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index 247a81511..d2402c7f2 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -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(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 14763515b..2e0de4906 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -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(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 09d62b384..dfa6834ca 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -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(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index aa91a974f..743154d5f 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -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(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 594a57cc1..3bcc10e6c 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -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(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 18e21e29a..b75d5950d 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -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(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 2e0128cdd..d7e707988 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -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(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index ca308a7be..c99330096 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -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(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 691c77968..99e3f2805 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -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(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 5b2e34e27..04735b4b8 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -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(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index e9c8178e9..9a9e251de 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -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(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 0e17e1a26..73eb138bd 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -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(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 1cd755c53..e5fa47fd2 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -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(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 3f1127932..78aa94c6f 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -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(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 64c97fcf3..bc9cd694f 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -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(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 123a259e7..5f5136134 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -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(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 4b3d87019..135b3b357 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -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(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 04d9abcc2..05689843b 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -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(); } diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 90c262cc9..ada41e266 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -987,7 +987,7 @@ fn try_get_displays() -> ResultType> { } #[inline] -#[cfg(windows)] +#[cfg(all(windows, feature = "virtual_display_driver"))] fn no_displays(displays: &Vec) -> bool { let display_len = displays.len(); if display_len == 0 { diff --git a/src/ui/msgbox.tis b/src/ui/msgbox.tis index 8d54bf22c..d54b22c8e 100644 --- a/src/ui/msgbox.tis +++ b/src/ui/msgbox.tis @@ -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; } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index b61598251..e5a5c8e3b 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -423,7 +423,7 @@ impl IpcTaskRunner { Data::ClipboardFileEnabled(_enabled) => { #[cfg(windows)] { - self.file_transfer_enabled_peer =_enabled; + self.file_transfer_enabled_peer = _enabled; } } Data::Theme(dark) => {