Fix. Multi sub windows, sync peer options (#7247)

* Fix. Multi window, sync peer options

Signed-off-by: fufesou <shuanglongchen@yeah.net>

* Remove unused `use`

Signed-off-by: fufesou <shuanglongchen@yeah.net>

---------

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2024-02-23 22:49:53 +08:00 committed by GitHub
parent cce1ce0ee0
commit 2459bcd206
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 136 additions and 57 deletions

View File

@ -221,7 +221,7 @@ List<(String, String)> otherDefaultSettings() {
('Privacy mode', 'privacy_mode'), ('Privacy mode', 'privacy_mode'),
if (isMobile) ('Touch mode', 'touch-mode'), if (isMobile) ('Touch mode', 'touch-mode'),
('True color (4:4:4)', 'i444'), ('True color (4:4:4)', 'i444'),
('Reverse mouse wheel', 'reverse_mouse_wheel'), ('Reverse mouse wheel', kKeyReverseMouseWheel),
('swap-left-right-mouse', 'swap-left-right-mouse'), ('swap-left-right-mouse', 'swap-left-right-mouse'),
if (isDesktop && useTextureRender) if (isDesktop && useTextureRender)
( (

View File

@ -655,7 +655,7 @@ List<TToggleMenu> toolbarKeyboardToggles(FFI ffi) {
var optionValue = var optionValue =
bind.sessionGetReverseMouseWheelSync(sessionId: sessionId) ?? ''; bind.sessionGetReverseMouseWheelSync(sessionId: sessionId) ?? '';
if (optionValue == '') { if (optionValue == '') {
optionValue = bind.mainGetUserDefaultOption(key: 'reverse_mouse_wheel'); optionValue = bind.mainGetUserDefaultOption(key: kKeyReverseMouseWheel);
} }
onChanged(bool? value) async { onChanged(bool? value) async {
if (value == null) return; if (value == null) return;

View File

@ -23,7 +23,8 @@ const String kPlatformAdditionsHeadless = "headless";
const String kPlatformAdditionsIsInstalled = "is_installed"; const String kPlatformAdditionsIsInstalled = "is_installed";
const String kPlatformAdditionsVirtualDisplays = "virtual_displays"; const String kPlatformAdditionsVirtualDisplays = "virtual_displays";
const String kPlatformAdditionsHasFileClipboard = "has_file_clipboard"; const String kPlatformAdditionsHasFileClipboard = "has_file_clipboard";
const String kPlatformAdditionsSupportedPrivacyModeImpl = "supported_privacy_mode_impl"; const String kPlatformAdditionsSupportedPrivacyModeImpl =
"supported_privacy_mode_impl";
const String kPeerPlatformWindows = "Windows"; const String kPeerPlatformWindows = "Windows";
const String kPeerPlatformLinux = "Linux"; const String kPeerPlatformLinux = "Linux";
@ -68,6 +69,7 @@ const String kOptionOpenNewConnInTabs = "enable-open-new-connections-in-tabs";
const String kOptionOpenInTabs = "allow-open-in-tabs"; const String kOptionOpenInTabs = "allow-open-in-tabs";
const String kOptionOpenInWindows = "allow-open-in-windows"; const String kOptionOpenInWindows = "allow-open-in-windows";
const String kOptionForceAlwaysRelay = "force-always-relay"; const String kOptionForceAlwaysRelay = "force-always-relay";
const String kOptionViewOnly = "view-only";
const String kUniLinksPrefix = "rustdesk://"; const String kUniLinksPrefix = "rustdesk://";
const String kUrlActionClose = "close"; const String kUrlActionClose = "close";
@ -86,6 +88,7 @@ const String kKeyShowDisplaysAsIndividualWindows =
const String kKeyUseAllMyDisplaysForTheRemoteSession = const String kKeyUseAllMyDisplaysForTheRemoteSession =
'use_all_my_displays_for_the_remote_session'; 'use_all_my_displays_for_the_remote_session';
const String kKeyShowMonitorsToolbar = 'show_monitors_toolbar'; const String kKeyShowMonitorsToolbar = 'show_monitors_toolbar';
const String kKeyReverseMouseWheel = "reverse_mouse_wheel";
// the executable name of the portable version // the executable name of the portable version
const String kEnvPortableExecutable = "RUSTDESK_APPNAME"; const String kEnvPortableExecutable = "RUSTDESK_APPNAME";

View File

@ -1732,7 +1732,7 @@ class _KeyboardMenu extends StatelessWidget {
? (value) async { ? (value) async {
if (value == null) return; if (value == null) return;
await bind.sessionToggleOption( await bind.sessionToggleOption(
sessionId: ffi.sessionId, value: 'view-only'); sessionId: ffi.sessionId, value: kOptionViewOnly);
ffiModel.setViewOnly(id, value); ffiModel.setViewOnly(id, value);
} }
: null, : null,

View File

@ -357,12 +357,26 @@ class FfiModel with ChangeNotifier {
if (isDesktop) { if (isDesktop) {
gFFI.cmFileModel.onFileTransferLog(evt); gFFI.cmFileModel.onFileTransferLog(evt);
} }
} else if (name == 'sync_peer_option') {
_handleSyncPeerOption(evt, peerId);
} else { } else {
debugPrint('Unknown event name: $name'); debugPrint('Unknown event name: $name');
} }
}; };
} }
_handleSyncPeerOption(Map<String, dynamic> evt, String peer) {
final k = evt['k'];
final v = evt['v'];
if (k == kOptionViewOnly) {
setViewOnly(peer, v as bool);
} else if (k == 'keyboard_mode') {
parent.target?.inputModel.updateKeyboardMode();
} else if (k == 'input_source') {
stateGlobal.getInputSource(force: true);
}
}
onUrlSchemeReceived(Map<String, dynamic> evt) { onUrlSchemeReceived(Map<String, dynamic> evt) {
final url = evt['url'].toString().trim(); final url = evt['url'].toString().trim();
if (url.startsWith(kUniLinksPrefix) && handleUriLink(uriString: url)) { if (url.startsWith(kUniLinksPrefix) && handleUriLink(uriString: url)) {
@ -728,7 +742,7 @@ class FfiModel with ChangeNotifier {
setViewOnly( setViewOnly(
peerId, peerId,
bind.sessionGetToggleOptionSync( bind.sessionGetToggleOptionSync(
sessionId: sessionId, arg: 'view-only')); sessionId: sessionId, arg: kOptionViewOnly));
} }
if (connType == ConnType.defaultConn) { if (connType == ConnType.defaultConn) {
final platformAdditions = evt['platform_additions']; final platformAdditions = evt['platform_additions'];

View File

@ -13,6 +13,7 @@ use hbb_common::{
anyhow::anyhow, bail, config::LocalConfig, get_version_number, log, message_proto::*, anyhow::anyhow, bail, config::LocalConfig, get_version_number, log, message_proto::*,
rendezvous_proto::ConnType, ResultType, rendezvous_proto::ConnType, ResultType,
}; };
use serde::Serialize;
use serde_json::json; use serde_json::json;
#[cfg(any(feature = "flutter_texture_render", feature = "gpucodec"))] #[cfg(any(feature = "flutter_texture_render", feature = "gpucodec"))]
@ -471,12 +472,19 @@ impl FlutterHandler {
/// ///
/// * `name` - The name of the event. /// * `name` - The name of the event.
/// * `event` - Fields of the event content. /// * `event` - Fields of the event content.
pub fn push_event(&self, name: &str, event: Vec<(&str, &str)>) { pub fn push_event<V>(&self, name: &str, event: &[(&str, V)], excludes: &[&SessionID])
let mut h: HashMap<&str, &str> = event.iter().cloned().collect(); where
V: Sized + Serialize + Clone,
{
let mut h: HashMap<&str, serde_json::Value> =
event.iter().map(|(k, v)| (*k, json!(*v))).collect();
debug_assert!(h.get("name").is_none()); debug_assert!(h.get("name").is_none());
h.insert("name", name); h.insert("name", json!(name));
let out = serde_json::ser::to_string(&h).unwrap_or("".to_owned()); let out = serde_json::ser::to_string(&h).unwrap_or("".to_owned());
for (_, session) in self.session_handlers.read().unwrap().iter() { for (sid, session) in self.session_handlers.read().unwrap().iter() {
if excludes.contains(&sid) {
continue;
}
if let Some(stream) = &session.event_stream { if let Some(stream) = &session.event_stream {
stream.add(EventToUI::Event(out.clone())); stream.add(EventToUI::Event(out.clone()));
} }
@ -539,7 +547,7 @@ impl InvokeUiSession for FlutterHandler {
let colors = hbb_common::compress::decompress(&cd.colors); let colors = hbb_common::compress::decompress(&cd.colors);
self.push_event( self.push_event(
"cursor_data", "cursor_data",
vec![ &[
("id", &cd.id.to_string()), ("id", &cd.id.to_string()),
("hotx", &cd.hotx.to_string()), ("hotx", &cd.hotx.to_string()),
("hoty", &cd.hoty.to_string()), ("hoty", &cd.hoty.to_string()),
@ -550,17 +558,19 @@ impl InvokeUiSession for FlutterHandler {
&serde_json::ser::to_string(&colors).unwrap_or("".to_owned()), &serde_json::ser::to_string(&colors).unwrap_or("".to_owned()),
), ),
], ],
&[],
); );
} }
fn set_cursor_id(&self, id: String) { fn set_cursor_id(&self, id: String) {
self.push_event("cursor_id", vec![("id", &id.to_string())]); self.push_event("cursor_id", &[("id", &id.to_string())], &[]);
} }
fn set_cursor_position(&self, cp: CursorPosition) { fn set_cursor_position(&self, cp: CursorPosition) {
self.push_event( self.push_event(
"cursor_position", "cursor_position",
vec![("x", &cp.x.to_string()), ("y", &cp.y.to_string())], &[("x", &cp.x.to_string()), ("y", &cp.y.to_string())],
&[],
); );
} }
@ -568,11 +578,11 @@ impl InvokeUiSession for FlutterHandler {
fn set_display(&self, _x: i32, _y: i32, _w: i32, _h: i32, _cursor_embedded: bool) {} fn set_display(&self, _x: i32, _y: i32, _w: i32, _h: i32, _cursor_embedded: bool) {}
fn update_privacy_mode(&self) { fn update_privacy_mode(&self) {
self.push_event("update_privacy_mode", [].into()); self.push_event::<&str>("update_privacy_mode", &[], &[]);
} }
fn set_permission(&self, name: &str, value: bool) { fn set_permission(&self, name: &str, value: bool) {
self.push_event("permission", vec![(name, &value.to_string())]); self.push_event("permission", &[(name, &value.to_string())], &[]);
} }
// unused in flutter // unused in flutter
@ -582,7 +592,7 @@ impl InvokeUiSession for FlutterHandler {
const NULL: String = String::new(); const NULL: String = String::new();
self.push_event( self.push_event(
"update_quality_status", "update_quality_status",
vec![ &[
("speed", &status.speed.map_or(NULL, |it| it)), ("speed", &status.speed.map_or(NULL, |it| it)),
( (
"fps", "fps",
@ -599,38 +609,42 @@ impl InvokeUiSession for FlutterHandler {
), ),
("chroma", &status.chroma.map_or(NULL, |it| it.to_string())), ("chroma", &status.chroma.map_or(NULL, |it| it.to_string())),
], ],
&[],
); );
} }
fn set_connection_type(&self, is_secured: bool, direct: bool) { fn set_connection_type(&self, is_secured: bool, direct: bool) {
self.push_event( self.push_event(
"connection_ready", "connection_ready",
vec![ &[
("secure", &is_secured.to_string()), ("secure", &is_secured.to_string()),
("direct", &direct.to_string()), ("direct", &direct.to_string()),
], ],
&[],
); );
} }
fn set_fingerprint(&self, fingerprint: String) { fn set_fingerprint(&self, fingerprint: String) {
self.push_event("fingerprint", vec![("fingerprint", &fingerprint)]); self.push_event("fingerprint", &[("fingerprint", &fingerprint)], &[]);
} }
fn job_error(&self, id: i32, err: String, file_num: i32) { fn job_error(&self, id: i32, err: String, file_num: i32) {
self.push_event( self.push_event(
"job_error", "job_error",
vec![ &[
("id", &id.to_string()), ("id", &id.to_string()),
("err", &err), ("err", &err),
("file_num", &file_num.to_string()), ("file_num", &file_num.to_string()),
], ],
&[],
); );
} }
fn job_done(&self, id: i32, file_num: i32) { fn job_done(&self, id: i32, file_num: i32) {
self.push_event( self.push_event(
"job_done", "job_done",
vec![("id", &id.to_string()), ("file_num", &file_num.to_string())], &[("id", &id.to_string()), ("file_num", &file_num.to_string())],
&[],
); );
} }
@ -638,7 +652,7 @@ impl InvokeUiSession for FlutterHandler {
fn clear_all_jobs(&self) {} fn clear_all_jobs(&self) {}
fn load_last_job(&self, _cnt: i32, job_json: &str) { fn load_last_job(&self, _cnt: i32, job_json: &str) {
self.push_event("load_last_job", vec![("value", job_json)]); self.push_event("load_last_job", &[("value", job_json)], &[]);
} }
fn update_folder_files( fn update_folder_files(
@ -653,15 +667,17 @@ impl InvokeUiSession for FlutterHandler {
if only_count { if only_count {
self.push_event( self.push_event(
"update_folder_files", "update_folder_files",
vec![("info", &make_fd_flutter(id, entries, only_count))], &[("info", &make_fd_flutter(id, entries, only_count))],
&[],
); );
} else { } else {
self.push_event( self.push_event(
"file_dir", "file_dir",
vec![ &[
("value", &crate::common::make_fd_to_json(id, path, entries)),
("is_local", "false"), ("is_local", "false"),
("value", &crate::common::make_fd_to_json(id, path, entries)),
], ],
&[],
); );
} }
} }
@ -682,25 +698,27 @@ impl InvokeUiSession for FlutterHandler {
) { ) {
self.push_event( self.push_event(
"override_file_confirm", "override_file_confirm",
vec![ &[
("id", &id.to_string()), ("id", &id.to_string()),
("file_num", &file_num.to_string()), ("file_num", &file_num.to_string()),
("read_path", &to), ("read_path", &to),
("is_upload", &is_upload.to_string()), ("is_upload", &is_upload.to_string()),
("is_identical", &is_identical.to_string()), ("is_identical", &is_identical.to_string()),
], ],
&[],
); );
} }
fn job_progress(&self, id: i32, file_num: i32, speed: f64, finished_size: f64) { fn job_progress(&self, id: i32, file_num: i32, speed: f64, finished_size: f64) {
self.push_event( self.push_event(
"job_progress", "job_progress",
vec![ &[
("id", &id.to_string()), ("id", &id.to_string()),
("file_num", &file_num.to_string()), ("file_num", &file_num.to_string()),
("speed", &speed.to_string()), ("speed", &speed.to_string()),
("finished_size", &finished_size.to_string()), ("finished_size", &finished_size.to_string()),
], ],
&[],
); );
} }
@ -796,7 +814,7 @@ impl InvokeUiSession for FlutterHandler {
} }
self.push_event( self.push_event(
"peer_info", "peer_info",
vec![ &[
("username", &pi.username), ("username", &pi.username),
("hostname", &pi.hostname), ("hostname", &pi.hostname),
("platform", &pi.platform), ("platform", &pi.platform),
@ -808,6 +826,7 @@ impl InvokeUiSession for FlutterHandler {
("resolutions", &resolutions), ("resolutions", &resolutions),
("platform_additions", &pi.platform_additions), ("platform_additions", &pi.platform_additions),
], ],
&[],
); );
} }
@ -815,14 +834,16 @@ impl InvokeUiSession for FlutterHandler {
self.peer_info.write().unwrap().displays = displays.clone(); self.peer_info.write().unwrap().displays = displays.clone();
self.push_event( self.push_event(
"sync_peer_info", "sync_peer_info",
vec![("displays", &Self::make_displays_msg(displays))], &[("displays", &Self::make_displays_msg(displays))],
&[],
); );
} }
fn set_platform_additions(&self, data: &str) { fn set_platform_additions(&self, data: &str) {
self.push_event( self.push_event(
"sync_platform_additions", "sync_platform_additions",
vec![("platform_additions", &data)], &[("platform_additions", &data)],
&[],
) )
} }
@ -837,10 +858,11 @@ impl InvokeUiSession for FlutterHandler {
} }
self.push_event( self.push_event(
"set_multiple_windows_session", "set_multiple_windows_session",
vec![( &[(
"windows_sessions", "windows_sessions",
&serde_json::ser::to_string(&msg_vec).unwrap_or("".to_owned()), &serde_json::ser::to_string(&msg_vec).unwrap_or("".to_owned()),
)], )],
&[],
); );
} }
@ -850,29 +872,30 @@ impl InvokeUiSession for FlutterHandler {
let has_retry = if retry { "true" } else { "" }; let has_retry = if retry { "true" } else { "" };
self.push_event( self.push_event(
"msgbox", "msgbox",
vec![ &[
("type", msgtype), ("type", msgtype),
("title", title), ("title", title),
("text", text), ("text", text),
("link", link), ("link", link),
("hasRetry", has_retry), ("hasRetry", has_retry),
], ],
&[],
); );
} }
fn cancel_msgbox(&self, tag: &str) { fn cancel_msgbox(&self, tag: &str) {
self.push_event("cancel_msgbox", vec![("tag", tag)]); self.push_event("cancel_msgbox", &[("tag", tag)], &[]);
} }
fn new_message(&self, msg: String) { fn new_message(&self, msg: String) {
self.push_event("chat_client_mode", vec![("text", &msg)]); self.push_event("chat_client_mode", &[("text", &msg)], &[]);
} }
fn switch_display(&self, display: &SwitchDisplay) { fn switch_display(&self, display: &SwitchDisplay) {
let resolutions = serialize_resolutions(&display.resolutions.resolutions); let resolutions = serialize_resolutions(&display.resolutions.resolutions);
self.push_event( self.push_event(
"switch_display", "switch_display",
vec![ &[
("display", &display.display.to_string()), ("display", &display.display.to_string()),
("x", &display.x.to_string()), ("x", &display.x.to_string()),
("y", &display.y.to_string()), ("y", &display.y.to_string()),
@ -899,46 +922,49 @@ impl InvokeUiSession for FlutterHandler {
&display.original_resolution.height.to_string(), &display.original_resolution.height.to_string(),
), ),
], ],
&[],
); );
} }
fn update_block_input_state(&self, on: bool) { fn update_block_input_state(&self, on: bool) {
self.push_event( self.push_event(
"update_block_input_state", "update_block_input_state",
[("input_state", if on { "on" } else { "off" })].into(), &[("input_state", if on { "on" } else { "off" })],
&[],
); );
} }
#[cfg(any(target_os = "android", target_os = "ios"))] #[cfg(any(target_os = "android", target_os = "ios"))]
fn clipboard(&self, content: String) { fn clipboard(&self, content: String) {
self.push_event("clipboard", vec![("content", &content)]); self.push_event("clipboard", &[("content", &content)], &[]);
} }
fn switch_back(&self, peer_id: &str) { fn switch_back(&self, peer_id: &str) {
self.push_event("switch_back", [("peer_id", peer_id)].into()); self.push_event("switch_back", &[("peer_id", peer_id)], &[]);
} }
fn portable_service_running(&self, running: bool) { fn portable_service_running(&self, running: bool) {
self.push_event( self.push_event(
"portable_service_running", "portable_service_running",
[("running", running.to_string().as_str())].into(), &[("running", running.to_string().as_str())],
&[],
); );
} }
fn on_voice_call_started(&self) { fn on_voice_call_started(&self) {
self.push_event("on_voice_call_started", [].into()); self.push_event::<&str>("on_voice_call_started", &[], &[]);
} }
fn on_voice_call_closed(&self, reason: &str) { fn on_voice_call_closed(&self, reason: &str) {
let _res = self.push_event("on_voice_call_closed", [("reason", reason)].into()); let _res = self.push_event("on_voice_call_closed", &[("reason", reason)], &[]);
} }
fn on_voice_call_waiting(&self) { fn on_voice_call_waiting(&self) {
self.push_event("on_voice_call_waiting", [].into()); self.push_event::<&str>("on_voice_call_waiting", &[], &[]);
} }
fn on_voice_call_incoming(&self) { fn on_voice_call_incoming(&self) {
self.push_event("on_voice_call_incoming", [].into()); self.push_event::<&str>("on_voice_call_incoming", &[], &[]);
} }
#[inline] #[inline]
@ -1129,6 +1155,7 @@ pub mod connection_manager {
use hbb_common::log; use hbb_common::log;
#[cfg(any(target_os = "android"))] #[cfg(any(target_os = "android"))]
use scrap::android::call_main_service_set_by_name; use scrap::android::call_main_service_set_by_name;
use serde_json::json;
use crate::ui_cm_interface::InvokeUiCM; use crate::ui_cm_interface::InvokeUiCM;
@ -1149,50 +1176,54 @@ pub mod connection_manager {
log::debug!("call_service_set_by_name fail,{}", e); log::debug!("call_service_set_by_name fail,{}", e);
} }
// send to UI, refresh widget // send to UI, refresh widget
self.push_event("add_connection", vec![("client", &client_json)]); self.push_event("add_connection", &[("client", &client_json)]);
} }
fn remove_connection(&self, id: i32, close: bool) { fn remove_connection(&self, id: i32, close: bool) {
self.push_event( self.push_event(
"on_client_remove", "on_client_remove",
vec![("id", &id.to_string()), ("close", &close.to_string())], &[("id", &id.to_string()), ("close", &close.to_string())],
); );
} }
fn new_message(&self, id: i32, text: String) { fn new_message(&self, id: i32, text: String) {
self.push_event( self.push_event(
"chat_server_mode", "chat_server_mode",
vec![("id", &id.to_string()), ("text", &text)], &[("id", &id.to_string()), ("text", &text)],
); );
} }
fn change_theme(&self, dark: String) { fn change_theme(&self, dark: String) {
self.push_event("theme", vec![("dark", &dark)]); self.push_event("theme", &[("dark", &dark)]);
} }
fn change_language(&self) { fn change_language(&self) {
self.push_event("language", vec![]); self.push_event::<&str>("language", &[]);
} }
fn show_elevation(&self, show: bool) { fn show_elevation(&self, show: bool) {
self.push_event("show_elevation", vec![("show", &show.to_string())]); self.push_event("show_elevation", &[("show", &show.to_string())]);
} }
fn update_voice_call_state(&self, client: &crate::ui_cm_interface::Client) { fn update_voice_call_state(&self, client: &crate::ui_cm_interface::Client) {
let client_json = serde_json::to_string(&client).unwrap_or("".into()); let client_json = serde_json::to_string(&client).unwrap_or("".into());
self.push_event("update_voice_call_state", vec![("client", &client_json)]); self.push_event("update_voice_call_state", &[("client", &client_json)]);
} }
fn file_transfer_log(&self, action: &str, log: &str) { fn file_transfer_log(&self, action: &str, log: &str) {
self.push_event("cm_file_transfer_log", vec![(action, log)]); self.push_event("cm_file_transfer_log", &[(action, log)]);
} }
} }
impl FlutterHandler { impl FlutterHandler {
fn push_event(&self, name: &str, event: Vec<(&str, &str)>) { fn push_event<V>(&self, name: &str, event: &[(&str, V)])
let mut h: HashMap<&str, &str> = event.iter().cloned().collect(); where
V: Sized + serde::Serialize + Clone,
{
let mut h: HashMap<&str, serde_json::Value> =
event.iter().map(|(k, v)| (*k, json!(*v))).collect();
debug_assert!(h.get("name").is_none()); debug_assert!(h.get("name").is_none());
h.insert("name", name); h.insert("name", json!(name));
if let Some(s) = GLOBAL_EVENT_STREAM.read().unwrap().get(super::APP_TYPE_CM) { if let Some(s) = GLOBAL_EVENT_STREAM.read().unwrap().get(super::APP_TYPE_CM) {
s.add(serde_json::ser::to_string(&h).unwrap_or("".to_owned())); s.add(serde_json::ser::to_string(&h).unwrap_or("".to_owned()));
@ -1442,7 +1473,7 @@ pub fn get_adapter_luid() -> Option<i64> {
#[inline] #[inline]
pub fn push_session_event(session_id: &SessionID, name: &str, event: Vec<(&str, &str)>) { pub fn push_session_event(session_id: &SessionID, name: &str, event: Vec<(&str, &str)>) {
if let Some(s) = sessions::get_session_by_session_id(session_id) { if let Some(s) = sessions::get_session_by_session_id(session_id) {
s.push_event(name, event); s.push_event(name, &event, &[]);
} }
} }
@ -1580,6 +1611,29 @@ pub fn get_cur_session() -> Option<FlutterSession> {
sessions::get_session_by_session_id(&*CUR_SESSION_ID.read().unwrap()) sessions::get_session_by_session_id(&*CUR_SESSION_ID.read().unwrap())
} }
#[inline]
pub fn try_sync_peer_option(
session: &FlutterSession,
cur_id: &SessionID,
key: &str,
_value: Option<serde_json::Value>,
) {
let mut event = Vec::new();
#[cfg(not(any(target_os = "android", target_os = "ios")))]
if key == "view-only" {
event = vec![
("k", json!(key.to_string())),
("v", json!(session.lc.read().unwrap().view_only.v)),
];
}
if ["keyboard_mode", "input_source"].contains(&key) {
event = vec![("k", json!(key.to_string())), ("v", json!(""))];
}
if !event.is_empty() {
session.push_event("sync_peer_option", &event, &[cur_id]);
}
}
// sessions mod is used to avoid the big lock of sessions' map. // sessions mod is used to avoid the big lock of sessions' map.
pub mod sessions { pub mod sessions {
#[cfg(feature = "flutter_texture_render")] #[cfg(feature = "flutter_texture_render")]

View File

@ -1,8 +1,9 @@
use crate::{ use crate::{
client::file_trait::FileManager, client::file_trait::FileManager,
common::is_keyboard_mode_supported, common::{is_keyboard_mode_supported, make_fd_to_json},
common::make_fd_to_json, flutter::{
flutter::{self, session_add, session_add_existed, session_start_, sessions}, self, session_add, session_add_existed, session_start_, sessions, try_sync_peer_option,
},
input::*, input::*,
ui_interface::{self, *}, ui_interface::{self, *},
}; };
@ -228,6 +229,7 @@ pub fn session_toggle_option(session_id: SessionID, value: String) {
if let Some(session) = sessions::get_session_by_session_id(&session_id) { if let Some(session) = sessions::get_session_by_session_id(&session_id) {
log::warn!("toggle option {}", &value); log::warn!("toggle option {}", &value);
session.toggle_option(value.clone()); session.toggle_option(value.clone());
try_sync_peer_option(&session, &session_id, &value, None);
} }
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
if sessions::get_session_by_session_id(&session_id).is_some() && value == "disable-clipboard" { if sessions::get_session_by_session_id(&session_id).is_some() && value == "disable-clipboard" {
@ -340,6 +342,7 @@ pub fn session_set_keyboard_mode(session_id: SessionID, value: String) {
if let Some(session) = sessions::get_session_by_session_id(&session_id) { if let Some(session) = sessions::get_session_by_session_id(&session_id) {
session.save_keyboard_mode(value.clone()); session.save_keyboard_mode(value.clone());
_mode_updated = true; _mode_updated = true;
try_sync_peer_option(&session, &session_id, "keyboard_mode", None);
} }
#[cfg(windows)] #[cfg(windows)]
if _mode_updated { if _mode_updated {
@ -884,7 +887,12 @@ pub fn main_get_input_source() -> SyncReturn<String> {
pub fn main_set_input_source(session_id: SessionID, value: String) { pub fn main_set_input_source(session_id: SessionID, value: String) {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
change_input_source(session_id, value); {
change_input_source(session_id, value);
if let Some(session) = sessions::get_session_by_session_id(&session_id) {
try_sync_peer_option(&session, &session_id, "input_source", None);
}
}
} }
pub fn main_get_my_id() -> String { pub fn main_get_my_id() -> String {