From 5f10d1aae6d4a2964111f30739ef7876311744b7 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 19 May 2023 02:34:39 -0700 Subject: [PATCH] support custom resolution ui Signed-off-by: fufesou --- .../lib/desktop/widgets/remote_toolbar.dart | 105 ++++++++++++++---- 1 file changed, 86 insertions(+), 19 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index bba146fa8..9f05b3f73 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -995,10 +995,19 @@ class _ResolutionsMenu extends StatefulWidget { State<_ResolutionsMenu> createState() => _ResolutionsMenuState(); } +const double _kCustonResolutionEditingWidth = 42; +const _kCustomResolutionValue = 'custom'; +String? _lastResolutionGroupValue; + class _ResolutionsMenuState extends State<_ResolutionsMenu> { String _groupValue = ''; Resolution? _localResolution; + late final TextEditingController _customWidth = + TextEditingController(text: display.width.toString()); + late final TextEditingController _customHeight = + TextEditingController(text: display.height.toString()); + PeerInfo get pi => widget.ffi.ffiModel.pi; FfiModel get ffiModel => widget.ffi.ffiModel; Display get display => ffiModel.display; @@ -1012,22 +1021,20 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> { @override Widget build(BuildContext context) { final isVirtualDisplay = display.isVirtualDisplayResolution; - // final visible = - // ffiModel.keyboard && (isVirtualDisplay || resolutions.length > 1); - final visible = ffiModel.keyboard && resolutions.length > 1; + final visible = + ffiModel.keyboard && (isVirtualDisplay || resolutions.length > 1); if (!visible) return Offstage(); - _groupValue = '${display.width}x${display.height}'; _getLocalResolution(); final showOriginalBtn = display.isOriginalResolutionSet && !display.isOriginalResolution; final showFitLocalBtn = !_isRemoteResolutionFitLocal(); - + _setGroupValue(); return _SubmenuButton( ffi: widget.ffi, menuChildren: [ _OriginalResolutionMenuButton(showOriginalBtn), _FitLocalResolutionMenuButton(showFitLocalBtn), - // _customResolutionMenuButton(isVirtualDisplay), + _customResolutionMenuButton(isVirtualDisplay), _menuDivider(showOriginalBtn, showFitLocalBtn, isVirtualDisplay), ] + _supportedResolutionMenuButtons(), @@ -1035,6 +1042,14 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> { ); } + _setGroupValue() { + if (_lastResolutionGroupValue == _kCustomResolutionValue) { + _groupValue = _kCustomResolutionValue; + } else { + _groupValue = '${display.width}x${display.height}'; + } + } + _menuDivider( bool showOriginalBtn, bool showFitLocalBtn, bool isVirtualDisplay) { return Offstage( @@ -1060,12 +1075,24 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> { } _onChanged(String? value) async { + _lastResolutionGroupValue = value; if (value == null) return; - final list = value.split('x'); - if (list.length == 2) { - final w = int.tryParse(list[0]); - final h = int.tryParse(list[1]); - if (w != null && h != null) { + + int? w; + int? h; + if (value == _kCustomResolutionValue) { + w = int.tryParse(_customWidth.text); + h = int.tryParse(_customHeight.text); + } else { + final list = value.split('x'); + if (list.length == 2) { + w = int.tryParse(list[0]); + h = int.tryParse(list[1]); + } + } + + if (w != null && h != null) { + if (w != display.width && h != display.height) { await _changeResolution(w, h); } } @@ -1117,6 +1144,46 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> { ); } + Widget _customResolutionMenuButton(isVirtualDisplay) { + return RdoMenuButton( + value: _kCustomResolutionValue, + groupValue: _groupValue, + onChanged: _onChanged, + ffi: widget.ffi, + child: Row( + children: [ + Text('${translate('resolution_custom_tip')} '), + SizedBox( + width: _kCustonResolutionEditingWidth, + child: _resolutionInput(_customWidth), + ), + Text(' x '), + SizedBox( + width: _kCustonResolutionEditingWidth, + child: _resolutionInput(_customHeight), + ), + ], + ), + ); + } + + TextField _resolutionInput(TextEditingController controller) { + return TextField( + decoration: InputDecoration( + border: InputBorder.none, + isDense: true, + contentPadding: EdgeInsets.fromLTRB(3, 3, 3, 3), + ), + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(4), + FilteringTextInputFormatter.allow(RegExp(r'[0-9]')), + ], + controller: controller, + ); + } + List _supportedResolutionMenuButtons() => resolutions .map((e) => RdoMenuButton( value: '${e.width}x${e.height}', @@ -1655,14 +1722,14 @@ class RdoMenuButton extends StatelessWidget { final ValueChanged? onChanged; final Widget? child; final FFI ffi; - const RdoMenuButton( - {Key? key, - required this.value, - required this.groupValue, - required this.onChanged, - required this.child, - required this.ffi}) - : super(key: key); + const RdoMenuButton({ + Key? key, + required this.value, + required this.groupValue, + required this.child, + required this.ffi, + this.onChanged, + }) : super(key: key); @override Widget build(BuildContext context) {