flutter_desktop: cursor image cache mismatch
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
ef0980a9b1
commit
aa6e747e8a
@ -33,6 +33,8 @@ late final DesktopType? desktopType;
|
||||
typedef F = String Function(String);
|
||||
typedef FMethod = String Function(String, dynamic);
|
||||
|
||||
typedef StreamEventHandler = Future<void> Function(Map<String, dynamic>);
|
||||
|
||||
late final iconKeyboard = MemoryImage(Uint8List.fromList(base64Decode(
|
||||
"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAgVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9d3yJTAAAAKnRSTlMA0Gd/0y8ILZgbJffDPUwV2nvzt+TMqZxyU7CMb1pYQyzsvKunkXE4AwJnNC24AAAA+0lEQVQ4y83O2U7DMBCF4ZMxk9rZk26kpQs7nPd/QJy4EiLbLf01N5Y/2YP/qxDFQvGB5NPC/ZpVnfJx4b5xyGfF95rkHvNCWH1u+N6J6T0sC7gqRy8uGPfBLEbozPXUjlkQKwGaFPNizwQbwkx0TDvhCii34ExZCSQVBdzIOEOyeclSHgBGXkpeygXSQgStACtWx4Z8rr8COHOvfEP/IbbsQAToFUAAV1M408IIjIGYAPoCSNRP7DQutfQTqxuAiH7UUg1FaJR2AGrrx52sK2ye28LZ0wBAEyR6y8X+NADhm1B4fgiiHXbRrTrxpwEY9RdM9wsepnvFHfUDwYEeiwAJr/gAAAAASUVORK5CYII=")));
|
||||
late final iconClipboard = MemoryImage(Uint8List.fromList(base64Decode(
|
||||
|
@ -594,8 +594,8 @@ class ImagePaint extends StatelessWidget {
|
||||
} else {
|
||||
final key = cacheLinux.key(scale);
|
||||
cursor.addKeyLinux(key);
|
||||
// debugPrint(
|
||||
// 'REMOVE ME ================================= linux curor key: $key');
|
||||
debugPrint(
|
||||
'REMOVE ME ================================= linux curor key: $key');
|
||||
return FlutterCustomMemoryImageCursor(
|
||||
pixbuf: cacheLinux.data,
|
||||
key: key,
|
||||
|
@ -4,7 +4,6 @@ import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -21,6 +20,7 @@ import 'package:flutter_custom_cursor/flutter_custom_cursor.dart';
|
||||
|
||||
import '../common.dart';
|
||||
import '../common/shared_state.dart';
|
||||
import '../utils/image.dart' as img;
|
||||
import '../mobile/widgets/dialog.dart';
|
||||
import 'peer_model.dart';
|
||||
import 'platform_model.dart';
|
||||
@ -127,8 +127,8 @@ class FfiModel with ChangeNotifier {
|
||||
_permissions.clear();
|
||||
}
|
||||
|
||||
void Function(Map<String, dynamic>) startEventListener(String peerId) {
|
||||
return (evt) {
|
||||
StreamEventHandler startEventListener(String peerId) {
|
||||
return (evt) async {
|
||||
var name = evt['name'];
|
||||
if (name == 'msgbox') {
|
||||
handleMsgBox(evt, peerId);
|
||||
@ -140,11 +140,11 @@ class FfiModel with ChangeNotifier {
|
||||
} else if (name == 'switch_display') {
|
||||
handleSwitchDisplay(evt);
|
||||
} else if (name == 'cursor_data') {
|
||||
parent.target?.cursorModel.updateCursorData(evt);
|
||||
await parent.target?.cursorModel.updateCursorData(evt);
|
||||
} else if (name == 'cursor_id') {
|
||||
parent.target?.cursorModel.updateCursorId(evt);
|
||||
await parent.target?.cursorModel.updateCursorId(evt);
|
||||
} else if (name == 'cursor_position') {
|
||||
parent.target?.cursorModel.updateCursorPosition(evt, peerId);
|
||||
await parent.target?.cursorModel.updateCursorPosition(evt, peerId);
|
||||
} else if (name == 'clipboard') {
|
||||
Clipboard.setData(ClipboardData(text: evt['content']));
|
||||
} else if (name == 'permission') {
|
||||
@ -780,7 +780,7 @@ class CursorModel with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void updateCursorData(Map<String, dynamic> evt) {
|
||||
updateCursorData(Map<String, dynamic> evt) async {
|
||||
var id = int.parse(evt['id']);
|
||||
_hotx = double.parse(evt['hotx']);
|
||||
_hoty = double.parse(evt['hoty']);
|
||||
@ -789,34 +789,26 @@ class CursorModel with ChangeNotifier {
|
||||
List<dynamic> colors = json.decode(evt['colors']);
|
||||
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
|
||||
var pid = parent.target?.id;
|
||||
ui.decodeImageFromPixels(rgba, width, height, ui.PixelFormat.rgba8888,
|
||||
(image) {
|
||||
() async {
|
||||
if (parent.target?.id != pid) return;
|
||||
_image = image;
|
||||
_images[id] = Tuple3(image, _hotx, _hoty);
|
||||
_updateCacheLinux(image, id, width, height);
|
||||
try {
|
||||
// my throw exception, because the listener maybe already dispose
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('notify cursor: $e');
|
||||
}
|
||||
}();
|
||||
});
|
||||
|
||||
final image = await img.decodeImageFromPixels(
|
||||
rgba, width, height, ui.PixelFormat.rgba8888);
|
||||
if (parent.target?.id != pid) return;
|
||||
_image = image;
|
||||
_images[id] = Tuple3(image, _hotx, _hoty);
|
||||
await _updateCacheLinux(image, id, width, height);
|
||||
try {
|
||||
// my throw exception, because the listener maybe already dispose
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('notify cursor: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void _updateCacheLinux(ui.Image image, int id, int w, int h) async {
|
||||
final data = await image.toByteData(format: ImageByteFormat.png);
|
||||
late Uint8List? dataLinux;
|
||||
if (data != null) {
|
||||
dataLinux = data.buffer.asUint8List();
|
||||
} else {
|
||||
dataLinux = null;
|
||||
}
|
||||
_updateCacheLinux(ui.Image image, int id, int w, int h) async {
|
||||
final data = await image.toByteData(format: ui.ImageByteFormat.png);
|
||||
_cacheLinux = CursorData(
|
||||
peerId: this.id,
|
||||
data: dataLinux,
|
||||
data: data?.buffer.asUint8List(),
|
||||
id: id,
|
||||
hotx: _hotx,
|
||||
hoty: _hoty,
|
||||
@ -826,9 +818,10 @@ class CursorModel with ChangeNotifier {
|
||||
_cacheMapLinux[id] = _cacheLinux!;
|
||||
}
|
||||
|
||||
void updateCursorId(Map<String, dynamic> evt) {
|
||||
_cacheLinux = _cacheMapLinux[int.parse(evt['id'])];
|
||||
final tmp = _images[int.parse(evt['id'])];
|
||||
updateCursorId(Map<String, dynamic> evt) async {
|
||||
final id = int.parse(evt['id']);
|
||||
_cacheLinux = _cacheMapLinux[id];
|
||||
final tmp = _images[id];
|
||||
if (tmp != null) {
|
||||
_image = tmp.item1;
|
||||
_hotx = tmp.item2;
|
||||
@ -838,7 +831,7 @@ class CursorModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
/// Update the cursor position.
|
||||
void updateCursorPosition(Map<String, dynamic> evt, String id) {
|
||||
updateCursorPosition(Map<String, dynamic> evt, String id) async {
|
||||
_x = double.parse(evt['x']);
|
||||
_y = double.parse(evt['y']);
|
||||
try {
|
||||
|
@ -30,15 +30,15 @@ class PlatformFFI {
|
||||
String _dir = '';
|
||||
String _homeDir = '';
|
||||
F2? _translate;
|
||||
final _eventHandlers = Map<String, Map<String, HandleEvent>>();
|
||||
final _eventHandlers = <String, Map<String, HandleEvent>>{};
|
||||
late RustdeskImpl _ffiBind;
|
||||
late String _appType;
|
||||
void Function(Map<String, dynamic>)? _eventCallback;
|
||||
StreamEventHandler? _eventCallback;
|
||||
|
||||
PlatformFFI._();
|
||||
|
||||
static final PlatformFFI instance = PlatformFFI._();
|
||||
final _toAndroidChannel = MethodChannel("mChannel");
|
||||
final _toAndroidChannel = const MethodChannel("mChannel");
|
||||
|
||||
RustdeskImpl get ffiBind => _ffiBind;
|
||||
|
||||
@ -88,7 +88,7 @@ class PlatformFFI {
|
||||
}
|
||||
|
||||
/// Init the FFI class, loads the native Rust core library.
|
||||
Future<Null> init(String appType) async {
|
||||
Future<void> init(String appType) async {
|
||||
_appType = appType;
|
||||
// if (isDesktop) {
|
||||
// // TODO
|
||||
@ -117,7 +117,7 @@ class PlatformFFI {
|
||||
_homeDir = (await getDownloadsDirectory())?.path ?? "";
|
||||
}
|
||||
} catch (e) {
|
||||
print("initialize failed: $e");
|
||||
debugPrint('initialize failed: $e');
|
||||
}
|
||||
String id = 'NA';
|
||||
String name = 'Flutter';
|
||||
@ -144,14 +144,14 @@ class PlatformFFI {
|
||||
name = macOsInfo.computerName;
|
||||
id = macOsInfo.systemGUID ?? "";
|
||||
}
|
||||
print(
|
||||
"_appType:$_appType,info1-id:$id,info2-name:$name,dir:$_dir,homeDir:$_homeDir");
|
||||
debugPrint(
|
||||
'_appType:$_appType,info1-id:$id,info2-name:$name,dir:$_dir,homeDir:$_homeDir');
|
||||
await _ffiBind.mainDeviceId(id: id);
|
||||
await _ffiBind.mainDeviceName(name: name);
|
||||
await _ffiBind.mainSetHomeDir(home: _homeDir);
|
||||
await _ffiBind.mainInit(appDir: _dir);
|
||||
} catch (e) {
|
||||
print("initialize failed: $e");
|
||||
debugPrint('initialize failed: $e');
|
||||
}
|
||||
version = await getVersion();
|
||||
}
|
||||
@ -162,9 +162,9 @@ class PlatformFFI {
|
||||
final handlers = _eventHandlers[name];
|
||||
if (handlers != null) {
|
||||
if (handlers.isNotEmpty) {
|
||||
handlers.values.forEach((handler) {
|
||||
for (var handler in handlers.values) {
|
||||
handler(evt);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -182,17 +182,17 @@ class PlatformFFI {
|
||||
// _tryHandle here may be more flexible than _eventCallback
|
||||
if (!_tryHandle(event)) {
|
||||
if (_eventCallback != null) {
|
||||
_eventCallback!(event);
|
||||
await _eventCallback!(event);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('json.decode fail(): $e');
|
||||
debugPrint('json.decode fail(): $e');
|
||||
}
|
||||
}
|
||||
}();
|
||||
}
|
||||
|
||||
void setEventCallback(void Function(Map<String, dynamic>) fun) async {
|
||||
void setEventCallback(StreamEventHandler fun) async {
|
||||
_eventCallback = fun;
|
||||
}
|
||||
|
||||
|
49
flutter/lib/utils/image.dart
Normal file
49
flutter/lib/utils/image.dart
Normal file
@ -0,0 +1,49 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
Future<ui.Image> decodeImageFromPixels(
|
||||
Uint8List pixels,
|
||||
int width,
|
||||
int height,
|
||||
ui.PixelFormat format, {
|
||||
int? rowBytes,
|
||||
int? targetWidth,
|
||||
int? targetHeight,
|
||||
bool allowUpscaling = true,
|
||||
}) async {
|
||||
if (targetWidth != null) {
|
||||
assert(allowUpscaling || targetWidth <= width);
|
||||
}
|
||||
if (targetHeight != null) {
|
||||
assert(allowUpscaling || targetHeight <= height);
|
||||
}
|
||||
|
||||
final ui.ImmutableBuffer buffer =
|
||||
await ui.ImmutableBuffer.fromUint8List(pixels);
|
||||
final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw(
|
||||
buffer,
|
||||
width: width,
|
||||
height: height,
|
||||
rowBytes: rowBytes,
|
||||
pixelFormat: format,
|
||||
);
|
||||
if (!allowUpscaling) {
|
||||
if (targetWidth != null && targetWidth! > descriptor.width) {
|
||||
targetWidth = descriptor.width;
|
||||
}
|
||||
if (targetHeight != null && targetHeight! > descriptor.height) {
|
||||
targetHeight = descriptor.height;
|
||||
}
|
||||
}
|
||||
|
||||
final ui.Codec codec = await descriptor.instantiateCodec(
|
||||
targetWidth: targetWidth,
|
||||
targetHeight: targetHeight,
|
||||
);
|
||||
|
||||
final ui.FrameInfo frameInfo = await codec.getNextFrame();
|
||||
codec.dispose();
|
||||
buffer.dispose();
|
||||
descriptor.dispose();
|
||||
return frameInfo.image;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user