From 0d5eb639a0dd656a0fc07467c1c8cc0533859fd4 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 27 Oct 2022 18:40:45 +0800 Subject: [PATCH 1/6] 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)) { From 2cb99dbbff0fc9d12d74b95b346b73fcc1fd3924 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 27 Oct 2022 20:05:36 +0800 Subject: [PATCH 2/6] flutter_desktop: default cursor init commit Signed-off-by: fufesou --- flutter/lib/models/model.dart | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index d619364dc..7a656faae 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -894,22 +894,37 @@ class CursorModel with ChangeNotifier { } _updateCacheLinux(ui.Image image, int id, int w, int h) async { - ByteData? data; + Uint8List? 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()); + ByteData? data2 = + await image.toByteData(format: ui.ImageByteFormat.rawRgba); + if (data2 != null) { + data = data2.buffer.asUint8List(); + image2 = img2.Image.fromBytes(w, h, data); + } else { + data = defaultCursorImage?.getBytes(format: img2.Format.bgra); + image2 = defaultCursorImage?.clone(); + _hotx = defaultCursorImage!.width / 2; + _hoty = defaultCursorImage!.height / 2; } } else { - data = await image.toByteData(format: ui.ImageByteFormat.png); + ByteData? data2 = await image.toByteData(format: ui.ImageByteFormat.png); + if (data2 != null) { + data = data2.buffer.asUint8List(); + } else { + data = Uint8List.fromList(img2.encodePng(defaultCursorImage!)); + _hotx = defaultCursorImage!.width / 2; + _hoty = defaultCursorImage!.height / 2; + } } + _cacheLinux = CursorData( peerId: this.id, id: id, image: image2, scale: 1.0, - data: data?.buffer.asUint8List(), + data: data, hotx: _hotx, hoty: _hoty, width: w, @@ -985,6 +1000,9 @@ class CursorModel with ChangeNotifier { cachedForbidmemoryCursorData ??= base64Decode( 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAkZQTFRFAAAA2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4G2B4GWAwCAAAAAAAA2B4GAAAAMTExAAAAAAAA2B4G2B4G2B4GAAAAmZmZkZGRAQEBAAAA2B4G2B4G2B4G////oKCgAwMDag8D2B4G2B4G2B4Gra2tBgYGbg8D2B4G2B4Gubm5CQkJTwsCVgwC2B4GxcXFDg4OAAAAAAAA2B4G2B4Gz8/PFBQUAAAAAAAA2B4G2B4G2B4G2B4G2B4G2B4G2B4GDgIA2NjYGxsbAAAAAAAA2B4GFwMB4eHhIyMjAAAAAAAA2B4G6OjoLCwsAAAAAAAA2B4G2B4G2B4G2B4G2B4GCQEA4ODgv7+/iYmJY2NjAgICAAAA9PT0Ojo6AAAAAAAAAAAA+/v7SkpKhYWFr6+vAAAAAAAA8/PzOTk5ERER9fX1KCgoAAAAgYGBKioqAAAAAAAApqamlpaWAAAAAAAAAAAAAAAAAAAAAAAALi4u/v7+GRkZAAAAAAAAAAAAAAAAAAAAfn5+AAAAAAAAV1dXkJCQAAAAAAAAAQEBAAAAAAAAAAAA7Hz6BAAAAMJ0Uk5TAAIWEwEynNz6//fVkCAatP2fDUHs6cDD8d0mPfT5fiEskiIR584A0gejr3AZ+P4plfALf5ZiTL85a4ziD6697fzN3UYE4v/4TwrNHuT///tdRKZh///+1U/ZBv///yjb///eAVL//50Cocv//6oFBbPvpGZCbfT//7cIhv///8INM///zBEcWYSZmO7//////1P////ts/////8vBv//////gv//R/z///QQz9sevP///2waXhNO/+fc//8mev/5gAe2r90MAAAByUlEQVR4nGNggANGJmYWBpyAlY2dg5OTi5uHF6s0H78AJxRwCAphyguLgKRExcQlQLSkFLq8tAwnp6ycPNABjAqKQKNElVDllVU4OVVhVquJA81Q10BRoAkUUYbJa4Edoo0sr6PLqaePLG/AyWlohKTAmJPTBFnelAFoixmSAnNOTgsUeQZLTk4rJAXWnJw2EHlbiDyDPCenHZICe04HFrh+RydnBgYWPU5uJAWinJwucPNd3dw9GDw5Ob2QFHBzcnrD7ffx9fMPCOTkDEINhmC4+3x8Q0LDwlEDIoKTMzIKKg9SEBIdE8sZh6SAJZ6Tkx0qD1YQkpCYlIwclCng0AXLQxSEpKalZyCryATKZwkhKQjJzsnNQ1KQXwBUUVhUXBJYWgZREFJeUVmFpMKlWg+anmqgCkJq6+obkG1pLEBTENLU3NKKrIKhrb2js8u4G6Kgpze0r3/CRAZMAHbkpJDJU6ZMmTqtFbuC6TNmhsyaMnsOFlmwgrnzpsxfELJwEXZ5Bp/FS3yWLlsesmLlKuwKVk9Ys5Zh3foN0zduwq5g85atDAzbpqSGbN9RhV0FGOzctWH3lD14FOzdt3H/gQw8Cg4u2gQPAwBYDXXdIH+wqAAAAABJRU5ErkJggg=='); } + + img2.Image? defaultCursorImage = img2.decodePng(base64Decode( + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAPCSURBVFiF7ZZBbBVVFIa/c+8w01daaKHYSkUQsQSbSIm4ELRqYlyoUQHbVcUmYmIg7EQSE5MmxI0LN4YuTBCDicYiDYSExiAxJrpoiDGURK2ChZYioNjS1/de583cOS5eiQJ99BU0uui/vDPn/N+Ze/PfgVnN6j+W3Grh9iMapMPRlI2MCZiX72whg4j+qwAvfa5zTTZcL4YnUX0ApAZJPEXSRvlFha9szLE9m1Jn/3GA9oO5RxF2ojwBlBd5TYGfFOm0Euz94HlJ3zZAR4eaM2smXkHZBdROumSShEGX8BtIZAxVVnSJCHdMljkVPpHQ7fiwteLCbQG0H8q9qsq7AhVAOBHJ0aFRc7B/WE7/Pu7lUJJUGXMaFrrapYvj5qpANxlhSQFUPtMk/9q+jfMu3xLAy4dyzaJ0AbWqMnopLbt7+vzDZAkRDPZv9XkSDPrQqvzKlfW6wzP6IICIvDMeBm/ubxU3lYcpZr61SytE2Unhs4eX0rK7p9fvJkeEh73GHMDH4GGP/+D3nzzjve0SfgRQ1S1z/Yl1xXyKAuT8cD3wOEAmL1/09PmHAW4wvl4e9sQpO/DrmLwP5IAFIrShOmVdUQAVngLKVckMj5pDZAmnNb8qwXzzc9AbOU4AKDS3dWfrSgbYfkQDVBsBnHKu/7ycRorD3iCL5EbIZvLyXWEa6o3IspIB0uFoCpFFAC6Ri5fHvUzJ01+VQ7ORDAOqkBJrFpUMYCNjILEFAGIcM45YCs4xoAIiLvFKBgiYl1cKKeYZqsvK8WcMYRHfUA0YhEhFrpQM0NlCRuA0gGf1rnsXuNoZAwR4FWWFc4QyYo2cKxkAERXha0CNsGh5bfLYjMzzJE1L3T3BHF07udKXDoPB0gEAE3EUoR+gqtxtbFrlVhEzZZpdI4d680k1LI7bDNQBTiyf7m+V3IwA9mxKnUWkE3DWUH9/ffx643K3ghhXdDtinFdB2TNNYXvK16cBFL4MJTxYzMfebJh1G3Z9H9n4bmC1NdxZOz9pWljjrlzIehfjLCERCY4EUCze6hXuvkcaoq2VZdoi4AEDBt320XOVp4p5TH8bdo3Xqe+9J+iLkxNNRDEnx0P5NpeX84kSB3OonutrY8rXteavK3kgUdm2b0NZz836lxQum7vHFlrrv6GqW4AF1z3W6/okCMdE9a29L5T3Tte75HRr6VJb6U08nFg2ozQDixVSACLEKH8g9IlwIDThgY+frRoppe+Mf0o7OtQMrsnWqcqyREyNamJFZUxVhnJxMFTstM9qVv9b/QkV/YOrhHDdtAAAAABJRU5ErkJggg==')); } class QualityMonitorData { From 6fb52573e73afa20b244bfe26479d8c80d557a5d Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 28 Oct 2022 10:16:00 +0800 Subject: [PATCH 3/6] win clipboard remove debug msg Signed-off-by: fufesou --- libs/clipboard/src/windows/wf_cliprdr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index 7374b27c1..00ef7254e 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -135,14 +135,14 @@ typedef struct _FORMAT_IDS FORMAT_IDS; #define TAG "windows" -// #ifdef WITH_DEBUG_CLIPRDR +#ifdef WITH_DEBUG_CLIPRDR #define DEBUG_CLIPRDR(fmt, ...) fprintf(stderr, "DEBUG %s[%d] %s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);fflush(stderr) -// #else -// #define DEBUG_CLIPRDR(fmt, ...) \ -// do \ -// { \ -// } while (0) -// #endif +#else +#define DEBUG_CLIPRDR(fmt, ...) \ + do \ + { \ + } while (0) +#endif typedef BOOL(WINAPI *fnAddClipboardFormatListener)(HWND hwnd); typedef BOOL(WINAPI *fnRemoveClipboardFormatListener)(HWND hwnd); From 9591c908a15feb0a7e568a11d395b41657a85b58 Mon Sep 17 00:00:00 2001 From: fufesou Date: Fri, 28 Oct 2022 10:19:22 +0800 Subject: [PATCH 4/6] trivial wayland changes Signed-off-by: fufesou --- src/server/wayland.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/server/wayland.rs b/src/server/wayland.rs index de304c459..7fd6f106b 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -17,18 +17,18 @@ pub fn set_wayland_scrap_map_err() { } fn map_err_scrap(err: String) -> io::Error { - // REMOVE ME ===================================== uncomment to handle error - // // to-do: Handle error better, do not restart server - // if err.starts_with("Did not receive a reply") { - // log::error!("Fatal pipewire error, {}", &err); - // std::process::exit(-1); - // } - + // to-do: Remove this the following log log::error!( "REMOVE ME ===================================== wayland scrap error {}", &err ); + // to-do: Handle error better, do not restart server + if err.starts_with("Did not receive a reply") { + log::error!("Fatal pipewire error, {}", &err); + std::process::exit(-1); + } + if DISTRO.name.to_uppercase() == "Ubuntu".to_uppercase() { if DISTRO.version_id < "21".to_owned() { io::Error::new(io::ErrorKind::Other, SCRAP_UBUNTU_HIGHER_REQUIRED) From 2c34112492bcd50fe5e002844b9500f649391579 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 30 Oct 2022 13:50:44 +0800 Subject: [PATCH 5/6] flutter_desktop: debug win cursor Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 10 +++--- flutter/lib/models/model.dart | 42 +++++++++++----------- flutter/lib/models/user_model.dart | 4 ++- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 4febd3878..b10534030 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -340,12 +340,14 @@ class ImagePaint extends StatelessWidget { return MouseCursor.defer; } else { final key = cacheLinux.updateGetKey(scale); - cursor.addKeyLinux(key); + cursor.addKey(key); return FlutterCustomMemoryImageCursor( pixbuf: cacheLinux.data, key: key, - hotx: cacheLinux.hotx, - hoty: cacheLinux.hoty, + // hotx: cacheLinux.hotx, + // hoty: cacheLinux.hoty, + hotx: 0, + hoty: 0, imageWidth: (cacheLinux.width * cacheLinux.scale).toInt(), imageHeight: (cacheLinux.height * cacheLinux.scale).toInt(), ); @@ -362,7 +364,7 @@ class ImagePaint extends StatelessWidget { cursor.updateForbiddenCursorBuffer(); } final key = 'disabled_cursor_key'; - cursor.addKeyLinux(key); + cursor.addKey(key); return FlutterCustomMemoryImageCursor( pixbuf: cursor.cachedForbidmemoryCursorData, key: key, diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 7a656faae..754d62fac 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -669,8 +669,8 @@ class CursorData { final img2.Image? image; double scale; Uint8List? data; - final double hotx; - final double hoty; + double hotx; + double hoty; final int width; final int height; @@ -705,7 +705,9 @@ class CursorData { width: (width * scale).toInt(), height: (height * scale).toInt(), ) - .getBytes(); + .getBytes(format: img2.Format.bgra); + hotx = (width * scale) / 2; + hoty = (height * scale) / 2; } } this.scale = scale; @@ -721,9 +723,9 @@ class CursorData { class CursorModel with ChangeNotifier { ui.Image? _image; final _images = >{}; - CursorData? _cacheLinux; - final _cacheMapLinux = {}; - final _cacheKeysLinux = {}; + CursorData? _cache; + final _cacheMap = {}; + final _cacheKeys = {}; double _x = -10000; double _y = -10000; double _hotx = 0; @@ -734,7 +736,7 @@ class CursorModel with ChangeNotifier { WeakReference parent; ui.Image? get image => _image; - CursorData? get cacheLinux => _cacheLinux; + CursorData? get cacheLinux => _cache; double get x => _x - _displayOriginX; @@ -748,8 +750,8 @@ class CursorModel with ChangeNotifier { CursorModel(this.parent); - Set get cachedKeysLinux => _cacheKeysLinux; - addKeyLinux(String key) => _cacheKeysLinux.add(key); + Set get cachedKeys => _cacheKeys; + addKey(String key) => _cacheKeys.add(key); // remote physical display coordinate Rect getVisibleRect() { @@ -919,7 +921,7 @@ class CursorModel with ChangeNotifier { } } - _cacheLinux = CursorData( + _cache = CursorData( peerId: this.id, id: id, image: image2, @@ -930,12 +932,12 @@ class CursorModel with ChangeNotifier { width: w, height: h, ); - _cacheMapLinux[id] = _cacheLinux!; + _cacheMap[id] = _cache!; } updateCursorId(Map evt) async { final id = int.parse(evt['id']); - _cacheLinux = _cacheMapLinux[id]; + _cache = _cacheMap[id]; final tmp = _images[id]; if (tmp != null) { _image = tmp.item1; @@ -983,15 +985,15 @@ class CursorModel with ChangeNotifier { _image = null; _images.clear(); - _clearCacheLinux(); - _cacheLinux = null; - _cacheMapLinux.clear(); + _clearCache(); + _cache = null; + _cacheMap.clear(); } - _clearCacheLinux() { - final cachedKeys = {...cachedKeysLinux}; - for (var key in cachedKeys) { - customCursorController.freeCache(key); + _clearCache() { + final keys = {...cachedKeys}; + for (var k in keys) { + customCursorController.freeCache(k); } } @@ -1002,7 +1004,7 @@ class CursorModel with ChangeNotifier { } img2.Image? defaultCursorImage = img2.decodePng(base64Decode( - 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAPCSURBVFiF7ZZBbBVVFIa/c+8w01daaKHYSkUQsQSbSIm4ELRqYlyoUQHbVcUmYmIg7EQSE5MmxI0LN4YuTBCDicYiDYSExiAxJrpoiDGURK2ChZYioNjS1/de583cOS5eiQJ99BU0uui/vDPn/N+Ze/PfgVnN6j+W3Grh9iMapMPRlI2MCZiX72whg4j+qwAvfa5zTTZcL4YnUX0ApAZJPEXSRvlFha9szLE9m1Jn/3GA9oO5RxF2ojwBlBd5TYGfFOm0Euz94HlJ3zZAR4eaM2smXkHZBdROumSShEGX8BtIZAxVVnSJCHdMljkVPpHQ7fiwteLCbQG0H8q9qsq7AhVAOBHJ0aFRc7B/WE7/Pu7lUJJUGXMaFrrapYvj5qpANxlhSQFUPtMk/9q+jfMu3xLAy4dyzaJ0AbWqMnopLbt7+vzDZAkRDPZv9XkSDPrQqvzKlfW6wzP6IICIvDMeBm/ubxU3lYcpZr61SytE2Unhs4eX0rK7p9fvJkeEh73GHMDH4GGP/+D3nzzjve0SfgRQ1S1z/Yl1xXyKAuT8cD3wOEAmL1/09PmHAW4wvl4e9sQpO/DrmLwP5IAFIrShOmVdUQAVngLKVckMj5pDZAmnNb8qwXzzc9AbOU4AKDS3dWfrSgbYfkQDVBsBnHKu/7ycRorD3iCL5EbIZvLyXWEa6o3IspIB0uFoCpFFAC6Ri5fHvUzJ01+VQ7ORDAOqkBJrFpUMYCNjILEFAGIcM45YCs4xoAIiLvFKBgiYl1cKKeYZqsvK8WcMYRHfUA0YhEhFrpQM0NlCRuA0gGf1rnsXuNoZAwR4FWWFc4QyYo2cKxkAERXha0CNsGh5bfLYjMzzJE1L3T3BHF07udKXDoPB0gEAE3EUoR+gqtxtbFrlVhEzZZpdI4d680k1LI7bDNQBTiyf7m+V3IwA9mxKnUWkE3DWUH9/ffx643K3ghhXdDtinFdB2TNNYXvK16cBFL4MJTxYzMfebJh1G3Z9H9n4bmC1NdxZOz9pWljjrlzIehfjLCERCY4EUCze6hXuvkcaoq2VZdoi4AEDBt320XOVp4p5TH8bdo3Xqe+9J+iLkxNNRDEnx0P5NpeX84kSB3OonutrY8rXteavK3kgUdm2b0NZz836lxQum7vHFlrrv6GqW4AF1z3W6/okCMdE9a29L5T3Tte75HRr6VJb6U08nFg2ozQDixVSACLEKH8g9IlwIDThgY+frRoppe+Mf0o7OtQMrsnWqcqyREyNamJFZUxVhnJxMFTstM9qVv9b/QkV/YOrhHDdtAAAAABJRU5ErkJggg==')); + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAFmSURBVFiF7dWxSlxREMbx34QFDRowYBchZSxSCWlMCOwD5FGEFHap06UI7KPsAyyEEIQFqxRaCqYTsqCJFsKkuAeRXb17wrqV918dztw55zszc2fo6Oh47MR/e3zO1/iAHWmznHKGQwx9ip/LEbCfazbsoY8j/JLOhcC6sCW9wsjEwJf483AC9nPNc1+lFRwI13d+l3rYFS799rFGxJMqARv2pBXh+72XQ7gWvklPS7TmMl9Ak/M+DqrENvxAv/guKKApuKPWl0/TROK4+LbSqzhuB+OZ3fRSeFPWY+Fkyn56Y29hfgTSpnQ+s98cvorVey66uPlNFxKwZOYLCGfCs5n9NMYVrsp6mvXSoFqpqYFDvMBkStgJJe93dZOwVXxbqUnBENulydSReqUrDhcX0PT2EXarBYS3GNXMhboinBgIl9K71kg0L3+PvyYGdVpruT2MwrF0iotiXfIwus0Dj+OOjo6Of+e7ab74RkpgAAAAAElFTkSuQmCC')); } class QualityMonitorData { diff --git a/flutter/lib/models/user_model.dart b/flutter/lib/models/user_model.dart index 163efaebc..721aac5b5 100644 --- a/flutter/lib/models/user_model.dart +++ b/flutter/lib/models/user_model.dart @@ -77,7 +77,9 @@ class UserModel { return ""; } final m = jsonDecode(userInfo); - userName.value = m['name'] ?? ''; + if (m != null) { + userName.value = m['name'] ?? ''; + } return userName.value; } From b321dff158f9a6a4a117059faa9467deb26a7761 Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 30 Oct 2022 14:38:35 +0800 Subject: [PATCH 6/6] flutter_desktop: debug win cursor 2 Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 28 +++++++++++----------- flutter/lib/models/model.dart | 28 +++++++++++++++++++++- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index b10534030..05a244802 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -284,7 +284,7 @@ class ImagePaint extends StatelessWidget { ? keyboardEnabled.isTrue ? (remoteCursorMoved.isTrue ? SystemMouseCursors.none - : _buildCustomCursorLinux(context, s)) + : _buildCustomCursor(context, s)) : _buildDisabledCursor(context, s) : MouseCursor.defer, onHover: (evt) {}, @@ -333,31 +333,31 @@ class ImagePaint extends StatelessWidget { } } - MouseCursor _buildCustomCursorLinux(BuildContext context, double scale) { + MouseCursor _buildCustomCursor(BuildContext context, double scale) { final cursor = Provider.of(context); - final cacheLinux = cursor.cacheLinux; - if (cacheLinux == null) { + final cache = cursor.cache ?? cursor.defaultCache; + if (cache == null) { return MouseCursor.defer; } else { - final key = cacheLinux.updateGetKey(scale); + final key = cache.updateGetKey(scale); cursor.addKey(key); return FlutterCustomMemoryImageCursor( - pixbuf: cacheLinux.data, + pixbuf: cache.data, key: key, - // hotx: cacheLinux.hotx, - // hoty: cacheLinux.hoty, + // hotx: cache.hotx, + // hoty: cache.hoty, hotx: 0, hoty: 0, - imageWidth: (cacheLinux.width * cacheLinux.scale).toInt(), - imageHeight: (cacheLinux.height * cacheLinux.scale).toInt(), + imageWidth: (cache.width * cache.scale).toInt(), + imageHeight: (cache.height * cache.scale).toInt(), ); } } MouseCursor _buildDisabledCursor(BuildContext context, double scale) { final cursor = Provider.of(context); - final cacheLinux = cursor.cacheLinux; - if (cacheLinux == null) { + final cache = cursor.cache; + if (cache == null) { return MouseCursor.defer; } else { if (cursor.cachedForbidmemoryCursorData == null) { @@ -368,8 +368,8 @@ class ImagePaint extends StatelessWidget { return FlutterCustomMemoryImageCursor( pixbuf: cursor.cachedForbidmemoryCursorData, key: key, - hotx: cacheLinux.hotx, - hoty: cacheLinux.hoty, + hotx: 0, + hoty: 0, imageWidth: 32, imageHeight: 32, ); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 754d62fac..54d77ca95 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -724,6 +724,8 @@ class CursorModel with ChangeNotifier { ui.Image? _image; final _images = >{}; CursorData? _cache; + final _defaultCacheId = -1; + CursorData? _defaultCache; final _cacheMap = {}; final _cacheKeys = {}; double _x = -10000; @@ -736,7 +738,8 @@ class CursorModel with ChangeNotifier { WeakReference parent; ui.Image? get image => _image; - CursorData? get cacheLinux => _cache; + CursorData? get cache => _cache; + CursorData? get defaultCache => _getDefaultCache(); double get x => _x - _displayOriginX; @@ -753,6 +756,29 @@ class CursorModel with ChangeNotifier { Set get cachedKeys => _cacheKeys; addKey(String key) => _cacheKeys.add(key); + CursorData? _getDefaultCache() { + if (_defaultCache == null) { + if (Platform.isWindows) { + Uint8List data = defaultCursorImage!.getBytes(format: img2.Format.bgra); + _hotx = defaultCursorImage!.width / 2; + _hoty = defaultCursorImage!.height / 2; + + _defaultCache = CursorData( + peerId: id, + id: _defaultCacheId, + image: defaultCursorImage?.clone(), + scale: 1.0, + data: data, + hotx: _hotx, + hoty: _hoty, + width: defaultCursorImage!.width, + height: defaultCursorImage!.height, + ); + } + } + return _defaultCache; + } + // remote physical display coordinate Rect getVisibleRect() { final size = MediaQueryData.fromWindow(ui.window).size;