diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 3c1c0af16..6df1ce531 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -13,7 +13,6 @@ import 'package:flutter_hbb/desktop/pages/desktop_home_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart'; import 'package:flutter_hbb/desktop/widgets/remote_toolbar.dart'; import 'package:flutter_hbb/mobile/widgets/dialog.dart'; -import 'package:flutter_hbb/models/model.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/printer_model.dart'; import 'package:flutter_hbb/models/server_model.dart'; @@ -1813,21 +1812,25 @@ class _DisplayState extends State<_Display> { } Widget remoteCanvasMargin(BuildContext context) { - final canvasModel = Provider.of(context, listen: false); onChanged(double value) async { - await canvasModel.setRemoteCanvasMargin(value); + final normalizedValue = value.clamp(0, 400).round(); + await bind.mainSetUserDefaultOption( + key: kOptionRemoteCanvasMargin, value: normalizedValue.toString()); setState(() {}); } - final currentValue = canvasModel.remoteCanvasMargin; + final currentValue = (double.tryParse(bind.mainGetUserDefaultOption( + key: kOptionRemoteCanvasMargin)) ?? + 0) + .clamp(0, 400) + .toDouble(); - return _Card(title: 'Remote canvas margin', children: [ + return _Card(title: 'canvas_margin', children: [ EdgeThicknessControl( value: currentValue, min: 0, max: 400, - onChanged: - isOptionFixed(kOptionRemoteCanvasMargin) ? null : onChanged, + onChanged: onChanged, ), ]); } diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index 8ad6238bc..820b78730 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -1104,32 +1104,24 @@ class _DisplayMenuState extends State<_DisplayMenu> { return futureBuilder(future: () async { final viewStyle = await bind.sessionGetViewStyle(sessionId: ffi.sessionId) ?? ''; - final visible = viewStyle == kRemoteViewStyleOriginal || + final scrollVisible = viewStyle == kRemoteViewStyleOriginal || viewStyle == kRemoteViewStyleCustom; final scrollStyle = await bind.sessionGetScrollStyle(sessionId: ffi.sessionId) ?? ''; final edgeScrollEdgeThickness = await bind .sessionGetEdgeScrollEdgeThickness(sessionId: ffi.sessionId); - final remoteCanvasMargin = - (double.tryParse(bind.mainGetUserDefaultOption( - key: kOptionRemoteCanvasMargin)) ?? - 0) - .clamp(0, 400) - .toDouble(); + await widget.ffi.canvasModel.initializeRemoteCanvasMargin(); return { - 'visible': visible, + 'scrollVisible': scrollVisible, 'scrollStyle': scrollStyle, 'edgeScrollEdgeThickness': edgeScrollEdgeThickness, - 'remoteCanvasMargin': remoteCanvasMargin, + 'remoteCanvasMargin': widget.ffi.canvasModel.remoteCanvasMargin, }; }(), hasData: (data) { - final visible = data['visible'] as bool; - if (!visible) return Offstage(); + final scrollVisible = data['scrollVisible'] as bool; final groupValue = data['scrollStyle'] as String; final edgeScrollEdgeThickness = data['edgeScrollEdgeThickness'] as int; final remoteCanvasMargin = data['remoteCanvasMargin'] as double; - final isRemoteCanvasMarginFixed = - isOptionFixed(kOptionRemoteCanvasMargin); onChangeScrollStyle(String? value) async { if (value == null) return; @@ -1149,73 +1141,73 @@ class _DisplayMenuState extends State<_DisplayMenu> { } onChangeRemoteCanvasMargin(double? value) async { - if (value == null || isRemoteCanvasMarginFixed) return; + if (value == null) return; await widget.ffi.canvasModel.setRemoteCanvasMargin(value); state.setState(() {}); } - return Obx(() => Column(children: [ - RdoMenuButton( - child: Text(translate('ScrollAuto')), - value: kRemoteScrollStyleAuto, - groupValue: groupValue, - onChanged: widget.ffi.canvasModel.imageOverflow.value - ? (value) => onChangeScrollStyle(value) - : null, - closeOnActivate: groupValue != kRemoteScrollStyleEdge, - ffi: widget.ffi, - ), - RdoMenuButton( - child: Text(translate('Scrollbar')), - value: kRemoteScrollStyleBar, - groupValue: groupValue, - onChanged: widget.ffi.canvasModel.imageOverflow.value - ? (value) => onChangeScrollStyle(value) - : null, - closeOnActivate: groupValue != kRemoteScrollStyleEdge, - ffi: widget.ffi, - ), - if (!isWeb) ...[ - RdoMenuButton( - child: Text(translate('ScrollEdge')), - value: kRemoteScrollStyleEdge, + return Column(children: [ + if (scrollVisible) ...[ + Obx(() => RdoMenuButton( + child: Text(translate('ScrollAuto')), + value: kRemoteScrollStyleAuto, groupValue: groupValue, - closeOnActivate: false, onChanged: widget.ffi.canvasModel.imageOverflow.value ? (value) => onChangeScrollStyle(value) : null, + closeOnActivate: groupValue != kRemoteScrollStyleEdge, ffi: widget.ffi, + )), + Obx(() => RdoMenuButton( + child: Text(translate('Scrollbar')), + value: kRemoteScrollStyleBar, + groupValue: groupValue, + onChanged: widget.ffi.canvasModel.imageOverflow.value + ? (value) => onChangeScrollStyle(value) + : null, + closeOnActivate: groupValue != kRemoteScrollStyleEdge, + ffi: widget.ffi, + )), + if (!isWeb) ...[ + Obx(() => RdoMenuButton( + child: Text(translate('ScrollEdge')), + value: kRemoteScrollStyleEdge, + groupValue: groupValue, + closeOnActivate: false, + onChanged: widget.ffi.canvasModel.imageOverflow.value + ? (value) => onChangeScrollStyle(value) + : null, + ffi: widget.ffi, + )), + Offstage( + offstage: groupValue != kRemoteScrollStyleEdge, + child: EdgeThicknessControl( + value: edgeScrollEdgeThickness.toDouble(), + onChanged: onChangeEdgeScrollEdgeThickness, + colorScheme: colorScheme, + )), + ], + ], + Padding( + padding: EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + Expanded(child: Text(translate('canvas_margin'))), + SizedBox( + width: 160, + child: EdgeThicknessControl( + value: remoteCanvasMargin, + min: 0, + max: 400, + onChanged: onChangeRemoteCanvasMargin, + colorScheme: colorScheme, + ), ), - Offstage( - offstage: groupValue != kRemoteScrollStyleEdge, - child: EdgeThicknessControl( - value: edgeScrollEdgeThickness.toDouble(), - onChanged: onChangeEdgeScrollEdgeThickness, - colorScheme: colorScheme, - )), ], - Padding( - padding: EdgeInsets.symmetric(horizontal: 12), - child: Row( - children: [ - Expanded(child: Text(translate('canvas_margin'))), - SizedBox( - width: 160, - child: EdgeThicknessControl( - value: remoteCanvasMargin, - min: 0, - max: 400, - onChanged: isRemoteCanvasMarginFixed - ? null - : onChangeRemoteCanvasMargin, - colorScheme: colorScheme, - ), - ), - ], - ), - ), - Divider(), - ])); + ), + ), + Divider(), + ]); }); } diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 617d7975e..7ff88609c 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -2154,6 +2154,8 @@ class CanvasModel with ChangeNotifier { ScrollStyle _scrollStyle = ScrollStyle.scrollauto; // edge scroll mode: trigger scrolling when the cursor is close to the edge of the view int _edgeScrollEdgeThickness = 100; + double _remoteCanvasMargin = 0; + bool _remoteCanvasMarginInitialized = false; // tracks whether edge scroll should be active, prevents spurious // scrolling when the cursor enters the view from outside EdgeScrollState _edgeScrollState = EdgeScrollState.inactive; @@ -2197,19 +2199,35 @@ class CanvasModel with ChangeNotifier { if (!(isDesktop || isWebDesktop)) { return 0; } - final value = - double.tryParse(bind.mainGetUserDefaultOption(key: kOptionRemoteCanvasMargin)) ?? - 0; - return min(400, max(0, value)); + return _remoteCanvasMargin; } Future setRemoteCanvasMargin(double value) async { final normalizedValue = value.clamp(0, 400).round(); - await bind.mainSetUserDefaultOption( - key: kOptionRemoteCanvasMargin, value: normalizedValue.toString()); + await bind.sessionSetFlutterOption( + sessionId: sessionId, + k: kOptionRemoteCanvasMargin, + v: normalizedValue.toString()); + _remoteCanvasMargin = normalizedValue.toDouble(); + _remoteCanvasMarginInitialized = true; await updateViewStyle(); } + Future initializeRemoteCanvasMargin() async { + if (_remoteCanvasMarginInitialized || !(isDesktop || isWebDesktop)) { + return; + } + final sessionValue = await bind.sessionGetFlutterOption( + sessionId: sessionId, k: kOptionRemoteCanvasMargin); + final defaultValue = + bind.mainGetUserDefaultOption(key: kOptionRemoteCanvasMargin); + final value = + sessionValue?.isNotEmpty == true ? sessionValue : defaultValue; + _remoteCanvasMargin = + (double.tryParse(value ?? '') ?? 0).clamp(0, 400).toDouble(); + _remoteCanvasMarginInitialized = true; + } + Rect? get paddedRect { final rect = realRect; if (rect == null) { @@ -2328,6 +2346,7 @@ class CanvasModel with ChangeNotifier { return; } + await initializeRemoteCanvasMargin(); updateSize(); final displayWidth = getDisplayWidth(); final displayHeight = getDisplayHeight(); @@ -2706,6 +2725,8 @@ class CanvasModel with ChangeNotifier { _y = 0; _scale = 1.0; _lastViewStyle = ViewStyle.defaultViewStyle(); + _remoteCanvasMargin = 0; + _remoteCanvasMarginInitialized = false; _timerMobileFocusCanvasCursor?.cancel(); _timerMobileRestoreCanvasOffset?.cancel(); _offsetBeforeMobileSoftKeyboard = null; @@ -3230,7 +3251,8 @@ class CursorModel with ChangeNotifier { dx = min(dx, maxCursorCanMove); } } else if (dx < 0) { - final maxCanvasCanMove = (displayRect?.left ?? 0) - r.left.roundToDouble(); + final maxCanvasCanMove = + (displayRect?.left ?? 0) - r.left.roundToDouble(); tryMoveCanvasX = _x + dx < cx && maxCanvasCanMove < 0; if (tryMoveCanvasX) { dx = max(dx, maxCanvasCanMove);