Merge pull request #1840 from fufesou/win_fix_multi_tab

Win fix multi tab
This commit is contained in:
RustDesk 2022-10-27 16:21:11 +08:00 committed by GitHub
commit cf1ba283b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 553 additions and 389 deletions

View File

@ -43,7 +43,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
void initState() {
super.initState();
tabController.onRemove = (_, id) => onRemoveId(id);
tabController.onRemoved = (_, id) => onRemoveId(id);
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
print(

View File

@ -46,7 +46,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
void initState() {
super.initState();
tabController.onRemove = (_, id) => onRemoveId(id);
tabController.onRemoved = (_, id) => onRemoveId(id);
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
debugPrint(

View File

@ -24,8 +24,9 @@ class ConnectionTabPage extends StatefulWidget {
}
class _ConnectionTabPageState extends State<ConnectionTabPage> {
final tabController =
Get.put(DesktopTabController(tabType: DesktopTabType.remoteScreen));
final tabController = Get.put(DesktopTabController(
tabType: DesktopTabType.remoteScreen,
onSelected: (_, id) => bind.setCurSessionId(id: id)));
static const IconData selectedIcon = Icons.desktop_windows_sharp;
static const IconData unselectedIcon = Icons.desktop_windows_outlined;
@ -59,11 +60,11 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
void initState() {
super.initState();
tabController.onRemove = (_, id) => onRemoveId(id);
tabController.onRemoved = (_, id) => onRemoveId(id);
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
print(
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
"call ${call.method} with args ${call.arguments} from window $fromWindowId");
final RxBool fullscreen = Get.find(tag: 'fullscreen');
// for simplify, just replace connectionId

View File

@ -30,7 +30,7 @@ class _DesktopServerPageState extends State<DesktopServerPage>
void initState() {
gFFI.ffiModel.updateEventListener("");
windowManager.addListener(this);
tabController.onRemove = (_, id) => onRemoveId(id);
tabController.onRemoved = (_, id) => onRemoveId(id);
super.initState();
}
@ -99,7 +99,7 @@ class ConnectionManagerState extends State<ConnectionManager> {
@override
void initState() {
gFFI.serverModel.updateClientState();
gFFI.serverModel.tabController.onSelected = (index) =>
gFFI.serverModel.tabController.onSelected = (index, _) =>
gFFI.chatModel.changeCurrentID(gFFI.serverModel.clients[index].id);
super.initState();
}

View File

@ -70,10 +70,11 @@ class DesktopTabController {
final DesktopTabType tabType;
/// index, key
Function(int, String)? onRemove;
Function(int)? onSelected;
Function(int, String)? onRemoved;
Function(int, String)? onSelected;
DesktopTabController({required this.tabType});
DesktopTabController(
{required this.tabType, this.onRemoved, this.onSelected});
int get length => state.value.tabs.length;
@ -114,7 +115,7 @@ class DesktopTabController {
state.value.tabs.removeAt(index);
state.value.scrollController.itemCount = state.value.tabs.length;
jumpTo(toIndex);
onRemove?.call(index, key);
onRemoved?.call(index, key);
}
void jumpTo(int index) {
@ -134,7 +135,8 @@ class DesktopTabController {
}));
});
if (state.value.tabs.length > index) {
onSelected?.call(index);
final key = state.value.tabs[index].key;
onSelected?.call(index, key);
}
}
@ -146,7 +148,7 @@ class DesktopTabController {
void closeBy(String? key) {
if (!isDesktop) return;
assert(onRemove != null);
assert(onRemoved != null);
if (key == null) {
if (state.value.selected < state.value.tabs.length) {
remove(state.value.selected);

View File

@ -28,7 +28,7 @@ import 'input_model.dart';
import 'platform_model.dart';
typedef HandleMsgBox = Function(Map<String, dynamic> evt, String id);
bool _waitForImage = false;
final _waitForImage = <String, bool>{};
class FfiModel with ChangeNotifier {
PeerInfo _pi = PeerInfo();
@ -92,7 +92,6 @@ class FfiModel with ChangeNotifier {
clear() {
_pi = PeerInfo();
_display = Display();
_waitForImage = false;
_secure = null;
_direct = null;
_inputBlocked = false;
@ -314,7 +313,7 @@ class FfiModel with ChangeNotifier {
parent.target?.dialogManager.showLoading(
translate('Connected, waiting for image...'),
onCancel: closeConnection);
_waitForImage = true;
_waitForImage[peerId] = true;
_reconnects = 1;
}
}
@ -354,8 +353,8 @@ class ImageModel with ChangeNotifier {
ImageModel(this.parent);
onRgba(Uint8List rgba) {
if (_waitForImage) {
_waitForImage = false;
if (_waitForImage[id]!) {
_waitForImage[id] = false;
parent.target?.dialogManager.dismissAll();
}
final pid = parent.target?.id;

View File

@ -0,0 +1,59 @@
use crate::cliprdr::*;
use hbb_common::log;
use std::sync::Mutex;
lazy_static::lazy_static! {
static ref CONTEXT_SEND: ContextSend = ContextSend{addr: Mutex::new(0)};
}
pub struct ContextSend {
addr: Mutex<u64>,
}
impl ContextSend {
pub fn is_enabled() -> bool {
*CONTEXT_SEND.addr.lock().unwrap() != 0
}
pub fn enable(enabled: bool) {
let mut lock = CONTEXT_SEND.addr.lock().unwrap();
if enabled {
if *lock == 0 {
match crate::create_cliprdr_context(true, false, crate::ProcessSide::ClientSide) {
Ok(context) => {
log::info!("clipboard context for file transfer created.");
*lock = Box::into_raw(context) as _;
}
Err(err) => {
log::error!(
"Create clipboard context for file transfer: {}",
err.to_string()
);
}
}
}
} else {
if *lock != 0 {
unsafe {
let _ = Box::from_raw(*lock as *mut CliprdrClientContext);
}
log::info!("clipboard context for file transfer destroyed.");
*lock = 0;
}
}
}
pub fn proc<F: FnOnce(&mut Box<CliprdrClientContext>) -> u32>(f: F) -> u32 {
let mut lock = CONTEXT_SEND.addr.lock().unwrap();
if *lock != 0 {
unsafe {
let mut context = Box::from_raw(*lock as *mut CliprdrClientContext);
let res = f(&mut context);
*lock = Box::into_raw(context) as _;
res
}
} else {
0
}
}
}

View File

@ -1,6 +1,6 @@
use cliprdr::*;
use hbb_common::{
log,
allow_err, log,
tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex,
@ -12,33 +12,31 @@ use std::{
boxed::Box,
collections::HashMap,
ffi::{CStr, CString},
sync::Mutex,
sync::{Arc, Mutex, RwLock},
};
pub mod cliprdr;
pub mod context_send;
pub use context_send::*;
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "t", content = "c")]
pub enum ClipbaordFile {
ServerFormatList {
conn_id: i32,
MonitorReady,
FormatList {
format_list: Vec<(i32, String)>,
},
ServerFormatListResponse {
conn_id: i32,
FormatListResponse {
msg_flags: i32,
},
ServerFormatDataRequest {
conn_id: i32,
FormatDataRequest {
requested_format_id: i32,
},
ServerFormatDataResponse {
conn_id: i32,
FormatDataResponse {
msg_flags: i32,
format_data: Vec<u8>,
},
FileContentsRequest {
conn_id: i32,
stream_id: i32,
list_index: i32,
dw_flags: i32,
@ -49,7 +47,6 @@ pub enum ClipbaordFile {
clip_data_id: i32,
},
FileContentsResponse {
conn_id: i32,
msg_flags: i32,
stream_id: i32,
requested_data: Vec<u8>,
@ -61,18 +58,89 @@ struct ConnEnabled {
conn_enabled: HashMap<i32, bool>,
}
lazy_static::lazy_static! {
static ref MSG_CHANNEL_CLIENT: (UnboundedSender<(i32, ClipbaordFile)>, TokioMutex<UnboundedReceiver<(i32, ClipbaordFile)>>) = {
let (tx, rx) = unbounded_channel();
(tx, TokioMutex::new(rx))
};
static ref CLIP_CONN_ENABLED: Mutex<ConnEnabled> = Mutex::new(ConnEnabled::default());
struct MsgChannel {
peer_id: String,
conn_id: i32,
sender: UnboundedSender<ClipbaordFile>,
receiver: Arc<TokioMutex<UnboundedReceiver<ClipbaordFile>>>,
}
#[inline(always)]
pub fn get_rx_clip_client<'a>() -> &'a TokioMutex<UnboundedReceiver<(i32, ClipbaordFile)>> {
&MSG_CHANNEL_CLIENT.1
#[derive(PartialEq)]
pub enum ProcessSide {
UnknownSide,
ClientSide,
ServerSide,
}
lazy_static::lazy_static! {
static ref VEC_MSG_CHANNEL: RwLock<Vec<MsgChannel>> = Default::default();
static ref CLIP_CONN_ENABLED: Mutex<ConnEnabled> = Mutex::new(ConnEnabled::default());
static ref PROCESS_SIDE: RwLock<ProcessSide> = RwLock::new(ProcessSide::UnknownSide);
}
pub fn get_client_conn_id(peer_id: &str) -> Option<i32> {
VEC_MSG_CHANNEL
.read()
.unwrap()
.iter()
.find(|x| x.peer_id == peer_id.to_owned())
.map(|x| x.conn_id)
}
pub fn get_rx_cliprdr_client(
peer_id: &str,
) -> (i32, Arc<TokioMutex<UnboundedReceiver<ClipbaordFile>>>) {
let mut lock = VEC_MSG_CHANNEL.write().unwrap();
match lock.iter().find(|x| x.peer_id == peer_id.to_owned()) {
Some(msg_channel) => (msg_channel.conn_id, msg_channel.receiver.clone()),
None => {
let (sender, receiver) = unbounded_channel();
let receiver = Arc::new(TokioMutex::new(receiver));
let receiver2 = receiver.clone();
let conn_id = lock.len() as i32 + 1;
let msg_channel = MsgChannel {
peer_id: peer_id.to_owned(),
conn_id,
sender,
receiver,
};
lock.push(msg_channel);
(conn_id, receiver2)
}
}
}
pub fn get_rx_cliprdr_server(conn_id: i32) -> Arc<TokioMutex<UnboundedReceiver<ClipbaordFile>>> {
let mut lock = VEC_MSG_CHANNEL.write().unwrap();
match lock.iter().find(|x| x.conn_id == conn_id) {
Some(msg_channel) => msg_channel.receiver.clone(),
None => {
let (sender, receiver) = unbounded_channel();
let receiver = Arc::new(TokioMutex::new(receiver));
let receiver2 = receiver.clone();
let msg_channel = MsgChannel {
peer_id: "".to_owned(),
conn_id,
sender,
receiver,
};
lock.push(msg_channel);
receiver2
}
}
}
#[inline]
fn send_data(conn_id: i32, data: ClipbaordFile) {
// no need to handle result here
if let Some(msg_channel) = VEC_MSG_CHANNEL
.read()
.unwrap()
.iter()
.find(|x| x.conn_id == conn_id)
{
allow_err!(msg_channel.sender.send(data));
}
}
pub fn set_conn_enabled(conn_id: i32, enabled: bool) {
@ -88,61 +156,46 @@ pub fn empty_clipboard(context: &mut Box<CliprdrClientContext>, conn_id: i32) ->
pub fn server_clip_file(
context: &mut Box<CliprdrClientContext>,
s_conn_id: i32,
conn_id: i32,
msg: ClipbaordFile,
) -> u32 {
match msg {
ClipbaordFile::ServerFormatList {
mut conn_id,
format_list,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
ClipbaordFile::MonitorReady => {
log::debug!("server_monitor_ready called");
let ret = server_monitor_ready(context, conn_id);
log::debug!("server_monitor_ready called, return {}", ret);
ret
}
ClipbaordFile::FormatList { format_list } => {
log::debug!("server_format_list called");
let ret = server_format_list(context, conn_id, format_list);
log::debug!("server_format_list called, return {}", ret);
ret
}
ClipbaordFile::ServerFormatListResponse {
mut conn_id,
msg_flags,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
ClipbaordFile::FormatListResponse { msg_flags } => {
log::debug!("format_list_response called");
let ret = server_format_list_response(context, conn_id, msg_flags);
log::debug!("server_format_list_response called, return {}", ret);
ret
}
ClipbaordFile::ServerFormatDataRequest {
mut conn_id,
ClipbaordFile::FormatDataRequest {
requested_format_id,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("format_data_request called");
let ret = server_format_data_request(context, conn_id, requested_format_id);
log::debug!("server_format_data_request called, return {}", ret);
ret
}
ClipbaordFile::ServerFormatDataResponse {
mut conn_id,
ClipbaordFile::FormatDataResponse {
msg_flags,
format_data,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("format_data_response called");
let ret = server_format_data_response(context, conn_id, msg_flags, format_data);
log::debug!("server_format_data_response called, return {}", ret);
ret
}
ClipbaordFile::FileContentsRequest {
mut conn_id,
stream_id,
list_index,
dw_flags,
@ -152,9 +205,6 @@ pub fn server_clip_file(
have_clip_data_id,
clip_data_id,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("file_contents_request called");
let ret = server_file_contents_request(
context,
@ -172,14 +222,10 @@ pub fn server_clip_file(
ret
}
ClipbaordFile::FileContentsResponse {
mut conn_id,
msg_flags,
stream_id,
requested_data,
} => {
if s_conn_id != 0 {
conn_id = s_conn_id as i32;
}
log::debug!("file_contents_response called");
let ret = server_file_contents_response(
context,
@ -194,6 +240,19 @@ pub fn server_clip_file(
}
}
pub fn server_monitor_ready(context: &mut Box<CliprdrClientContext>, conn_id: i32) -> u32 {
unsafe {
let monitor_ready = CLIPRDR_MONITOR_READY {
connID: conn_id as UINT32,
msgType: 0 as UINT16,
msgFlags: 0 as UINT16,
dataLen: 0 as UINT32,
};
let ret = ((**context).MonitorReady.unwrap())(&mut (**context), &monitor_ready);
ret as u32
}
}
pub fn server_format_list(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
@ -243,6 +302,7 @@ pub fn server_format_list(
ret as u32
}
}
pub fn server_format_list_response(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
@ -262,6 +322,7 @@ pub fn server_format_list_response(
ret as u32
}
}
pub fn server_format_data_request(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
@ -280,6 +341,7 @@ pub fn server_format_data_request(
ret as u32
}
}
pub fn server_format_data_response(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
@ -301,6 +363,7 @@ pub fn server_format_data_response(
ret as u32
}
}
pub fn server_file_contents_request(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
@ -335,6 +398,7 @@ pub fn server_file_contents_request(
ret as u32
}
}
pub fn server_file_contents_response(
context: &mut Box<CliprdrClientContext>,
conn_id: i32,
@ -363,7 +427,10 @@ pub fn server_file_contents_response(
pub fn create_cliprdr_context(
enable_files: bool,
enable_others: bool,
process_side: ProcessSide,
) -> ResultType<Box<CliprdrClientContext>> {
*PROCESS_SIDE.write().unwrap() = process_side;
Ok(CliprdrClientContext::create(
enable_files,
enable_others,
@ -378,8 +445,11 @@ pub fn create_cliprdr_context(
}
extern "C" fn check_enabled(conn_id: UINT32) -> BOOL {
let lock = CLIP_CONN_ENABLED.lock().unwrap();
if *PROCESS_SIDE.read().unwrap() == ProcessSide::ClientSide {
return TRUE;
}
let lock = CLIP_CONN_ENABLED.lock().unwrap();
let mut connd_enabled = false;
if conn_id != 0 {
if let Some(true) = lock.conn_enabled.get(&(conn_id as i32)) {
@ -422,12 +492,17 @@ extern "C" fn client_format_list(
}
conn_id = (*clip_format_list).connID as i32;
}
let data = ClipbaordFile::ServerFormatList {
conn_id,
format_list,
};
let data = ClipbaordFile::FormatList { format_list };
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
if conn_id == 0 {
VEC_MSG_CHANNEL
.read()
.unwrap()
.iter()
.for_each(|msg_channel| allow_err!(msg_channel.sender.send(data.clone())));
} else {
send_data(conn_id, data);
}
0
}
@ -444,9 +519,8 @@ extern "C" fn client_format_list_response(
conn_id = (*format_list_response).connID as i32;
msg_flags = (*format_list_response).msgFlags as i32;
}
let data = ClipbaordFile::ServerFormatListResponse { conn_id, msg_flags };
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
let data = ClipbaordFile::FormatListResponse { msg_flags };
send_data(conn_id, data);
0
}
@ -463,12 +537,11 @@ extern "C" fn client_format_data_request(
conn_id = (*format_data_request).connID as i32;
requested_format_id = (*format_data_request).requestedFormatId as i32;
}
let data = ClipbaordFile::ServerFormatDataRequest {
conn_id,
let data = ClipbaordFile::FormatDataRequest {
requested_format_id,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
send_data(conn_id, data);
0
}
@ -495,13 +568,11 @@ extern "C" fn client_format_data_response(
.to_vec();
}
}
let data = ClipbaordFile::ServerFormatDataResponse {
conn_id,
let data = ClipbaordFile::FormatDataResponse {
msg_flags,
format_data,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
send_data(conn_id, data);
0
}
@ -544,7 +615,6 @@ extern "C" fn client_file_contents_request(
}
let data = ClipbaordFile::FileContentsRequest {
conn_id,
stream_id,
list_index,
dw_flags,
@ -554,8 +624,7 @@ extern "C" fn client_file_contents_request(
have_clip_data_id,
clip_data_id,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
send_data(conn_id, data);
0
}
@ -585,13 +654,11 @@ extern "C" fn client_file_contents_response(
}
}
let data = ClipbaordFile::FileContentsResponse {
conn_id,
msg_flags,
stream_id,
requested_data,
};
// no need to handle result here
MSG_CHANNEL_CLIENT.0.send((conn_id, data)).unwrap();
send_data(conn_id, data);
0
}

View File

@ -135,14 +135,14 @@ typedef struct _FORMAT_IDS FORMAT_IDS;
#define TAG "windows"
#ifdef WITH_DEBUG_CLIPRDR
#define DEBUG_CLIPRDR(...) printf(TAG, __VA_ARGS__)
#else
#define DEBUG_CLIPRDR(...) \
do \
{ \
} while (0)
#endif
// #ifdef WITH_DEBUG_CLIPRDR
#define DEBUG_CLIPRDR(fmt, ...) fprintf(stderr, "DEBUG %s[%d] %s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);fflush(stderr)
// #else
// #define DEBUG_CLIPRDR(fmt, ...) \
// do \
// { \
// } while (0)
// #endif
typedef BOOL(WINAPI *fnAddClipboardFormatListener)(HWND hwnd);
typedef BOOL(WINAPI *fnRemoveClipboardFormatListener)(HWND hwnd);
@ -193,6 +193,7 @@ struct _CliprdrDataObject
ULONG m_nStreams;
IStream **m_pStream;
void *m_pData;
DWORD m_processID;
UINT32 m_connID;
};
typedef struct _CliprdrDataObject CliprdrDataObject;
@ -246,7 +247,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr);
BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr);
BOOL wf_do_empty_cliprdr(wfClipboard *clipboard);
static BOOL wf_create_file_obj(UINT32 connID, wfClipboard *cliprdrrdr, IDataObject **ppDataObject);
static BOOL wf_create_file_obj(UINT32 *connID, wfClipboard *clipboard, IDataObject **ppDataObject);
static void wf_destroy_file_obj(IDataObject *instance);
static UINT32 get_remote_format_id(wfClipboard *clipboard, UINT32 local_format);
static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UINT32 format);
@ -673,6 +674,12 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
if (!pFormatEtc || !pMedium || !instance)
return E_INVALIDARG;
// Not the same process id
if (instance->m_processID != GetCurrentProcessId())
{
return E_INVALIDARG;
}
clipboard = (wfClipboard *)instance->m_pData;
if (!clipboard->context->CheckEnabled(instance->m_connID))
{
@ -892,6 +899,7 @@ static CliprdrDataObject *CliprdrDataObject_New(UINT32 connID, FORMATETC *fmtetc
instance->m_pData = data;
instance->m_nStreams = 0;
instance->m_pStream = NULL;
instance->m_processID = GetCurrentProcessId();
instance->m_connID = connID;
if (count > 0)
@ -1340,7 +1348,7 @@ static BOOL cliprdr_GetUpdatedClipboardFormats(wfClipboard *clipboard, PUINT lpu
return TRUE;
}
static UINT cliprdr_send_format_list(wfClipboard *clipboard)
static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID)
{
UINT rc;
int count = 0;
@ -1415,7 +1423,7 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard)
}
}
formatList.connID = 0;
formatList.connID = connID;
formatList.numFormats = numFormats;
formatList.formats = formats;
formatList.msgType = CB_FORMAT_LIST;
@ -1645,7 +1653,7 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
clipboard->hmem = NULL;
}
cliprdr_send_format_list(clipboard);
cliprdr_send_format_list(clipboard, 0);
}
}
@ -1669,7 +1677,8 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
DEBUG_CLIPRDR("info: WM_RENDERFORMAT");
// https://docs.microsoft.com/en-us/windows/win32/dataxchg/wm-renderformat?redirectedfrom=MSDN
if (cliprdr_send_data_request(0, 0, clipboard, (UINT32)wParam) != 0)
// to-do: ensure usage of 0
if (cliprdr_send_data_request(0, clipboard, (UINT32)wParam) != 0)
{
DEBUG_CLIPRDR("error: cliprdr_send_data_request failed.");
break;
@ -1695,7 +1704,7 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
if ((GetClipboardOwner() != clipboard->hwnd) &&
(S_FALSE == OleIsCurrentClipboard(clipboard->data_obj)))
{
cliprdr_send_format_list(clipboard);
cliprdr_send_format_list(clipboard, 0);
}
SendMessage(clipboard->hWndNextViewer, Msg, wParam, lParam);
@ -2128,9 +2137,14 @@ static UINT wf_cliprdr_send_client_capabilities(wfClipboard *clipboard)
CLIPRDR_CAPABILITIES capabilities;
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
if (!clipboard || !clipboard->context || !clipboard->context->ClientCapabilities)
if (!clipboard || !clipboard->context)
return ERROR_INTERNAL_ERROR;
// Ignore ClientCapabilities for now
if (!clipboard->context->ClientCapabilities) {
return CHANNEL_RC_OK;
}
capabilities.connID = 0;
capabilities.cCapabilitiesSets = 1;
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET *)&(generalCapabilitySet);
@ -2162,7 +2176,7 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext *context,
if (rc != CHANNEL_RC_OK)
return rc;
return cliprdr_send_format_list(clipboard);
return cliprdr_send_format_list(clipboard, monitorReady->connID);
}
/**

View File

@ -360,38 +360,31 @@ message FileDirCreate {
// main logic from freeRDP
message CliprdrMonitorReady {
int32 conn_id = 1;
}
message CliprdrFormat {
int32 conn_id = 1;
int32 id = 2;
string format = 3;
}
message CliprdrServerFormatList {
int32 conn_id = 1;
repeated CliprdrFormat formats = 2;
}
message CliprdrServerFormatListResponse {
int32 conn_id = 1;
int32 msg_flags = 2;
}
message CliprdrServerFormatDataRequest {
int32 conn_id = 1;
int32 requested_format_id = 2;
}
message CliprdrServerFormatDataResponse {
int32 conn_id = 1;
int32 msg_flags = 2;
bytes format_data = 3;
}
message CliprdrFileContentsRequest {
int32 conn_id = 1;
int32 stream_id = 2;
int32 list_index = 3;
int32 dw_flags = 4;
@ -403,7 +396,6 @@ message CliprdrFileContentsRequest {
}
message CliprdrFileContentsResponse {
int32 conn_id = 1;
int32 msg_flags = 3;
int32 stream_id = 4;
bytes requested_data = 5;

View File

@ -6,6 +6,9 @@ use crate::common;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::common::{check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL};
#[cfg(windows)]
use clipboard::{cliprdr::CliprdrClientContext, ContextSend};
use crate::ui_session_interface::{InvokeUiSession, Session};
use crate::{client::Data, client::Interface};
@ -22,7 +25,11 @@ use hbb_common::tokio::{
sync::mpsc,
time::{self, Duration, Instant, Interval},
};
use hbb_common::{allow_err, message_proto::*, sleep};
use hbb_common::{
allow_err,
message_proto::{self, *},
sleep,
};
use hbb_common::{fs, log, Stream};
use std::collections::HashMap;
@ -43,7 +50,7 @@ pub struct Remote<T: InvokeUiSession> {
last_update_jobs_status: (Instant, HashMap<i32, u64>),
first_frame: bool,
#[cfg(windows)]
clipboard_file_context: Option<Box<clipboard::cliprdr::CliprdrClientContext>>,
client_conn_id: i32, // used for clipboard
data_count: Arc<AtomicUsize>,
frame_count: Arc<AtomicUsize>,
video_format: CodecFormat,
@ -72,7 +79,7 @@ impl<T: InvokeUiSession> Remote<T> {
last_update_jobs_status: (Instant::now(), Default::default()),
first_frame: false,
#[cfg(windows)]
clipboard_file_context: None,
client_conn_id: 0,
data_count: Arc::new(AtomicUsize::new(0)),
frame_count,
video_format: CodecFormat::Unknown,
@ -107,7 +114,14 @@ impl<T: InvokeUiSession> Remote<T> {
#[cfg(not(windows))]
let (_tx_holder, mut rx_clip_client) = mpsc::unbounded_channel::<i32>();
#[cfg(windows)]
let mut rx_clip_client = clipboard::get_rx_clip_client().lock().await;
let (client_conn_id, rx_clip_client1) =
clipboard::get_rx_cliprdr_client(&self.handler.id);
#[cfg(windows)]
let mut rx_clip_client = rx_clip_client1.lock().await;
#[cfg(windows)]
{
self.client_conn_id = client_conn_id;
}
let mut status_timer = time::interval(Duration::new(1, 0));
@ -152,7 +166,7 @@ impl<T: InvokeUiSession> Remote<T> {
_msg = rx_clip_client.recv() => {
#[cfg(windows)]
match _msg {
Some((_, clip)) => {
Some(clip) => {
allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await);
}
None => {
@ -778,13 +792,7 @@ impl<T: InvokeUiSession> Remote<T> {
}
#[cfg(windows)]
Some(message::Union::Cliprdr(clip)) => {
if !self.handler.lc.read().unwrap().disable_clipboard {
if let Some(context) = &mut self.clipboard_file_context {
if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) {
clipboard::server_clip_file(context, 0, clip);
}
}
}
self.handle_cliprdr_msg(clip);
}
Some(message::Union::FileResponse(fr)) => {
match fr.union {
@ -1158,30 +1166,32 @@ impl<T: InvokeUiSession> Remote<T> {
true
}
fn check_clipboard_file_context(&mut self) {
fn check_clipboard_file_context(&self) {
#[cfg(windows)]
{
let enabled = SERVER_FILE_TRANSFER_ENABLED.load(Ordering::SeqCst)
&& self.handler.lc.read().unwrap().enable_file_transfer;
if enabled == self.clipboard_file_context.is_none() {
self.clipboard_file_context = if enabled {
match clipboard::create_cliprdr_context(true, false) {
Ok(context) => {
log::info!("clipboard context for file transfer created.");
Some(context)
}
Err(err) => {
log::error!(
"Create clipboard context for file transfer: {}",
err.to_string()
);
None
}
}
} else {
log::info!("clipboard context for file transfer destroyed.");
None
};
ContextSend::enable(enabled);
}
}
#[cfg(windows)]
fn handle_cliprdr_msg(&self, clip: message_proto::Cliprdr) {
if !self.handler.lc.read().unwrap().disable_clipboard {
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
if let Some(message_proto::cliprdr::Union::FormatList(_)) = &clip.union {
if self.client_conn_id
!= clipboard::get_client_conn_id(&crate::flutter::get_cur_session_id())
.unwrap_or(0)
{
return;
}
}
if let Some(clip) = crate::clipboard_file::msg_2_clip(clip) {
ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 {
clipboard::server_clip_file(context, self.client_conn_id, clip)
});
}
}
}

View File

@ -3,14 +3,19 @@ use hbb_common::message_proto::*;
pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
match clip {
ClipbaordFile::ServerFormatList {
conn_id,
format_list,
} => {
ClipbaordFile::MonitorReady => Message {
union: Some(message::Union::Cliprdr(Cliprdr {
union: Some(cliprdr::Union::Ready(CliprdrMonitorReady {
..Default::default()
})),
..Default::default()
})),
..Default::default()
},
ClipbaordFile::FormatList { format_list } => {
let mut formats: Vec<CliprdrFormat> = Vec::new();
for v in format_list.iter() {
formats.push(CliprdrFormat {
conn_id: 0,
id: v.0,
format: v.1.clone(),
..Default::default()
@ -19,7 +24,6 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
Message {
union: Some(message::Union::Cliprdr(Cliprdr {
union: Some(cliprdr::Union::FormatList(CliprdrServerFormatList {
conn_id,
formats,
..Default::default()
})),
@ -28,11 +32,10 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
..Default::default()
}
}
ClipbaordFile::ServerFormatListResponse { conn_id, msg_flags } => Message {
ClipbaordFile::FormatListResponse { msg_flags } => Message {
union: Some(message::Union::Cliprdr(Cliprdr {
union: Some(cliprdr::Union::FormatListResponse(
CliprdrServerFormatListResponse {
conn_id,
msg_flags,
..Default::default()
},
@ -41,14 +44,12 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
})),
..Default::default()
},
ClipbaordFile::ServerFormatDataRequest {
conn_id,
ClipbaordFile::FormatDataRequest {
requested_format_id,
} => Message {
union: Some(message::Union::Cliprdr(Cliprdr {
union: Some(cliprdr::Union::FormatDataRequest(
CliprdrServerFormatDataRequest {
conn_id,
requested_format_id,
..Default::default()
},
@ -57,15 +58,13 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
})),
..Default::default()
},
ClipbaordFile::ServerFormatDataResponse {
conn_id,
ClipbaordFile::FormatDataResponse {
msg_flags,
format_data,
} => Message {
union: Some(message::Union::Cliprdr(Cliprdr {
union: Some(cliprdr::Union::FormatDataResponse(
CliprdrServerFormatDataResponse {
conn_id,
msg_flags,
format_data: format_data.into(),
..Default::default()
@ -76,7 +75,6 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
..Default::default()
},
ClipbaordFile::FileContentsRequest {
conn_id,
stream_id,
list_index,
dw_flags,
@ -89,7 +87,6 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
union: Some(message::Union::Cliprdr(Cliprdr {
union: Some(cliprdr::Union::FileContentsRequest(
CliprdrFileContentsRequest {
conn_id,
stream_id,
list_index,
dw_flags,
@ -106,7 +103,6 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
..Default::default()
},
ClipbaordFile::FileContentsResponse {
conn_id,
msg_flags,
stream_id,
requested_data,
@ -114,7 +110,6 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
union: Some(message::Union::Cliprdr(Cliprdr {
union: Some(cliprdr::Union::FileContentsResponse(
CliprdrFileContentsResponse {
conn_id,
msg_flags,
stream_id,
requested_data: requested_data.into(),
@ -130,38 +125,26 @@ pub fn clip_2_msg(clip: ClipbaordFile) -> Message {
pub fn msg_2_clip(msg: Cliprdr) -> Option<ClipbaordFile> {
match msg.union {
Some(cliprdr::Union::Ready(_)) => Some(ClipbaordFile::MonitorReady),
Some(cliprdr::Union::FormatList(data)) => {
let mut format_list: Vec<(i32, String)> = Vec::new();
for v in data.formats.iter() {
format_list.push((v.id, v.format.clone()));
}
Some(ClipbaordFile::ServerFormatList {
conn_id: data.conn_id,
format_list,
})
}
Some(cliprdr::Union::FormatListResponse(data)) => {
Some(ClipbaordFile::ServerFormatListResponse {
conn_id: data.conn_id,
msg_flags: data.msg_flags,
})
}
Some(cliprdr::Union::FormatDataRequest(data)) => {
Some(ClipbaordFile::ServerFormatDataRequest {
conn_id: data.conn_id,
requested_format_id: data.requested_format_id,
})
}
Some(cliprdr::Union::FormatDataResponse(data)) => {
Some(ClipbaordFile::ServerFormatDataResponse {
conn_id: data.conn_id,
msg_flags: data.msg_flags,
format_data: data.format_data.into(),
})
Some(ClipbaordFile::FormatList { format_list })
}
Some(cliprdr::Union::FormatListResponse(data)) => Some(ClipbaordFile::FormatListResponse {
msg_flags: data.msg_flags,
}),
Some(cliprdr::Union::FormatDataRequest(data)) => Some(ClipbaordFile::FormatDataRequest {
requested_format_id: data.requested_format_id,
}),
Some(cliprdr::Union::FormatDataResponse(data)) => Some(ClipbaordFile::FormatDataResponse {
msg_flags: data.msg_flags,
format_data: data.format_data.into(),
}),
Some(cliprdr::Union::FileContentsRequest(data)) => {
Some(ClipbaordFile::FileContentsRequest {
conn_id: data.conn_id,
stream_id: data.stream_id,
list_index: data.list_index,
dw_flags: data.dw_flags,
@ -174,7 +157,6 @@ pub fn msg_2_clip(msg: Cliprdr) -> Option<ClipbaordFile> {
}
Some(cliprdr::Union::FileContentsResponse(data)) => {
Some(ClipbaordFile::FileContentsResponse {
conn_id: data.conn_id,
msg_flags: data.msg_flags,
stream_id: data.stream_id,
requested_data: data.requested_data.into(),

View File

@ -22,7 +22,8 @@ pub(super) const APP_TYPE_DESKTOP_FILE_TRANSFER: &str = "file transfer";
pub(super) const APP_TYPE_DESKTOP_PORT_FORWARD: &str = "port forward";
lazy_static::lazy_static! {
pub static ref SESSIONS: RwLock<HashMap<String,Session<FlutterHandler>>> = Default::default();
static ref CUR_SESSION_ID: RwLock<String> = Default::default();
pub static ref SESSIONS: RwLock<HashMap<String, Session<FlutterHandler>>> = Default::default();
pub static ref GLOBAL_EVENT_STREAM: RwLock<HashMap<String, StreamSink<String>>> = Default::default(); // rust to dart event channel
}
@ -564,3 +565,13 @@ pub fn make_fd_flutter(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> S
m.insert("total_size".into(), json!(n as f64));
serde_json::to_string(&m).unwrap_or("".into())
}
pub fn get_cur_session_id() -> String {
CUR_SESSION_ID.read().unwrap().clone()
}
pub fn set_cur_session_id(id: String) {
if get_cur_session_id() != id {
*CUR_SESSION_ID.write().unwrap() = id;
}
}

View File

@ -1052,6 +1052,10 @@ pub fn main_update_me() -> SyncReturn<bool> {
SyncReturn(true)
}
pub fn set_cur_session_id(id: String) {
super::flutter::set_cur_session_id(id)
}
pub fn install_show_run_without_install() -> SyncReturn<bool> {
SyncReturn(show_run_without_install())
}

View File

@ -249,8 +249,8 @@ pub(super) fn release_resouce() {
if *write_lock != 0 {
let cap_display_info: *mut CapDisplayInfo = *write_lock as _;
unsafe {
let box_capturer = Box::from_raw((*cap_display_info).capturer.0);
let box_cap_display_info = Box::from_raw(cap_display_info);
let _box_capturer = Box::from_raw((*cap_display_info).capturer.0);
let _box_cap_display_info = Box::from_raw(cap_display_info);
*write_lock = 0;
}
}

View File

@ -53,11 +53,8 @@ fn check_connect_status(
) {
let status = Arc::new(Mutex::new((0, false, 0, "".to_owned())));
let options = Arc::new(Mutex::new(Config::get_options()));
let cloned = status.clone();
let cloned_options = options.clone();
let (tx, rx) = mpsc::unbounded_channel::<ipc::Data>();
let password = Arc::new(Mutex::new(String::default()));
let cloned_password = password.clone();
std::thread::spawn(move || crate::ui_interface::check_connect_status_(reconnect, rx));
(status, options, tx, password)
}
@ -514,17 +511,17 @@ impl UI {
}
fn get_lan_peers(&self) -> String {
let peers = get_lan_peers()
.into_iter()
.map(|mut peer| {
(
peer.remove("id").unwrap_or_default(),
peer.remove("username").unwrap_or_default(),
peer.remove("hostname").unwrap_or_default(),
peer.remove("platform").unwrap_or_default(),
)
})
.collect::<Vec<(String, String, String, String)>>();
// let peers = get_lan_peers()
// .into_iter()
// .map(|mut peer| {
// (
// peer.remove("id").unwrap_or_default(),
// peer.remove("username").unwrap_or_default(),
// peer.remove("hostname").unwrap_or_default(),
// peer.remove("platform").unwrap_or_default(),
// )
// })
// .collect::<Vec<(String, String, String, String)>>();
serde_json::to_string(&get_lan_peers()).unwrap_or_default()
}

View File

@ -2,11 +2,6 @@
use crate::ipc::start_pa;
use crate::ui_cm_interface::{start_ipc, ConnectionManager, InvokeUiCM};
#[cfg(windows)]
use clipboard::{
create_cliprdr_context, empty_clipboard, get_rx_clip_client, server_clip_file, set_conn_enabled,
};
use hbb_common::{allow_err, log};
use sciter::{make_args, Element, Value, HELEMENT};
use std::sync::Mutex;

View File

@ -14,12 +14,6 @@ use sciter::{
Value,
};
#[cfg(windows)]
use clipboard::{
cliprdr::CliprdrClientContext, create_cliprdr_context as create_clipboard_file_context,
get_rx_clip_client, server_clip_file,
};
use hbb_common::{
allow_err, fs::TransferJobMeta, log, message_proto::*, rendezvous_proto::ConnType,
};

View File

@ -1,17 +1,22 @@
use std::ops::{Deref, DerefMut};
#[cfg(windows)]
use std::sync::Arc;
use std::{
collections::HashMap,
iter::FromIterator,
ops::{Deref, DerefMut},
sync::{
atomic::{AtomicI64, Ordering},
RwLock,
},
};
#[cfg(windows)]
use clipboard::{cliprdr::CliprdrClientContext, empty_clipboard, ContextSend};
use serde_derive::Serialize;
use crate::ipc::Data;
use crate::ipc::{self, new_listener, Connection};
use crate::ipc::{self, new_listener, Connection, Data};
#[cfg(windows)]
use hbb_common::tokio::sync::Mutex as TokioMutex;
use hbb_common::{
allow_err,
config::Config,
@ -22,7 +27,7 @@ use hbb_common::{
protobuf::Message as _,
tokio::{
self,
sync::mpsc::{self, UnboundedSender},
sync::mpsc::{self, unbounded_channel, UnboundedSender},
task::spawn_blocking,
},
};
@ -46,8 +51,19 @@ pub struct Client {
tx: UnboundedSender<Data>,
}
struct IpcTaskRunner<T: InvokeUiCM> {
stream: Connection,
cm: ConnectionManager<T>,
tx: mpsc::UnboundedSender<Data>,
rx: mpsc::UnboundedReceiver<Data>,
close: bool,
conn_id: i32,
#[cfg(windows)]
file_transfer_enabled: bool,
}
lazy_static::lazy_static! {
static ref CLIENTS: RwLock<HashMap<i32,Client>> = Default::default();
static ref CLIENTS: RwLock<HashMap<i32, Client>> = Default::default();
static ref CLICK_TIME: AtomicI64 = AtomicI64::new(0);
}
@ -215,23 +231,185 @@ pub fn get_clients_length() -> usize {
clients.len()
}
pub enum ClipboardFileData {
impl<T: InvokeUiCM> IpcTaskRunner<T> {
#[cfg(windows)]
Clip((i32, ipc::ClipbaordFile)),
Enable((i32, bool)),
async fn enable_cliprdr_file_context(&mut self, conn_id: i32, enabled: bool) {
if conn_id == 0 {
return;
}
let pre_enabled = ContextSend::is_enabled();
ContextSend::enable(enabled);
if !pre_enabled && ContextSend::is_enabled() {
allow_err!(
self.stream
.send(&Data::ClipbaordFile(clipboard::ClipbaordFile::MonitorReady))
.await
);
}
clipboard::set_conn_enabled(conn_id, enabled);
if !enabled {
ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 {
clipboard::empty_clipboard(context, conn_id);
0
});
}
}
async fn run(&mut self) {
use hbb_common::config::LocalConfig;
// for tmp use, without real conn id
let mut write_jobs: Vec<fs::TransferJob> = Vec::new();
#[cfg(windows)]
if self.conn_id > 0 {
self.enable_cliprdr_file_context(self.conn_id, self.file_transfer_enabled)
.await;
}
#[cfg(windows)]
let rx_clip1;
let mut rx_clip;
let _tx_clip;
#[cfg(windows)]
if self.conn_id > 0 {
rx_clip1 = clipboard::get_rx_cliprdr_server(self.conn_id);
rx_clip = rx_clip1.lock().await;
} else {
let rx_clip2;
(_tx_clip, rx_clip2) = unbounded_channel::<clipboard::ClipbaordFile>();
rx_clip1 = Arc::new(TokioMutex::new(rx_clip2));
rx_clip = rx_clip1.lock().await;
}
#[cfg(not(windows))]
{
(_tx_clip, rx_clip) = unbounded_channel::<i32>();
}
loop {
tokio::select! {
res = self.stream.next() => {
match res {
Err(err) => {
log::info!("cm ipc connection closed: {}", err);
break;
}
Ok(Some(data)) => {
match data {
Data::Login{id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, file_transfer_enabled: _file_transfer_enabled, restart, recording} => {
log::debug!("conn_id: {}", id);
self.cm.add_connection(id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, restart, recording, self.tx.clone());
self.conn_id = id;
#[cfg(windows)]
{
self.file_transfer_enabled = _file_transfer_enabled;
}
break;
}
Data::Close => {
#[cfg(windows)]
self.enable_cliprdr_file_context(self.conn_id, false).await;
log::info!("cm ipc connection closed from connection request");
break;
}
Data::Disconnected => {
self.close = false;
#[cfg(windows)]
self.enable_cliprdr_file_context(self.conn_id, false).await;
log::info!("cm ipc connection disconnect");
break;
}
Data::PrivacyModeState((_id, _)) => {
#[cfg(windows)]
cm_inner_send(_id, data);
}
Data::ClickTime(ms) => {
CLICK_TIME.store(ms, Ordering::SeqCst);
}
Data::ChatMessage { text } => {
self.cm.new_message(self.conn_id, text);
}
Data::FS(fs) => {
handle_fs(fs, &mut write_jobs, &self.tx).await;
}
Data::ClipbaordFile(_clip) => {
#[cfg(windows)]
{
let conn_id = self.conn_id;
ContextSend::proc(|context: &mut Box<CliprdrClientContext>| -> u32 {
clipboard::server_clip_file(context, conn_id, _clip)
});
}
}
#[cfg(windows)]
Data::ClipboardFileEnabled(_enabled) => {
#[cfg(windows)]
self.enable_cliprdr_file_context(self.conn_id, _enabled).await;
}
Data::Theme(dark) => {
self.cm.change_theme(dark);
}
Data::Language(lang) => {
LocalConfig::set_option("lang".to_owned(), lang);
self.cm.change_language();
}
_ => {
}
}
}
_ => {}
}
}
Some(data) = self.rx.recv() => {
if self.stream.send(&data).await.is_err() {
break;
}
}
clip_file = rx_clip.recv() => match clip_file {
Some(_clip) => {
#[cfg(windows)]
allow_err!(self.tx.send(Data::ClipbaordFile(_clip)));
}
None => {
//
}
},
}
}
}
async fn ipc_task(stream: Connection, cm: ConnectionManager<T>) {
log::debug!("ipc task begin");
let (tx, rx) = mpsc::unbounded_channel::<Data>();
let mut task_runner = Self {
stream,
cm,
tx,
rx,
close: true,
conn_id: 0,
#[cfg(windows)]
file_transfer_enabled: false,
};
task_runner.run().await;
if task_runner.conn_id > 0 {
task_runner.run().await;
}
if task_runner.conn_id > 0 {
task_runner
.cm
.remove_connection(task_runner.conn_id, task_runner.close);
}
log::debug!("ipc task end");
}
}
#[cfg(not(any(target_os = "android", target_os = "ios")))]
#[tokio::main(flavor = "current_thread")]
pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
use hbb_common::config::LocalConfig;
let (tx_file, _rx_file) = mpsc::unbounded_channel::<ClipboardFileData>();
#[cfg(windows)]
let cm_clip = cm.clone();
#[cfg(windows)]
std::thread::spawn(move || start_clipboard_file(cm_clip, _rx_file));
#[cfg(windows)]
std::thread::spawn(move || {
log::info!("try create privacy mode window");
@ -253,94 +431,10 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
match result {
Ok(stream) => {
log::debug!("Got new connection");
let mut stream = Connection::new(stream);
let cm = cm.clone();
let tx_file = tx_file.clone();
tokio::spawn(async move {
// for tmp use, without real conn id
let conn_id_tmp = -1;
let mut conn_id: i32 = 0;
let (tx, mut rx) = mpsc::unbounded_channel::<Data>();
let mut write_jobs: Vec<fs::TransferJob> = Vec::new();
let mut close = true;
loop {
tokio::select! {
res = stream.next() => {
match res {
Err(err) => {
log::info!("cm ipc connection closed: {}", err);
break;
}
Ok(Some(data)) => {
match data {
Data::Login{id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, file_transfer_enabled, restart, recording} => {
log::debug!("conn_id: {}", id);
conn_id = id;
tx_file.send(ClipboardFileData::Enable((id, file_transfer_enabled))).ok();
cm.add_connection(id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, restart, recording, tx.clone());
}
Data::Close => {
tx_file.send(ClipboardFileData::Enable((conn_id, false))).ok();
log::info!("cm ipc connection closed from connection request");
break;
}
Data::Disconnected => {
close = false;
tx_file.send(ClipboardFileData::Enable((conn_id, false))).ok();
log::info!("cm ipc connection disconnect");
break;
}
Data::PrivacyModeState((id, _)) => {
conn_id = conn_id_tmp;
allow_err!(tx.send(data));
}
Data::ClickTime(ms) => {
CLICK_TIME.store(ms, Ordering::SeqCst);
}
Data::ChatMessage { text } => {
cm.new_message(conn_id, text);
}
Data::FS(fs) => {
handle_fs(fs, &mut write_jobs, &tx).await;
}
#[cfg(windows)]
Data::ClipbaordFile(_clip) => {
tx_file
.send(ClipboardFileData::Clip((conn_id, _clip)))
.ok();
}
#[cfg(windows)]
Data::ClipboardFileEnabled(enabled) => {
tx_file
.send(ClipboardFileData::Enable((conn_id, enabled)))
.ok();
}
Data::Theme(dark) => {
cm.change_theme(dark);
}
Data::Language(lang) => {
LocalConfig::set_option("lang".to_owned(), lang);
cm.change_language();
}
_ => {
}
}
}
_ => {}
}
}
Some(data) = rx.recv() => {
if stream.send(&data).await.is_err() {
break;
}
}
}
}
if conn_id != conn_id_tmp {
cm.remove_connection(conn_id, close);
}
});
tokio::spawn(IpcTaskRunner::<T>::ipc_task(
Connection::new(stream),
cm.clone(),
));
}
Err(err) => {
log::error!("Couldn't get cm client: {:?}", err);
@ -642,66 +736,7 @@ fn send_raw(msg: Message, tx: &UnboundedSender<Data>) {
}
#[cfg(windows)]
#[tokio::main(flavor = "current_thread")]
pub async fn start_clipboard_file<T: InvokeUiCM>(
cm: ConnectionManager<T>,
mut rx: mpsc::UnboundedReceiver<ClipboardFileData>,
) {
let mut cliprdr_context = None;
let mut rx_clip_client = clipboard::get_rx_clip_client().lock().await;
loop {
tokio::select! {
clip_file = rx_clip_client.recv() => match clip_file {
Some((conn_id, clip)) => {
cmd_inner_send(
conn_id,
Data::ClipbaordFile(clip)
);
}
None => {
//
}
},
server_msg = rx.recv() => match server_msg {
Some(ClipboardFileData::Clip((conn_id, clip))) => {
if let Some(ctx) = cliprdr_context.as_mut() {
clipboard::server_clip_file(ctx, conn_id, clip);
}
}
Some(ClipboardFileData::Enable((id, enabled))) => {
if enabled && cliprdr_context.is_none() {
cliprdr_context = Some(match clipboard::create_cliprdr_context(true, false) {
Ok(context) => {
log::info!("clipboard context for file transfer created.");
context
}
Err(err) => {
log::error!(
"Create clipboard context for file transfer: {}",
err.to_string()
);
return;
}
});
}
clipboard::set_conn_enabled(id, enabled);
if !enabled {
if let Some(ctx) = cliprdr_context.as_mut() {
clipboard::empty_clipboard(ctx, id);
}
}
}
None => {
break
}
}
}
}
}
#[cfg(windows)]
fn cmd_inner_send(id: i32, data: Data) {
fn cm_inner_send(id: i32, data: Data) {
let lock = CLIENTS.read().unwrap();
if id != 0 {
if let Some(s) = lock.get(&id) {

View File

@ -76,11 +76,11 @@ pub fn goto_install() {
}
#[inline]
pub fn install_me(_options: String, _path: String, silent: bool, debug: bool) {
pub fn install_me(_options: String, _path: String, _silent: bool, _debug: bool) {
#[cfg(windows)]
std::thread::spawn(move || {
allow_err!(crate::platform::windows::install_me(
&_options, _path, silent, debug
&_options, _path, _silent, _debug
));
std::process::exit(0);
});

View File

@ -6,6 +6,7 @@ use crate::client::{
load_config, send_mouse, start_video_audio_threads, FileManager, Key, LoginConfigHandler,
QualityStatus, KEY_MAP, SERVER_KEYBOARD_ENABLED,
};
#[cfg(target_os = "linux")]
use crate::common::IS_X11;
use crate::{client::Data, client::Interface};
use async_trait::async_trait;
@ -812,6 +813,7 @@ impl<T: InvokeUiSession> Session<T> {
let keycode: u32 = keycode as u32;
let scancode: u32 = scancode as u32;
#[cfg(not(target_os = "windows"))]
let key = rdev::key_from_scancode(scancode) as RdevKey;
// Windows requires special handling
#[cfg(target_os = "windows")]