Merge pull request #1875 from fufesou/flutter_win_cursor
Flutter win cursor
This commit is contained in:
commit
1c899fb988
@ -41,6 +41,9 @@ const Duration kTabTransitionDuration = Duration.zero;
|
|||||||
const double kEmptyMarginTop = 50;
|
const double kEmptyMarginTop = 50;
|
||||||
const double kDesktopIconButtonSplashRadius = 20;
|
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
|
/// [kDefaultScrollAmountMultiplier] indicates how many rows can be scrolled after a minimum scroll action of mouse
|
||||||
const kDefaultScrollAmountMultiplier = 5.0;
|
const kDefaultScrollAmountMultiplier = 5.0;
|
||||||
const kDefaultScrollDuration = Duration(milliseconds: 50);
|
const kDefaultScrollDuration = Duration(milliseconds: 50);
|
||||||
|
@ -284,7 +284,7 @@ class ImagePaint extends StatelessWidget {
|
|||||||
? keyboardEnabled.isTrue
|
? keyboardEnabled.isTrue
|
||||||
? (remoteCursorMoved.isTrue
|
? (remoteCursorMoved.isTrue
|
||||||
? SystemMouseCursors.none
|
? SystemMouseCursors.none
|
||||||
: _buildCustomCursorLinux(context, s))
|
: _buildCustomCursor(context, s))
|
||||||
: _buildDisabledCursor(context, s)
|
: _buildDisabledCursor(context, s)
|
||||||
: MouseCursor.defer,
|
: MouseCursor.defer,
|
||||||
onHover: (evt) {},
|
onHover: (evt) {},
|
||||||
@ -333,41 +333,43 @@ class ImagePaint extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseCursor _buildCustomCursorLinux(BuildContext context, double scale) {
|
MouseCursor _buildCustomCursor(BuildContext context, double scale) {
|
||||||
final cursor = Provider.of<CursorModel>(context);
|
final cursor = Provider.of<CursorModel>(context);
|
||||||
final cacheLinux = cursor.cacheLinux;
|
final cache = cursor.cache ?? cursor.defaultCache;
|
||||||
if (cacheLinux == null) {
|
if (cache == null) {
|
||||||
return MouseCursor.defer;
|
return MouseCursor.defer;
|
||||||
} else {
|
} else {
|
||||||
final key = cacheLinux.key(scale);
|
final key = cache.updateGetKey(scale);
|
||||||
cursor.addKeyLinux(key);
|
cursor.addKey(key);
|
||||||
return FlutterCustomMemoryImageCursor(
|
return FlutterCustomMemoryImageCursor(
|
||||||
pixbuf: cacheLinux.data,
|
pixbuf: cache.data,
|
||||||
key: key,
|
key: key,
|
||||||
hotx: cacheLinux.hotx,
|
// hotx: cache.hotx,
|
||||||
hoty: cacheLinux.hoty,
|
// hoty: cache.hoty,
|
||||||
imageWidth: (cacheLinux.width * scale).toInt(),
|
hotx: 0,
|
||||||
imageHeight: (cacheLinux.height * scale).toInt(),
|
hoty: 0,
|
||||||
|
imageWidth: (cache.width * cache.scale).toInt(),
|
||||||
|
imageHeight: (cache.height * cache.scale).toInt(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseCursor _buildDisabledCursor(BuildContext context, double scale) {
|
MouseCursor _buildDisabledCursor(BuildContext context, double scale) {
|
||||||
final cursor = Provider.of<CursorModel>(context);
|
final cursor = Provider.of<CursorModel>(context);
|
||||||
final cacheLinux = cursor.cacheLinux;
|
final cache = cursor.cache;
|
||||||
if (cacheLinux == null) {
|
if (cache == null) {
|
||||||
return MouseCursor.defer;
|
return MouseCursor.defer;
|
||||||
} else {
|
} else {
|
||||||
if (cursor.cachedForbidmemoryCursorData == null) {
|
if (cursor.cachedForbidmemoryCursorData == null) {
|
||||||
cursor.updateForbiddenCursorBuffer();
|
cursor.updateForbiddenCursorBuffer();
|
||||||
}
|
}
|
||||||
final key = 'disabled_cursor_key';
|
final key = 'disabled_cursor_key';
|
||||||
cursor.addKeyLinux(key);
|
cursor.addKey(key);
|
||||||
return FlutterCustomMemoryImageCursor(
|
return FlutterCustomMemoryImageCursor(
|
||||||
pixbuf: cursor.cachedForbidmemoryCursorData,
|
pixbuf: cursor.cachedForbidmemoryCursorData,
|
||||||
key: key,
|
key: key,
|
||||||
hotx: cacheLinux.hotx,
|
hotx: 0,
|
||||||
hoty: cacheLinux.hoty,
|
hoty: 0,
|
||||||
imageWidth: 32,
|
imageWidth: 32,
|
||||||
imageHeight: 32,
|
imageHeight: 32,
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,7 @@ import 'package:flutter_hbb/models/user_model.dart';
|
|||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:tuple/tuple.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_custom_cursor/flutter_custom_cursor.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
@ -665,15 +666,19 @@ class CanvasModel with ChangeNotifier {
|
|||||||
class CursorData {
|
class CursorData {
|
||||||
final String peerId;
|
final String peerId;
|
||||||
final int id;
|
final int id;
|
||||||
final Uint8List? data;
|
final img2.Image? image;
|
||||||
final double hotx;
|
double scale;
|
||||||
final double hoty;
|
Uint8List? data;
|
||||||
|
double hotx;
|
||||||
|
double hoty;
|
||||||
final int width;
|
final int width;
|
||||||
final int height;
|
final int height;
|
||||||
|
|
||||||
CursorData({
|
CursorData({
|
||||||
required this.peerId,
|
required this.peerId,
|
||||||
required this.id,
|
required this.id,
|
||||||
|
required this.image,
|
||||||
|
required this.scale,
|
||||||
required this.data,
|
required this.data,
|
||||||
required this.hotx,
|
required this.hotx,
|
||||||
required this.hoty,
|
required this.hoty,
|
||||||
@ -683,16 +688,46 @@ class CursorData {
|
|||||||
|
|
||||||
int _doubleToInt(double v) => (v * 10e6).round().toInt();
|
int _doubleToInt(double v) => (v * 10e6).round().toInt();
|
||||||
|
|
||||||
String key(double scale) =>
|
double _checkUpdateScale(double scale) {
|
||||||
'${peerId}_${id}_${_doubleToInt(width * scale)}_${_doubleToInt(height * 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(format: img2.Format.bgra);
|
||||||
|
hotx = (width * scale) / 2;
|
||||||
|
hoty = (height * scale) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 {
|
class CursorModel with ChangeNotifier {
|
||||||
ui.Image? _image;
|
ui.Image? _image;
|
||||||
final _images = <int, Tuple3<ui.Image, double, double>>{};
|
final _images = <int, Tuple3<ui.Image, double, double>>{};
|
||||||
CursorData? _cacheLinux;
|
CursorData? _cache;
|
||||||
final _cacheMapLinux = <int, CursorData>{};
|
final _defaultCacheId = -1;
|
||||||
final _cacheKeysLinux = <String>{};
|
CursorData? _defaultCache;
|
||||||
|
final _cacheMap = <int, CursorData>{};
|
||||||
|
final _cacheKeys = <String>{};
|
||||||
double _x = -10000;
|
double _x = -10000;
|
||||||
double _y = -10000;
|
double _y = -10000;
|
||||||
double _hotx = 0;
|
double _hotx = 0;
|
||||||
@ -703,7 +738,8 @@ class CursorModel with ChangeNotifier {
|
|||||||
WeakReference<FFI> parent;
|
WeakReference<FFI> parent;
|
||||||
|
|
||||||
ui.Image? get image => _image;
|
ui.Image? get image => _image;
|
||||||
CursorData? get cacheLinux => _cacheLinux;
|
CursorData? get cache => _cache;
|
||||||
|
CursorData? get defaultCache => _getDefaultCache();
|
||||||
|
|
||||||
double get x => _x - _displayOriginX;
|
double get x => _x - _displayOriginX;
|
||||||
|
|
||||||
@ -717,8 +753,31 @@ class CursorModel with ChangeNotifier {
|
|||||||
|
|
||||||
CursorModel(this.parent);
|
CursorModel(this.parent);
|
||||||
|
|
||||||
Set<String> get cachedKeysLinux => _cacheKeysLinux;
|
Set<String> get cachedKeys => _cacheKeys;
|
||||||
addKeyLinux(String key) => _cacheKeysLinux.add(key);
|
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
|
// remote physical display coordinate
|
||||||
Rect getVisibleRect() {
|
Rect getVisibleRect() {
|
||||||
@ -863,27 +922,48 @@ class CursorModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_updateCacheLinux(ui.Image image, int id, int w, int h) async {
|
_updateCacheLinux(ui.Image image, int id, int w, int h) async {
|
||||||
ByteData? data;
|
Uint8List? data;
|
||||||
|
img2.Image? image2;
|
||||||
if (Platform.isWindows) {
|
if (Platform.isWindows) {
|
||||||
data = await image.toByteData(format: ui.ImageByteFormat.rawRgba);
|
ByteData? data2 =
|
||||||
|
await image.toByteData(format: ui.ImageByteFormat.rawRgba);
|
||||||
|
if (data2 != null) {
|
||||||
|
data = data2.buffer.asUint8List();
|
||||||
|
image2 = img2.Image.fromBytes(w, h, data);
|
||||||
} else {
|
} else {
|
||||||
data = await image.toByteData(format: ui.ImageByteFormat.png);
|
data = defaultCursorImage?.getBytes(format: img2.Format.bgra);
|
||||||
|
image2 = defaultCursorImage?.clone();
|
||||||
|
_hotx = defaultCursorImage!.width / 2;
|
||||||
|
_hoty = defaultCursorImage!.height / 2;
|
||||||
}
|
}
|
||||||
_cacheLinux = CursorData(
|
} else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cache = CursorData(
|
||||||
peerId: this.id,
|
peerId: this.id,
|
||||||
data: data?.buffer.asUint8List(),
|
|
||||||
id: id,
|
id: id,
|
||||||
|
image: image2,
|
||||||
|
scale: 1.0,
|
||||||
|
data: data,
|
||||||
hotx: _hotx,
|
hotx: _hotx,
|
||||||
hoty: _hoty,
|
hoty: _hoty,
|
||||||
width: w,
|
width: w,
|
||||||
height: h,
|
height: h,
|
||||||
);
|
);
|
||||||
_cacheMapLinux[id] = _cacheLinux!;
|
_cacheMap[id] = _cache!;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCursorId(Map<String, dynamic> evt) async {
|
updateCursorId(Map<String, dynamic> evt) async {
|
||||||
final id = int.parse(evt['id']);
|
final id = int.parse(evt['id']);
|
||||||
_cacheLinux = _cacheMapLinux[id];
|
_cache = _cacheMap[id];
|
||||||
final tmp = _images[id];
|
final tmp = _images[id];
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
_image = tmp.item1;
|
_image = tmp.item1;
|
||||||
@ -931,15 +1011,15 @@ class CursorModel with ChangeNotifier {
|
|||||||
_image = null;
|
_image = null;
|
||||||
_images.clear();
|
_images.clear();
|
||||||
|
|
||||||
_clearCacheLinux();
|
_clearCache();
|
||||||
_cacheLinux = null;
|
_cache = null;
|
||||||
_cacheMapLinux.clear();
|
_cacheMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearCacheLinux() {
|
_clearCache() {
|
||||||
final cachedKeys = {...cachedKeysLinux};
|
final keys = {...cachedKeys};
|
||||||
for (var key in cachedKeys) {
|
for (var k in keys) {
|
||||||
customCursorController.freeCache(key);
|
customCursorController.freeCache(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -948,6 +1028,9 @@ class CursorModel with ChangeNotifier {
|
|||||||
cachedForbidmemoryCursorData ??= base64Decode(
|
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==');
|
'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(
|
||||||
|
'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAFmSURBVFiF7dWxSlxREMbx34QFDRowYBchZSxSCWlMCOwD5FGEFHap06UI7KPsAyyEEIQFqxRaCqYTsqCJFsKkuAeRXb17wrqV918dztw55zszc2fo6Oh47MR/e3zO1/iAHWmznHKGQwx9ip/LEbCfazbsoY8j/JLOhcC6sCW9wsjEwJf483AC9nPNc1+lFRwI13d+l3rYFS799rFGxJMqARv2pBXh+72XQ7gWvklPS7TmMl9Ak/M+DqrENvxAv/guKKApuKPWl0/TROK4+LbSqzhuB+OZ3fRSeFPWY+Fkyn56Y29hfgTSpnQ+s98cvorVey66uPlNFxKwZOYLCGfCs5n9NMYVrsp6mvXSoFqpqYFDvMBkStgJJe93dZOwVXxbqUnBENulydSReqUrDhcX0PT2EXarBYS3GNXMhboinBgIl9K71kg0L3+PvyYGdVpruT2MwrF0iotiXfIwus0Dj+OOjo6Of+e7ab74RkpgAAAAAElFTkSuQmCC'));
|
||||||
}
|
}
|
||||||
|
|
||||||
class QualityMonitorData {
|
class QualityMonitorData {
|
||||||
|
@ -77,7 +77,9 @@ class UserModel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
final m = jsonDecode(userInfo);
|
final m = jsonDecode(userInfo);
|
||||||
|
if (m != null) {
|
||||||
userName.value = m['name'] ?? '';
|
userName.value = m['name'] ?? '';
|
||||||
|
}
|
||||||
return userName.value;
|
return userName.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ class RustDeskMultiWindowManager {
|
|||||||
int? wId = findWindowByType(type);
|
int? wId = findWindowByType(type);
|
||||||
if (wId != null) {
|
if (wId != null) {
|
||||||
debugPrint("closing multi window: ${type.toString()}");
|
debugPrint("closing multi window: ${type.toString()}");
|
||||||
saveWindowPosition(type, windowId: wId);
|
await saveWindowPosition(type, windowId: wId);
|
||||||
try {
|
try {
|
||||||
final ids = await DesktopMultiWindow.getAllSubWindowIds();
|
final ids = await DesktopMultiWindow.getAllSubWindowIds();
|
||||||
if (!ids.contains(wId)) {
|
if (!ids.contains(wId)) {
|
||||||
|
@ -135,14 +135,14 @@ typedef struct _FORMAT_IDS FORMAT_IDS;
|
|||||||
|
|
||||||
#define TAG "windows"
|
#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)
|
#define DEBUG_CLIPRDR(fmt, ...) fprintf(stderr, "DEBUG %s[%d] %s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);fflush(stderr)
|
||||||
// #else
|
#else
|
||||||
// #define DEBUG_CLIPRDR(fmt, ...) \
|
#define DEBUG_CLIPRDR(fmt, ...) \
|
||||||
// do \
|
do \
|
||||||
// { \
|
{ \
|
||||||
// } while (0)
|
} while (0)
|
||||||
// #endif
|
#endif
|
||||||
|
|
||||||
typedef BOOL(WINAPI *fnAddClipboardFormatListener)(HWND hwnd);
|
typedef BOOL(WINAPI *fnAddClipboardFormatListener)(HWND hwnd);
|
||||||
typedef BOOL(WINAPI *fnRemoveClipboardFormatListener)(HWND hwnd);
|
typedef BOOL(WINAPI *fnRemoveClipboardFormatListener)(HWND hwnd);
|
||||||
|
@ -17,18 +17,18 @@ pub fn set_wayland_scrap_map_err() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn map_err_scrap(err: String) -> io::Error {
|
fn map_err_scrap(err: String) -> io::Error {
|
||||||
// REMOVE ME ===================================== uncomment to handle error
|
// to-do: Remove this the following log
|
||||||
// // 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);
|
|
||||||
// }
|
|
||||||
|
|
||||||
log::error!(
|
log::error!(
|
||||||
"REMOVE ME ===================================== wayland scrap error {}",
|
"REMOVE ME ===================================== wayland scrap error {}",
|
||||||
&err
|
&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.name.to_uppercase() == "Ubuntu".to_uppercase() {
|
||||||
if DISTRO.version_id < "21".to_owned() {
|
if DISTRO.version_id < "21".to_owned() {
|
||||||
io::Error::new(io::ErrorKind::Other, SCRAP_UBUNTU_HIGHER_REQUIRED)
|
io::Error::new(io::ErrorKind::Other, SCRAP_UBUNTU_HIGHER_REQUIRED)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user