diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index f7bb85a37..53774e36d 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -259,7 +259,9 @@ class _ConnectionTabPageState extends State { ), ]); - if (!ffi.canvasModel.cursorEmbedded && !ffi.ffiModel.viewOnly) { + if (!ffi.canvasModel.cursorEmbedded && + !ffi.ffiModel.viewOnly && + !pi.is_wayland) { menu.add(MenuEntryDivider()); menu.add(RemoteMenuEntry.showRemoteCursor( key, diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index 30dc09a6e..ec039b67c 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -1464,7 +1464,8 @@ class _DisplayMenuState extends State<_DisplayMenu> { return Offstage(); } final ffiModel = widget.ffi.ffiModel; - final visible = !widget.ffi.canvasModel.cursorEmbedded; + final visible = + !widget.ffi.canvasModel.cursorEmbedded && !ffiModel.pi.is_wayland; if (!visible) return Offstage(); final enabled = !ffiModel.viewOnly; final state = ShowRemoteCursorState.find(widget.id); @@ -1684,6 +1685,9 @@ class _KeyboardMenu extends StatelessWidget { for (KeyboardModeMenu mode in modes) { if (bind.sessionIsKeyboardModeSupported(id: id, mode: mode.key)) { + if (pi.is_wayland && mode.key != _kKeyMapMode) { + continue; + } if (mode.key == _kKeyTranslateMode) { if (Platform.isLinux) { continue; diff --git a/flutter/lib/mobile/pages/remote_page.dart b/flutter/lib/mobile/pages/remote_page.dart index 951d63faf..4d94dc669 100644 --- a/flutter/lib/mobile/pages/remote_page.dart +++ b/flutter/lib/mobile/pages/remote_page.dart @@ -1059,7 +1059,7 @@ void showOptions( final toggles = [ getToggle(id, setState, 'show-quality-monitor', 'Show quality monitor'), ]; - if (!gFFI.canvasModel.cursorEmbedded) { + if (!gFFI.canvasModel.cursorEmbedded && !pi.is_wayland) { toggles.insert(0, getToggle(id, setState, 'show-remote-cursor', 'Show remote cursor')); } diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 1cc059ce0..b8d4f2ebc 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -452,6 +452,16 @@ class FfiModel with ChangeNotifier { setViewOnly(peerId, bind.sessionGetToggleOptionSync(id: peerId, arg: 'view-only')); } + if (connType == ConnType.defaultConn) { + final platform_additions = evt['platform_additions']; + if (platform_additions != null && platform_additions != '') { + try { + _pi.platform_additions = json.decode(platform_additions); + } catch (e) { + debugPrint('Failed to decode platform_additions $e'); + } + } + } notifyListeners(); } @@ -1687,6 +1697,9 @@ class PeerInfo { List displays = []; Features features = Features(); List resolutions = []; + Map platform_additions = {}; + + bool get is_wayland => platform_additions['is_wayland'] == true; } const canvasKey = 'canvas'; diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index ed704f91e..bb4492b74 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -91,6 +91,8 @@ message PeerInfo { Features features = 9; SupportedEncoding encoding = 10; SupportedResolutions resolutions = 11; + // Use JSON's key-value format which is friendly for peer to handle. + string platform_additions = 12; } message LoginResponse { diff --git a/src/flutter.rs b/src/flutter.rs index 089daff5c..fde9ce7cd 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -509,6 +509,7 @@ impl InvokeUiSession for FlutterHandler { ("features", &features), ("current_display", &pi.current_display.to_string()), ("resolutions", &resolutions), + ("platform_additions", &pi.platform_additions), ], ); } diff --git a/src/server/connection.rs b/src/server/connection.rs index 5e6fbe50e..07c37b12c 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -843,6 +843,16 @@ impl Connection { pi.hostname = DEVICE_NAME.lock().unwrap().clone(); pi.platform = "Android".into(); } + + #[cfg(target_os = "linux")] + { + pi.platform_additions = format!(r#" + {{ + "is_wayland": {} + }} + "#, crate::platform::current_is_wayland()); + } + #[cfg(feature = "hwcodec")] { let (h264, h265) = scrap::codec::Encoder::supported_encoding();