Merge pull request #3675 from 21pages/view_mode

client side view mode
This commit is contained in:
RustDesk 2023-03-16 15:04:45 +08:00 committed by GitHub
commit e17717b9c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 203 additions and 46 deletions

View File

@ -1318,6 +1318,7 @@ class _DisplayState extends State<_Display> {
Widget other(BuildContext context) { Widget other(BuildContext context) {
return _Card(title: 'Other Default Options', children: [ return _Card(title: 'Other Default Options', children: [
otherRow('View Mode', 'view-only'),
otherRow('show_monitors_tip', 'show_monitors_toolbar'), otherRow('show_monitors_tip', 'show_monitors_toolbar'),
otherRow('Show remote cursor', 'show_remote_cursor'), otherRow('Show remote cursor', 'show_remote_cursor'),
otherRow('Zoom cursor', 'zoom-cursor'), otherRow('Zoom cursor', 'zoom-cursor'),

View File

@ -139,8 +139,9 @@ class _RemotePageState extends State<RemotePage>
_ffi.ffiModel.updateEventListener(widget.id); _ffi.ffiModel.updateEventListener(widget.id);
_ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id); _ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id);
// Session option should be set after models.dart/FFI.start // Session option should be set after models.dart/FFI.start
_showRemoteCursor.value = bind.sessionGetToggleOptionSync( // _showRemoteCursor has been set by setViewOnly
id: widget.id, arg: 'show-remote-cursor'); _ffi.ffiModel.setViewOnly(widget.id,
bind.sessionGetToggleOptionSync(id: widget.id, arg: 'view-only'));
_zoomCursor.value = _zoomCursor.value =
bind.sessionGetToggleOptionSync(id: widget.id, arg: 'zoom-cursor'); bind.sessionGetToggleOptionSync(id: widget.id, arg: 'zoom-cursor');
DesktopMultiWindow.addListener(this); DesktopMultiWindow.addListener(this);

View File

@ -385,6 +385,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
} }
Widget _buildToolbar(BuildContext context) { Widget _buildToolbar(BuildContext context) {
final ffiModel = Provider.of<FfiModel>(context);
final List<Widget> toolbarItems = []; final List<Widget> toolbarItems = [];
if (!isWebDesktop) { if (!isWebDesktop) {
toolbarItems.add(_PinMenu(state: widget.state)); toolbarItems.add(_PinMenu(state: widget.state));
@ -410,7 +411,9 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
state: widget.state, state: widget.state,
setFullscreen: _setFullscreen, setFullscreen: _setFullscreen,
)); ));
toolbarItems.add(_KeyboardMenu(id: widget.id, ffi: widget.ffi)); if (!ffiModel.viewOnly) {
toolbarItems.add(_KeyboardMenu(id: widget.id, ffi: widget.ffi));
}
if (!isWeb) { if (!isWeb) {
toolbarItems.add(_ChatMenu(id: widget.id, ffi: widget.ffi)); toolbarItems.add(_ChatMenu(id: widget.id, ffi: widget.ffi));
toolbarItems.add(_VoiceCallMenu(id: widget.id, ffi: widget.ffi)); toolbarItems.add(_VoiceCallMenu(id: widget.id, ffi: widget.ffi));
@ -820,8 +823,10 @@ class _ControlMenu extends StatelessWidget {
ctrlAltDel() { ctrlAltDel() {
final perms = ffi.ffiModel.permissions; final perms = ffi.ffiModel.permissions;
final viewOnly = ffi.ffiModel.viewOnly;
final pi = ffi.ffiModel.pi; final pi = ffi.ffiModel.pi;
final visible = perms['keyboard'] != false && final visible = !viewOnly &&
perms['keyboard'] != false &&
(pi.platform == kPeerPlatformLinux || pi.sasEnabled); (pi.platform == kPeerPlatformLinux || pi.sasEnabled);
if (!visible) return Offstage(); if (!visible) return Offstage();
return _MenuItemButton( return _MenuItemButton(
@ -846,7 +851,8 @@ class _ControlMenu extends StatelessWidget {
insertLock() { insertLock() {
final perms = ffi.ffiModel.permissions; final perms = ffi.ffiModel.permissions;
final visible = perms['keyboard'] != false; final viewOnly = ffi.ffiModel.viewOnly;
final visible = !viewOnly && perms['keyboard'] != false;
if (!visible) return Offstage(); if (!visible) return Offstage();
return _MenuItemButton( return _MenuItemButton(
child: Text(translate('Insert Lock')), child: Text(translate('Insert Lock')),
@ -963,6 +969,7 @@ class _DisplayMenuState extends State<_DisplayMenu> {
codec(), codec(),
resolutions(), resolutions(),
Divider(), Divider(),
view_only(),
showRemoteCursor(), showRemoteCursor(),
zoomCursor(), zoomCursor(),
showQualityMonitor(), showQualityMonitor(),
@ -1456,11 +1463,28 @@ class _DisplayMenuState extends State<_DisplayMenu> {
child: Text(translate("Resolution"))); child: Text(translate("Resolution")));
} }
view_only() {
final visible = version_cmp(pi.version, '1.2.0') >= 0;
if (!visible) return Offstage();
final ffiModel = widget.ffi.ffiModel;
return _CheckboxMenuButton(
value: ffiModel.viewOnly,
onChanged: (value) async {
if (value == null) return;
bind.sessionSetViewOnly(id: widget.id, viewOnly: value);
ffiModel.setViewOnly(widget.id, value);
},
ffi: widget.ffi,
child: Text(translate('View Mode')));
}
showRemoteCursor() { showRemoteCursor() {
if (widget.ffi.ffiModel.pi.platform == kPeerPlatformAndroid) { if (widget.ffi.ffiModel.pi.platform == kPeerPlatformAndroid) {
return Offstage(); return Offstage();
} }
final visible = !widget.ffi.canvasModel.cursorEmbedded; final ffiModel = widget.ffi.ffiModel;
final visible =
!ffiModel.viewOnly && !widget.ffi.canvasModel.cursorEmbedded;
if (!visible) return Offstage(); if (!visible) return Offstage();
final state = ShowRemoteCursorState.find(widget.id); final state = ShowRemoteCursorState.find(widget.id);
final option = 'show-remote-cursor'; final option = 'show-remote-cursor';
@ -1543,7 +1567,10 @@ class _DisplayMenuState extends State<_DisplayMenu> {
} }
disableClipboard() { disableClipboard() {
final visible = perms['keyboard'] != false && perms['clipboard'] != false; final ffiModel = widget.ffi.ffiModel;
final visible = perms['keyboard'] != false &&
perms['clipboard'] != false &&
!ffiModel.viewOnly;
if (!visible) return Offstage(); if (!visible) return Offstage();
final option = 'disable-clipboard'; final option = 'disable-clipboard';
final value = bind.sessionGetToggleOptionSync(id: widget.id, arg: option); final value = bind.sessionGetToggleOptionSync(id: widget.id, arg: option);

View File

@ -47,6 +47,7 @@ class FfiModel with ChangeNotifier {
bool _touchMode = false; bool _touchMode = false;
Timer? _timer; Timer? _timer;
var _reconnects = 1; var _reconnects = 1;
bool _viewOnly = false;
WeakReference<FFI> parent; WeakReference<FFI> parent;
Map<String, bool> get permissions => _permissions; Map<String, bool> get permissions => _permissions;
@ -65,6 +66,8 @@ class FfiModel with ChangeNotifier {
bool get isPeerAndroid => _pi.platform == kPeerPlatformAndroid; bool get isPeerAndroid => _pi.platform == kPeerPlatformAndroid;
bool get viewOnly => _viewOnly;
set inputBlocked(v) { set inputBlocked(v) {
_inputBlocked = v; _inputBlocked = v;
} }
@ -373,7 +376,8 @@ class FfiModel with ChangeNotifier {
_updateSessionWidthHeight(String id) { _updateSessionWidthHeight(String id) {
parent.target?.canvasModel.updateViewStyle(); parent.target?.canvasModel.updateViewStyle();
if (display.width <= 0 || display.height <= 0) { if (display.width <= 0 || display.height <= 0) {
debugPrintStack(label: 'invalid display size (${display.width},${display.height})'); debugPrintStack(
label: 'invalid display size (${display.width},${display.height})');
} else { } else {
bind.sessionSetSize(id: id, width: display.width, height: display.height); bind.sessionSetSize(id: id, width: display.width, height: display.height);
} }
@ -516,6 +520,19 @@ class FfiModel with ChangeNotifier {
// //
} }
} }
void setViewOnly(String id, bool value) {
if (value) {
ShowRemoteCursorState.find(id).value = value;
} else {
ShowRemoteCursorState.find(id).value =
bind.sessionGetToggleOptionSync(id: id, arg: 'show-remote-cursor');
}
if (_viewOnly != value) {
_viewOnly = value;
notifyListeners();
}
}
} }
class ImageModel with ChangeNotifier { class ImageModel with ChangeNotifier {

View File

@ -487,6 +487,7 @@ message OptionMessage {
BoolOption enable_file_transfer = 9; BoolOption enable_file_transfer = 9;
VideoCodecState video_codec_state = 10; VideoCodecState video_codec_state = 10;
int32 custom_fps = 11; int32 custom_fps = 11;
BoolOption disable_keyboard = 12;
} }
message TestDelay { message TestDelay {

View File

@ -1061,6 +1061,10 @@ impl PeerConfig {
if !mp.contains_key(key) { if !mp.contains_key(key) {
mp.insert(key.to_owned(), UserDefaultConfig::read().get(key)); mp.insert(key.to_owned(), UserDefaultConfig::read().get(key));
} }
key = "view-only";
if !mp.contains_key(key) {
mp.insert(key.to_owned(), UserDefaultConfig::read().get(key));
}
Ok(mp) Ok(mp)
} }
} }

View File

@ -1296,7 +1296,12 @@ impl LoginConfigHandler {
if let Some(custom_fps) = self.options.get("custom-fps") { if let Some(custom_fps) = self.options.get("custom-fps") {
msg.custom_fps = custom_fps.parse().unwrap_or(30); msg.custom_fps = custom_fps.parse().unwrap_or(30);
} }
if self.get_toggle_option("show-remote-cursor") { let view_only = self.get_toggle_option("view-only");
if view_only {
msg.disable_keyboard = BoolOption::Yes.into();
n += 1;
}
if view_only || self.get_toggle_option("show-remote-cursor") {
msg.show_remote_cursor = BoolOption::Yes.into(); msg.show_remote_cursor = BoolOption::Yes.into();
n += 1; n += 1;
} }
@ -1312,7 +1317,7 @@ impl LoginConfigHandler {
msg.enable_file_transfer = BoolOption::Yes.into(); msg.enable_file_transfer = BoolOption::Yes.into();
n += 1; n += 1;
} }
if self.get_toggle_option("disable-clipboard") { if view_only || self.get_toggle_option("disable-clipboard") {
msg.disable_clipboard = BoolOption::Yes.into(); msg.disable_clipboard = BoolOption::Yes.into();
n += 1; n += 1;
} }

View File

@ -543,6 +543,12 @@ pub fn session_set_size(_id: String, _width: i32, _height: i32) {
} }
} }
pub fn session_set_view_only(id: String, view_only: bool) {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
session.set_view_only(view_only);
}
}
pub fn main_get_sound_inputs() -> Vec<String> { pub fn main_get_sound_inputs() -> Vec<String> {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
return get_sound_inputs(); return get_sound_inputs();

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", "此文件与对方的一致"), ("identical_file_tip", "此文件与对方的一致"),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", "浏览模式"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", "Mig"), ("Me", "Mig"),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", "Ich"), ("Me", "Ich"),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", "Yo"), ("Me", "Yo"),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", "من"), ("Me", "من"),
("identical_file_tip", "این فایل با فایل همتا یکسان است."), ("identical_file_tip", "این فایل با فایل همتا یکسان است."),
("show_monitors_tip", "نمایش مانیتورها در نوار ابزار"), ("show_monitors_tip", "نمایش مانیتورها در نوار ابزار"),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", "Io"), ("Me", "Io"),
("identical_file_tip", "Questo file è identico a quello del peer."), ("identical_file_tip", "Questo file è identico a quello del peer."),
("show_monitors_tip", "Mostra schermi nella barra degli strumenti"), ("show_monitors_tip", "Mostra schermi nella barra degli strumenti"),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", "瀏覽模式"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -479,5 +479,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Me", ""), ("Me", ""),
("identical_file_tip", ""), ("identical_file_tip", ""),
("show_monitors_tip", ""), ("show_monitors_tip", ""),
("View Mode", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }

View File

@ -103,6 +103,9 @@ pub struct Connection {
show_remote_cursor: bool, show_remote_cursor: bool,
// by peer // by peer
ip: String, ip: String,
// by peer
disable_keyboard: bool,
// by peer
disable_clipboard: bool, disable_clipboard: bool,
// by peer // by peer
disable_audio: bool, disable_audio: bool,
@ -219,6 +222,7 @@ impl Connection {
disable_audio: false, disable_audio: false,
enable_file_transfer: false, enable_file_transfer: false,
disable_clipboard: false, disable_clipboard: false,
disable_keyboard: false,
tx_input, tx_input,
video_ack_required: false, video_ack_required: false,
peer_info: Default::default(), peer_info: Default::default(),
@ -327,7 +331,7 @@ impl Connection {
if let Some(s) = conn.server.upgrade() { if let Some(s) = conn.server.upgrade() {
s.write().unwrap().subscribe( s.write().unwrap().subscribe(
super::clipboard_service::NAME, super::clipboard_service::NAME,
conn.inner.clone(), conn.clipboard_enabled() && conn.keyboard); conn.inner.clone(), conn.clipboard_enabled() && conn.peer_keyboard_enabled());
} }
} else if &name == "audio" { } else if &name == "audio" {
conn.audio = enabled; conn.audio = enabled;
@ -939,13 +943,13 @@ impl Connection {
} else if sub_service { } else if sub_service {
if let Some(s) = self.server.upgrade() { if let Some(s) = self.server.upgrade() {
let mut noperms = Vec::new(); let mut noperms = Vec::new();
if !self.keyboard && !self.show_remote_cursor { if !self.peer_keyboard_enabled() && !self.show_remote_cursor {
noperms.push(NAME_CURSOR); noperms.push(NAME_CURSOR);
} }
if !self.show_remote_cursor { if !self.show_remote_cursor {
noperms.push(NAME_POS); noperms.push(NAME_POS);
} }
if !self.clipboard_enabled() || !self.keyboard { if !self.clipboard_enabled() || !self.peer_keyboard_enabled() {
noperms.push(super::clipboard_service::NAME); noperms.push(super::clipboard_service::NAME);
} }
if !self.audio_enabled() { if !self.audio_enabled() {
@ -959,6 +963,10 @@ impl Connection {
} }
} }
fn peer_keyboard_enabled(&self) -> bool {
self.keyboard && !self.disable_keyboard
}
fn clipboard_enabled(&self) -> bool { fn clipboard_enabled(&self) -> bool {
self.clipboard && !self.disable_clipboard self.clipboard && !self.disable_clipboard
} }
@ -1312,7 +1320,7 @@ impl Connection {
log::debug!("call_main_service_mouse_input fail:{}", e); log::debug!("call_main_service_mouse_input fail:{}", e);
} }
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
if self.keyboard { if self.peer_keyboard_enabled() {
if is_left_up(&me) { if is_left_up(&me) {
CLICK_TIME.store(get_time(), Ordering::SeqCst); CLICK_TIME.store(get_time(), Ordering::SeqCst);
} else { } else {
@ -1323,7 +1331,7 @@ impl Connection {
} }
Some(message::Union::KeyEvent(me)) => { Some(message::Union::KeyEvent(me)) => {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
if self.keyboard { if self.peer_keyboard_enabled() {
if is_enter(&me) { if is_enter(&me) {
CLICK_TIME.store(get_time(), Ordering::SeqCst); CLICK_TIME.store(get_time(), Ordering::SeqCst);
} }
@ -1750,7 +1758,7 @@ impl Connection {
s.write().unwrap().subscribe( s.write().unwrap().subscribe(
NAME_CURSOR, NAME_CURSOR,
self.inner.clone(), self.inner.clone(),
self.keyboard || self.show_remote_cursor, self.peer_keyboard_enabled() || self.show_remote_cursor,
); );
s.write().unwrap().subscribe( s.write().unwrap().subscribe(
NAME_POS, NAME_POS,
@ -1788,7 +1796,24 @@ impl Connection {
s.write().unwrap().subscribe( s.write().unwrap().subscribe(
super::clipboard_service::NAME, super::clipboard_service::NAME,
self.inner.clone(), self.inner.clone(),
self.clipboard_enabled() && self.keyboard, self.clipboard_enabled() && self.peer_keyboard_enabled(),
);
}
}
}
if let Ok(q) = o.disable_keyboard.enum_value() {
if q != BoolOption::NotSet {
self.disable_keyboard = q == BoolOption::Yes;
if let Some(s) = self.server.upgrade() {
s.write().unwrap().subscribe(
super::clipboard_service::NAME,
self.inner.clone(),
self.clipboard_enabled() && self.peer_keyboard_enabled(),
);
s.write().unwrap().subscribe(
NAME_CURSOR,
self.inner.clone(),
self.peer_keyboard_enabled() || self.show_remote_cursor,
); );
} }
} }

View File

@ -10,6 +10,7 @@ use std::time::{Duration, SystemTime};
use async_trait::async_trait; use async_trait::async_trait;
use bytes::Bytes; use bytes::Bytes;
use hbb_common::message_proto::option_message::BoolOption;
use rdev::{Event, EventType::*}; use rdev::{Event, EventType::*};
use uuid::Uuid; use uuid::Uuid;
@ -374,7 +375,6 @@ impl<T: InvokeUiSession> Session<T> {
} }
pub fn swab_modifier_key(&self, msg: &mut KeyEvent) { pub fn swab_modifier_key(&self, msg: &mut KeyEvent) {
let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string()); let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string());
if allow_swap_key { if allow_swap_key {
if let Some(key_event::Union::ControlKey(ck)) = msg.union { if let Some(key_event::Union::ControlKey(ck)) = msg.union {
@ -388,19 +388,22 @@ impl<T: InvokeUiSession> Session<T> {
}; };
msg.set_control_key(ck); msg.set_control_key(ck);
} }
msg.modifiers = msg.modifiers.iter().map(|ck| { msg.modifiers = msg
let ck = ck.enum_value_or_default(); .modifiers
let ck = match ck { .iter()
ControlKey::Control => ControlKey::Meta, .map(|ck| {
ControlKey::Meta => ControlKey::Control, let ck = ck.enum_value_or_default();
ControlKey::RControl => ControlKey::Meta, let ck = match ck {
ControlKey::RWin => ControlKey::Control, ControlKey::Control => ControlKey::Meta,
_ => ck, ControlKey::Meta => ControlKey::Control,
}; ControlKey::RControl => ControlKey::Meta,
hbb_common::protobuf::EnumOrUnknown::new(ck) ControlKey::RWin => ControlKey::Control,
}).collect(); _ => ck,
};
hbb_common::protobuf::EnumOrUnknown::new(ck)
})
.collect();
let code = msg.chr(); let code = msg.chr();
if code != 0 { if code != 0 {
let mut peer = self.peer_platform().to_lowercase(); let mut peer = self.peer_platform().to_lowercase();
@ -444,7 +447,6 @@ impl<T: InvokeUiSession> Session<T> {
msg.set_chr(key); msg.set_chr(key);
} }
} }
} }
pub fn send_key_event(&self, evt: &KeyEvent) { pub fn send_key_event(&self, evt: &KeyEvent) {
@ -841,6 +843,37 @@ impl<T: InvokeUiSession> Session<T> {
} }
false false
} }
pub fn set_view_only(&self, view_only: bool) {
let mut option = OptionMessage::default();
let f = |b: bool| {
if b {
BoolOption::Yes.into()
} else {
BoolOption::No.into()
}
};
if view_only {
option.disable_keyboard = f(true);
option.disable_clipboard = f(true);
option.show_remote_cursor = f(true);
} else {
option.disable_keyboard = f(false);
option.disable_clipboard = f(self.get_toggle_option("disable-clipboard".to_string()));
option.show_remote_cursor = f(self.get_toggle_option("show-remote-cursor".to_string()));
}
let mut misc = Misc::new();
misc.set_option(option);
let mut msg = Message::new();
msg.set_misc(misc);
self.send(Data::Message(msg));
if self.get_toggle_option("view-only".to_string()) != view_only {
self.lc
.write()
.unwrap()
.toggle_option("view-only".to_string());
}
}
} }
pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default { pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {
@ -1011,21 +1044,25 @@ impl<T: InvokeUiSession> Interface for Session<T> {
handle_test_delay(t, peer).await; handle_test_delay(t, peer).await;
} }
} }
fn swap_modifier_mouse(&self, msg : &mut hbb_common::protos::message::MouseEvent) { fn swap_modifier_mouse(&self, msg: &mut hbb_common::protos::message::MouseEvent) {
let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string()); let allow_swap_key = self.get_toggle_option("allow_swap_key".to_string());
if allow_swap_key { if allow_swap_key {
msg.modifiers = msg.modifiers.iter().map(|ck| { msg.modifiers = msg
let ck = ck.enum_value_or_default(); .modifiers
let ck = match ck { .iter()
ControlKey::Control => ControlKey::Meta, .map(|ck| {
ControlKey::Meta => ControlKey::Control, let ck = ck.enum_value_or_default();
ControlKey::RControl => ControlKey::Meta, let ck = match ck {
ControlKey::RWin => ControlKey::Control, ControlKey::Control => ControlKey::Meta,
_ => ck, ControlKey::Meta => ControlKey::Control,
}; ControlKey::RControl => ControlKey::Meta,
hbb_common::protobuf::EnumOrUnknown::new(ck) ControlKey::RWin => ControlKey::Control,
}).collect(); _ => ck,
};
hbb_common::protobuf::EnumOrUnknown::new(ck)
})
.collect();
}; };
} }
} }