From 0d5eb639a0dd656a0fc07467c1c8cc0533859fd4 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 27 Oct 2022 18:40:45 +0800 Subject: [PATCH] flutter_desktop: win scale cursor data Signed-off-by: fufesou --- flutter/lib/consts.dart | 3 ++ flutter/lib/desktop/pages/remote_page.dart | 6 +-- flutter/lib/models/model.dart | 45 +++++++++++++++++++-- flutter/lib/utils/multi_window_manager.dart | 2 +- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index bc5128d34..dc4dc2c94 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -41,6 +41,9 @@ const Duration kTabTransitionDuration = Duration.zero; const double kEmptyMarginTop = 50; const double kDesktopIconButtonSplashRadius = 20; +/// [kMinCursorSize] indicates min cursor (w, h) +const int kMinCursorSize = 24; + /// [kDefaultScrollAmountMultiplier] indicates how many rows can be scrolled after a minimum scroll action of mouse const kDefaultScrollAmountMultiplier = 5.0; const kDefaultScrollDuration = Duration(milliseconds: 50); diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 01229ab2b..4febd3878 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -339,15 +339,15 @@ class ImagePaint extends StatelessWidget { if (cacheLinux == null) { return MouseCursor.defer; } else { - final key = cacheLinux.key(scale); + final key = cacheLinux.updateGetKey(scale); cursor.addKeyLinux(key); return FlutterCustomMemoryImageCursor( pixbuf: cacheLinux.data, key: key, hotx: cacheLinux.hotx, hoty: cacheLinux.hoty, - imageWidth: (cacheLinux.width * scale).toInt(), - imageHeight: (cacheLinux.height * scale).toInt(), + imageWidth: (cacheLinux.width * cacheLinux.scale).toInt(), + imageHeight: (cacheLinux.height * cacheLinux.scale).toInt(), ); } } diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index aa9dfd8e2..d619364dc 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -17,6 +17,7 @@ import 'package:flutter_hbb/models/user_model.dart'; import 'package:flutter_hbb/utils/multi_window_manager.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tuple/tuple.dart'; +import 'package:image/image.dart' as img2; import 'package:flutter_custom_cursor/flutter_custom_cursor.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -665,7 +666,9 @@ class CanvasModel with ChangeNotifier { class CursorData { final String peerId; final int id; - final Uint8List? data; + final img2.Image? image; + double scale; + Uint8List? data; final double hotx; final double hoty; final int width; @@ -674,6 +677,8 @@ class CursorData { CursorData({ required this.peerId, required this.id, + required this.image, + required this.scale, required this.data, required this.hotx, required this.hoty, @@ -683,8 +688,34 @@ class CursorData { int _doubleToInt(double v) => (v * 10e6).round().toInt(); - String key(double scale) => - '${peerId}_${id}_${_doubleToInt(width * scale)}_${_doubleToInt(height * scale)}'; + double _checkUpdateScale(double scale) { + // Update data if scale changed. + if (Platform.isWindows) { + final tgtWidth = (width * scale).toInt(); + final tgtHeight = (width * scale).toInt(); + if (tgtWidth < kMinCursorSize || tgtHeight < kMinCursorSize) { + double sw = kMinCursorSize.toDouble() / width; + double sh = kMinCursorSize.toDouble() / height; + scale = sw < sh ? sh : sw; + } + if (_doubleToInt(this.scale) != _doubleToInt(scale)) { + data = img2 + .copyResize( + image!, + width: (width * scale).toInt(), + height: (height * scale).toInt(), + ) + .getBytes(); + } + } + this.scale = scale; + return scale; + } + + String updateGetKey(double scale) { + scale = _checkUpdateScale(scale); + return '${peerId}_${id}_${_doubleToInt(width * scale)}_${_doubleToInt(height * scale)}'; + } } class CursorModel with ChangeNotifier { @@ -864,15 +895,21 @@ class CursorModel with ChangeNotifier { _updateCacheLinux(ui.Image image, int id, int w, int h) async { ByteData? data; + img2.Image? image2; if (Platform.isWindows) { data = await image.toByteData(format: ui.ImageByteFormat.rawRgba); + if (data != null) { + image2 = img2.Image.fromBytes(w, h, data.buffer.asUint8List()); + } } else { data = await image.toByteData(format: ui.ImageByteFormat.png); } _cacheLinux = CursorData( peerId: this.id, - data: data?.buffer.asUint8List(), id: id, + image: image2, + scale: 1.0, + data: data?.buffer.asUint8List(), hotx: _hotx, hoty: _hoty, width: w, diff --git a/flutter/lib/utils/multi_window_manager.dart b/flutter/lib/utils/multi_window_manager.dart index 8fd71540d..a88f19a57 100644 --- a/flutter/lib/utils/multi_window_manager.dart +++ b/flutter/lib/utils/multi_window_manager.dart @@ -154,7 +154,7 @@ class RustDeskMultiWindowManager { int? wId = findWindowByType(type); if (wId != null) { debugPrint("closing multi window: ${type.toString()}"); - saveWindowPosition(type, windowId: wId); + await saveWindowPosition(type, windowId: wId); try { final ids = await DesktopMultiWindow.getAllSubWindowIds(); if (!ids.contains(wId)) {