From 921b049e1e6468dd469d8f7e1d46ca69fd253ad1 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 6 Jan 2023 18:14:31 +0800 Subject: [PATCH 1/2] ignore dpi while scale original Signed-off-by: fufesou --- flutter/lib/consts.dart | 2 + flutter/lib/desktop/pages/remote_page.dart | 69 ++++++++----------- .../lib/desktop/widgets/remote_menubar.dart | 22 +++--- flutter/lib/models/model.dart | 34 +++++---- 4 files changed, 61 insertions(+), 66 deletions(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 50e7f594b..7aa200ae9 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -100,6 +100,8 @@ const kRemoteImageQualityLow = 'low'; /// [kRemoteImageQualityCustom] Custom image quality. const kRemoteImageQualityCustom = 'custom'; +const kIgnoreDpi = true; + /// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels /// see [LogicalKeyboardKey.keyLabel] const Map logicalKeyMap = { diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 102dc784a..21728ee38 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -402,35 +402,38 @@ class _ImagePaintState extends State { onHover: (evt) {}, child: child)); - if (c.scrollStyle == ScrollStyle.scrollbar) { - final imageWidth = c.getDisplayWidth() * s; - final imageHeight = c.getDisplayHeight() * s; + final imageWidth = c.getDisplayWidth() * s; + final imageHeight = c.getDisplayHeight() * s; + final imageSize = Size(imageWidth, imageHeight); + bool overflow = + c.size.width < imageSize.width || c.size.height < imageSize.height; + if (overflow && c.scrollStyle == ScrollStyle.scrollbar) { final imageWidget = CustomPaint( - size: Size(imageWidth, imageHeight), + size: imageSize, painter: ImagePainter(image: m.image, x: 0, y: 0, scale: s), ); return NotificationListener( - onNotification: (notification) { - final percentX = _horizontal.hasClients - ? _horizontal.position.extentBefore / - (_horizontal.position.extentBefore + - _horizontal.position.extentInside + - _horizontal.position.extentAfter) - : 0.0; - final percentY = _vertical.hasClients - ? _vertical.position.extentBefore / - (_vertical.position.extentBefore + - _vertical.position.extentInside + - _vertical.position.extentAfter) - : 0.0; - c.setScrollPercent(percentX, percentY); - return false; - }, - child: mouseRegion( - child: _buildCrossScrollbar(context, _buildListener(imageWidget), - Size(imageWidth, imageHeight))), - ); + onNotification: (notification) { + final percentX = _horizontal.hasClients + ? _horizontal.position.extentBefore / + (_horizontal.position.extentBefore + + _horizontal.position.extentInside + + _horizontal.position.extentAfter) + : 0.0; + final percentY = _vertical.hasClients + ? _vertical.position.extentBefore / + (_vertical.position.extentBefore + + _vertical.position.extentInside + + _vertical.position.extentAfter) + : 0.0; + c.setScrollPercent(percentX, percentY); + return false; + }, + child: mouseRegion( + child: Obx(() => _buildCrossScrollbarFromLayout( + context, _buildListener(imageWidget), c.size, imageSize)), + )); } else { final imageWidget = CustomPaint( size: Size(c.size.width, c.size.height), @@ -565,24 +568,6 @@ class _ImagePaintState extends State { return widget; } - Widget _buildCrossScrollbar(BuildContext context, Widget child, Size size) { - var layoutSize = MediaQuery.of(context).size; - // If minimized, w or h may be negative here. - final w = layoutSize.width - kWindowBorderWidth * 2; - final h = - layoutSize.height - kWindowBorderWidth * 2 - kDesktopRemoteTabBarHeight; - layoutSize = Size( - w < 0 ? 0 : w, - h < 0 ? 0 : h, - ); - bool overflow = - layoutSize.width < size.width || layoutSize.height < size.height; - return overflow - ? Obx(() => - _buildCrossScrollbarFromLayout(context, child, layoutSize, size)) - : _buildCrossScrollbarFromLayout(context, child, layoutSize, size); - } - Widget _buildListener(Widget child) { if (listenerBuilder != null) { return listenerBuilder!(child); diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 1aa2647ee..2a7a26d08 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -699,7 +699,7 @@ class _RemoteMenubarState extends State { if (_screen == null) { return false; } - double scale = _screen!.scaleFactor; + final scale = kIgnoreDpi ? 1.0 : _screen!.scaleFactor; double selfWidth = _screen!.visibleFrame.width; double selfHeight = _screen!.visibleFrame.height; if (isFullscreen) { @@ -986,15 +986,17 @@ class _RemoteMenubarState extends State { wndRect.bottom - wndRect.top - mediaSize.height * scale; final canvasModel = widget.ffi.canvasModel; - final width = (canvasModel.getDisplayWidth() + - canvasModel.windowBorderWidth * 2) * - scale + - magicWidth; - final height = (canvasModel.getDisplayHeight() + - canvasModel.tabBarHeight + - canvasModel.windowBorderWidth * 2) * - scale + - magicHeight; + final width = + (canvasModel.getDisplayWidth() * canvasModel.scale + + canvasModel.windowBorderWidth * 2) * + scale + + magicWidth; + final height = + (canvasModel.getDisplayHeight() * canvasModel.scale + + canvasModel.tabBarHeight + + canvasModel.windowBorderWidth * 2) * + scale + + magicHeight; double left = wndRect.left + (wndRect.width - width) / 2; double top = wndRect.top + (wndRect.height - height) / 2; diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 0f7099bc8..39e78cd6b 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -528,6 +528,7 @@ class CanvasModel with ChangeNotifier { double _y = 0; // image scale double _scale = 1.0; + Size _size = Size.zero; // the tabbar over the image // double tabBarHeight = 0.0; // the window border's width @@ -548,6 +549,7 @@ class CanvasModel with ChangeNotifier { double get x => _x; double get y => _y; double get scale => _scale; + Size get size => _size; ScrollStyle get scrollStyle => _scrollStyle; ViewStyle get viewStyle => _lastViewStyle; @@ -562,18 +564,26 @@ class CanvasModel with ChangeNotifier { double get scrollY => _scrollY; updateViewStyle() async { + 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; + return Size(w < 0 ? 0 : w, h < 0 ? 0 : h); + } + final style = await bind.sessionGetViewStyle(id: id); if (style == null) { return; } - final sizeWidth = size.width; - final sizeHeight = size.height; + + _size = getSize(); final displayWidth = getDisplayWidth(); final displayHeight = getDisplayHeight(); final viewStyle = ViewStyle( style: style, - width: sizeWidth, - height: sizeHeight, + width: size.width, + height: size.height, displayWidth: displayWidth, displayHeight: displayHeight, ); @@ -585,8 +595,12 @@ class CanvasModel with ChangeNotifier { } _lastViewStyle = viewStyle; _scale = viewStyle.scale; - _x = (sizeWidth - displayWidth * _scale) / 2; - _y = (sizeHeight - displayHeight * _scale) / 2; + + if (kIgnoreDpi && style == kRemoteViewStyleOriginal) { + _scale = 1.0 / ui.window.devicePixelRatio; + } + _x = (size.width - displayWidth * _scale) / 2; + _y = (size.height - displayHeight * _scale) / 2; notifyListeners(); } @@ -628,14 +642,6 @@ class CanvasModel with ChangeNotifier { double get windowBorderWidth => stateGlobal.windowBorderWidth.value; double get tabBarHeight => stateGlobal.tabBarHeight; - Size get size { - 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; - return Size(w < 0 ? 0 : w, h < 0 ? 0 : h); - } - moveDesktopMouse(double x, double y) { // On mobile platforms, move the canvas with the cursor. final dw = getDisplayWidth() * _scale; From 947b7c9a4d4c2c4ad433b2404ec0b26c61e14120 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 6 Jan 2023 20:25:18 +0800 Subject: [PATCH 2/2] disable scroll options when image is wrapped by window Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 10 +- flutter/lib/desktop/widgets/popup_menu.dart | 138 ++++++++++-------- .../lib/desktop/widgets/remote_menubar.dart | 3 +- flutter/lib/models/model.dart | 5 + 4 files changed, 90 insertions(+), 66 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 21728ee38..55a5bbaef 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -402,12 +402,10 @@ class _ImagePaintState extends State { onHover: (evt) {}, child: child)); - final imageWidth = c.getDisplayWidth() * s; - final imageHeight = c.getDisplayHeight() * s; - final imageSize = Size(imageWidth, imageHeight); - bool overflow = - c.size.width < imageSize.width || c.size.height < imageSize.height; - if (overflow && c.scrollStyle == ScrollStyle.scrollbar) { + if (c.imageOverflow.isTrue && c.scrollStyle == ScrollStyle.scrollbar) { + final imageWidth = c.getDisplayWidth() * s; + final imageHeight = c.getDisplayHeight() * s; + final imageSize = Size(imageWidth, imageHeight); final imageWidget = CustomPaint( size: imageSize, painter: ImagePainter(image: m.image, x: 0, y: 0, scale: s), diff --git a/flutter/lib/desktop/widgets/popup_menu.dart b/flutter/lib/desktop/widgets/popup_menu.dart index 20ab31ed9..0cbdad929 100644 --- a/flutter/lib/desktop/widgets/popup_menu.dart +++ b/flutter/lib/desktop/widgets/popup_menu.dart @@ -118,6 +118,15 @@ abstract class MenuEntryBase { this.enabled, }); List> build(BuildContext context, MenuConfig conf); + + enabledStyle(BuildContext context) => TextStyle( + color: Theme.of(context).textTheme.titleLarge?.color, + fontSize: MenuConfig.fontSize, + fontWeight: FontWeight.normal); + disabledStyle() => TextStyle( + color: Colors.grey, + fontSize: MenuConfig.fontSize, + fontWeight: FontWeight.normal); } class MenuEntryDivider extends MenuEntryBase { @@ -189,54 +198,76 @@ class MenuEntryRadios extends MenuEntryBase { mod_menu.PopupMenuEntry _buildMenuItem( BuildContext context, MenuConfig conf, MenuEntryRadioOption opt) { + Widget getTextChild() { + final enabledTextChild = Text( + opt.text, + style: enabledStyle(context), + ); + final disabledTextChild = Text( + opt.text, + style: disabledStyle(), + ); + if (opt.enabled == null) { + return enabledTextChild; + } else { + return Obx( + () => opt.enabled!.isTrue ? enabledTextChild : disabledTextChild); + } + } + + final child = Container( + padding: padding, + alignment: AlignmentDirectional.centerStart, + constraints: + BoxConstraints(minHeight: conf.height, maxHeight: conf.height), + child: Row( + children: [ + getTextChild(), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Transform.scale( + scale: MenuConfig.iconScale, + child: Obx(() => opt.value == curOption.value + ? IconButton( + padding: + const EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0), + hoverColor: Colors.transparent, + focusColor: Colors.transparent, + onPressed: () {}, + icon: Icon( + Icons.check, + color: (opt.enabled ?? true.obs).isTrue + ? conf.commonColor + : Colors.grey, + )) + : const SizedBox.shrink()), + ))), + ], + ), + ); + onPressed() { + if (opt.dismissOnClicked && Navigator.canPop(context)) { + Navigator.pop(context); + } + setOption(opt.value); + } + return mod_menu.PopupMenuItem( padding: EdgeInsets.zero, height: conf.height, child: Container( - width: conf.boxWidth, - child: TextButton( - child: Container( - padding: padding, - alignment: AlignmentDirectional.centerStart, - constraints: BoxConstraints( - minHeight: conf.height, maxHeight: conf.height), - child: Row( - children: [ - Text( - opt.text, - style: TextStyle( - color: Theme.of(context).textTheme.titleLarge?.color, - fontSize: MenuConfig.fontSize, - fontWeight: FontWeight.normal), - ), - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: Transform.scale( - scale: MenuConfig.iconScale, - child: Obx(() => opt.value == curOption.value - ? IconButton( - padding: const EdgeInsets.fromLTRB( - 8.0, 0.0, 8.0, 0.0), - hoverColor: Colors.transparent, - focusColor: Colors.transparent, - onPressed: () {}, - icon: Icon( - Icons.check, - color: conf.commonColor, - )) - : const SizedBox.shrink()), - ))), - ], - ), - ), - onPressed: () { - if (opt.dismissOnClicked && Navigator.canPop(context)) { - Navigator.pop(context); - } - setOption(opt.value); - }, - )), + width: conf.boxWidth, + child: opt.enabled == null + ? TextButton( + child: child, + onPressed: onPressed, + ) + : Obx(() => TextButton( + child: child, + onPressed: opt.enabled!.isTrue ? onPressed : null, + )), + ), ); } @@ -567,12 +598,9 @@ class MenuEntrySubMenu extends MenuEntryBase { const SizedBox(width: MenuConfig.midPadding), Obx(() => Text( text, - style: TextStyle( - color: super.enabled!.value - ? Theme.of(context).textTheme.titleLarge?.color - : Colors.grey, - fontSize: MenuConfig.fontSize, - fontWeight: FontWeight.normal), + style: super.enabled!.value + ? enabledStyle(context) + : disabledStyle(), )), Expanded( child: Align( @@ -605,14 +633,6 @@ class MenuEntryButton extends MenuEntryBase { ); Widget _buildChild(BuildContext context, MenuConfig conf) { - final enabledStyle = TextStyle( - color: Theme.of(context).textTheme.titleLarge?.color, - fontSize: MenuConfig.fontSize, - fontWeight: FontWeight.normal); - const disabledStyle = TextStyle( - color: Colors.grey, - fontSize: MenuConfig.fontSize, - fontWeight: FontWeight.normal); super.enabled ??= true.obs; return Obx(() => Container( width: conf.boxWidth, @@ -631,7 +651,7 @@ class MenuEntryButton extends MenuEntryBase { constraints: BoxConstraints(minHeight: conf.height, maxHeight: conf.height), child: childBuilder( - super.enabled!.value ? enabledStyle : disabledStyle), + super.enabled!.value ? enabledStyle(context) : disabledStyle()), ), ))); } diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart index 2a7a26d08..b69c73091 100644 --- a/flutter/lib/desktop/widgets/remote_menubar.dart +++ b/flutter/lib/desktop/widgets/remote_menubar.dart @@ -936,11 +936,13 @@ class _RemoteMenubarState extends State { text: translate('ScrollAuto'), value: kRemoteScrollStyleAuto, dismissOnClicked: true, + enabled: widget.ffi.canvasModel.imageOverflow, ), MenuEntryRadioOption( text: translate('Scrollbar'), value: kRemoteScrollStyleBar, dismissOnClicked: true, + enabled: widget.ffi.canvasModel.imageOverflow, ), ], curOptionGetter: () async => @@ -1200,7 +1202,6 @@ class _RemoteMenubarState extends State { }, optionSetter: (String oldValue, String newValue) async { await bind.sessionSetKeyboardMode(id: widget.id, value: newValue); - widget.ffi.canvasModel.updateViewStyle(); }, ) ]; diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 39e78cd6b..1cdecbd03 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -22,6 +22,7 @@ import 'package:tuple/tuple.dart'; import 'package:image/image.dart' as img2; import 'package:flutter_custom_cursor/cursor_manager.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; import '../common.dart'; import '../common/shared_state.dart'; @@ -542,6 +543,8 @@ class CanvasModel with ChangeNotifier { ScrollStyle _scrollStyle = ScrollStyle.scrollauto; ViewStyle _lastViewStyle = ViewStyle(); + final _imageOverflow = false.obs; + WeakReference parent; CanvasModel(this.parent); @@ -552,6 +555,7 @@ class CanvasModel with ChangeNotifier { Size get size => _size; ScrollStyle get scrollStyle => _scrollStyle; ViewStyle get viewStyle => _lastViewStyle; + RxBool get imageOverflow => _imageOverflow; _resetScroll() => setScrollPercent(0.0, 0.0); @@ -601,6 +605,7 @@ class CanvasModel with ChangeNotifier { } _x = (size.width - displayWidth * _scale) / 2; _y = (size.height - displayHeight * _scale) / 2; + _imageOverflow.value = _x < 0 || y < 0; notifyListeners(); }