From 920477bbb2d9fde761fc1c1321ea19bca7d58912 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 24 Feb 2023 13:13:51 +0800 Subject: [PATCH 01/51] delete discovery from RustDesk_lan_peers.toml Signed-off-by: 21pages --- flutter/lib/common/widgets/peer_card.dart | 8 ++++++-- src/flutter_ffi.rs | 4 ++++ src/ui.rs | 4 +--- src/ui_interface.rs | 7 +++++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 8d4d58772..470b631ce 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -534,7 +534,7 @@ abstract class BasePeerCard extends StatelessWidget { proc: () { () async { if (isLan) { - // TODO + bind.mainRemoveDiscovered(id: id); } else { final favs = (await bind.mainGetFav()).toList(); if (favs.remove(id)) { @@ -859,7 +859,11 @@ class DiscoveredPeerCard extends BasePeerCard { } menuItems.add(MenuEntryDivider()); - menuItems.add(_removeAction(peer.id, () async {})); + menuItems.add( + _removeAction(peer.id, () async { + await bind.mainLoadLanPeers(); + }, isLan: true), + ); return menuItems; } diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 8a8bf4de4..23a65c2da 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -796,6 +796,10 @@ pub fn main_load_lan_peers() { }; } +pub fn main_remove_discovered(id: String) { + remove_discovered(id); +} + fn main_broadcast_message(data: &HashMap<&str, &str>) { let apps = vec![ flutter::APP_TYPE_DESKTOP_REMOTE, diff --git a/src/ui.rs b/src/ui.rs index 1b6838e46..a197cb257 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -413,9 +413,7 @@ impl UI { } fn remove_discovered(&mut self, id: String) { - let mut peers = config::LanPeers::load().peers; - peers.retain(|x| x.id != id); - config::LanPeers::store(&peers); + remove_discovered(id); } fn send_wol(&mut self, id: String) { diff --git a/src/ui_interface.rs b/src/ui_interface.rs index dd111f86e..3b2ba0897 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -596,6 +596,13 @@ pub fn get_lan_peers() -> Vec> { .collect() } +#[inline] +pub fn remove_discovered(id: String) { + let mut peers = config::LanPeers::load().peers; + peers.retain(|x| x.id != id); + config::LanPeers::store(&peers); +} + #[inline] pub fn get_uuid() -> String { base64::encode(hbb_common::get_uuid()) From 0ad6bca9ceb87bcdd17354a29460ac34aec3fef5 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 24 Feb 2023 13:39:28 +0800 Subject: [PATCH 02/51] check existence for visibility of addFavAction/addToAb Signed-off-by: 21pages --- flutter/lib/common/widgets/peer_card.dart | 38 ++++++++++------------- src/flutter_ffi.rs | 4 +++ 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 470b631ce..5b6120a02 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -745,12 +745,9 @@ class RecentPeerCard extends BasePeerCard { } if (gFFI.userModel.userName.isNotEmpty) { - // if (!gFFI.abModel.idContainBy(peer.id)) { - // menuItems.add(_addToAb(peer)); - // } else { - // menuItems.add(_removeFromAb(peer)); - // } - menuItems.add(_addToAb(peer)); + if (!gFFI.abModel.idContainBy(peer.id)) { + menuItems.add(_addToAb(peer)); + } } menuItems.add(MenuEntryDivider()); @@ -797,12 +794,9 @@ class FavoritePeerCard extends BasePeerCard { })); if (gFFI.userModel.userName.isNotEmpty) { - // if (!gFFI.abModel.idContainBy(peer.id)) { - // menuItems.add(_addToAb(peer)); - // } else { - // menuItems.add(_removeFromAb(peer)); - // } - menuItems.add(_addToAb(peer)); + if (!gFFI.abModel.idContainBy(peer.id)) { + menuItems.add(_addToAb(peer)); + } } menuItems.add(MenuEntryDivider()); @@ -843,19 +837,19 @@ class DiscoveredPeerCard extends BasePeerCard { menuItems.add(_createShortCutAction(peer.id)); } - if (!favs.contains(peer.id)) { - menuItems.add(_addFavAction(peer.id)); - } else { - menuItems.add(_rmFavAction(peer.id, () async {})); + final inRecent = await bind.mainIsInRecentPeers(id: peer.id); + if (inRecent) { + if (!favs.contains(peer.id)) { + menuItems.add(_addFavAction(peer.id)); + } else { + menuItems.add(_rmFavAction(peer.id, () async {})); + } } if (gFFI.userModel.userName.isNotEmpty) { - // if (!gFFI.abModel.idContainBy(peer.id)) { - // menuItems.add(_addToAb(peer)); - // } else { - // menuItems.add(_removeFromAb(peer)); - // } - menuItems.add(_addToAb(peer)); + if (!gFFI.abModel.idContainBy(peer.id)) { + menuItems.add(_addToAb(peer)); + } } menuItems.add(MenuEntryDivider()); diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 23a65c2da..0866ff739 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -726,6 +726,10 @@ pub fn main_peer_has_password(id: String) -> bool { peer_has_password(id) } +pub fn main_is_in_recent_peers(id: String) -> bool { + PeerConfig::peers().iter().any(|e| e.0 == id) +} + pub fn main_load_recent_peers() { if !config::APP_DIR.read().unwrap().is_empty() { let peers: Vec> = PeerConfig::peers() From a9598e006a61a6eeee758c0031025b9a50eca0a1 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 24 Feb 2023 15:51:13 +0800 Subject: [PATCH 03/51] request elevation menu Signed-off-by: 21pages --- .../lib/desktop/widgets/remote_menubar.dart | 10 ++++++++++ flutter/lib/mobile/widgets/dialog.dart | 7 +++---- flutter/lib/models/model.dart | 20 +++++++++++++++++++ src/client/io_loop.rs | 19 ++++++++++-------- src/flutter.rs | 7 +++++++ src/server/connection.rs | 16 +++++---------- src/ui/remote.rs | 2 ++ src/ui_session_interface.rs | 1 + 8 files changed, 59 insertions(+), 23 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 4f9a227bd..bdf9c1f1d 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -598,6 +598,7 @@ class _ControlMenu extends StatelessWidget { hoverColor: _MenubarTheme.hoverBlueColor, ffi: ffi, menuChildren: [ + requestElevation(), osPassword(), transferFile(context), tcpTunneling(context), @@ -611,6 +612,15 @@ class _ControlMenu extends StatelessWidget { ]); } + requestElevation() { + final visible = ffi.elevationModel.showRequestMenu; + if (!visible) return Offstage(); + return _MenuItemButton( + child: Text(translate('Request Elevation')), + ffi: ffi, + onPressed: () => showRequestElevationDialog(id, ffi.dialogManager)); + } + osPassword() { return _MenuItemButton( child: Text(translate('OS Password')), diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 7e9a9879c..931999382 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -374,8 +374,7 @@ void showWaitUacDialog( )); } -void _showRequestElevationDialog( - String id, OverlayDialogManager dialogManager) { +void showRequestElevationDialog(String id, OverlayDialogManager dialogManager) { RxString groupValue = ''.obs; RxString errUser = ''.obs; RxString errPwd = ''.obs; @@ -531,7 +530,7 @@ void showOnBlockDialog( dialogManager.show(tag: '$id-$type', (setState, close) { void submit() { close(); - _showRequestElevationDialog(id, dialogManager); + showRequestElevationDialog(id, dialogManager); } return CustomAlertDialog( @@ -553,7 +552,7 @@ void showElevationError(String id, String type, String title, String text, dialogManager.show(tag: '$id-$type', (setState, close) { void submit() { close(); - _showRequestElevationDialog(id, dialogManager); + showRequestElevationDialog(id, dialogManager); } return CustomAlertDialog( diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index f4efe2f08..eae41679f 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -203,6 +203,8 @@ class FfiModel with ChangeNotifier { final peer_id = evt['peer_id'].toString(); await bind.sessionSwitchSides(id: peer_id); closeConnection(id: peer_id); + } else if (name == 'portable_service_running') { + parent.target?.elevationModel.onPortableServiceRunning(evt); } else if (name == "on_url_scheme_received") { final url = evt['url'].toString(); parseRustdeskUri(url); @@ -439,6 +441,7 @@ class FfiModel with ChangeNotifier { Map features = json.decode(evt['features']); _pi.features.privacyMode = features['privacy_mode'] == 1; handleResolutions(peerId, evt["resolutions"]); + parent.target?.elevationModel.onPeerInfo(_pi); } notifyListeners(); } @@ -1395,6 +1398,21 @@ class RecordingModel with ChangeNotifier { } } +class ElevationModel with ChangeNotifier { + WeakReference parent; + ElevationModel(this.parent); + bool _running = false; + bool _canElevate = false; + bool get showRequestMenu => _canElevate && !_running; + onPeerInfo(PeerInfo pi) { + _canElevate = pi.platform == kPeerPlatformWindows && pi.sasEnabled == false; + } + + onPortableServiceRunning(Map evt) { + _running = evt['running'] == 'true'; + } +} + enum ConnType { defaultConn, fileTransfer, portForward, rdp } /// Flutter state manager and data communication with the Rust core. @@ -1420,6 +1438,7 @@ class FFI { late final QualityMonitorModel qualityMonitorModel; // session late final RecordingModel recordingModel; // session late final InputModel inputModel; // session + late final ElevationModel elevationModel; // session FFI() { imageModel = ImageModel(WeakReference(this)); @@ -1436,6 +1455,7 @@ class FFI { qualityMonitorModel = QualityMonitorModel(WeakReference(this)); recordingModel = RecordingModel(WeakReference(this)); inputModel = InputModel(WeakReference(this)); + elevationModel = ElevationModel(WeakReference(this)); } /// Start with the given [id]. Only transfer file if [isFileTransfer], only port forward if [isPortForward]. diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index b51c481a5..1c7788193 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -56,6 +56,7 @@ pub struct Remote { data_count: Arc, frame_count: Arc, video_format: CodecFormat, + elevation_requested: bool, } impl Remote { @@ -87,6 +88,7 @@ impl Remote { video_format: CodecFormat::Unknown, stop_voice_call_sender: None, voice_call_request_timestamp: None, + elevation_requested: false, } } @@ -686,6 +688,7 @@ impl Remote { let mut msg = Message::new(); msg.set_misc(misc); allow_err!(peer.send(&msg).await); + self.elevation_requested = true; } Data::ElevateWithLogon(username, password) => { let mut request = ElevationRequest::new(); @@ -699,6 +702,7 @@ impl Remote { let mut msg = Message::new(); msg.set_misc(misc); allow_err!(peer.send(&msg).await); + self.elevation_requested = true; } Data::NewVoiceCall => { let msg = new_voice_call_request(true); @@ -1181,7 +1185,8 @@ impl Remote { } } Some(misc::Union::PortableServiceRunning(b)) => { - if b { + self.handler.portable_service_running(b); + if self.elevation_requested && b { self.handler.msgbox( "custom-nocancel-success", "Successful", @@ -1253,14 +1258,12 @@ impl Remote { } } } - Some(message::Union::PeerInfo(pi)) => { - match pi.conn_id { - crate::SYNC_PEER_INFO_DISPLAYS => { - self.handler.set_displays(&pi.displays); - } - _ => {} + Some(message::Union::PeerInfo(pi)) => match pi.conn_id { + crate::SYNC_PEER_INFO_DISPLAYS => { + self.handler.set_displays(&pi.displays); } - } + _ => {} + }, _ => {} } } diff --git a/src/flutter.rs b/src/flutter.rs index ea73eb925..2f660775f 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -572,6 +572,13 @@ impl InvokeUiSession for FlutterHandler { self.push_event("switch_back", [("peer_id", peer_id)].into()); } + fn portable_service_running(&self, running: bool) { + self.push_event( + "portable_service_running", + [("running", running.to_string().as_str())].into(), + ); + } + fn on_voice_call_started(&self) { self.push_event("on_voice_call_started", [].into()); } diff --git a/src/server/connection.rs b/src/server/connection.rs index 85fcb676b..b2e198681 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1552,7 +1552,6 @@ impl Connection { .err() .map_or("".to_string(), |e| e.to_string()); } - self.portable.elevation_requested = err.is_empty(); let mut misc = Misc::new(); misc.set_elevation_response(err); let mut msg = Message::new(); @@ -1571,7 +1570,6 @@ impl Connection { .err() .map_or("".to_string(), |e| e.to_string()); } - self.portable.elevation_requested = err.is_empty(); let mut misc = Misc::new(); misc.set_elevation_response(err); let mut msg = Message::new(); @@ -1936,13 +1934,11 @@ impl Connection { let p = &mut self.portable; if running != p.last_running { p.last_running = running; - if running && p.elevation_requested { - let mut misc = Misc::new(); - misc.set_portable_service_running(running); - let mut msg = Message::new(); - msg.set_misc(misc); - self.inner.send(msg.into()); - } + let mut misc = Misc::new(); + misc.set_portable_service_running(running); + let mut msg = Message::new(); + msg.set_misc(misc); + self.inner.send(msg.into()); } let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone(); if p.last_uac != uac { @@ -2166,7 +2162,6 @@ pub struct PortableState { pub last_foreground_window_elevated: bool, pub last_running: bool, pub is_installed: bool, - pub elevation_requested: bool, } #[cfg(windows)] @@ -2177,7 +2172,6 @@ impl Default for PortableState { last_uac: Default::default(), last_foreground_window_elevated: Default::default(), last_running: Default::default(), - elevation_requested: Default::default(), } } } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 7b31c84e9..c6e0229b2 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -277,6 +277,8 @@ impl InvokeUiSession for SciterHandler { fn switch_back(&self, _id: &str) {} + fn portable_service_running(&self, _running: bool) {} + fn on_voice_call_started(&self) { self.call("onVoiceCallStart", &make_args!()); } diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index fd5a7d9c0..f726ed526 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -805,6 +805,7 @@ pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default { fn clipboard(&self, content: String); fn cancel_msgbox(&self, tag: &str); fn switch_back(&self, id: &str); + fn portable_service_running(&self, running: bool); fn on_voice_call_started(&self); fn on_voice_call_closed(&self, reason: &str); fn on_voice_call_waiting(&self); From 47a514a41670b2a4f9134219bf2854dd412c0d0f Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 24 Feb 2023 16:20:00 +0800 Subject: [PATCH 04/51] optimize menubar code Signed-off-by: 21pages --- .../lib/desktop/widgets/remote_menubar.dart | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index bdf9c1f1d..8710d27c3 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1101,7 +1101,8 @@ class _DisplayMenuState extends State<_DisplayMenu> { await bind.sessionSetImageQuality(id: widget.id, value: value); } - return SubmenuButton( + return _SubmenuButton( + ffi: widget.ffi, child: Text(translate('Image Quality')), menuChildren: [ _RadioMenuButton( @@ -1135,7 +1136,7 @@ class _DisplayMenuState extends State<_DisplayMenu> { }, ffi: widget.ffi, ), - ].map((e) => _buildPointerTrackWidget(e, widget.ffi)).toList(), + ], ); }); } @@ -1310,7 +1311,8 @@ class _DisplayMenuState extends State<_DisplayMenu> { bind.sessionChangePreferCodec(id: widget.id); } - return SubmenuButton( + return _SubmenuButton( + ffi: widget.ffi, child: Text(translate('Codec')), menuChildren: [ _RadioMenuButton( @@ -1341,7 +1343,7 @@ class _DisplayMenuState extends State<_DisplayMenu> { onChanged: onChanged, ffi: widget.ffi, ), - ].map((e) => _buildPointerTrackWidget(e, widget.ffi)).toList()); + ]); }); } @@ -1373,7 +1375,8 @@ class _DisplayMenuState extends State<_DisplayMenu> { } } - return SubmenuButton( + return _SubmenuButton( + ffi: widget.ffi, menuChildren: resolutions .map((e) => _RadioMenuButton( value: '${e.width}x${e.height}', @@ -1381,8 +1384,6 @@ class _DisplayMenuState extends State<_DisplayMenu> { onChanged: onChanged, ffi: widget.ffi, child: Text('${e.width}x${e.height}'))) - .toList() - .map((e) => _buildPointerTrackWidget(e, widget.ffi)) .toList(), child: Text(translate("Resolution"))); } @@ -1869,6 +1870,28 @@ class _IconSubmenuButtonState extends State<_IconSubmenuButton> { } } +class _SubmenuButton extends StatelessWidget { + final List menuChildren; + final Widget? child; + final FFI ffi; + const _SubmenuButton({ + Key? key, + required this.menuChildren, + required this.child, + required this.ffi, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return SubmenuButton( + key: key, + child: child, + menuChildren: + menuChildren.map((e) => _buildPointerTrackWidget(e, ffi)).toList(), + ); + } +} + class _MenuItemButton extends StatelessWidget { final VoidCallback? onPressed; final Widget? trailingIcon; From 2a71b65a618364aaf9f30f75fc428a2fc07f8940 Mon Sep 17 00:00:00 2001 From: 21pages Date: Fri, 24 Feb 2023 19:06:37 +0800 Subject: [PATCH 05/51] add missing insertLock menu Signed-off-by: 21pages --- flutter/lib/desktop/widgets/remote_menubar.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 8710d27c3..37bbbd66a 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -606,6 +606,7 @@ class _ControlMenu extends StatelessWidget { Divider(), ctrlAltDel(), restart(), + insertLock(), blockUserInput(), switchSides(), refresh(), @@ -789,6 +790,16 @@ class _ControlMenu extends StatelessWidget { onPressed: () => showRestartRemoteDevice(pi, id, ffi.dialogManager)); } + insertLock() { + final perms = ffi.ffiModel.permissions; + final visible = perms['keyboard'] != false; + if (!visible) return Offstage(); + return _MenuItemButton( + child: Text(translate('Insert Lock')), + ffi: ffi, + onPressed: () => bind.sessionLockScreen(id: id)); + } + blockUserInput() { final perms = ffi.ffiModel.permissions; final pi = ffi.ffiModel.pi; From c6f8df36a2018ea3a20cb692bf439ea989c6a6cc Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 24 Feb 2023 19:55:46 +0800 Subject: [PATCH 06/51] update options after login Signed-off-by: fufesou --- src/server/connection.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/server/connection.rs b/src/server/connection.rs index b2e198681..898939b62 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -126,6 +126,7 @@ pub struct Connection { origin_resolution: HashMap, voice_call_request_timestamp: Option, audio_input_device_before_voice_call: Option, + options_in_login: Option, } impl ConnInner { @@ -233,6 +234,7 @@ impl Connection { audio_sender: None, voice_call_request_timestamp: None, audio_input_device_before_voice_call: None, + options_in_login: None, }; #[cfg(not(any(target_os = "android", target_os = "ios")))] tokio::spawn(async move { @@ -921,6 +923,9 @@ impl Connection { let mut msg_out = Message::new(); msg_out.set_login_response(res); self.send(msg_out).await; + if let Some(o) = self.options_in_login.take() { + self.update_options(&o).await; + } if let Some((dir, show_hidden)) = self.file_transfer.clone() { let dir = if !dir.is_empty() && std::path::Path::new(&dir).is_dir() { &dir @@ -1106,8 +1111,7 @@ impl Connection { async fn handle_login_request_without_validation(&mut self, lr: &LoginRequest) { self.lr = lr.clone(); if let Some(o) = lr.option.as_ref() { - // It may not be a good practice to update all options here. - self.update_options(o).await; + self.options_in_login = Some(o.clone()); if let Some(q) = o.video_codec_state.clone().take() { scrap::codec::Encoder::update_video_encoder( self.inner.id(), @@ -1697,7 +1701,8 @@ impl Connection { self.send_to_cm(Data::CloseVoiceCall("".to_owned())); } - async fn update_options_without_auth(&mut self, o: &OptionMessage) { + async fn update_options(&mut self, o: &OptionMessage) { + log::info!("Option update: {:?}", o); if let Ok(q) = o.image_quality.enum_value() { let image_quality; if let ImageQuality::NotSet = q { @@ -1728,12 +1733,6 @@ impl Connection { scrap::codec::EncoderUpdate::State(q), ); } - } - - async fn update_options_with_auth(&mut self, o: &OptionMessage) { - if !self.authorized { - return; - } if let Ok(q) = o.lock_after_session_end.enum_value() { if q != BoolOption::NotSet { self.lock_after_session_end = q == BoolOption::Yes; @@ -1862,12 +1861,6 @@ impl Connection { } } - async fn update_options(&mut self, o: &OptionMessage) { - log::info!("Option update: {:?}", o); - self.update_options_without_auth(o).await; - self.update_options_with_auth(o).await; - } - async fn on_close(&mut self, reason: &str, lock: bool) { log::info!("#{} Connection closed: {}", self.inner.id(), reason); if lock && self.lock_after_session_end && self.keyboard { From 1e387ce01917c7951f2b88dcb59c08bd59627cbf Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 24 Feb 2023 20:24:31 +0800 Subject: [PATCH 07/51] simple refact Signed-off-by: fufesou --- src/platform/linux.rs | 120 +++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 08e343d49..47184e796 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -1,14 +1,22 @@ use super::{CursorData, ResultType}; -use hbb_common::libc::{c_char, c_int, c_long, c_void}; pub use hbb_common::platform::linux::*; -use hbb_common::{allow_err, anyhow::anyhow, bail, log, message_proto::Resolution}; +use hbb_common::{ + allow_err, + anyhow::anyhow, + bail, + libc::{c_char, c_int, c_long, c_void}, + log, + message_proto::Resolution, +}; use std::{ cell::RefCell, - path::PathBuf, + path::{Path, PathBuf}, + process::{Child, Command}, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, + time::{Duration, Instant}, }; use xrandr_parser::Parser; @@ -162,10 +170,29 @@ fn start_uinput_service() { }); } -fn stop_server(server: &mut Option) { +#[inline] +fn try_start_server_(user: Option<(String, String)>) -> ResultType> { + if user.is_some() { + run_as_user(vec!["--server"], user) + } else { + Ok(Some(crate::run_me(vec!["--server"])?)) + } +} + +#[inline] +fn start_server(user: Option<(String, String)>, server: &mut Option) { + match try_start_server_(user) { + Ok(ps) => *server = ps, + Err(err) => { + log::error!("Failed to start server: {}", err); + } + } +} + +fn stop_server(server: &mut Option) { if let Some(mut ps) = server.take() { allow_err!(ps.kill()); - std::thread::sleep(std::time::Duration::from_millis(30)); + std::thread::sleep(Duration::from_millis(30)); match ps.try_wait() { Ok(Some(_status)) => {} Ok(None) => { @@ -182,7 +209,7 @@ fn set_x11_env(uid: &str) { let mut auth = get_env_tries("XAUTHORITY", uid, 10); // auth is another user's when uid = 0, https://github.com/rustdesk/rustdesk/issues/2468 if auth.is_empty() || uid == "0" { - auth = if std::path::Path::new(&gdm).exists() { + auth = if Path::new(&gdm).exists() { gdm } else { let username = get_active_username(); @@ -190,7 +217,7 @@ fn set_x11_env(uid: &str) { format!("/{}/.Xauthority", username) } else { let tmp = format!("/home/{}/.Xauthority", username); - if std::path::Path::new(&tmp).exists() { + if Path::new(&tmp).exists() { tmp } else { format!("/var/lib/{}/.Xauthority", username) @@ -223,8 +250,8 @@ fn should_start_server( uid: &mut String, cur_uid: String, cm0: &mut bool, - last_restart: &mut std::time::Instant, - server: &mut Option, + last_restart: &mut Instant, + server: &mut Option, ) -> bool { let cm = get_cm(); let mut start_new = false; @@ -235,8 +262,8 @@ fn should_start_server( } if let Some(ps) = server.as_mut() { allow_err!(ps.kill()); - std::thread::sleep(std::time::Duration::from_millis(30)); - *last_restart = std::time::Instant::now(); + std::thread::sleep(Duration::from_millis(30)); + *last_restart = Instant::now(); } } else if !cm && ((*cm0 && last_restart.elapsed().as_secs() > 60) @@ -247,8 +274,8 @@ fn should_start_server( // and x server get displays failure issue if let Some(ps) = server.as_mut() { allow_err!(ps.kill()); - std::thread::sleep(std::time::Duration::from_millis(30)); - *last_restart = std::time::Instant::now(); + std::thread::sleep(Duration::from_millis(30)); + *last_restart = Instant::now(); log::info!("restart server"); } } @@ -267,6 +294,13 @@ fn should_start_server( start_new } +// to-do: stop_server(&mut user_server); may not stop child correctly +// stop_rustdesk_servers() is just a temp solution here. +fn force_stop_server() { + stop_rustdesk_servers(); + std::thread::sleep(Duration::from_millis(super::SERVICE_INTERVAL)); +} + pub fn start_os_service() { stop_rustdesk_servers(); start_uinput_service(); @@ -274,8 +308,8 @@ pub fn start_os_service() { let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); let mut uid = "".to_owned(); - let mut server: Option = None; - let mut user_server: Option = None; + let mut server: Option = None; + let mut user_server: Option = None; if let Err(err) = ctrlc::set_handler(move || { r.store(false, Ordering::SeqCst); }) { @@ -283,12 +317,13 @@ pub fn start_os_service() { } let mut cm0 = false; - let mut last_restart = std::time::Instant::now(); + let mut last_restart = Instant::now(); while running.load(Ordering::SeqCst) { let (cur_uid, cur_user) = get_active_user_id_name(); let is_wayland = current_is_wayland(); if cur_user == "root" || !is_wayland { + // try kill subprocess "--server" stop_server(&mut user_server); // try start subprocess "--server" if should_start_server( @@ -299,16 +334,8 @@ pub fn start_os_service() { &mut last_restart, &mut server, ) { - // to-do: stop_server(&mut user_server); may not stop child correctly - // stop_rustdesk_servers() is just a temp solution here. - stop_rustdesk_servers(); - std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL)); - match crate::run_me(vec!["--server"]) { - Ok(ps) => server = Some(ps), - Err(err) => { - log::error!("Failed to start server: {}", err); - } - } + force_stop_server(); + start_server(None, &mut server); } } else if cur_user != "" { if cur_user != "gdm" { @@ -324,23 +351,16 @@ pub fn start_os_service() { &mut last_restart, &mut user_server, ) { - stop_rustdesk_servers(); - std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL)); - match run_as_user(vec!["--server"], Some((cur_uid, cur_user))) { - Ok(ps) => user_server = ps, - Err(err) => { - log::error!("Failed to start server: {}", err); - } - } + force_stop_server(); + start_server(Some((cur_uid, cur_user)), &mut user_server); } } } else { - stop_rustdesk_servers(); - std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL)); + force_stop_server(); stop_server(&mut user_server); stop_server(&mut server); } - std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL)); + std::thread::sleep(Duration::from_millis(super::SERVICE_INTERVAL)); } if let Some(ps) = user_server.take().as_mut() { @@ -362,7 +382,7 @@ pub fn get_active_userid() -> String { } fn get_cm() -> bool { - if let Ok(output) = std::process::Command::new("ps").args(vec!["aux"]).output() { + if let Ok(output) = Command::new("ps").args(vec!["aux"]).output() { for line in String::from_utf8_lossy(&output.stdout).lines() { if line.contains(&format!( "{} --cm", @@ -380,7 +400,7 @@ fn get_cm() -> bool { fn get_display() -> String { let user = get_active_username(); log::debug!("w {}", &user); - if let Ok(output) = std::process::Command::new("w").arg(&user).output() { + if let Ok(output) = Command::new("w").arg(&user).output() { for line in String::from_utf8_lossy(&output.stdout).lines() { log::debug!(" {}", line); let mut iter = line.split_whitespace(); @@ -395,7 +415,7 @@ fn get_display() -> String { // above not work for gdm user log::debug!("ls -l /tmp/.X11-unix/"); let mut last = "".to_owned(); - if let Ok(output) = std::process::Command::new("ls") + if let Ok(output) = Command::new("ls") .args(vec!["-l", "/tmp/.X11-unix/"]) .output() { @@ -474,10 +494,7 @@ fn is_opensuse() -> bool { false } -pub fn run_as_user( - arg: Vec<&str>, - user: Option<(String, String)>, -) -> ResultType> { +pub fn run_as_user(arg: Vec<&str>, user: Option<(String, String)>) -> ResultType> { let (uid, username) = match user { Some(id_name) => id_name, None => get_active_user_id_name(), @@ -491,7 +508,7 @@ pub fn run_as_user( args.insert(0, "-E"); } - let task = std::process::Command::new("sudo").args(args).spawn()?; + let task = Command::new("sudo").args(args).spawn()?; Ok(Some(task)) } @@ -553,10 +570,7 @@ pub fn get_default_pa_source() -> Option<(String, String)> { } pub fn lock_screen() { - std::process::Command::new("xdg-screensaver") - .arg("lock") - .spawn() - .ok(); + Command::new("xdg-screensaver").arg("lock").spawn().ok(); } pub fn toggle_blank_screen(_v: bool) { @@ -577,7 +591,7 @@ fn get_env_tries(name: &str, uid: &str, n: usize) -> String { if !x.is_empty() { return x; } - std::thread::sleep(std::time::Duration::from_millis(300)); + std::thread::sleep(Duration::from_millis(300)); } "".to_owned() } @@ -604,12 +618,12 @@ pub fn quit_gui() { pub fn check_super_user_permission() -> ResultType { let file = "/usr/share/rustdesk/files/polkit"; let arg; - if std::path::Path::new(file).is_file() { + if Path::new(file).is_file() { arg = file; } else { arg = "echo"; } - let status = std::process::Command::new("pkexec").arg(arg).status()?; + let status = Command::new("pkexec").arg(arg).status()?; Ok(status.success() && status.code() == Some(0)) } @@ -684,7 +698,7 @@ pub fn current_resolution(name: &str) -> ResultType { } pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType<()> { - std::process::Command::new("xrandr") + Command::new("xrandr") .args(vec![ "--output", name, From 8d726f53aabf33652bb8efaa190bb24ca7093a28 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 24 Feb 2023 23:38:23 +0800 Subject: [PATCH 08/51] better mouse position Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 9a5b06b14..fca73eac7 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -459,17 +459,22 @@ class InputModel { } evt['type'] = type; if (isDesktop) { - y = y - stateGlobal.tabBarHeight; + y = y - stateGlobal.tabBarHeight - stateGlobal.windowBorderWidth.value; + x -= stateGlobal.windowBorderWidth.value; } final canvasModel = parent.target!.canvasModel; + final nearThr = 3; + var nearRight = (canvasModel.size.width - x) < nearThr; + var nearBottom = (canvasModel.size.height - y) < nearThr; + final ffiModel = parent.target!.ffiModel; if (isMove) { canvasModel.moveDesktopMouse(x, y); } final d = ffiModel.display; + final imageWidth = d.width * canvasModel.scale; + final imageHeight = d.height * canvasModel.scale; if (canvasModel.scrollStyle == ScrollStyle.scrollbar) { - final imageWidth = d.width * canvasModel.scale; - final imageHeight = d.height * canvasModel.scale; x += imageWidth * canvasModel.scrollX; y += imageHeight * canvasModel.scrollY; @@ -487,6 +492,15 @@ class InputModel { x /= canvasModel.scale; y /= canvasModel.scale; + if (canvasModel.scale > 0 && canvasModel.scale < 1) { + final step = 1.0 / canvasModel.scale - 1; + if (nearRight) { + x += step; + } + if (nearBottom) { + y += step; + } + } x += d.x; y += d.y; From ac2c7115344e1065cfc77efc8d6f516a2b660b58 Mon Sep 17 00:00:00 2001 From: ilGigioVr88 Date: Fri, 24 Feb 2023 17:04:05 +0100 Subject: [PATCH 09/51] Update it.rs --- src/lang/it.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/it.rs b/src/lang/it.rs index 7256b13d8..04b2488a7 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -454,7 +454,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Interrompi la chiamata vocale"), ("relay_hint_tip", "Se non è possibile connettersi direttamente, si può provare a farlo tramite relay.\nInoltre, se si desidera utilizzare il relay al primo tentativo, è possibile aggiungere il suffisso \"/r\" all'ID o selezionare l'opzione \"Collegati sempre tramite relay\" nella scheda peer."), ("Reconnect", "Riconnetti"), - ("Codec", ""), - ("Resolution", ""), + ("Codec", "Codec"), + ("Resolution", "Risoluzione"), ].iter().cloned().collect(); } From 0a51fff04c984355efcc30a1d5130d0174a591cc Mon Sep 17 00:00:00 2001 From: Michal Witek Date: Fri, 24 Feb 2023 17:19:33 +0100 Subject: [PATCH 10/51] Added additional intent-filter --- flutter/android/app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/flutter/android/app/src/main/AndroidManifest.xml b/flutter/android/app/src/main/AndroidManifest.xml index 9b25f4973..ede6353ef 100644 --- a/flutter/android/app/src/main/AndroidManifest.xml +++ b/flutter/android/app/src/main/AndroidManifest.xml @@ -26,6 +26,7 @@ android:exported="false"> + From 218ce22fbd6f7d0d1c4acc9f03a10bb5419914e6 Mon Sep 17 00:00:00 2001 From: Integral <71180087+Integral-Tech@users.noreply.github.com> Date: Sat, 25 Feb 2023 14:25:35 +0800 Subject: [PATCH 11/51] Update cn.rs Some small fixes --- src/lang/cn.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 818e63203..fd2e04c53 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -38,7 +38,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop service", "停止服务"), ("Change ID", "更改 ID"), ("Your new ID", "你的新 ID"), - ("length %min% to %max%", "长度在 %min 与 %max 之间"), + ("length %min% to %max%", "长度在 %min% 与 %max% 之间"), ("starts with a letter", "以字母开头"), ("allowed characters", "使用允许的字符"), ("id_change_tip", "只可以使用字母 a-z, A-Z, 0-9, _ (下划线)。首字母必须是 a-z, A-Z。长度在 6 与 16 之间。"), @@ -137,7 +137,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Failed to connect to rendezvous server", "连接注册服务器失败"), ("Please try later", "请稍后再试"), ("Remote desktop is offline", "远程电脑处于离线状态"), - ("Key mismatch", "密钥不匹配"), + ("Key mismatch", "Key 不匹配"), ("Timeout", "连接超时"), ("Failed to connect to relay server", "无法连接到中继服务器"), ("Failed to connect via rendezvous server", "无法通过注册服务器建立连接"), From abeb2058eeb3e05691721c421913116f369b5197 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sat, 25 Feb 2023 09:44:23 +0100 Subject: [PATCH 12/51] implemented shrinking transfers --- .../lib/desktop/pages/file_manager_page.dart | 291 +++++++++--------- 1 file changed, 144 insertions(+), 147 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 39d66f568..a709ccba5 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -153,9 +153,17 @@ class _FileManagerPageState extends State backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: Row( children: [ - Flexible(flex: 3, child: body(isLocal: true)), - Flexible(flex: 3, child: body(isLocal: false)), - Flexible(flex: 2, child: statusList()) + Flexible( + flex: 3, + child: body(isLocal: true), + ), + Flexible( + flex: 3, + child: body(isLocal: false), + ), + model.jobTable.isEmpty + ? SizedBox() + : Flexible(flex: 2, child: statusList()) ], ), ); @@ -546,157 +554,146 @@ class _FileManagerPageState extends State /// watch transfer status Widget statusList() { return PreferredSize( - preferredSize: const Size(200, double.infinity), - child: model.jobTable.isEmpty - ? Center(child: Text(translate("Empty"))) - : Container( - margin: - const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), - padding: const EdgeInsets.all(8.0), - child: Obx( - () => ListView.builder( - controller: ScrollController(), - itemBuilder: (BuildContext context, int index) { - final item = model.jobTable[index]; - return Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: BorderRadius.all( - Radius.circular(15.0), + preferredSize: const Size(200, double.infinity), + child: Container( + margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), + padding: const EdgeInsets.all(8.0), + child: Obx( + () => ListView.builder( + controller: ScrollController(), + itemBuilder: (BuildContext context, int index) { + final item = model.jobTable[index]; + return Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.all( + Radius.circular(15.0), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Transform.rotate( + angle: item.isRemote ? pi : 0, + child: SvgPicture.asset( + "assets/arrow.svg", + color: Theme.of(context).tabBarTheme.labelColor, + ), + ).paddingOnly(left: 15), + const SizedBox( + width: 16.0, + ), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Tooltip( + waitDuration: Duration(milliseconds: 500), + message: item.jobName, + child: Text( + item.jobName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ).paddingSymmetric(vertical: 10), + ), + Text( + '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + Offstage( + offstage: item.state != JobState.inProgress, + child: Text( + '${translate("Speed")} ${readableFileSize(item.speed)}/s', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: item.state == JobState.inProgress, + child: Text( + translate( + item.display(), + ), + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: item.state != JobState.inProgress, + child: LinearPercentIndicator( + padding: EdgeInsets.only(right: 15), + animateFromLastPercent: true, + center: Text( + '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', + ), + barRadius: Radius.circular(15), + percent: item.finishedSize / item.totalSize, + progressColor: MyTheme.accent, + backgroundColor: + Theme.of(context).hoverColor, + lineHeight: kDesktopFileTransferRowHeight, + ).paddingSymmetric(vertical: 15), + ), + ], ), ), - child: Column( - mainAxisSize: MainAxisSize.min, + Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Transform.rotate( - angle: item.isRemote ? pi : 0, - child: SvgPicture.asset( - "assets/arrow.svg", - color: Theme.of(context) - .tabBarTheme - .labelColor, - ), - ).paddingOnly(left: 15), - const SizedBox( - width: 16.0, + Offstage( + offstage: item.state != JobState.paused, + child: MenuButton( + onPressed: () { + model.resumeJob(item.id); + }, + child: SvgPicture.asset( + "assets/refresh.svg", + color: Colors.white, ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Tooltip( - waitDuration: - Duration(milliseconds: 500), - message: item.jobName, - child: Text( - item.jobName, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ).paddingSymmetric(vertical: 10), - ), - Text( - '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - Offstage( - offstage: - item.state != JobState.inProgress, - child: Text( - '${translate("Speed")} ${readableFileSize(item.speed)}/s', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - ), - Offstage( - offstage: - item.state == JobState.inProgress, - child: Text( - translate( - item.display(), - ), - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - ), - Offstage( - offstage: - item.state != JobState.inProgress, - child: LinearPercentIndicator( - padding: EdgeInsets.only(right: 15), - animateFromLastPercent: true, - center: Text( - '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', - ), - barRadius: Radius.circular(15), - percent: item.finishedSize / - item.totalSize, - progressColor: MyTheme.accent, - backgroundColor: - Theme.of(context).hoverColor, - lineHeight: - kDesktopFileTransferRowHeight, - ).paddingSymmetric(vertical: 15), - ), - ], - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Offstage( - offstage: item.state != JobState.paused, - child: MenuButton( - onPressed: () { - model.resumeJob(item.id); - }, - child: SvgPicture.asset( - "assets/refresh.svg", - color: Colors.white, - ), - color: MyTheme.accent, - hoverColor: MyTheme.accent80, - ), - ), - MenuButton( - padding: EdgeInsets.only(right: 15), - child: SvgPicture.asset( - "assets/close.svg", - color: Colors.white, - ), - onPressed: () { - model.jobTable.removeAt(index); - model.cancelJob(item.id); - }, - color: MyTheme.accent, - hoverColor: MyTheme.accent80, - ), - ], - ), - ], + color: MyTheme.accent, + hoverColor: MyTheme.accent80, + ), + ), + MenuButton( + padding: EdgeInsets.only(right: 15), + child: SvgPicture.asset( + "assets/close.svg", + color: Colors.white, + ), + onPressed: () { + model.jobTable.removeAt(index); + model.cancelJob(item.id); + }, + color: MyTheme.accent, + hoverColor: MyTheme.accent80, ), ], - ).paddingSymmetric(vertical: 10), - ), - ); - }, - itemCount: model.jobTable.length, - ), + ), + ], + ), + ], + ).paddingSymmetric(vertical: 10), ), - )); + ); + }, + itemCount: model.jobTable.length, + ), + ), + ), + ); } Widget headTools(bool isLocal) { From 75ecb66576226292b9d4845c6e91b5e9d8fb323b Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sat, 25 Feb 2023 09:50:40 +0100 Subject: [PATCH 13/51] improved light mode send/receive button readability --- flutter/lib/desktop/pages/file_manager_page.dart | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index a709ccba5..96ab4044f 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -1000,7 +1000,9 @@ class _FileManagerPageState extends State textAlign: TextAlign.right, style: TextStyle( color: selectedItems.length == 0 - ? MyTheme.darkGray + ? Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray : Colors.white, ), ) @@ -1009,7 +1011,9 @@ class _FileManagerPageState extends State child: SvgPicture.asset( "assets/arrow.svg", color: selectedItems.length == 0 - ? MyTheme.darkGray + ? Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray : Colors.white, alignment: Alignment.bottomRight, ), @@ -1018,14 +1022,18 @@ class _FileManagerPageState extends State ? SvgPicture.asset( "assets/arrow.svg", color: selectedItems.length == 0 - ? MyTheme.darkGray + ? Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray : Colors.white, ) : Text( translate('Receive'), style: TextStyle( color: selectedItems.length == 0 - ? MyTheme.darkGray + ? Theme.of(context).brightness == Brightness.light + ? MyTheme.grayBg + : MyTheme.darkGray : Colors.white, ), ), From eb39cc5da189e3c67c5b270dc38f1c18c9248ce4 Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sat, 25 Feb 2023 10:08:34 +0100 Subject: [PATCH 14/51] fix button flicker --- flutter/lib/desktop/pages/file_manager_page.dart | 2 +- flutter/lib/desktop/widgets/menu_button.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 96ab4044f..5df9c9a80 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -678,7 +678,7 @@ class _FileManagerPageState extends State model.cancelJob(item.id); }, color: MyTheme.accent, - hoverColor: MyTheme.accent80, + hoverColor: MyTheme.button, ), ], ), diff --git a/flutter/lib/desktop/widgets/menu_button.dart b/flutter/lib/desktop/widgets/menu_button.dart index df2c48ab4..17b160fed 100644 --- a/flutter/lib/desktop/widgets/menu_button.dart +++ b/flutter/lib/desktop/widgets/menu_button.dart @@ -37,7 +37,7 @@ class _MenuButtonState extends State { message: widget.tooltip, child: Material( type: MaterialType.transparency, - child: Ink( + child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(_borderRadius), color: _isHover ? widget.hoverColor : widget.color, From f71d4e9e815edf2486f01158250ef50873f5f1b4 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sat, 25 Feb 2023 18:39:27 +0800 Subject: [PATCH 15/51] initialize vdi with .devcontainer --- vdi/README.md | 1 + vdi/host/.devcontainer/Dockerfile | 16 + vdi/host/.devcontainer/devcontainer.json | 27 + vdi/host/.gitignore | 1 + vdi/host/Cargo.lock | 1185 ++++++++++++++++++++++ vdi/host/Cargo.toml | 9 + vdi/host/README.md | 1 + vdi/host/src/main.rs | 2 + 8 files changed, 1242 insertions(+) create mode 100644 vdi/README.md create mode 100644 vdi/host/.devcontainer/Dockerfile create mode 100644 vdi/host/.devcontainer/devcontainer.json create mode 100644 vdi/host/.gitignore create mode 100644 vdi/host/Cargo.lock create mode 100644 vdi/host/Cargo.toml create mode 100644 vdi/host/README.md create mode 100644 vdi/host/src/main.rs diff --git a/vdi/README.md b/vdi/README.md new file mode 100644 index 000000000..85e6ff194 --- /dev/null +++ b/vdi/README.md @@ -0,0 +1 @@ +# WIP diff --git a/vdi/host/.devcontainer/Dockerfile b/vdi/host/.devcontainer/Dockerfile new file mode 100644 index 000000000..f02042771 --- /dev/null +++ b/vdi/host/.devcontainer/Dockerfile @@ -0,0 +1,16 @@ +FROM rockylinux:9.1 +ENV HOME=/home/vscode +ENV WORKDIR=$HOME/rustdesk/vdi/host + +# https://ciq.co/blog/top-10-things-to-do-after-rocky-linux-9-install/ also gpu driver install +WORKDIR $HOME +RUN dnf -y install epel-release +RUN dnf config-manager --set-enabled crb +RUN dnf -y install cargo libvpx-devel opus-devel usbredir-devel git cmake gcc-c++ pkg-config nasm yasm ninja-build automake libtool libva-devel libvdpau-devel llvm-devel +WORKDIR / + +RUN git clone https://chromium.googlesource.com/libyuv/libyuv +WORKDIR /libyuv +RUN cmake . -DCMAKE_INSTALL_PREFIX=/user +RUN make -j4 && make install +WORKDIR / \ No newline at end of file diff --git a/vdi/host/.devcontainer/devcontainer.json b/vdi/host/.devcontainer/devcontainer.json new file mode 100644 index 000000000..02c6e589b --- /dev/null +++ b/vdi/host/.devcontainer/devcontainer.json @@ -0,0 +1,27 @@ +{ + "name": "rustdesk", + "build": { + "dockerfile": "./Dockerfile", + "context": "." + }, + "workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rustdesk,type=bind,consistency=cache", + "workspaceFolder": "/home/vscode/rustdesk", + "customizations": { + "vscode": { + "extensions": [ + "vadimcn.vscode-lldb", + "mutantdino.resourcemonitor", + "rust-lang.rust-analyzer", + "tamasfe.even-better-toml", + "serayuzgur.crates", + "mhutchie.git-graph", + "eamodio.gitlens" + ], + "settings": { + "files.watcherExclude": { + "**/target/**": true + } + } + } + } +} \ No newline at end of file diff --git a/vdi/host/.gitignore b/vdi/host/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/vdi/host/.gitignore @@ -0,0 +1 @@ +/target diff --git a/vdi/host/Cargo.lock b/vdi/host/Cargo.lock new file mode 100644 index 000000000..d4254717e --- /dev/null +++ b/vdi/host/Cargo.lock @@ -0,0 +1,1185 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "async-broadcast" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90622698a1218e0b2fb846c97b5f19a0831f6baddee73d9454156365ccfa473b" +dependencies = [ + "easy-parallel", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-broadcast" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d26004fe83b2d1cd3a97609b21e39f9a31535822210fe83205d2ce48866ea61" +dependencies = [ + "event-listener", + "futures-core", + "parking_lot", +] + +[[package]] +name = "async-channel" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +dependencies = [ + "async-lock", + "autocfg", + "concurrent-queue", + "futures-lite", + "libc", + "log", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "windows-sys 0.42.0", +] + +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + +[[package]] +name = "async-recursion" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "async-trait" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "concurrent-queue" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "easy-parallel" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" + +[[package]] +name = "enumflags2" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "futures" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" + +[[package]] +name = "futures-executor" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" + +[[package]] +name = "futures-task" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" + +[[package]] +name = "futures-util" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libusb1-sys" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "ordered-stream" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.45.0", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "polling" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "windows-sys 0.42.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qemu-display" +version = "0.1.0" +source = "git+https://gitlab.com/marcandre.lureau/qemu-display#544a4075615702abf414cd2d63bbb6a9ca10d0ea" +dependencies = [ + "async-broadcast 0.3.4", + "async-lock", + "async-trait", + "cfg-if", + "derivative", + "enumflags2", + "futures", + "futures-util", + "libc", + "log", + "once_cell", + "serde", + "serde_bytes", + "serde_repr", + "uds_windows", + "usbredirhost", + "windows", + "zbus", + "zvariant", +] + +[[package]] +name = "qemu-rustdesk" +version = "0.1.0" +dependencies = [ + "qemu-display", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rusb" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703aa035c21c589b34fb5136b12e68fc8dcf7ea46486861381361dd8ebf5cee0" +dependencies = [ + "libc", + "libusb1-sys", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-xml-rs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0bf1ba0696ccf0872866277143ff1fd14d22eec235d2b23702f95e6660f7dfa" +dependencies = [ + "log", + "serde", + "thiserror", + "xml-rs", +] + +[[package]] +name = "serde_bytes" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_repr" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "uds_windows" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +dependencies = [ + "tempfile", + "winapi", +] + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "usbredirhost" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87485e4dfeb0176203afd1086f11ed2ead837053143b12b6eed55c598e9393d5" +dependencies = [ + "libc", + "rusb", + "usbredirhost-sys", + "usbredirparser", +] + +[[package]] +name = "usbredirhost-sys" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b27c305da1f7601b665d68948bcfaf9909d443bec94510ab776118ab8afc2c7d" +dependencies = [ + "libusb1-sys", + "pkg-config", + "usbredirparser-sys", +] + +[[package]] +name = "usbredirparser" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f8b5241d7cbb3e08b4677212a9ac001f116f50731c2737d16129a84ecf6a56" +dependencies = [ + "libc", + "usbredirparser-sys", +] + +[[package]] +name = "usbredirparser-sys" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b0e834e187916fc762bccdc9d64e454a0ee58b134f8f7adab321141e8e0d91" +dependencies = [ + "pkg-config", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "zbus" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ce2de393c874ba871292e881bf3c13a0d5eb38170ebab2e50b4c410eaa222b" +dependencies = [ + "async-broadcast 0.4.1", + "async-channel", + "async-executor", + "async-io", + "async-lock", + "async-recursion", + "async-task", + "async-trait", + "byteorder", + "derivative", + "dirs", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "once_cell", + "ordered-stream", + "rand", + "serde", + "serde-xml-rs", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13d08f5dc6cf725b693cb6ceacd43cd430ec0664a879188f29e7d7dcd98f96d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "zbus_names" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zvariant" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903169c05b9ab948ee93fefc9127d08930df4ce031d46c980784274439803e51" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "serde_bytes", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cce76636e8fab7911be67211cf378c252b115ee7f2bae14b18b84821b39260b5" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] diff --git a/vdi/host/Cargo.toml b/vdi/host/Cargo.toml new file mode 100644 index 000000000..62c964122 --- /dev/null +++ b/vdi/host/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "qemu-rustdesk" +version = "0.1.0" +authors = ["rustdesk "] +edition = "2021" + + +[dependencies] +qemu-display = { git = "https://gitlab.com/marcandre.lureau/qemu-display" } \ No newline at end of file diff --git a/vdi/host/README.md b/vdi/host/README.md new file mode 100644 index 000000000..3b29a10e3 --- /dev/null +++ b/vdi/host/README.md @@ -0,0 +1 @@ +# RustDesk protocol on QEMU D-Bus display diff --git a/vdi/host/src/main.rs b/vdi/host/src/main.rs new file mode 100644 index 000000000..f79c691f0 --- /dev/null +++ b/vdi/host/src/main.rs @@ -0,0 +1,2 @@ +fn main() { +} From b8b3e996026fa47352feb9bcb30c45cc5b4a1442 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Feb 2023 22:39:12 +0800 Subject: [PATCH 16/51] macos, periodically check if current display is changed Signed-off-by: fufesou --- src/platform/macos.mm | 3 +-- src/platform/macos.rs | 8 ++++---- src/server/video_service.rs | 8 ++++++++ src/ui.rs | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/platform/macos.mm b/src/platform/macos.mm index 443351469..8be0c6db5 100644 --- a/src/platform/macos.mm +++ b/src/platform/macos.mm @@ -60,7 +60,7 @@ extern "C" bool MacGetModes(CGDirectDisplayID display, uint32_t *widths, uint32_ return false; } *numModes = CFArrayGetCount(allModes); - for (int i = 0; i < *numModes && i < max; i++) { + for (uint32_t i = 0; i < *numModes && i < max; i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); widths[i] = (uint32_t)CGDisplayModeGetWidth(mode); heights[i] = (uint32_t)CGDisplayModeGetHeight(mode); @@ -136,7 +136,6 @@ extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t h return ret; } int numModes = CFArrayGetCount(allModes); - CGDisplayModeRef bestMode = NULL; for (int i = 0; i < numModes; i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); if (width == CGDisplayModeGetWidth(mode) && diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 025274840..b663b0f41 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -612,18 +612,18 @@ pub fn resolutions(name: &str) -> Vec { unsafe { if YES == MacGetModeNum(display, &mut num) { let (mut widths, mut heights) = (vec![0; num as _], vec![0; num as _]); - let mut realNum = 0; + let mut real_num = 0; if YES == MacGetModes( display, widths.as_mut_ptr(), heights.as_mut_ptr(), num, - &mut realNum, + &mut real_num, ) { - if realNum <= num { - for i in 0..realNum { + if real_num <= num { + for i in 0..real_num { let resolution = Resolution { width: widths[i as usize] as _, height: heights[i as usize] as _, diff --git a/src/server/video_service.rs b/src/server/video_service.rs index a9a9fd9ab..affb5eb17 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -577,6 +577,14 @@ fn run(sp: GenericService) -> ResultType<()> { if last_check_displays.elapsed().as_millis() > 1000 { last_check_displays = now; + // Capturer on macos does not return Err event the solution is changed. + #[cfg(target_os = "macos")] + if check_display_changed(c.ndisplay, c.current, c.width, c.height) { + log::info!("Displays changed"); + *SWITCH.lock().unwrap() = true; + bail!("SWITCH"); + } + if let Some(msg_out) = check_displays_changed() { sp.send(msg_out); } diff --git a/src/ui.rs b/src/ui.rs index a197cb257..e0449fd95 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -9,7 +9,7 @@ use sciter::Value; use hbb_common::{ allow_err, - config::{self, LocalConfig, PeerConfig}, + config::{LocalConfig, PeerConfig}, log, }; From 59cd775d5fe7606891ebbcff80f329510b52bff8 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Feb 2023 22:47:22 +0800 Subject: [PATCH 17/51] fix notify peer resolution change Signed-off-by: fufesou --- flutter/lib/models/model.dart | 79 +++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index eae41679f..e48d74dac 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -156,7 +156,7 @@ class FfiModel with ChangeNotifier { } else if (name == 'clipboard') { Clipboard.setData(ClipboardData(text: evt['content'])); } else if (name == 'permission') { - parent.target?.ffiModel.updatePermission(evt, peerId); + updatePermission(evt, peerId); } else if (name == 'chat_client_mode') { parent.target?.chatModel .receive(ChatModel.clientModeID, evt['text'] ?? ''); @@ -241,36 +241,33 @@ class FfiModel with ChangeNotifier { } } - handleSwitchDisplay(Map evt, String peerId) { - final oldOrientation = _display.width > _display.height; - var old = _pi.currentDisplay; - _pi.currentDisplay = int.parse(evt['display']); - _display.x = double.parse(evt['x']); - _display.y = double.parse(evt['y']); - _display.width = int.parse(evt['width']); - _display.height = int.parse(evt['height']); - _display.cursorEmbedded = int.parse(evt['cursor_embedded']) == 1; - if (old != _pi.currentDisplay) { - parent.target?.cursorModel.updateDisplayOrigin(_display.x, _display.y); + _updateCurDisplay(String peerId, Display newDisplay) { + if (newDisplay != _display) { + if (newDisplay.x != _display.x || newDisplay.y != _display.y) { + parent.target?.cursorModel + .updateDisplayOrigin(newDisplay.x, newDisplay.y); + } + _display = newDisplay; + _updateSessionWidthHeight(peerId); } + } - _updateSessionWidthHeight(peerId, display.width, display.height); + handleSwitchDisplay(Map evt, String peerId) { + _pi.currentDisplay = int.parse(evt['display']); + var newDisplay = Display(); + newDisplay.x = double.parse(evt['x']); + newDisplay.y = double.parse(evt['y']); + newDisplay.width = int.parse(evt['width']); + newDisplay.height = int.parse(evt['height']); + newDisplay.cursorEmbedded = int.parse(evt['cursor_embedded']) == 1; + + _updateCurDisplay(peerId, newDisplay); try { CurrentDisplayState.find(peerId).value = _pi.currentDisplay; } catch (e) { // } - - // remote is mobile, and orientation changed - if ((_display.width > _display.height) != oldOrientation) { - gFFI.canvasModel.updateViewStyle(); - } - if (_pi.platform == kPeerPlatformLinux || - _pi.platform == kPeerPlatformWindows || - _pi.platform == kPeerPlatformMacOS) { - parent.target?.canvasModel.updateViewStyle(); - } parent.target?.recordingModel.onSwitchDisplay(); handleResolutions(peerId, evt["resolutions"]); notifyListeners(); @@ -372,7 +369,8 @@ class FfiModel with ChangeNotifier { }); } - _updateSessionWidthHeight(String id, int width, int height) { + _updateSessionWidthHeight(String id) { + parent.target?.canvasModel.updateViewStyle(); bind.sessionSetSize(id: id, width: display.width, height: display.height); } @@ -429,7 +427,7 @@ class FfiModel with ChangeNotifier { stateGlobal.displaysCount.value = _pi.displays.length; if (_pi.currentDisplay < _pi.displays.length) { _display = _pi.displays[_pi.currentDisplay]; - _updateSessionWidthHeight(peerId, display.width, display.height); + _updateSessionWidthHeight(peerId); } if (displays.isNotEmpty) { parent.target?.dialogManager.showLoading( @@ -488,7 +486,7 @@ class FfiModel with ChangeNotifier { _pi.displays = newDisplays; stateGlobal.displaysCount.value = _pi.displays.length; if (_pi.currentDisplay >= 0 && _pi.currentDisplay < _pi.displays.length) { - _display = _pi.displays[_pi.currentDisplay]; + _updateCurDisplay(peerId, _pi.displays[_pi.currentDisplay]); } } notifyListeners(); @@ -797,12 +795,18 @@ class CanvasModel with ChangeNotifier { final dh = getDisplayHeight() * _scale; var dxOffset = 0; var dyOffset = 0; - if (dw > size.width) { - dxOffset = (x - dw * (x / size.width) - _x).toInt(); - } - if (dh > size.height) { - dyOffset = (y - dh * (y / size.height) - _y).toInt(); + try { + if (dw > size.width) { + dxOffset = (x - dw * (x / size.width) - _x).toInt(); + } + if (dh > size.height) { + dyOffset = (y - dh * (y / size.height) - _y).toInt(); + } + } catch (e) { + // Unhandled Exception: Unsupported operation: Infinity or NaN toInt + return; } + _x += dxOffset; _y += dyOffset; if (dxOffset != 0 || dyOffset != 0) { @@ -1579,6 +1583,19 @@ class Display { ? kDesktopDefaultDisplayHeight : kMobileDefaultDisplayHeight; } + + @override + bool operator ==(Object other) => + other is Display && + other.runtimeType == runtimeType && + _innerEqual(other); + + bool _innerEqual(Display other) => + other.x == x && + other.y == y && + other.width == width && + other.height == height && + other.cursorEmbedded == cursorEmbedded; } class Resolution { From e876adaec58ed45761a0aae250425d49b75faebd Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Feb 2023 22:59:59 +0800 Subject: [PATCH 18/51] fix, flutter keyboard grab, connecting peers of older version Signed-off-by: fufesou --- .../lib/desktop/widgets/remote_menubar.dart | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 37bbbd66a..8500bec03 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -23,6 +23,10 @@ import '../../common/shared_state.dart'; import './popup_menu.dart'; import './kb_layout_type_chooser.dart'; +const _kKeyLegacyMode = 'legacy'; +const _kKeyMapMode = 'map'; +const _kKeyTranslateMode = 'translate'; + class MenubarState { final kStoreKey = 'remoteMenubarState'; late RxBool show; @@ -1540,9 +1544,10 @@ class _KeyboardMenu extends StatelessWidget { Widget build(BuildContext context) { var ffiModel = Provider.of(context); if (ffiModel.permissions['keyboard'] == false) return Offstage(); - // Do not support peer 1.1.9. if (stateGlobal.grabKeyboard) { - bind.sessionSetKeyboardMode(id: id, value: 'map'); + if (bind.sessionIsKeyboardModeSupported(id: id, mode: _kKeyMapMode)) { + bind.sessionSetKeyboardMode(id: id, value: _kKeyMapMode); + } return Offstage(); } return _IconSubmenuButton( @@ -1555,13 +1560,13 @@ class _KeyboardMenu extends StatelessWidget { mode() { return futureBuilder(future: () async { - return await bind.sessionGetKeyboardMode(id: id) ?? 'legacy'; + return await bind.sessionGetKeyboardMode(id: id) ?? _kKeyLegacyMode; }(), hasData: (data) { final groupValue = data as String; List modes = [ - KeyboardModeMenu(key: 'legacy', menu: 'Legacy mode'), - KeyboardModeMenu(key: 'map', menu: 'Map mode'), - KeyboardModeMenu(key: 'translate', menu: 'Translate mode'), + KeyboardModeMenu(key: _kKeyLegacyMode, menu: 'Legacy mode'), + KeyboardModeMenu(key: _kKeyMapMode, menu: 'Map mode'), + KeyboardModeMenu(key: _kKeyTranslateMode, menu: 'Translate mode'), ]; List<_RadioMenuButton> list = []; onChanged(String? value) async { @@ -1571,13 +1576,13 @@ class _KeyboardMenu extends StatelessWidget { for (KeyboardModeMenu mode in modes) { if (bind.sessionIsKeyboardModeSupported(id: id, mode: mode.key)) { - if (mode.key == 'translate') { + if (mode.key == _kKeyTranslateMode) { if (Platform.isLinux || pi.platform == kPeerPlatformLinux) { continue; } } var text = translate(mode.menu); - if (mode.key == 'translate') { + if (mode.key == _kKeyTranslateMode) { text = '$text beta'; } list.add(_RadioMenuButton( From 6740587d8adf6a8cc62c6d09ead26a1a878400c2 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sat, 25 Feb 2023 23:11:28 +0800 Subject: [PATCH 19/51] do not check keyboard permission on menu build Signed-off-by: fufesou --- flutter/lib/desktop/widgets/remote_menubar.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 8500bec03..c27546d9f 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -1542,11 +1542,15 @@ class _KeyboardMenu extends StatelessWidget { @override Widget build(BuildContext context) { - var ffiModel = Provider.of(context); - if (ffiModel.permissions['keyboard'] == false) return Offstage(); + // Do not check permission here? + // var ffiModel = Provider.of(context); + // if (ffiModel.permissions['keyboard'] == false) return Offstage(); if (stateGlobal.grabKeyboard) { if (bind.sessionIsKeyboardModeSupported(id: id, mode: _kKeyMapMode)) { bind.sessionSetKeyboardMode(id: id, value: _kKeyMapMode); + } else if (bind.sessionIsKeyboardModeSupported( + id: id, mode: _kKeyLegacyMode)) { + bind.sessionSetKeyboardMode(id: id, value: _kKeyLegacyMode); } return Offstage(); } From 037641624c82aa5cd0cf6ae8475bb9ef82b4172a Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Sat, 25 Feb 2023 21:39:21 +0100 Subject: [PATCH 20/51] Update es.rs New terms added --- src/lang/es.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/es.rs b/src/lang/es.rs index d7e43b6bf..5ae368581 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -454,7 +454,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Detener llamada de voz"), ("relay_hint_tip", "Puede que no sea posible conectar directamente. Puedes tratar de conectar a través de relay. \nAdicionalmente, si quieres usar relay en el primer intento, puedes añadir el sufijo \"/r\" a la ID o seleccionar la opción \"Conectar siempre a través de relay\" en la tarjeta del par."), ("Reconnect", "Reconectar"), - ("Codec", ""), - ("Resolution", ""), + ("Codec", "Códec"), + ("Resolution", "Resolución"), ].iter().cloned().collect(); } From 8092f3ad94f11112d8c37b60d45dfd928be1eeb1 Mon Sep 17 00:00:00 2001 From: PCKUO Date: Sun, 26 Feb 2023 12:51:16 +0800 Subject: [PATCH 21/51] Make up for the missing --- src/lang/tw.rs | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/lang/tw.rs b/src/lang/tw.rs index ca1193eaa..e20c7f254 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -37,19 +37,19 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Clipboard is empty", "剪貼簿是空的"), ("Stop service", "停止服務"), ("Change ID", "更改 ID"), - ("Your new ID", ""), - ("length %min% to %max%", ""), - ("starts with a letter", ""), - ("allowed characters", ""), + ("Your new ID", "你的新 ID"), + ("length %min% to %max%", "長度在 %min% 與 %max% 之間"), + ("starts with a letter", "以字母開頭"), + ("allowed characters", "使用允許的字元"), ("id_change_tip", "僅能使用以下字元:a-z、A-Z、0-9、_ (底線)。首字元必須為 a-z 或 A-Z。長度介於 6 到 16 之間。"), ("Website", "網站"), ("About", "關於"), ("Slogan_tip", ""), - ("Privacy Statement", ""), + ("Privacy Statement", "隱私聲明"), ("Mute", "靜音"), - ("Build Date", ""), - ("Version", ""), - ("Home", ""), + ("Build Date", "建構日期"), + ("Version", "版本"), + ("Home", "主頁"), ("Audio Input", "音訊輸入"), ("Enhancements", "增強功能"), ("Hardware Codec", "硬件編解碼"), @@ -213,15 +213,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the peer", "由對方手動關閉"), ("Enable remote configuration modification", "啟用遠端更改設定"), ("Run without install", "跳過安裝直接執行"), - ("Connect via relay", ""), + ("Connect via relay", "中繼連線"), ("Always connect via relay", "一律透過轉送連線"), ("whitelist_tip", "只有白名單中的 IP 可以存取"), ("Login", "登入"), - ("Verify", ""), - ("Remember me", ""), - ("Trust this device", ""), - ("Verification code", ""), - ("verification_tip", ""), + ("Verify", "驗證"), + ("Remember me", "記住我"), + ("Trust this device", "信任此設備"), + ("Verification code", "驗證碼"), + ("verification_tip", "檢測到新設備登錄,已向註冊郵箱發送了登入驗證碼,請輸入驗證碼繼續登錄"), ("Logout", "登出"), ("Tags", "標籤"), ("Search ID", "搜尋 ID"), @@ -391,12 +391,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland 需要更高版本的 linux 發行版。 請嘗試 X11 桌面或更改您的操作系統。"), ("JumpLink", "查看"), ("Please Select the screen to be shared(Operate on the peer side).", "請選擇要分享的畫面(在對端操作)。"), - ("Show RustDesk", ""), - ("This PC", ""), - ("or", ""), - ("Continue with", ""), + ("Show RustDesk", "顯示 RustDesk"), + ("This PC", "此電腦"), + ("or", "或"), + ("Continue with", "使用"), ("Elevate", "提權"), - ("Zoom cursor", ""), + ("Zoom cursor", "縮放游標"), ("Accept sessions via password", "只允許密碼訪問"), ("Accept sessions via click", "只允許點擊訪問"), ("Accept sessions via both", "允許密碼或點擊訪問"), @@ -407,9 +407,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Request access to your device", "請求訪問你的設備"), ("Hide connection management window", "隱藏連接管理窗口"), ("hide_cm_tip", "在只允許密碼連接並且只用固定密碼的情況下才允許隱藏"), - ("wayland_experiment_tip", ""), + ("wayland_experiment_tip", "Wayland 支持處於實驗階段,如果你需要使用無人值守訪問,請使用 X11。"), ("Right click to select tabs", "右鍵選擇選項卡"), - ("Skipped", ""), + ("Skipped", "已略過"), ("Add to Address Book", "添加到地址簿"), ("Group", "小組"), ("Search", "搜索"), @@ -418,8 +418,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Select local keyboard type", "請選擇本地鍵盤類型"), ("software_render_tip", "如果你使用英偉達顯卡, 並且遠程窗口在會話建立後會立刻關閉, 那麼安裝nouveau驅動並且選擇使用軟件渲染可能會有幫助。重啟軟件後生效。"), ("Always use software rendering", "使用軟件渲染"), - ("config_input", ""), - ("config_microphone", ""), + ("config_input", "為了能夠通過鍵盤控制遠程桌面, 請給予 RustDesk \"輸入監控\" 權限。"), + ("config_microphone", "為了支持通過麥克風進行音訊傳輸,請給予 RustDesk \"錄音\"權限。"), ("request_elevation_tip", "如果對面有人, 也可以請求提升權限。"), ("Wait", "等待"), ("Elevation Error", "提權失敗"), @@ -438,8 +438,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Weak", "弱"), ("Medium", "中"), ("Strong", "強"), - ("Switch Sides", ""), - ("Please confirm if you want to share your desktop?", ""), + ("Switch Sides", "反轉訪問方向"), + ("Please confirm if you want to share your desktop?", "請確認是否要讓對方訪問你的桌面?"), ("Display", "顯示"), ("Default View Style", "默認顯示方式"), ("Default Scroll Style", "默認滾動方式"), From 4b2529125567207721489caaf2085532d998705c Mon Sep 17 00:00:00 2001 From: 21pages Date: Sun, 26 Feb 2023 11:23:43 +0800 Subject: [PATCH 22/51] sciter/mobile id suffix "\r" or "/r" for relay Signed-off-by: 21pages --- flutter/lib/common.dart | 6 ++++-- .../lib/desktop/pages/connection_page.dart | 5 +---- src/flutter_ffi.rs | 4 ++++ src/ui.rs | 19 ++++++++++++++----- src/ui/index.tis | 5 ++++- src/ui/remote.rs | 3 ++- src/ui_interface.rs | 9 +++++++++ 7 files changed, 38 insertions(+), 13 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index ff373cc9c..e89671711 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1453,10 +1453,12 @@ connectMainDesktop(String id, connect(BuildContext context, String id, {bool isFileTransfer = false, bool isTcpTunneling = false, - bool isRDP = false, - bool forceRelay = false}) async { + bool isRDP = false}) async { if (id == '') return; id = id.replaceAll(' ', ''); + final oldId = id; + id = await bind.mainHandleRelayId(id: id); + final forceRelay = id != oldId; assert(!(isFileTransfer && isTcpTunneling && isRDP), "more than one connect type"); diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart index 4aad66eee..edbd5b7c6 100644 --- a/flutter/lib/desktop/pages/connection_page.dart +++ b/flutter/lib/desktop/pages/connection_page.dart @@ -151,10 +151,7 @@ class _ConnectionPageState extends State /// Connects to the selected peer. void onConnect({bool isFileTransfer = false}) { var id = _idController.id; - var forceRelay = id.endsWith(r'/r'); - if (forceRelay) id = id.substring(0, id.length - 2); - connect(context, id, - isFileTransfer: isFileTransfer, forceRelay: forceRelay); + connect(context, id, isFileTransfer: isFileTransfer); } /// UI for the remote ID TextField. diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 0866ff739..e49ba65f7 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -840,6 +840,10 @@ pub fn main_get_user_default_option(key: String) -> SyncReturn { SyncReturn(get_user_default_option(key)) } +pub fn main_handle_relay_id(id: String) -> String { + handle_relay_id(id) +} + pub fn session_add_port_forward( id: String, local_port: i32, diff --git a/src/ui.rs b/src/ui.rs index e0449fd95..22c44ec5f 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -420,8 +420,8 @@ impl UI { crate::lan::send_wol(id) } - fn new_remote(&mut self, id: String, remote_type: String) { - new_remote(id, remote_type) + fn new_remote(&mut self, id: String, remote_type: String, force_relay: bool) { + new_remote(id, remote_type, force_relay) } fn is_process_trusted(&mut self, _prompt: bool) -> bool { @@ -571,6 +571,10 @@ impl UI { fn default_video_save_directory(&self) -> String { default_video_save_directory() } + + fn handle_relay_id(&self, id: String) -> String { + handle_relay_id(id) + } } impl sciter::EventHandler for UI { @@ -588,7 +592,7 @@ impl sciter::EventHandler for UI { fn set_remote_id(String); fn closing(i32, i32, i32, i32); fn get_size(); - fn new_remote(String, bool); + fn new_remote(String, String, bool); fn send_wol(String); fn remove_peer(String); fn remove_discovered(String); @@ -653,6 +657,7 @@ impl sciter::EventHandler for UI { fn has_hwcodec(); fn get_langs(); fn default_video_save_directory(); + fn handle_relay_id(String); } } @@ -718,9 +723,13 @@ pub fn value_crash_workaround(values: &[Value]) -> Arc> { } #[inline] -pub fn new_remote(id: String, remote_type: String) { +pub fn new_remote(id: String, remote_type: String, force_relay: bool) { let mut lock = CHILDREN.lock().unwrap(); - let args = vec![format!("--{}", remote_type), id.clone()]; + let mut args = vec![format!("--{}", remote_type), id.clone()]; + if force_relay { + args.push("".to_string()); // password + args.push("--relay".to_string()); + } let key = (id.clone(), remote_type.clone()); if let Some(c) = lock.1.get_mut(&key) { if let Ok(Some(_)) = c.try_wait() { diff --git a/src/ui/index.tis b/src/ui/index.tis index ec2e0a748..0e2247070 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -62,12 +62,15 @@ function createNewConnect(id, type) { id = id.replace(/\s/g, ""); app.remote_id.value = formatId(id); if (!id) return; + var old_id = id; + id = handler.handle_relay_id(id); + var force_relay = old_id != id; if (id == my_id) { msgbox("custom-error", "Error", "You cannot connect to your own computer"); return; } handler.set_remote_id(id); - handler.new_remote(id, type); + handler.new_remote(id, type, force_relay); } class ShareRdp: Reactor.Component { diff --git a/src/ui/remote.rs b/src/ui/remote.rs index c6e0229b2..ed16f1e0e 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -462,6 +462,7 @@ impl sciter::EventHandler for SciterSession { impl SciterSession { pub fn new(cmd: String, id: String, password: String, args: Vec) -> Self { + let force_relay = args.contains(&"--relay".to_string()); let session: Session = Session { id: id.clone(), password: password.clone(), @@ -486,7 +487,7 @@ impl SciterSession { .lc .write() .unwrap() - .initialize(id, conn_type, None, false); + .initialize(id, conn_type, None, force_relay); Self(session) } diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 3b2ba0897..62eba25c1 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -970,3 +970,12 @@ async fn check_id( } "" } + +// if it's relay id, return id processed, otherwise return original id +pub fn handle_relay_id(id: String) -> String { + if id.ends_with(r"\r") || id.ends_with(r"/r") { + id[0..id.len() - 2].to_string() + } else { + id + } +} From 8fa487e5b07f1c53b6cfd79fbda952e22e2bbcea Mon Sep 17 00:00:00 2001 From: Michal Witek Date: Sun, 26 Feb 2023 09:07:00 +0100 Subject: [PATCH 23/51] Added missing translation --- src/lang/pl.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/lang/pl.rs b/src/lang/pl.rs index eea46accb..fe6454fad 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -284,13 +284,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Do you accept?", "Akceptujesz?"), ("Open System Setting", "Otwórz ustawienia systemowe"), ("How to get Android input permission?", "Jak uzyskać uprawnienia do wprowadzania danych w systemie Android?"), - ("android_input_permission_tip1", "android_input_permission_tip1"), - ("android_input_permission_tip2", "android_input_permission_tip2"), - ("android_new_connection_tip", "android_new_connection_tip"), - ("android_service_will_start_tip", "android_service_will_start_tip"), - ("android_stop_service_tip", "android_stop_service_tip"), - ("android_version_audio_tip", "android_version_audio_tip"), - ("android_start_service_tip", "android_start_service_tip"), + ("android_input_permission_tip1", "Aby można było sterować Twoim urządzeniem za pomocą myszy lub dotyku, musisz zezwolić RustDesk na korzystanie z usługi \"Ułatwienia dostępu\"."), + ("android_input_permission_tip2", "Przejdź do następnej strony ustawień systemowych, znajdź i wejdź w [Zainstalowane usługi], włącz usługę [RustDesk Input]."), + ("android_new_connection_tip", "Otrzymano nowe żądanie zdalnego dostępu, które chce przejąć kontrolę nad Twoim urządzeniem."), + ("android_service_will_start_tip", "Włączenie opcji „Przechwytywanie ekranu” spowoduje automatyczne uruchomienie usługi, umożliwiając innym urządzeniom żądanie połączenia z Twoim urządzeniem."), + ("android_stop_service_tip", "Zamknięcie usługi spowoduje automatyczne zamknięcie wszystkich nawiązanych połączeń."), + ("android_version_audio_tip", "Bieżąca wersja systemu Android nie obsługuje przechwytywania dźwięku, zaktualizuj system do wersji Android 10 lub nowszej."), + ("android_start_service_tip", "Kliknij [Uruchom usługę] lub Otwórz [Przechwytywanie ekranu], aby uruchomić usługę udostępniania ekranu."), ("Account", "Konto"), ("Overwrite", "Nadpisz"), ("This file exists, skip or overwrite this file?", "Ten plik istnieje, pominąć czy nadpisać ten plik?"), @@ -311,7 +311,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Language", "Język"), ("Keep RustDesk background service", "Zachowaj usługę RustDesk w tle"), ("Ignore Battery Optimizations", "Ignoruj optymalizację baterii"), - ("android_open_battery_optimizations_tip", "android_open_battery_optimizations_tip"), + ("android_open_battery_optimizations_tip", "Jeśli chcesz wyłączyć tę funkcję, przejdź do następnej strony ustawień aplikacji RustDesk, znajdź i wprowadź [Bateria], odznacz [Bez ograniczeń]"), ("Connection not allowed", "Połączenie niedozwolone"), ("Legacy mode", "Tryb kompatybilności wstecznej (legacy)"), ("Map mode", "Tryb mapowania"), @@ -449,12 +449,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("FPS", "FPS"), ("Auto", "Auto"), ("Other Default Options", "Inne opcje domyślne"), - ("Voice call", ""), - ("Text chat", ""), - ("Stop voice call", ""), - ("relay_hint_tip", ""), - ("Reconnect", ""), - ("Codec", ""), - ("Resolution", ""), + ("Voice call", "Rozmowa głosowa"), + ("Text chat", "Chat tekstowy"), + ("Stop voice call", "Rozłącz"), + ("relay_hint_tip", "Bezpośrednie połączenie może nie być możliwe, możesz spróbować połączyć się przez serwer przekazujący. \nDodatkowo, jeśli chcesz użyć serwera przekazującego przy pierwszej próbie, możesz dodać sufiks \"/r\" do identyfikatora lub wybrać opcję \"Zawsze łącz przez serwer przekazujący\" na karcie peer-ów."), + ("Reconnect", "Połącz ponownie"), + ("Codec", "Kodek"), + ("Resolution", "Rozdzielczość"), + ("Use temporary password", "Użyj hasła tymczasowego"), + ("Set temporary password length", "Ustaw długość hasła tymczasowego"), + ("Key", "Klucz") ].iter().cloned().collect(); } From ee893ce744dd2d06020a80849f707c9902fa495e Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sun, 26 Feb 2023 09:13:42 +0100 Subject: [PATCH 24/51] changed empty job list logic --- flutter/assets/transfer.svg | 2 + .../lib/desktop/pages/file_manager_page.dart | 293 ++++++++++-------- 2 files changed, 163 insertions(+), 132 deletions(-) create mode 100644 flutter/assets/transfer.svg diff --git a/flutter/assets/transfer.svg b/flutter/assets/transfer.svg new file mode 100644 index 000000000..24149bf58 --- /dev/null +++ b/flutter/assets/transfer.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/flutter/lib/desktop/pages/file_manager_page.dart b/flutter/lib/desktop/pages/file_manager_page.dart index 5df9c9a80..c3322fef7 100644 --- a/flutter/lib/desktop/pages/file_manager_page.dart +++ b/flutter/lib/desktop/pages/file_manager_page.dart @@ -153,17 +153,9 @@ class _FileManagerPageState extends State backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: Row( children: [ - Flexible( - flex: 3, - child: body(isLocal: true), - ), - Flexible( - flex: 3, - child: body(isLocal: false), - ), - model.jobTable.isEmpty - ? SizedBox() - : Flexible(flex: 2, child: statusList()) + Flexible(flex: 3, child: body(isLocal: true)), + Flexible(flex: 3, child: body(isLocal: false)), + Flexible(flex: 2, child: statusList()) ], ), ); @@ -550,6 +542,18 @@ class _FileManagerPageState extends State return false; } + Widget generateCard(Widget child) { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.all( + Radius.circular(15.0), + ), + ), + child: child, + ); + } + /// transfer status list /// watch transfer status Widget statusList() { @@ -558,140 +562,165 @@ class _FileManagerPageState extends State child: Container( margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0), padding: const EdgeInsets.all(8.0), - child: Obx( - () => ListView.builder( - controller: ScrollController(), - itemBuilder: (BuildContext context, int index) { - final item = model.jobTable[index]; - return Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: BorderRadius.all( - Radius.circular(15.0), - ), - ), + child: model.jobTable.isEmpty + ? generateCard( + Center( child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Transform.rotate( - angle: item.isRemote ? pi : 0, - child: SvgPicture.asset( - "assets/arrow.svg", - color: Theme.of(context).tabBarTheme.labelColor, - ), - ).paddingOnly(left: 15), - const SizedBox( - width: 16.0, - ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + SvgPicture.asset( + "assets/transfer.svg", + color: Theme.of(context).tabBarTheme.labelColor, + height: 40, + ).paddingOnly(bottom: 10), + Text( + translate("No transfers in progress"), + textAlign: TextAlign.center, + textScaleFactor: 1.20, + style: TextStyle( + color: Theme.of(context).tabBarTheme.labelColor), + ), + ], + ), + ), + ) + : Obx( + () => ListView.builder( + controller: ScrollController(), + itemBuilder: (BuildContext context, int index) { + final item = model.jobTable[index]; + return Padding( + padding: const EdgeInsets.only(bottom: 5), + child: generateCard( + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Tooltip( - waitDuration: Duration(milliseconds: 500), - message: item.jobName, - child: Text( - item.jobName, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ).paddingSymmetric(vertical: 10), + Transform.rotate( + angle: item.isRemote ? pi : 0, + child: SvgPicture.asset( + "assets/arrow.svg", + color: Theme.of(context) + .tabBarTheme + .labelColor, + ), + ).paddingOnly(left: 15), + const SizedBox( + width: 16.0, ), - Text( - '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Tooltip( + waitDuration: + Duration(milliseconds: 500), + message: item.jobName, + child: Text( + item.jobName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ).paddingSymmetric(vertical: 10), + ), + Text( + '${translate("Total")} ${readableFileSize(item.totalSize.toDouble())}', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + Offstage( + offstage: + item.state != JobState.inProgress, + child: Text( + '${translate("Speed")} ${readableFileSize(item.speed)}/s', + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: + item.state == JobState.inProgress, + child: Text( + translate( + item.display(), + ), + style: TextStyle( + fontSize: 12, + color: MyTheme.darkGray, + ), + ), + ), + Offstage( + offstage: + item.state != JobState.inProgress, + child: LinearPercentIndicator( + padding: EdgeInsets.only(right: 15), + animateFromLastPercent: true, + center: Text( + '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', + ), + barRadius: Radius.circular(15), + percent: item.finishedSize / + item.totalSize, + progressColor: MyTheme.accent, + backgroundColor: + Theme.of(context).hoverColor, + lineHeight: + kDesktopFileTransferRowHeight, + ).paddingSymmetric(vertical: 15), + ), + ], ), ), - Offstage( - offstage: item.state != JobState.inProgress, - child: Text( - '${translate("Speed")} ${readableFileSize(item.speed)}/s', - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Offstage( + offstage: item.state != JobState.paused, + child: MenuButton( + onPressed: () { + model.resumeJob(item.id); + }, + child: SvgPicture.asset( + "assets/refresh.svg", + color: Colors.white, + ), + color: MyTheme.accent, + hoverColor: MyTheme.accent80, + ), ), - ), - ), - Offstage( - offstage: item.state == JobState.inProgress, - child: Text( - translate( - item.display(), + MenuButton( + padding: EdgeInsets.only(right: 15), + child: SvgPicture.asset( + "assets/close.svg", + color: Colors.white, + ), + onPressed: () { + model.jobTable.removeAt(index); + model.cancelJob(item.id); + }, + color: MyTheme.accent, + hoverColor: MyTheme.accent80, ), - style: TextStyle( - fontSize: 12, - color: MyTheme.darkGray, - ), - ), - ), - Offstage( - offstage: item.state != JobState.inProgress, - child: LinearPercentIndicator( - padding: EdgeInsets.only(right: 15), - animateFromLastPercent: true, - center: Text( - '${(item.finishedSize / item.totalSize * 100).toStringAsFixed(0)}%', - ), - barRadius: Radius.circular(15), - percent: item.finishedSize / item.totalSize, - progressColor: MyTheme.accent, - backgroundColor: - Theme.of(context).hoverColor, - lineHeight: kDesktopFileTransferRowHeight, - ).paddingSymmetric(vertical: 15), + ], ), ], ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Offstage( - offstage: item.state != JobState.paused, - child: MenuButton( - onPressed: () { - model.resumeJob(item.id); - }, - child: SvgPicture.asset( - "assets/refresh.svg", - color: Colors.white, - ), - color: MyTheme.accent, - hoverColor: MyTheme.accent80, - ), - ), - MenuButton( - padding: EdgeInsets.only(right: 15), - child: SvgPicture.asset( - "assets/close.svg", - color: Colors.white, - ), - onPressed: () { - model.jobTable.removeAt(index); - model.cancelJob(item.id); - }, - color: MyTheme.accent, - hoverColor: MyTheme.button, - ), - ], - ), - ], + ], + ).paddingSymmetric(vertical: 10), ), - ], - ).paddingSymmetric(vertical: 10), + ); + }, + itemCount: model.jobTable.length, ), - ); - }, - itemCount: model.jobTable.length, - ), - ), + ), ), ); } From d8af4f2acb9b157b037203770ea445993425e71f Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sun, 26 Feb 2023 09:14:22 +0100 Subject: [PATCH 25/51] added new string "No transfers in progress" --- src/lang/ca.rs | 1 + src/lang/cn.rs | 1 + src/lang/cs.rs | 1 + src/lang/da.rs | 1 + src/lang/de.rs | 1 + src/lang/en.rs | 1 + src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fa.rs | 1 + src/lang/fr.rs | 1 + src/lang/gr.rs | 1 + src/lang/hu.rs | 1 + src/lang/id.rs | 1 + src/lang/it.rs | 1 + src/lang/ja.rs | 1 + src/lang/ko.rs | 1 + src/lang/kz.rs | 1 + src/lang/nl.rs | 1 + src/lang/pl.rs | 1 + src/lang/pt_PT.rs | 1 + src/lang/ptbr.rs | 1 + src/lang/ro.rs | 1 + src/lang/ru.rs | 1 + src/lang/sk.rs | 1 + src/lang/sl.rs | 1 + src/lang/sq.rs | 1 + src/lang/sr.rs | 1 + src/lang/sv.rs | 1 + src/lang/template.rs | 1 + src/lang/th.rs | 1 + src/lang/tr.rs | 1 + src/lang/tw.rs | 1 + src/lang/ua.rs | 1 + src/lang/vn.rs | 1 + 34 files changed, 34 insertions(+) diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 45c552848..4a6536afa 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 4824ac5e9..593e023d2 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "停止语音通话"), ("relay_hint_tip", "可能无法直连,可以尝试中继连接。\n另外,如果想直接使用中继连接,可以在 ID 后面添加/r,或者在卡片选项里选择强制走中继连接。"), ("Reconnect", "重连"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index e2761e45e..d09bba096 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 2020a2b6f..428150eff 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 7cf563fc3..8bfa973c4 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Sprachanruf beenden"), ("relay_hint_tip", "Wenn eine direkte Verbindung nicht möglich ist, können Sie versuchen, eine Verbindung über einen Relay-Server herzustellen. \nWenn Sie eine Relay-Verbindung beim ersten Versuch herstellen möchten, können Sie das Suffix \"/r\" an die ID anhängen oder die Option \"Immer über Relay-Server verbinden\" auf der Gegenstelle auswählen."), ("Reconnect", "Erneut verbinden"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 4bfa86349..3e87cd661 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -44,5 +44,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk."), ("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."), ("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index c22532440..1ea05d5ab 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 3ce2860f0..494dd4cb7 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Detener llamada de voz"), ("relay_hint_tip", "Puede que no sea posible conectar directamente. Puedes tratar de conectar a través de relay. \nAdicionalmente, si quieres usar relay en el primer intento, puedes añadir el sufijo \"/r\" a la ID o seleccionar la opción \"Conectar siempre a través de relay\" en la tarjeta del par."), ("Reconnect", "Reconectar"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 70051f3e8..72dd93a10 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "توقف تماس صوتی"), ("relay_hint_tip", " را به شناسه اضافه کنید یا گزینه \"همیشه از طریق رله متصل شوید\" را در کارت همتا انتخاب کنید. همچنین، اگر می‌خواهید فوراً از سرور رله استفاده کنید، می‌توانید پسوند \"/r\".\n اتصال مستقیم ممکن است امکان پذیر نباشد. در این صورت می توانید سعی کنید از طریق سرور رله متصل شوید"), ("Reconnect", "اتصال مجدد"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 1f6e9f55b..a600c92eb 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index b7ebf4577..26e5a649c 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 21ab28214..125d982dc 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index f48de17f6..17a9589a8 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 4c63106da..0749603b0 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Interrompi la chiamata vocale"), ("relay_hint_tip", "Se non è possibile connettersi direttamente, si può provare a farlo tramite relay.\nInoltre, se si desidera utilizzare il relay al primo tentativo, è possibile aggiungere il suffisso \"/r\" all'ID o selezionare l'opzione \"Collegati sempre tramite relay\" nella scheda peer."), ("Reconnect", "Riconnetti"), + ("No transfers in progress", "Nessun trasferimento in corso"), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index b291a6e7a..7c810cbac 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index d63e83187..87425b402 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index b8b9eb1df..49017f4ff 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 1a806c803..615c3601b 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Stop spraakoproep"), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 2b29c7cb2..ae1743ee2 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index e91cd3909..4e619a6e4 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index b0fe9175d..8f4b2b13d 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index d0232ba37..ebefd1a80 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index fe5d708ad..d652904cc 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Завершить голосовой вызов"), ("relay_hint_tip", "Прямое подключение может оказаться невозможным. В этом случае можно попытаться подключиться через сервер ретрансляции. \nКроме того, если вы хотите сразу использовать сервер ретрансляции, можно добавить к ID суффикс \"/r\" или включить \"Всегда подключаться через ретранслятор\" в настройках удалённого узла."), ("Reconnect", "Переподключить"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 458002f4c..47843fd55 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 2abd1870f..95d65a453 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 6b739e8ab..3ec67d77a 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 90a435fd7..31f408748 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index a98ea6346..3afcf1a9a 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 61c2b5d28..53df7b4f7 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 236ee5e8d..a5db9708c 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index f2a34e212..96e35e2b1 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 84e74716f..f49e81a7b 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "停止語音聊天"), ("relay_hint_tip", "可能無法直連,可以嘗試中繼連接。 \n另外,如果想直接使用中繼連接,可以在ID後面添加/r,或者在卡片選項裡選擇強制走中繼連接。"), ("Reconnect", "重連"), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 0c4caf4db..1729d42a7 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 19e1184d9..5521022b7 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -454,5 +454,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", ""), ("relay_hint_tip", ""), ("Reconnect", ""), + ("No transfers in progress", ""), ].iter().cloned().collect(); } From ab792f798e0581084de7bb965fe88b979b11925b Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sun, 26 Feb 2023 10:19:13 +0100 Subject: [PATCH 26/51] fix missing comma --- src/lang/pl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 5269c4ee8..13027a682 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -458,7 +458,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Rozdzielczość"), ("Use temporary password", "Użyj hasła tymczasowego"), ("Set temporary password length", "Ustaw długość hasła tymczasowego"), - ("Key", "Klucz") + ("Key", "Klucz"), ("No transfers in progress", ""), ].iter().cloned().collect(); } From b83583769b51a01071ea241704607647e5130872 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sun, 26 Feb 2023 18:49:07 +0800 Subject: [PATCH 27/51] mount rustdesk rather than vdi/host --- Cargo.toml | 1 + vdi/host/.devcontainer/devcontainer.json | 5 +- vdi/host/Cargo.lock | 970 ++++++++++++++++++++++- vdi/host/Cargo.toml | 4 +- 4 files changed, 972 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f93f776a0..b53615c4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,6 +132,7 @@ flutter_rust_bridge = "1.61.1" [workspace] members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/simple_rc", "libs/portable"] +exclude = ["vdi/host"] [package.metadata.winres] LegalCopyright = "Copyright © 2022 Purslane, Inc." diff --git a/vdi/host/.devcontainer/devcontainer.json b/vdi/host/.devcontainer/devcontainer.json index 02c6e589b..f0016b5b1 100644 --- a/vdi/host/.devcontainer/devcontainer.json +++ b/vdi/host/.devcontainer/devcontainer.json @@ -4,8 +4,8 @@ "dockerfile": "./Dockerfile", "context": "." }, - "workspaceMount": "source=${localWorkspaceFolder},target=/home/vscode/rustdesk,type=bind,consistency=cache", - "workspaceFolder": "/home/vscode/rustdesk", + "workspaceMount": "source=${localWorkspaceFolder}/../..,target=/home/vscode/rustdesk,type=bind,consistency=cache", + "workspaceFolder": "/home/vscode/rustdesk/vdi/host", "customizations": { "vscode": { "extensions": [ @@ -15,6 +15,7 @@ "tamasfe.even-better-toml", "serayuzgur.crates", "mhutchie.git-graph", + "formulahendry.terminal", "eamodio.gitlens" ], "settings": { diff --git a/vdi/host/Cargo.lock b/vdi/host/Cargo.lock index d4254717e..7b7cf26bd 100644 --- a/vdi/host/Cargo.lock +++ b/vdi/host/Cargo.lock @@ -2,6 +2,32 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -11,6 +37,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + [[package]] name = "async-broadcast" version = "0.3.4" @@ -73,7 +114,7 @@ dependencies = [ "parking", "polling", "slab", - "socket2", + "socket2 0.4.7", "waker-fn", "windows-sys 0.42.0", ] @@ -116,29 +157,73 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] + [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -146,6 +231,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "concurrent-queue" version = "2.1.0" @@ -155,6 +265,57 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "confy" +version = "0.4.0" +source = "git+https://github.com/open-trade/confy#630cc28a396cb7d01eefdd9f3824486fe4d8554b" +dependencies = [ + "directories-next", + "serde", + "thiserror", + "toml", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.7.1", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.14" @@ -164,6 +325,50 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cxx" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derivative" version = "2.2.0" @@ -175,6 +380,16 @@ dependencies = [ "syn", ] +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs" version = "4.0.0" @@ -184,6 +399,16 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.3.7" @@ -195,12 +420,38 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "easy-parallel" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + [[package]] name = "enumflags2" version = "0.7.5" @@ -222,6 +473,19 @@ dependencies = [ "syn", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -237,6 +501,18 @@ dependencies = [ "instant", ] +[[package]] +name = "filetime" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.45.0", +] + [[package]] name = "futures" version = "0.3.26" @@ -349,14 +625,78 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hbb_common" +version = "0.1.0" +dependencies = [ + "anyhow", + "backtrace", + "bytes", + "chrono", + "confy", + "directories-next", + "dirs-next", + "env_logger", + "filetime", + "futures", + "futures-util", + "lazy_static", + "libc", + "log", + "mac_address", + "machine-uid", + "osascript", + "protobuf", + "protobuf-codegen", + "rand", + "regex", + "serde", + "serde_derive", + "socket2 0.3.19", + "sodiumoxide", + "sysinfo", + "tokio", + "tokio-socks", + "tokio-util", + "winapi", + "zstd", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] [[package]] name = "hex" @@ -364,6 +704,36 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "indexmap" version = "1.9.2" @@ -383,12 +753,54 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "jobserver" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "libsodium-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b779387cd56adfbc02ea4a668e704f729be8d6a6abd2c27ca5ee537849a92fd" +dependencies = [ + "cc", + "libc", + "pkg-config", + "walkdir", +] + [[package]] name = "libusb1-sys" version = "0.6.4" @@ -401,6 +813,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -420,6 +841,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "mac_address" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963" +dependencies = [ + "nix 0.23.2", + "winapi", +] + +[[package]] +name = "machine-uid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1595709b0a7386bcd56ba34d250d626e5503917d05d32cdccddcd68603e212" +dependencies = [ + "winreg", +] + [[package]] name = "memchr" version = "2.5.0" @@ -435,6 +875,49 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.45.0", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + [[package]] name = "nix" version = "0.24.3" @@ -444,7 +927,7 @@ dependencies = [ "bitflags", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -456,6 +939,53 @@ dependencies = [ "memchr", ] +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -472,6 +1002,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "osascript" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38731fa859ef679f1aec66ca9562165926b442f298467f76f5990f431efe87dc" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "parking" version = "2.0.0" @@ -501,6 +1042,26 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -558,6 +1119,58 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protobuf" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e" +dependencies = [ + "bytes", + "once_cell", + "protobuf-support", + "thiserror", +] + +[[package]] +name = "protobuf-codegen" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd418ac3c91caa4032d37cb80ff0d44e2ebe637b2fb243b6234bf89cdac4901" +dependencies = [ + "anyhow", + "once_cell", + "protobuf", + "protobuf-parse", + "regex", + "tempfile", + "thiserror", +] + +[[package]] +name = "protobuf-parse" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d39b14605eaa1f6a340aec7f320b34064feb26c93aec35d6a9a2272a8ddfa49" +dependencies = [ + "anyhow", + "indexmap", + "log", + "protobuf", + "protobuf-support", + "tempfile", + "thiserror", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372" +dependencies = [ + "thiserror", +] + [[package]] name = "qemu-display" version = "0.1.0" @@ -588,6 +1201,7 @@ dependencies = [ name = "qemu-rustdesk" version = "0.1.0" dependencies = [ + "hbb_common", "qemu-display", ] @@ -630,6 +1244,28 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -686,12 +1322,39 @@ dependencies = [ "libusb1-sys", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "serde" version = "1.0.152" @@ -733,6 +1396,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_repr" version = "0.1.10" @@ -759,6 +1433,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + [[package]] name = "slab" version = "0.4.8" @@ -774,6 +1463,17 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if", + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.4.7" @@ -784,6 +1484,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "sodiumoxide" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028" +dependencies = [ + "ed25519", + "libc", + "libsodium-sys", + "serde", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -801,6 +1513,21 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sysinfo" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb4ebf3d49308b99e6e9dc95e989e2fdbdc210e4f67c39db0bb89ba927001c" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -815,6 +1542,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.38" @@ -835,6 +1571,91 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "tokio" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.4.7", + "tokio-macros", + "windows-sys 0.42.0", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-socks" +version = "0.5.1-1" +source = "git+https://github.com/open-trade/tokio-socks#7034e79263ce25c348be072808d7601d82cd892d" +dependencies = [ + "bytes", + "either", + "futures-core", + "futures-sink", + "futures-util", + "pin-project", + "thiserror", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "futures-util", + "hashbrown", + "pin-project-lite", + "slab", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml_datetime" version = "0.5.1" @@ -900,6 +1721,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "usbredirhost" version = "0.0.1" @@ -948,18 +1775,95 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "waker-fn" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + [[package]] name = "wepoll-ffi" version = "0.1.2" @@ -969,6 +1873,17 @@ dependencies = [ "cc", ] +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "winapi" version = "0.3.9" @@ -985,6 +1900,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1087,6 +2011,15 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi", +] + [[package]] name = "xml-rs" version = "0.8.4" @@ -1116,7 +2049,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix", + "nix 0.24.3", "once_cell", "ordered-stream", "rand", @@ -1157,6 +2090,35 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zstd" +version = "0.9.2+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "4.1.3+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.6.2+zstd.1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "zvariant" version = "3.11.0" diff --git a/vdi/host/Cargo.toml b/vdi/host/Cargo.toml index 62c964122..6a67813a2 100644 --- a/vdi/host/Cargo.toml +++ b/vdi/host/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" authors = ["rustdesk "] edition = "2021" - [dependencies] -qemu-display = { git = "https://gitlab.com/marcandre.lureau/qemu-display" } \ No newline at end of file +qemu-display = { git = "https://gitlab.com/marcandre.lureau/qemu-display" } +hbb_common = { path = "../../libs/hbb_common" } From 459bed1a68cac7d1634e0101dd4fb05601be373b Mon Sep 17 00:00:00 2001 From: NicKoehler Date: Sun, 26 Feb 2023 11:49:22 +0100 Subject: [PATCH 28/51] dark theme fix --- flutter/lib/common.dart | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index e89671711..53a401230 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -189,7 +189,9 @@ class MyTheme { style: ButtonStyle(splashFactory: NoSplash.splashFactory), ) : null, - colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.blue).copyWith( + colorScheme: ColorScheme.fromSwatch( + primarySwatch: Colors.blue, + ).copyWith( brightness: Brightness.light, background: Color(0xFFEEEEEE), ), @@ -229,9 +231,11 @@ class MyTheme { checkboxTheme: const CheckboxThemeData(checkColor: MaterialStatePropertyAll(dark)), colorScheme: ColorScheme.fromSwatch( - brightness: Brightness.dark, primarySwatch: Colors.blue, - ).copyWith(background: Color(0xFF24252B)), + ).copyWith( + brightness: Brightness.dark, + background: Color(0xFF24252B), + ), ).copyWith( extensions: >[ ColorThemeExtension.dark, From 0a52d64900a8f1f182073eb79affdee4cf6a596c Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 26 Feb 2023 23:29:36 +0800 Subject: [PATCH 29/51] print stack Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 23 ++++++++++++++++++----- flutter/lib/models/model.dart | 4 +++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index fca73eac7..37c4a39dc 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -503,8 +503,21 @@ class InputModel { } x += d.x; y += d.y; + var evtX = 0; + var evtY = 0; + try { + x.round(); + y.round(); + } catch (e) { + debugPrintStack( + label: 'canvasModel.scale value ${canvasModel.scale}, $e'); + return; + } - if (x < d.x || y < d.y || x > (d.x + d.width) || y > (d.y + d.height)) { + if (evtX < d.x || + evtY < d.y || + evtX > (d.x + d.width) || + evtY > (d.y + d.height)) { // If left mouse up, no early return. if (evt['buttons'] != kPrimaryMouseButton || type != 'up') { return; @@ -512,12 +525,12 @@ class InputModel { } if (type != '') { - x = 0; - y = 0; + evtX = 0; + evtY = 0; } - evt['x'] = '${x.round()}'; - evt['y'] = '${y.round()}'; + evt['x'] = '$evtX'; + evt['y'] = '$evtY'; var buttons = ''; switch (evt['buttons']) { case kPrimaryMouseButton: diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index e48d74dac..74cc7f14f 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -803,7 +803,9 @@ class CanvasModel with ChangeNotifier { dyOffset = (y - dh * (y / size.height) - _y).toInt(); } } catch (e) { - // Unhandled Exception: Unsupported operation: Infinity or NaN toInt + debugPrintStack( + label: + '(x,y) ($x,$y), (_x,_y) ($_x,$_y), _scale $_scale, display size (${getDisplayWidth()},${getDisplayHeight()}), size $size, , $e'); return; } From 544e39e11cf5127944bd8d112a453f74cfa7f801 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 26 Feb 2023 23:31:11 +0800 Subject: [PATCH 30/51] fix assign Signed-off-by: fufesou --- flutter/lib/models/input_model.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 37c4a39dc..b91453138 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -506,8 +506,8 @@ class InputModel { var evtX = 0; var evtY = 0; try { - x.round(); - y.round(); + evtX = x.round(); + evtY = y.round(); } catch (e) { debugPrintStack( label: 'canvasModel.scale value ${canvasModel.scale}, $e'); From 8073fa2386bb4a407203e4a383c2cd14b48b21f9 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:43:24 +0100 Subject: [PATCH 31/51] Update de.rs --- src/lang/de.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lang/de.rs b/src/lang/de.rs index ee28fe0e7..3d95832ec 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -454,8 +454,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Sprachanruf beenden"), ("relay_hint_tip", "Wenn eine direkte Verbindung nicht möglich ist, können Sie versuchen, eine Verbindung über einen Relay-Server herzustellen. \nWenn Sie eine Relay-Verbindung beim ersten Versuch herstellen möchten, können Sie das Suffix \"/r\" an die ID anhängen oder die Option \"Immer über Relay-Server verbinden\" auf der Gegenstelle auswählen."), ("Reconnect", "Erneut verbinden"), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), - ].iter().cloned().collect(); + ("Codec", "Codec"), + ("Resolution", "Auflösung"), + ("No transfers in progress", "Keine Übertragungen im Gange"), + ].iter().cloned().collect(); } From 5793c730c8f1f9c5c96786a656db6546435fceeb Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:48:20 +0100 Subject: [PATCH 32/51] Update README-DE.md --- docs/README-DE.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/README-DE.md b/docs/README-DE.md index 8ee4a51fa..dd2aa8609 100644 --- a/docs/README-DE.md +++ b/docs/README-DE.md @@ -17,9 +17,9 @@ RustDesk ist eine in Rust geschriebene Remote-Desktop-Software, die out of the b ![image](https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png) -RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [`docs/CONTRIBUTING.md`](CONTRIBUTING.md) an, wenn du Unterstützung beim Start brauchst. +RustDesk heißt jegliche Mitarbeit willkommen. Schau dir [CONTRIBUTING-DE.md](CONTRIBUTING-DE.md) an, wenn du Unterstützung beim Start brauchst. -[**Wie arbeitet RustDesk?**](https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F) +[**FAQ**](https://github.com/rustdesk/rustdesk/wiki/FAQ) [**Programm herunterladen**](https://github.com/rustdesk/rustdesk/releases) @@ -41,6 +41,14 @@ Nachfolgend sind die Server gelistet, die du kostenlos nutzen kannst. Es kann se | USA (Ashburn) | 0x101 Cyber Security | 4 vCPU / 8 GB RAM | | Ukraine (Kiew) | dc.volia (2VM) | 2 vCPU / 4 GB RAM | +## Dev-Container + +[![In Dev-Containern öffnen](https://img.shields.io/static/v1?label=Dev%20Container&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/rustdesk/rustdesk) + +Wenn du VS Code und Docker bereits installiert hast, kannst du auf das Abzeichen oben klicken, um loszulegen. Wenn du darauf klickst, wird VS Code automatisch die Dev-Container-Erweiterung installieren, den Quellcode in ein Container-Volume klonen und einen Dev-Container für die Verwendung aufsetzen. + +Weitere Informationen findest du in [DEVCONTAINER-DE.md](DEVCONTAINER-DE.md). + ## Abhängigkeiten Desktop-Versionen verwenden [Sciter](https://sciter.com/) oder Flutter für die GUI, dieses Tutorial ist nur für Sciter. From c580bc16cc86919157d0e327ca97bc26db27cea5 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:48:55 +0100 Subject: [PATCH 33/51] Add files via upload --- docs/CONTRIBUTING-DE.md | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 docs/CONTRIBUTING-DE.md diff --git a/docs/CONTRIBUTING-DE.md b/docs/CONTRIBUTING-DE.md new file mode 100644 index 000000000..6258a9a7a --- /dev/null +++ b/docs/CONTRIBUTING-DE.md @@ -0,0 +1,50 @@ +# Beitrge zu RustDesk + +RustDesk begrt Beitrge von jedem. Hier sind die Richtlinien, wenn Sie uns +helfen mchten: + +## Beitrge + +Beitrge zu RustDesk oder seinen Abhngigkeiten sollten in Form von Pull +Requests auf GitHub erfolgen. Jeder Pull Request wird von einem Hauptakteur +(jemand mit der Erlaubnis, Korrekturen einzubringen) geprft und entweder in den +Hauptbaum eingefgt oder Feedback fr notwendige nderungen gegeben. Alle +Beitrge sollten diesem Format folgen, auch die von Hauptakteuren. + +Wenn Sie an einem Problem arbeiten mchten, melden Sie es bitte zuerst an, indem +Sie auf GitHub erklren, dass Sie daran arbeiten mchten. Damit soll verhindert +werden, dass Beitrge zum gleichen Thema doppelt bearbeitet werden. + +## Checkliste fr Pull Requests + +- Verzweigen Sie sich vom Master-Branch und, falls ntig, wechseln Sie zum + aktuellen Master-Branch, bevor Sie Ihren Pull Request einreichen. Wenn das + Zusammenfhren mit dem Master nicht reibungslos funktioniert, werden Sie + mglicherweise aufgefordert, Ihre nderungen zu berarbeiten. + +- Commits sollten so klein wie mglich sein und gleichzeitig sicherstellen, dass + jeder Commit unabhngig voneinander korrekt ist (d. h., jeder Commit sollte + sich bersetzen lassen und Tests bestehen). + +- Commits sollten von einem "Herkunftszertifikat fr Entwickler" + (https://developercertificate.org) begleitet werden, das besagt, dass Sie (und + ggf. Ihr Arbeitgeber) mit den Bedingungen der [Projektlizenz](../LICENCE) + einverstanden sind. In Git ist dies die Option `-s` fr `git commit`. + +- Wenn Ihr Patch nicht begutachtet wird oder Sie eine bestimmte Person zur + Begutachtung bentigen, knnen Sie einem Gutachter mit @ antworten und um eine + Begutachtung des Pull Requests oder einen Kommentar bitten. Sie knnen auch + per [E-Mail](mailto:info@rustdesk.com) um eine Begutachtung bitten. + +- Fgen Sie Tests hinzu, die sich auf den behobenen Fehler oder die neue + Funktion beziehen. + +Spezifische Git-Anweisungen finden Sie im [GitHub-Workflow](https://github.com/servo/servo/wiki/GitHub-workflow). + +## Verhalten + +https://github.com/rustdesk/rustdesk/blob/master/docs/CODE_OF_CONDUCT.md + +## Kommunikation + +RustDesk-Mitarbeiter arbeiten hufig im [Discord](https://discord.gg/nDceKgxnkV). From d25c8df0501cf60ee2dd5e0699475f220fa9fea1 Mon Sep 17 00:00:00 2001 From: Mr-Update <37781396+Mr-Update@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:49:36 +0100 Subject: [PATCH 34/51] Add files via upload --- docs/DEVCONTAINER-DE.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/DEVCONTAINER-DE.md diff --git a/docs/DEVCONTAINER-DE.md b/docs/DEVCONTAINER-DE.md new file mode 100644 index 000000000..2a0d73f17 --- /dev/null +++ b/docs/DEVCONTAINER-DE.md @@ -0,0 +1,14 @@ + +Nach dem Start von Dev-Container im Docker-Container wird ein Linux-Binrprogramm im Debug-Modus erstellt. + +Derzeit bietet Dev-Container Linux- und Android-Builds sowohl im Debug- als auch im Release-Modus an. + +Nachfolgend finden Sie eine Tabelle mit Befehlen, die im Stammverzeichnis des Projekts ausgefhrt werden mssen, um bestimmte Builds zu erstellen. + +Kommando|Build-Typ|Modus +-|-|-| +`.devcontainer/build.sh --debug linux`|Linux|debug +`.devcontainer/build.sh --release linux`|Linux|release +`.devcontainer/build.sh --debug android`|android-arm64|debug +`.devcontainer/build.sh --release android`|android-arm64|release + From b9b4913ca0d5f402db9a7cb2422f7167603f08ce Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 25 Feb 2023 04:55:37 -0800 Subject: [PATCH 35/51] mac admin auth check --- src/platform/macos.mm | 30 ++++++++++++++++++++++++++++++ src/platform/macos.rs | 8 ++++++++ src/ui_interface.rs | 6 +++--- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/platform/macos.mm b/src/platform/macos.mm index 8be0c6db5..ac9a69d04 100644 --- a/src/platform/macos.mm +++ b/src/platform/macos.mm @@ -1,6 +1,9 @@ #import #import #import +#include +#include + // https://github.com/codebytere/node-mac-permissions/blob/main/permissions.mm @@ -35,6 +38,33 @@ extern "C" bool InputMonitoringAuthStatus(bool prompt) { return false; } +extern "C" bool MacCheckAdminAuthorization() { + AuthorizationRef authRef; + OSStatus status; + + status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, + kAuthorizationFlagDefaults, &authRef); + if (status != errAuthorizationSuccess) { + printf("Failed to create AuthorizationRef\n"); + return false; + } + + AuthorizationItem authItem = {kAuthorizationRightExecute, 0, NULL, 0}; + AuthorizationRights authRights = {1, &authItem}; + AuthorizationFlags flags = kAuthorizationFlagDefaults | + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagPreAuthorize | + kAuthorizationFlagExtendRights; + status = AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, flags, NULL); + if (status != errAuthorizationSuccess) { + printf("Failed to authorize\n"); + return false; + } + + AuthorizationFree(authRef, kAuthorizationFlagDefaults); + return true; +} + extern "C" float BackingScaleFactor() { NSScreen* s = [NSScreen mainScreen]; if (s) return [s backingScaleFactor]; diff --git a/src/platform/macos.rs b/src/platform/macos.rs index b663b0f41..5c4c68e2c 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -34,6 +34,7 @@ extern "C" { static kAXTrustedCheckOptionPrompt: CFStringRef; fn AXIsProcessTrustedWithOptions(options: CFDictionaryRef) -> BOOL; fn InputMonitoringAuthStatus(_: BOOL) -> BOOL; + fn MacCheckAdminAuthorization() -> BOOL; fn MacGetModeNum(display: u32, numModes: *mut u32) -> BOOL; fn MacGetModes( display: u32, @@ -665,3 +666,10 @@ pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType< } Ok(()) } + + +pub fn check_super_user_permission() -> ResultType { + unsafe { + Ok(MacCheckAdminAuthorization() == YES) + } +} diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 62eba25c1..471150f60 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -707,10 +707,10 @@ pub fn is_root() -> bool { pub fn check_super_user_permission() -> bool { #[cfg(feature = "flatpak")] return true; - #[cfg(any(windows, target_os = "linux"))] + #[cfg(any(windows, target_os = "linux", target_os = "macos"))] return crate::platform::check_super_user_permission().unwrap_or(false); - #[cfg(not(any(windows, target_os = "linux")))] - true + #[cfg(not(any(windows, target_os = "linux", target_os = "macos")))] + return true; } #[allow(dead_code)] From e3d704dfdee6712eca17964a74ac3bb1ebe97526 Mon Sep 17 00:00:00 2001 From: 21pages Date: Sat, 25 Feb 2023 21:26:09 +0800 Subject: [PATCH 36/51] ensure same bpp and framerate when get and set for mac --- src/platform/macos.mm | 83 +++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/src/platform/macos.mm b/src/platform/macos.mm index ac9a69d04..3c90981c4 100644 --- a/src/platform/macos.mm +++ b/src/platform/macos.mm @@ -74,6 +74,33 @@ extern "C" float BackingScaleFactor() { // https://github.com/jhford/screenresolution/blob/master/cg_utils.c // https://github.com/jdoupe/screenres/blob/master/setgetscreen.m +size_t bitDepth(CGDisplayModeRef mode) { + size_t depth = 0; + // Deprecated, same display same bpp? + // https://stackoverflow.com/questions/8210824/how-to-avoid-cgdisplaymodecopypixelencoding-to-get-bpp + // https://github.com/libsdl-org/SDL/pull/6628 + CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); + // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels + // are made up and possibly non-sensical + if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO32BitFloatPixels), kCFCompareCaseInsensitive)) { + depth = 96; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 64; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO16BitFloatPixels), kCFCompareCaseInsensitive)) { + depth = 48; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 32; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 30; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)) { + depth = 16; + } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive)) { + depth = 8; + } + CFRelease(pixelEncoding); + return depth; +} + extern "C" bool MacGetModeNum(CGDirectDisplayID display, uint32_t *numModes) { CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); if (allModes == NULL) { @@ -85,16 +112,28 @@ extern "C" bool MacGetModeNum(CGDirectDisplayID display, uint32_t *numModes) { } extern "C" bool MacGetModes(CGDirectDisplayID display, uint32_t *widths, uint32_t *heights, uint32_t max, uint32_t *numModes) { - CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); - if (allModes == NULL) { + CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display); + if (currentMode == NULL) { return false; } - *numModes = CFArrayGetCount(allModes); - for (uint32_t i = 0; i < *numModes && i < max; i++) { - CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); - widths[i] = (uint32_t)CGDisplayModeGetWidth(mode); - heights[i] = (uint32_t)CGDisplayModeGetHeight(mode); + CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL); + if (allModes == NULL) { + CGDisplayModeRelease(currentMode); + return false; } + uint32_t allModeCount = CFArrayGetCount(allModes); + uint32_t realNum = 0; + for (uint32_t i = 0; i < allModeCount && realNum < max; i++) { + CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); + if (CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode) && + bitDepth(currentMode) == bitDepth(mode)) { + widths[realNum] = (uint32_t)CGDisplayModeGetWidth(mode); + heights[realNum] = (uint32_t)CGDisplayModeGetHeight(mode); + realNum++; + } + } + *numModes = realNum; + CGDisplayModeRelease(currentMode); CFRelease(allModes); return true; } @@ -110,31 +149,8 @@ extern "C" bool MacGetMode(CGDirectDisplayID display, uint32_t *width, uint32_t return true; } -size_t bitDepth(CGDisplayModeRef mode) { - size_t depth = 0; - CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); - // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels - // are made up and possibly non-sensical - if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO32BitFloatPixels), kCFCompareCaseInsensitive)) { - depth = 96; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 64; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO16BitFloatPixels), kCFCompareCaseInsensitive)) { - depth = 48; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 32; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 30; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)) { - depth = 16; - } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive)) { - depth = 8; - } - CFRelease(pixelEncoding); - return depth; -} -bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { +static bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { CGError rc; CGDisplayConfigRef config; rc = CGBeginDisplayConfiguration(&config); @@ -152,7 +168,6 @@ bool setDisplayToMode(CGDirectDisplayID display, CGDisplayModeRef mode) { return true; } - extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t height) { bool ret = false; @@ -170,8 +185,8 @@ extern "C" bool MacSetMode(CGDirectDisplayID display, uint32_t width, uint32_t h CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i); if (width == CGDisplayModeGetWidth(mode) && height == CGDisplayModeGetHeight(mode) && - bitDepth(currentMode) == bitDepth(mode) && - CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode)) { + CGDisplayModeGetRefreshRate(currentMode) == CGDisplayModeGetRefreshRate(mode) && + bitDepth(currentMode) == bitDepth(mode)) { ret = setDisplayToMode(display, mode); break; } From b6c3c74286e74b79e1eb688d4f44035f70dbf6a1 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 27 Feb 2023 12:01:22 +0800 Subject: [PATCH 37/51] opt: move the resize area out of the flutter view --- flutter/lib/consts.dart | 7 +++++++ flutter/lib/desktop/pages/port_forward_tab_page.dart | 12 +++++++----- flutter/lib/desktop/pages/remote_tab_page.dart | 2 ++ .../lib/desktop/screen/desktop_remote_screen.dart | 5 +++++ flutter/lib/desktop/widgets/tabbar_widget.dart | 7 +++++++ flutter/lib/models/state_model.dart | 11 +++++++++++ flutter/pubspec.yaml | 4 ++-- 7 files changed, 41 insertions(+), 7 deletions(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 537784918..789517bf7 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/models/state_model.dart'; const double kDesktopRemoteTabBarHeight = 28.0; const int kMainWindowId = 0; @@ -58,6 +59,11 @@ const double kDesktopFileTransferMaximumWidth = 300; const double kDesktopFileTransferRowHeight = 30.0; const double kDesktopFileTransferHeaderHeight = 25.0; +EdgeInsets get kDragToResizeAreaPadding => Platform.isLinux + ? stateGlobal.fullscreen || stateGlobal.maximize + ? EdgeInsets.zero + : EdgeInsets.all(4.0) + : EdgeInsets.zero; // https://en.wikipedia.org/wiki/Non-breaking_space const int $nbsp = 0x00A0; @@ -79,6 +85,7 @@ const kDefaultScrollAmountMultiplier = 5.0; const kDefaultScrollDuration = Duration(milliseconds: 50); const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50); const kFullScreenEdgeSize = 0.0; +const kMaximizeEdgeSize = 0.0; var kWindowEdgeSize = Platform.isWindows ? 1.0 : 5.0; const kWindowBorderWidth = 1.0; const kDesktopMenuPadding = EdgeInsets.only(left: 12.0, right: 3.0); diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index f2d75d00f..394d89e38 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -109,11 +109,13 @@ class _PortForwardTabPageState extends State { ); return Platform.isMacOS ? tabWidget - : SubWindowDragToResizeArea( - child: tabWidget, - resizeEdgeSize: stateGlobal.resizeEdgeSize.value, - windowId: stateGlobal.windowId, - ); + : Obx( + () => SubWindowDragToResizeArea( + child: tabWidget, + resizeEdgeSize: stateGlobal.resizeEdgeSize.value, + windowId: stateGlobal.windowId, + ), + ); } void onRemoveId(String id) { diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 0deb646c0..e7aed0358 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -210,6 +210,8 @@ class _ConnectionTabPageState extends State { : Obx(() => SubWindowDragToResizeArea( key: contentKey, child: tabWidget, + // Specially configured for a better resize area and remote control. + childPadding: kDragToResizeAreaPadding, resizeEdgeSize: stateGlobal.resizeEdgeSize.value, windowId: stateGlobal.windowId, )); diff --git a/flutter/lib/desktop/screen/desktop_remote_screen.dart b/flutter/lib/desktop/screen/desktop_remote_screen.dart index bb6bc431b..64af41401 100644 --- a/flutter/lib/desktop/screen/desktop_remote_screen.dart +++ b/flutter/lib/desktop/screen/desktop_remote_screen.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart'; @@ -26,6 +28,9 @@ class DesktopRemoteScreen extends StatelessWidget { ChangeNotifierProvider.value(value: gFFI.canvasModel), ], child: Scaffold( + // Set transparent background for padding the resize area out of the flutter view. + // This allows the wallpaper goes through our resize area. (Linux only now). + backgroundColor: Platform.isLinux ? Colors.transparent : null, body: ConnectionTabPage( params: params, ), diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index ee3aaaf2c..958c4c035 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -523,12 +523,18 @@ class WindowActionPanelState extends State super.dispose(); } + void _setMaximize(bool maximize) { + stateGlobal.setMaximize(maximize); + setState(() {}); + } + @override void onWindowMaximize() { // catch maximize from system if (!widget.isMaximized.value) { widget.isMaximized.value = true; } + _setMaximize(true); super.onWindowMaximize(); } @@ -538,6 +544,7 @@ class WindowActionPanelState extends State if (widget.isMaximized.value) { widget.isMaximized.value = false; } + _setMaximize(false); super.onWindowUnmaximize(); } diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index 761c95ded..7de258a39 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -9,8 +9,10 @@ import '../consts.dart'; class StateGlobal { int _windowId = -1; bool _fullscreen = false; + bool _maximize = false; bool grabKeyboard = false; final RxBool _showTabBar = true.obs; + final RxBool _showResizeEdge = true.obs; final RxDouble _resizeEdgeSize = RxDouble(kWindowEdgeSize); final RxDouble _windowBorderWidth = RxDouble(kWindowBorderWidth); final RxBool showRemoteMenuBar = false.obs; @@ -18,12 +20,21 @@ class StateGlobal { int get windowId => _windowId; bool get fullscreen => _fullscreen; + bool get maximize => _maximize; double get tabBarHeight => fullscreen ? 0 : kDesktopRemoteTabBarHeight; RxBool get showTabBar => _showTabBar; RxDouble get resizeEdgeSize => _resizeEdgeSize; RxDouble get windowBorderWidth => _windowBorderWidth; setWindowId(int id) => _windowId = id; + setMaximize(bool v) { + if (_maximize != v) { + print("set maximize"); + _maximize = v; + _resizeEdgeSize.value = + _maximize ? kMaximizeEdgeSize : kWindowEdgeSize; + } + } setFullscreen(bool v) { if (_fullscreen != v) { _fullscreen = v; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 572b3e20a..b10dd1ec0 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -59,7 +59,7 @@ dependencies: desktop_multi_window: git: url: https://github.com/Kingtous/rustdesk_desktop_multi_window - ref: f37357ed98a10717576eb9ed8413e92b2ec5d13a + ref: c717159ea8fc0b9c6b4ac50110efc1dfd3c1ba7a freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: @@ -76,7 +76,7 @@ dependencies: file_picker: ^5.1.0 flutter_svg: ^1.1.5 flutter_improved_scrolling: - # currently, we use flutter 3.0.5 for windows build, latest for other builds. + # currently, we use flutter 3.7.0+. # # for flutter 3.0.5, please use official version(just comment code below). # if build rustdesk by flutter >=3.3, please use our custom pub below (uncomment code below). From cb4b658e483c50c0028f0675eedff5bf40703a81 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 27 Feb 2023 14:24:15 +0800 Subject: [PATCH 38/51] Avoid dividing by 0 and setting scale to 0 Signed-off-by: fufesou --- flutter/lib/models/model.dart | 38 ++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 74cc7f14f..21949705f 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -617,13 +617,28 @@ class ViewStyle { final int displayWidth; final int displayHeight; ViewStyle({ - this.style = '', - this.width = 0.0, - this.height = 0.0, - this.displayWidth = 0, - this.displayHeight = 0, + required this.style, + required this.width, + required this.height, + required this.displayWidth, + required this.displayHeight, }); + static defaultViewStyle() { + final desktop = (isDesktop || isWebDesktop); + final w = + desktop ? kDesktopDefaultDisplayWidth : kMobileDefaultDisplayWidth; + final h = + desktop ? kDesktopDefaultDisplayHeight : kMobileDefaultDisplayHeight; + return ViewStyle( + style: '', + width: w.toDouble(), + height: h.toDouble(), + displayWidth: w, + displayHeight: h, + ); + } + static int _double2Int(double v) => (v * 100).round().toInt(); @override @@ -652,9 +667,14 @@ class ViewStyle { double get scale { double s = 1.0; if (style == kRemoteViewStyleAdaptive) { - final s1 = width / displayWidth; - final s2 = height / displayHeight; - s = s1 < s2 ? s1 : s2; + if (width != 0 && + height != 0 && + displayWidth != 0 && + displayHeight != 0) { + final s1 = width / displayWidth; + final s2 = height / displayHeight; + s = s1 < s2 ? s1 : s2; + } } return s; } @@ -680,7 +700,7 @@ class CanvasModel with ChangeNotifier { // scroll offset y percent double _scrollY = 0.0; ScrollStyle _scrollStyle = ScrollStyle.scrollauto; - ViewStyle _lastViewStyle = ViewStyle(); + ViewStyle _lastViewStyle = ViewStyle.defaultViewStyle(); final _imageOverflow = false.obs; From 6e6fc64f629c6b1a9067a7f16645451cd11f1073 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 27 Feb 2023 15:56:09 +0800 Subject: [PATCH 39/51] opt: add resize area into the compatible ui mode --- flutter/lib/consts.dart | 2 +- flutter/lib/desktop/pages/desktop_tab_page.dart | 2 +- flutter/lib/desktop/pages/file_manager_tab_page.dart | 2 +- flutter/lib/desktop/pages/port_forward_tab_page.dart | 2 +- flutter/lib/desktop/pages/remote_tab_page.dart | 2 +- flutter/lib/models/state_model.dart | 1 - flutter/pubspec.yaml | 2 +- 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 789517bf7..b43f3e7da 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -59,7 +59,7 @@ const double kDesktopFileTransferMaximumWidth = 300; const double kDesktopFileTransferRowHeight = 30.0; const double kDesktopFileTransferHeaderHeight = 25.0; -EdgeInsets get kDragToResizeAreaPadding => Platform.isLinux +EdgeInsets get kDragToResizeAreaPadding => !kUseCompatibleUiMode && Platform.isLinux ? stateGlobal.fullscreen || stateGlobal.maximize ? EdgeInsets.zero : EdgeInsets.all(4.0) diff --git a/flutter/lib/desktop/pages/desktop_tab_page.dart b/flutter/lib/desktop/pages/desktop_tab_page.dart index 053a2d8a2..4a1a40242 100644 --- a/flutter/lib/desktop/pages/desktop_tab_page.dart +++ b/flutter/lib/desktop/pages/desktop_tab_page.dart @@ -75,7 +75,7 @@ class _DesktopTabPageState extends State { isClose: false, ), ))); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : Obx( () => DragToResizeArea( diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart index 148d928d9..39958e88e 100644 --- a/flutter/lib/desktop/pages/file_manager_tab_page.dart +++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart @@ -98,7 +98,7 @@ class _FileManagerTabPageState extends State { labelGetter: DesktopTab.labelGetterAlias, )), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : SubWindowDragToResizeArea( child: tabWidget, diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index 394d89e38..32f02c9b7 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -107,7 +107,7 @@ class _PortForwardTabPageState extends State { labelGetter: DesktopTab.labelGetterAlias, )), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : Obx( () => SubWindowDragToResizeArea( diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index e7aed0358..d810650fd 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -205,7 +205,7 @@ class _ConnectionTabPageState extends State { ), ), ); - return Platform.isMacOS + return Platform.isMacOS || kUseCompatibleUiMode ? tabWidget : Obx(() => SubWindowDragToResizeArea( key: contentKey, diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index 7de258a39..aa4fab86e 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -29,7 +29,6 @@ class StateGlobal { setWindowId(int id) => _windowId = id; setMaximize(bool v) { if (_maximize != v) { - print("set maximize"); _maximize = v; _resizeEdgeSize.value = _maximize ? kMaximizeEdgeSize : kWindowEdgeSize; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index b10dd1ec0..8d390d370 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -59,7 +59,7 @@ dependencies: desktop_multi_window: git: url: https://github.com/Kingtous/rustdesk_desktop_multi_window - ref: c717159ea8fc0b9c6b4ac50110efc1dfd3c1ba7a + ref: e383fffb5c4529c9e0a710f1025a0c590b99ee08 freezed_annotation: ^2.0.3 flutter_custom_cursor: ^0.0.4 window_size: From 920fa6dac7c2d9aa6b709398a3f7cb10c65fcd7f Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 27 Feb 2023 16:53:13 +0800 Subject: [PATCH 40/51] opt: resize padding set to 5.0 --- flutter/lib/consts.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index b43f3e7da..3c414cd85 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -62,7 +62,7 @@ const double kDesktopFileTransferHeaderHeight = 25.0; EdgeInsets get kDragToResizeAreaPadding => !kUseCompatibleUiMode && Platform.isLinux ? stateGlobal.fullscreen || stateGlobal.maximize ? EdgeInsets.zero - : EdgeInsets.all(4.0) + : EdgeInsets.all(5.0) : EdgeInsets.zero; // https://en.wikipedia.org/wiki/Non-breaking_space const int $nbsp = 0x00A0; From 2f7e758c751538e3caf025081b230ed2b49ee60a Mon Sep 17 00:00:00 2001 From: FastAct <93490087+FastAct@users.noreply.github.com> Date: Mon, 27 Feb 2023 09:56:56 +0100 Subject: [PATCH 41/51] Update nl.rs corrected error --- src/lang/nl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/nl.rs b/src/lang/nl.rs index eb7c214ab..f38c14791 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -444,7 +444,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Default View Style", "Standaard Weergave Stijl"), ("Default Scroll Style", "Standaard Scroll Stijl"), ("Default Image Quality", "Standaard Beeldkwaliteit"), - ("Default Codec", "tandaard Codec"), + ("Default Codec", "Standaard Codec"), ("Bitrate", "Bitrate"), ("FPS", "FPS"), ("Auto", "Auto"), From 6971f45fd0734b4e56d416d9ee0bba49eabb5334 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 27 Feb 2023 17:54:18 +0800 Subject: [PATCH 42/51] dark theme install page Signed-off-by: 21pages --- flutter/lib/desktop/pages/install_page.dart | 20 ++++++++++---------- flutter/lib/main.dart | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/flutter/lib/desktop/pages/install_page.dart b/flutter/lib/desktop/pages/install_page.dart index e7bb28813..d7202e300 100644 --- a/flutter/lib/desktop/pages/install_page.dart +++ b/flutter/lib/desktop/pages/install_page.dart @@ -46,15 +46,19 @@ class _InstallPageState extends State with WindowListener { final double em = 13; final btnFontSize = 0.9 * em; final double button_radius = 6; + final isDarkTheme = MyTheme.currentThemeMode() == ThemeMode.dark; final buttonStyle = OutlinedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(button_radius)), )); final inputBorder = OutlineInputBorder( borderRadius: BorderRadius.zero, - borderSide: BorderSide(color: Colors.black12)); + borderSide: + BorderSide(color: isDarkTheme ? Colors.white70 : Colors.black12)); + final textColor = isDarkTheme ? null : Colors.black87; + final dividerColor = isDarkTheme ? Colors.white70 : Colors.black87; return Scaffold( - backgroundColor: Colors.white, + backgroundColor: null, body: SingleChildScrollView( child: Column( children: [ @@ -91,8 +95,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Change Path'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(left: em)) ], ).marginSymmetric(vertical: 2 * em), @@ -127,8 +130,7 @@ class _InstallPageState extends State with WindowListener { )).marginOnly(top: 2 * em), Row(children: [Text(translate('agreement_tip'))]) .marginOnly(top: em), - Divider(color: Colors.black87) - .marginSymmetric(vertical: 0.5 * em), + Divider(color: dividerColor).marginSymmetric(vertical: 0.5 * em), Row( children: [ Expanded( @@ -143,8 +145,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Cancel'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(right: 2 * em)), Obx(() => ElevatedButton( onPressed: btnEnabled.value ? install : null, @@ -167,8 +168,7 @@ class _InstallPageState extends State with WindowListener { style: buttonStyle, child: Text(translate('Run without install'), style: TextStyle( - color: Colors.black87, - fontSize: btnFontSize))) + color: textColor, fontSize: btnFontSize))) .marginOnly(left: 2 * em)), ), ], diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index c61287d4f..baf7193b3 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -291,7 +291,7 @@ void _runApp( void runInstallPage() async { await windowManager.ensureInitialized(); await initEnv(kAppTypeMain); - _runApp('', const InstallPage(), ThemeMode.light); + _runApp('', const InstallPage(), MyTheme.currentThemeMode()); windowManager.waitUntilReadyToShow( WindowOptions(size: Size(800, 600), center: true), () async { windowManager.show(); From 2678c503a01aaac28936a6128019c72e77e578ca Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 27 Feb 2023 20:28:55 +0800 Subject: [PATCH 43/51] chore: fix recursive os.system on my m1 in build.py, and modify windows subsystem macro --- build.py | 184 ++++++++++++++++++++++++---------------------------- src/main.rs | 7 +- 2 files changed, 90 insertions(+), 101 deletions(-) diff --git a/build.py b/build.py index 727b53fe0..b30f76f95 100755 --- a/build.py +++ b/build.py @@ -18,14 +18,11 @@ exe_path = 'target/release/' + hbb_name flutter_win_target_dir = 'flutter/build/windows/runner/Release/' skip_cargo = False -def custom_os_system(cmd): - err = os._system(cmd) +def system2(cmd): + err = os.system(cmd) if err != 0: print(f"Error occurred when executing: {cmd}. Exiting.") sys.exit(-1) -# replace prebuilt os.system -os._system = os.system -os.system = custom_os_system def get_version(): with open("Cargo.toml", encoding="utf-8") as fh: @@ -144,8 +141,8 @@ def generate_build_script_for_docker(): # build rustdesk ./build.py --flutter --hwcodec ''') - os.system("chmod +x /tmp/build.sh") - os.system("bash /tmp/build.sh") + system2("chmod +x /tmp/build.sh") + system2("bash /tmp/build.sh") def download_extract_features(features, res_dir): @@ -250,7 +247,7 @@ def get_features(args): def generate_control_file(version): control_file_path = "../res/DEBIAN/control" - os.system('/bin/rm -rf %s' % control_file_path) + system2('/bin/rm -rf %s' % control_file_path) content = """Package: rustdesk Version: %s @@ -268,45 +265,45 @@ Description: A remote control software. def ffi_bindgen_function_refactor(): # workaround ffigen - os.system( + system2( 'sed -i "s/ffi.NativeFunction> tmpdeb/usr/share/rustdesk/files/polkit && chmod a+x tmpdeb/usr/share/rustdesk/files/polkit") - os.system('mkdir -p tmpdeb/DEBIAN') + system2('mkdir -p tmpdeb/DEBIAN') generate_control_file(version) - os.system('cp -a ../res/DEBIAN/* tmpdeb/DEBIAN/') + system2('cp -a ../res/DEBIAN/* tmpdeb/DEBIAN/') md5_file('usr/share/rustdesk/files/systemd/rustdesk.service') - os.system('dpkg-deb -b tmpdeb rustdesk.deb;') + system2('dpkg-deb -b tmpdeb rustdesk.deb;') - os.system('/bin/rm -rf tmpdeb/') - os.system('/bin/rm -rf ../res/DEBIAN/control') + system2('/bin/rm -rf tmpdeb/') + system2('/bin/rm -rf ../res/DEBIAN/control') os.rename('rustdesk.deb', '../rustdesk-%s.deb' % version) os.chdir("..") @@ -314,16 +311,16 @@ def build_flutter_deb(version, features): def build_flutter_dmg(version, features): if not skip_cargo: # set minimum osx build target, now is 10.14, which is the same as the flutter xcode project - os.system(f'MACOSX_DEPLOYMENT_TARGET=10.14 cargo build --features {features} --lib --release') + system2(f'MACOSX_DEPLOYMENT_TARGET=10.14 cargo build --features {features} --lib --release') # copy dylib - os.system( + system2( "cp target/release/liblibrustdesk.dylib target/release/librustdesk.dylib") # ffi_bindgen_function_refactor() # limitations from flutter rust bridge - os.system('sed -i "" "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h') + system2('sed -i "" "s/char \*\*rustdesk_core_main(int \*args_len);//" flutter/macos/Runner/bridge_generated.h') os.chdir('flutter') - os.system('flutter build macos --release') - os.system( + system2('flutter build macos --release') + system2( "create-dmg rustdesk.dmg ./build/macos/Build/Products/Release/RustDesk.app") os.rename("rustdesk.dmg", f"../rustdesk-{version}.dmg") os.chdir("..") @@ -331,29 +328,29 @@ def build_flutter_dmg(version, features): def build_flutter_arch_manjaro(version, features): if not skip_cargo: - os.system(f'cargo build --features {features} --lib --release') + system2(f'cargo build --features {features} --lib --release') ffi_bindgen_function_refactor() os.chdir('flutter') - os.system('flutter build linux --release') - os.system('strip build/linux/x64/release/bundle/lib/librustdesk.so') + system2('flutter build linux --release') + system2('strip build/linux/x64/release/bundle/lib/librustdesk.so') os.chdir('../res') - os.system('HBB=`pwd`/.. FLUTTER=1 makepkg -f') + system2('HBB=`pwd`/.. FLUTTER=1 makepkg -f') def build_flutter_windows(version, features): if not skip_cargo: - os.system(f'cargo build --features {features} --lib --release') + system2(f'cargo build --features {features} --lib --release') if not os.path.exists("target/release/librustdesk.dll"): print("cargo build failed, please check rust source code.") exit(-1) os.chdir('flutter') - os.system('flutter build windows --release') + system2('flutter build windows --release') os.chdir('..') shutil.copy2('target/release/deps/dylib_virtual_display.dll', flutter_win_target_dir) os.chdir('libs/portable') - os.system('pip3 install -r requirements.txt') - os.system( + system2('pip3 install -r requirements.txt') + system2( f'python3 ./generate.py -f ../../{flutter_win_target_dir} -o . -e ../../{flutter_win_target_dir}/rustdesk.exe') os.chdir('../..') if os.path.exists('./rustdesk_portable.exe'): @@ -374,22 +371,15 @@ def main(): parser = make_parser() args = parser.parse_args() - shutil.copy2('Cargo.toml', 'Cargo.toml.bk') - shutil.copy2('src/main.rs', 'src/main.rs.bk') - if windows: - txt = open('src/main.rs', encoding='utf8').read() - with open('src/main.rs', 'wt', encoding='utf8') as fh: - fh.write(txt.replace( - '//#![windows_subsystem', '#![windows_subsystem')) if os.path.exists(exe_path): os.unlink(exe_path) if os.path.isfile('/usr/bin/pacman'): - os.system('git checkout src/ui/common.tis') + system2('git checkout src/ui/common.tis') version = get_version() features = ','.join(get_features(args)) flutter = args.flutter if not flutter: - os.system('python3 res/inline-sciter.py') + system2('python3 res/inline-sciter.py') print(args.skip_cargo) if args.skip_cargo: skip_cargo = True @@ -397,55 +387,55 @@ def main(): if windows: # build virtual display dynamic library os.chdir('libs/virtual_display/dylib') - os.system('cargo build --release') + system2('cargo build --release') os.chdir('../../..') if flutter: build_flutter_windows(version, features) return - os.system('cargo build --release --features ' + features) - # os.system('upx.exe target/release/rustdesk.exe') - os.system('mv target/release/rustdesk.exe target/release/RustDesk.exe') + system2('cargo build --release --features ' + features) + # system2('upx.exe target/release/rustdesk.exe') + system2('mv target/release/rustdesk.exe target/release/RustDesk.exe') pa = os.environ.get('P') if pa: - os.system( + system2( f'signtool sign /a /v /p {pa} /debug /f .\\cert.pfx /t http://timestamp.digicert.com ' 'target\\release\\rustdesk.exe') else: print('Not signed') - os.system( + system2( f'cp -rf target/release/RustDesk.exe rustdesk-{version}-win7-install.exe') elif os.path.isfile('/usr/bin/pacman'): # pacman -S -needed base-devel - os.system("sed -i 's/pkgver=.*/pkgver=%s/g' res/PKGBUILD" % version) + system2("sed -i 's/pkgver=.*/pkgver=%s/g' res/PKGBUILD" % version) if flutter: build_flutter_arch_manjaro(version, features) else: - os.system('cargo build --release --features ' + features) - os.system('git checkout src/ui/common.tis') - os.system('strip target/release/rustdesk') - os.system('ln -s res/pacman_install && ln -s res/PKGBUILD') - os.system('HBB=`pwd` makepkg -f') - os.system('mv rustdesk-%s-0-x86_64.pkg.tar.zst rustdesk-%s-manjaro-arch.pkg.tar.zst' % ( + system2('cargo build --release --features ' + features) + system2('git checkout src/ui/common.tis') + system2('strip target/release/rustdesk') + system2('ln -s res/pacman_install && ln -s res/PKGBUILD') + system2('HBB=`pwd` makepkg -f') + system2('mv rustdesk-%s-0-x86_64.pkg.tar.zst rustdesk-%s-manjaro-arch.pkg.tar.zst' % ( version, version)) # pacman -U ./rustdesk.pkg.tar.zst elif os.path.isfile('/usr/bin/yum'): - os.system('cargo build --release --features ' + features) - os.system('strip target/release/rustdesk') - os.system( + system2('cargo build --release --features ' + features) + system2('strip target/release/rustdesk') + system2( "sed -i 's/Version: .*/Version: %s/g' res/rpm.spec" % version) - os.system('HBB=`pwd` rpmbuild -ba res/rpm.spec') - os.system( + system2('HBB=`pwd` rpmbuild -ba res/rpm.spec') + system2( 'mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-fedora28-centos8.rpm' % ( version, version)) # yum localinstall rustdesk.rpm elif os.path.isfile('/usr/bin/zypper'): - os.system('cargo build --release --features ' + features) - os.system('strip target/release/rustdesk') - os.system( + system2('cargo build --release --features ' + features) + system2('strip target/release/rustdesk') + system2( "sed -i 's/Version: .*/Version: %s/g' res/rpm-suse.spec" % version) - os.system('HBB=`pwd` rpmbuild -ba res/rpm-suse.spec') - os.system( + system2('HBB=`pwd` rpmbuild -ba res/rpm-suse.spec') + system2( 'mv $HOME/rpmbuild/RPMS/x86_64/rustdesk-%s-0.x86_64.rpm ./rustdesk-%s-suse.rpm' % ( version, version)) # yum localinstall rustdesk.rpm @@ -455,18 +445,18 @@ def main(): build_flutter_dmg(version, features) pass else: - # os.system( + # system2( # 'mv target/release/bundle/deb/rustdesk*.deb ./flutter/rustdesk.deb') build_flutter_deb(version, features) else: - os.system('cargo bundle --release --features ' + features) + system2('cargo bundle --release --features ' + features) if osx: - os.system( + system2( 'strip target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk') - os.system( + system2( 'cp libsciter.dylib target/release/bundle/osx/RustDesk.app/Contents/MacOS/') # https://github.com/sindresorhus/create-dmg - os.system('/bin/rm -rf *.dmg') + system2('/bin/rm -rf *.dmg') plist = "target/release/bundle/osx/RustDesk.app/Contents/Info.plist" txt = open(plist).read() with open(plist, "wt") as fh: @@ -476,7 +466,7 @@ def main(): """)) pa = os.environ.get('P') if pa: - os.system(''' + system2(''' # buggy: rcodesign sign ... path/*, have to sign one by one # install rcodesign via cargo install apple-codesign #rcodesign sign --p12-file ~/.p12/rustdesk-developer-id.p12 --p12-password-file ~/.p12/.cert-pass --code-signature-flags runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/rustdesk @@ -486,11 +476,11 @@ def main(): codesign -s "Developer ID Application: {0}" --force --options runtime ./target/release/bundle/osx/RustDesk.app/Contents/MacOS/* codesign -s "Developer ID Application: {0}" --force --options runtime ./target/release/bundle/osx/RustDesk.app '''.format(pa)) - os.system('create-dmg target/release/bundle/osx/RustDesk.app') + system2('create-dmg target/release/bundle/osx/RustDesk.app') os.rename('RustDesk %s.dmg' % version, 'rustdesk-%s.dmg' % version) if pa: - os.system(''' + system2(''' # https://pyoxidizer.readthedocs.io/en/apple-codesign-0.14.0/apple_codesign.html # https://pyoxidizer.readthedocs.io/en/stable/tugger_code_signing.html # https://developer.apple.com/developer-id/ @@ -507,34 +497,32 @@ def main(): print('Not signed') else: # buid deb package - os.system( + system2( 'mv target/release/bundle/deb/rustdesk*.deb ./rustdesk.deb') - os.system('dpkg-deb -R rustdesk.deb tmpdeb') - os.system('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/') - os.system( + system2('dpkg-deb -R rustdesk.deb tmpdeb') + system2('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/') + system2( 'cp res/rustdesk.service tmpdeb/usr/share/rustdesk/files/systemd/') - os.system( + system2( 'cp res/128x128@2x.png tmpdeb/usr/share/rustdesk/files/rustdesk.png') - os.system( + system2( 'cp res/rustdesk.desktop tmpdeb/usr/share/applications/rustdesk.desktop') - os.system( + system2( 'cp res/rustdesk-link.desktop tmpdeb/usr/share/applications/rustdesk-link.desktop') - os.system('cp -a res/DEBIAN/* tmpdeb/DEBIAN/') - os.system('strip tmpdeb/usr/bin/rustdesk') - os.system('mkdir -p tmpdeb/usr/lib/rustdesk') - os.system('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/lib/rustdesk/') - os.system('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/') + system2('cp -a res/DEBIAN/* tmpdeb/DEBIAN/') + system2('strip tmpdeb/usr/bin/rustdesk') + system2('mkdir -p tmpdeb/usr/lib/rustdesk') + system2('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/lib/rustdesk/') + system2('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/') md5_file('usr/share/rustdesk/files/systemd/rustdesk.service') md5_file('usr/lib/rustdesk/libsciter-gtk.so') - os.system('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/') + system2('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/') os.rename('rustdesk.deb', 'rustdesk-%s.deb' % version) - os.system("mv Cargo.toml.bk Cargo.toml") - os.system("mv src/main.rs.bk src/main.rs") def md5_file(fn): md5 = hashlib.md5(open('tmpdeb/' + fn, 'rb').read()).hexdigest() - os.system('echo "%s %s" >> tmpdeb/DEBIAN/md5sums' % (md5, fn)) + system2('echo "%s %s" >> tmpdeb/DEBIAN/md5sums' % (md5, fn)) if __name__ == "__main__": diff --git a/src/main.rs b/src/main.rs index 169515425..3759f6056 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ -// Specify the Windows subsystem to eliminate console window. -// Requires Rust 1.18. -//#![windows_subsystem = "windows"] + #![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" + )] use librustdesk::*; From f94791793bdec5d83b011709261857a6d6a8f653 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 27 Feb 2023 19:22:52 +0800 Subject: [PATCH 44/51] fix can't install when username contains &, @, ^ Signed-off-by: 21pages --- src/platform/windows.rs | 25 +++++++++++++++++++++++++ src/server/portable_service.rs | 12 +----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 6b3f8013c..0bba649f4 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1236,6 +1236,15 @@ pub fn uninstall_me() -> ResultType<()> { fn write_cmds(cmds: String, ext: &str, tip: &str) -> ResultType { let mut tmp = std::env::temp_dir(); + // When dir contains these characters, the bat file will not execute in elevated mode. + if vec!["&", "@", "^"] + .drain(..) + .any(|s| tmp.to_string_lossy().to_string().contains(s)) + { + if let Ok(dir) = user_accessible_folder() { + tmp = dir; + } + } tmp.push(format!("{}_{}.{}", crate::get_app_name(), tip, ext)); let mut file = std::fs::File::create(&tmp)?; // in case cmds mixed with \r\n and \n, make sure all ending with \r\n @@ -1872,3 +1881,19 @@ pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType< Ok(()) } } + +pub fn user_accessible_folder() -> ResultType { + let disk = std::env::var("SystemDrive").unwrap_or("C:".to_string()); + let dir1 = PathBuf::from(format!("{}\\ProgramData", disk)); + // NOTICE: "C:\Windows\Temp" requires permanent authorization. + let dir2 = PathBuf::from(format!("{}\\Windows\\Temp", disk)); + let dir; + if dir1.exists() { + dir = dir1; + } else if dir2.exists() { + dir = dir2; + } else { + bail!("no vaild user accessible folder"); + } + Ok(dir) +} diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 7514ead38..c49f974a7 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -117,17 +117,7 @@ impl SharedMemory { } fn flink(name: String) -> ResultType { - let disk = std::env::var("SystemDrive").unwrap_or("C:".to_string()); - let dir1 = PathBuf::from(format!("{}\\ProgramData", disk)); - let dir2 = PathBuf::from(format!("{}\\Windows\\Temp", disk)); - let mut dir; - if dir1.exists() { - dir = dir1; - } else if dir2.exists() { - dir = dir2; - } else { - bail!("no vaild flink directory"); - } + let mut dir = crate::platform::user_accessible_folder()?; dir = dir.join(hbb_common::config::APP_NAME.read().unwrap().clone()); if !dir.exists() { std::fs::create_dir(&dir)?; From c7e8037a79f3446591e585bbdfe52ed696c26873 Mon Sep 17 00:00:00 2001 From: solokot Date: Mon, 27 Feb 2023 15:57:46 +0300 Subject: [PATCH 45/51] Update ru.rs --- src/lang/ru.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 07b8af998..3bfb5357d 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -454,8 +454,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Stop voice call", "Завершить голосовой вызов"), ("relay_hint_tip", "Прямое подключение может оказаться невозможным. В этом случае можно попытаться подключиться через сервер ретрансляции. \nКроме того, если вы хотите сразу использовать сервер ретрансляции, можно добавить к ID суффикс \"/r\" или включить \"Всегда подключаться через ретранслятор\" в настройках удалённого узла."), ("Reconnect", "Переподключить"), - ("Codec", ""), - ("Resolution", ""), - ("No transfers in progress", ""), + ("Codec", "Кодек"), + ("Resolution", "Разрешение"), + ("No transfers in progress", "Передача не осуществляется"), ].iter().cloned().collect(); } From 658c45d1c233a7be5997e38db701ea2af9c81c45 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 27 Feb 2023 21:46:26 +0800 Subject: [PATCH 46/51] Do not use flutter texture for render. Signed-off-by: fufesou --- .github/workflows/flutter-nightly.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index b08193971..ffcadd18b 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -732,7 +732,7 @@ jobs: x86_64) # no need mock on x86_64 export VCPKG_ROOT=/opt/artifacts/vcpkg - cargo build --lib --features hwcodec,flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features hwcodec,flutter,${{ matrix.job.extra-build-features }} --release ;; esac @@ -900,7 +900,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm64-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release ;; armv7) cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/arm-linux-gnueabihf/ @@ -910,7 +910,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release ;; esac From fb21f9df440101739875eece1c45383272394cd1 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 27 Feb 2023 22:24:00 +0800 Subject: [PATCH 47/51] check divide by 0 Signed-off-by: fufesou --- flutter/lib/models/model.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 21949705f..fd97b1e5c 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -810,6 +810,10 @@ class CanvasModel with ChangeNotifier { double get tabBarHeight => stateGlobal.tabBarHeight; moveDesktopMouse(double x, double y) { + if (size.width == 0 || size.height == 0) { + return; + } + // On mobile platforms, move the canvas with the cursor. final dw = getDisplayWidth() * _scale; final dh = getDisplayHeight() * _scale; From 7bbeb351ce4eb6c582a7b162b4e415270b86b1be Mon Sep 17 00:00:00 2001 From: Michal Witek Date: Mon, 27 Feb 2023 20:40:39 +0100 Subject: [PATCH 48/51] Updated Flutter Version to `3.7.5` Updated agents OS to `Ubuntu 20.04` where possible --- .github/workflows/flutter-ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/flutter-ci.yml b/.github/workflows/flutter-ci.yml index 74e4efa99..cae5b82c7 100644 --- a/.github/workflows/flutter-ci.yml +++ b/.github/workflows/flutter-ci.yml @@ -18,7 +18,7 @@ on: env: LLVM_VERSION: "15.0.6" - FLUTTER_VERSION: "3.7.0" + FLUTTER_VERSION: "3.7.5" # vcpkg version: 2022.05.10 # for multiarch gcc compatibility VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44" @@ -260,7 +260,7 @@ jobs: job: - { target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-args: "", } steps: @@ -330,13 +330,13 @@ jobs: - { arch: x86_64, target: aarch64-linux-android, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "", } # - { # arch: x86_64, # target: armv7-linux-androideabi, - # os: ubuntu-18.04, + # os: ubuntu-20.04, # extra-build-features: "", # } steps: @@ -907,19 +907,19 @@ jobs: - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "", } - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "flatpak", } - { arch: x86_64, target: x86_64-unknown-linux-gnu, - os: ubuntu-18.04, + os: ubuntu-20.04, extra-build-features: "appimage", } # - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } From 0380fc0c9e6235b86af42d99041a55401ea63e13 Mon Sep 17 00:00:00 2001 From: "Miguel F. G" <116861809+flusheDData@users.noreply.github.com> Date: Tue, 28 Feb 2023 00:50:07 +0100 Subject: [PATCH 49/51] Update es.rs New term added --- src/lang/es.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/es.rs b/src/lang/es.rs index af0da0479..a95d39776 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -456,6 +456,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Reconnect", "Reconectar"), ("Codec", "Códec"), ("Resolution", "Resolución"), - ("No transfers in progress", ""), + ("No transfers in progress", "No hay transferencias en curso"), ].iter().cloned().collect(); } From eebe3448786b1704d9be4c2b08e9d7de619511da Mon Sep 17 00:00:00 2001 From: Andi Ariffin Date: Tue, 28 Feb 2023 11:57:39 +0700 Subject: [PATCH 50/51] Fix typos causing gen_js_from_hbb.py to fail --- src/lang/en.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/en.rs b/src/lang/en.rs index 3e87cd661..250530013 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -39,8 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("verification_tip", "A new device has been detected, and a verification code has been sent to the registered email address, enter the verification code to continue logging in."), ("software_render_tip", "If you have an Nvidia graphics card and the remote window closes immediately after connecting, installing the nouveau driver and choosing to use software rendering may help. A software restart is required."), ("config_input", "In order to control remote desktop with keyboard, you need to grant RustDesk \"Input Monitoring\" permissions."), - ("request_elevation_tip","You can also request elevation if there is someone on the remote side."), - ("wait_accept_uac_tip","Please wait for the remote user to accept the UAC dialog."), + ("request_elevation_tip", "You can also request elevation if there is someone on the remote side."), + ("wait_accept_uac_tip", "Please wait for the remote user to accept the UAC dialog."), ("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk."), ("config_microphone", "In order to speak remotely, you need to grant RustDesk \"Record Audio\" permissions."), ("relay_hint_tip", "It may not be possible to connect directly, you can try to connect via relay. \nIn addition, if you want to use relay on your first try, you can add the \"/r\" suffix to the ID, or select the option \"Always connect via relay\" in the peer card."), From 6bd26ef3987db43cadfecb19267262c8d5cf50f1 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Tue, 28 Feb 2023 13:23:27 +0800 Subject: [PATCH 51/51] fix: linux canvas offset --- flutter/lib/models/model.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index fd97b1e5c..cea6785fc 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -731,8 +731,15 @@ class CanvasModel with ChangeNotifier { Size getSize() { final size = MediaQueryData.fromWindow(ui.window).size; // If minimized, w or h may be negative here. - double w = size.width - windowBorderWidth * 2; - double h = size.height - tabBarHeight - windowBorderWidth * 2; + double w = size.width - + windowBorderWidth * 2 - + kDragToResizeAreaPadding.left - + kDragToResizeAreaPadding.right; + double h = size.height - + tabBarHeight - + windowBorderWidth * 2 - + kDragToResizeAreaPadding.top - + kDragToResizeAreaPadding.bottom; return Size(w < 0 ? 0 : w, h < 0 ? 0 : h); }