diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index d8b330407..e0da98b16 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -580,6 +580,8 @@ class _MobileActionMenu extends StatelessWidget { } } +const _defaultButtonSize = Size(24.0, 18.0); + class _MonitorMenu extends StatelessWidget { final String id; final FFI ffi; @@ -604,7 +606,7 @@ class _MonitorMenu extends StatelessWidget { Widget buildMonitorMenu() { return _IconSubmenuButton( tooltip: 'Select Monitor', - icon: icon(), + icon: icon(_defaultButtonSize), ffi: ffi, color: _ToolbarTheme.blueColor, hoverColor: _ToolbarTheme.hoverBlueColor, @@ -644,26 +646,29 @@ class _MonitorMenu extends StatelessWidget { child: Text(translate('Show displays as individual windows'))); } + buildOneMonitorButton(i, curDisplay) => Text( + '${i + 1}', + style: TextStyle( + color: i == curDisplay + ? _ToolbarTheme.blueColor + : _ToolbarTheme.inactiveColor, + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ); + List buildMonitorList(bool isMulti) { final List monitorList = []; final pi = ffi.ffiModel.pi; - getMonitorText(int i) { - if (i == kAllDisplayValue) { - if (pi.displays.length == 2) { - return '1|2'; - } else { - return 'ALL'; - } - } else { - return (i + 1).toString(); - } - } - buildMonitorButton(int i) => Obx(() { RxInt display = CurrentDisplayState.find(id); return _IconMenuButton( - tooltip: isMulti ? '' : '#${i + 1} monitor', + tooltip: isMulti + ? '' + : i == kAllDisplayValue + ? 'all monitors' + : '#${i + 1} monitor', hMargin: isMulti ? null : 6, vMargin: isMulti ? null : 12, topLevel: false, @@ -685,18 +690,9 @@ class _MonitorMenu extends StatelessWidget { colorFilter: ColorFilter.mode(Colors.white, BlendMode.srcIn), ), - Obx( - () => Text( - getMonitorText(i), - style: TextStyle( - color: i == display.value - ? _ToolbarTheme.blueColor - : _ToolbarTheme.inactiveColor, - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), - ), + i == kAllDisplayValue + ? globalMonitorsWidget(_defaultButtonSize) + : Obx(() => buildOneMonitorButton(i, display.value)), ], ), ), @@ -713,30 +709,73 @@ class _MonitorMenu extends StatelessWidget { return monitorList; } - icon() { + globalMonitorsWidget(Size size) { final pi = ffi.ffiModel.pi; - return Stack( - alignment: Alignment.center, - children: [ - SvgPicture.asset( - "assets/screen.svg", - colorFilter: ColorFilter.mode(Colors.white, BlendMode.srcIn), - ), - Obx(() { - RxInt display = CurrentDisplayState.find(id); - return Text( - '${display.value == kAllDisplayValue ? 'A' : '${display.value + 1}'}/${pi.displays.length}', - style: const TextStyle( - color: _ToolbarTheme.blueColor, - fontSize: 8, - fontWeight: FontWeight.bold, + return Obx(() { + RxInt display = CurrentDisplayState.find(id); + final rect = ffi.ffiModel.globalDisplaysRect(); + if (rect == null) { + return Offstage(); + } + final scaleX = size.width / rect.width; + final scaleY = size.height / rect.height; + final children = []; + for (var i = 0; i < pi.displays.length; i++) { + final d = pi.displays[i]; + final fontSize = (d.width * scaleX < d.height * scaleY + ? d.width * scaleX + : d.height * scaleY) * + 0.75; + children.add(Positioned( + left: (d.x - rect.left) * scaleX, + top: (d.y - rect.top) * scaleY, + child: SizedBox( + width: d.width * scaleX, + height: d.height * scaleY, + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + borderRadius: BorderRadius.circular(1.0), + ), + child: Center( + child: Text( + '${i + 1}', + style: TextStyle( + color: display.value == i + ? _ToolbarTheme.blueColor + : _ToolbarTheme.inactiveColor, + fontSize: fontSize, + fontWeight: FontWeight.bold, + ), + )), ), - ); - }), - ], - ); + ), + )); + } + return Container( + width: size.width, + height: size.height, + child: Stack( + children: children, + ), + ); + }); } + icon(Size size) => Stack( + alignment: Alignment.center, + children: [ + SvgPicture.asset( + "assets/screen.svg", + colorFilter: ColorFilter.mode(Colors.white, BlendMode.srcIn), + ), + globalMonitorsWidget(size), + ], + ); + onPressed(int i, PeerInfo pi) { _menuDismissCallback(ffi); RxInt display = CurrentDisplayState.find(id); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 0aad54b37..b1a270718 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -138,8 +138,9 @@ class FfiModel with ChangeNotifier { sessionId = parent.target!.sessionId; } - Rect? displaysRect() { - final displays = _pi.getCurDisplays(); + Rect? globalDisplaysRect() => _getDisplaysRect(_pi.displays); + Rect? displaysRect() => _getDisplaysRect(_pi.getCurDisplays()); + Rect? _getDisplaysRect(List displays) { if (displays.isEmpty) { return null; } @@ -666,11 +667,12 @@ class FfiModel with ChangeNotifier { if (connType == ConnType.fileTransfer) { parent.target?.fileModel.onReady(); } else if (connType == ConnType.defaultConn) { - _pi.displays = []; + List newDisplays = []; List displays = json.decode(evt['displays']); for (int i = 0; i < displays.length; ++i) { - _pi.displays.add(evtToDisplay(displays[i])); + newDisplays.add(evtToDisplay(displays[i])); } + _pi.displays.value = newDisplays; _pi.displaysCount.value = _pi.displays.length; if (_pi.currentDisplay < _pi.displays.length) { // now replaced to _updateCurDisplay @@ -860,7 +862,7 @@ class FfiModel with ChangeNotifier { for (int i = 0; i < displays.length; ++i) { newDisplays.add(evtToDisplay(displays[i])); } - _pi.displays = newDisplays; + _pi.displays.value = newDisplays; _pi.displaysCount.value = _pi.displays.length; if (_pi.currentDisplay == kAllDisplayValue) { @@ -908,11 +910,11 @@ class FfiModel with ChangeNotifier { _pi.platformAdditions.remove(kPlatformAdditionsVirtualDisplays); } else { try { - final updateJson = json.decode(updateData); + final updateJson = json.decode(updateData) as Map; for (final key in updateJson.keys) { _pi.platformAdditions[key] = updateJson[key]; } - if (!updateJson.contains(kPlatformAdditionsVirtualDisplays)) { + if (!updateJson.containsKey(kPlatformAdditionsVirtualDisplays)) { _pi.platformAdditions.remove(kPlatformAdditionsVirtualDisplays); } } catch (e) { @@ -2321,7 +2323,7 @@ class PeerInfo with ChangeNotifier { bool isSupportMultiUiSession = false; int currentDisplay = 0; int primaryDisplay = kInvalidDisplayIndex; - List displays = []; + RxList displays = [].obs; Features features = Features(); List resolutions = []; Map platformAdditions = {}; diff --git a/src/virtual_display_manager.rs b/src/virtual_display_manager.rs index 1c53a964f..026be4e99 100644 --- a/src/virtual_display_manager.rs +++ b/src/virtual_display_manager.rs @@ -142,6 +142,8 @@ pub fn reset_all() -> ResultType<()> { let mut manager = VIRTUAL_DISPLAY_MANAGER.lock().unwrap(); if !manager.peer_index_name.is_empty() || manager.headless_index_name.is_some() { manager.install_update_driver()?; + manager.peer_index_name.clear(); + manager.headless_index_name = None; } Ok(()) }