fix, cursor (hotx,hoty) mismatch sometimes

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2023-10-03 21:16:12 +08:00
parent 03c0111017
commit 8b807d7b50
2 changed files with 46 additions and 29 deletions

View File

@ -614,7 +614,7 @@ class _ImagePaintState extends State<ImagePaint> {
} else {
final key = cache.updateGetKey(scale);
if (!cursor.cachedKeys.contains(key)) {
debugPrint("Register custom cursor with key $key");
debugPrint("Register custom cursor with key $key (${cache.hotx},${cache.hoty})");
// [Safety]
// It's ok to call async registerCursor in current synchronous context,
// because activating the cursor is also an async call and will always

View File

@ -1279,6 +1279,7 @@ class CursorModel with ChangeNotifier {
final _cacheKeys = <String>{};
double _x = -10000;
double _y = -10000;
int _id = -1;
double _hotx = 0;
double _hoty = 0;
double _displayOriginX = 0;
@ -1287,7 +1288,7 @@ class CursorModel with ChangeNotifier {
bool gotMouseControl = true;
DateTime _lastPeerMouse = DateTime.now()
.subtract(Duration(milliseconds: 3000 * kMouseControlTimeoutMSec));
String id = '';
String peerId = '';
WeakReference<FFI> parent;
ui.Image? get image => _image;
@ -1439,32 +1440,35 @@ class CursorModel with ChangeNotifier {
}
updateCursorData(Map<String, dynamic> evt) async {
var id = int.parse(evt['id']);
_hotx = double.parse(evt['hotx']);
_hoty = double.parse(evt['hoty']);
var width = int.parse(evt['width']);
var height = int.parse(evt['height']);
final id = int.parse(evt['id']);
// Update last cursor id.
_id = id;
final hotx = double.parse(evt['hotx']);
final hoty = double.parse(evt['hoty']);
final width = int.parse(evt['width']);
final height = int.parse(evt['height']);
List<dynamic> colors = json.decode(evt['colors']);
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
final image = await img.decodeImageFromPixels(
rgba, width, height, ui.PixelFormat.rgba8888);
_image = image;
if (await _updateCache(rgba, image, id, width, height)) {
_images[id] = Tuple3(image, _hotx, _hoty);
} else {
_hotx = 0;
_hoty = 0;
}
try {
// my throw exception, because the listener maybe already dispose
notifyListeners();
} catch (e) {
debugPrint('WARNING: updateCursorId $id, without notifyListeners(). $e');
if (await _updateCache(rgba, image, id, hotx, hoty, width, height)) {
_images[id] = Tuple3(image, hotx, hoty);
}
// Update last cursor data.
// Do not use the previous `image` and `id`, because `_id` may be changed.
_updateCursorIdData(_id);
}
Future<bool> _updateCache(
Uint8List rgba, ui.Image image, int id, int w, int h) async {
Uint8List rgba,
ui.Image image,
int id,
double hotx,
double hoty,
int w,
int h,
) async {
Uint8List? data;
img2.Image imgOrigin = img2.Image.fromBytes(
width: w, height: h, bytes: rgba.buffer, order: img2.ChannelOrder.rgba);
@ -1478,31 +1482,44 @@ class CursorModel with ChangeNotifier {
}
data = imgBytes.buffer.asUint8List();
}
_cache = CursorData(
peerId: this.id,
final cache = CursorData(
peerId: peerId,
id: id,
image: imgOrigin,
scale: 1.0,
data: data,
hotxOrigin: _hotx,
hotyOrigin: _hoty,
hotxOrigin: hotx,
hotyOrigin: hoty,
width: w,
height: h,
);
_cacheMap[id] = _cache!;
_cacheMap[id] = cache;
return true;
}
updateCursorId(Map<String, dynamic> evt) async {
final id = int.parse(evt['id']);
bool _updateCursorIdData(int id) {
_cache = _cacheMap[id];
final tmp = _images[id];
if (tmp != null) {
_image = tmp.item1;
_hotx = tmp.item2;
_hoty = tmp.item3;
notifyListeners();
try {
// may throw exception, because the listener maybe already dispose
notifyListeners();
} catch (e) {
debugPrint(
'WARNING: updateCursorId $id, without notifyListeners(). $e');
}
return true;
} else {
return false;
}
}
updateCursorId(Map<String, dynamic> evt) async {
final id = int.parse(evt['id']);
if (!_updateCursorIdData(id)) {
debugPrint(
'WARNING: updateCursorId $id, cache is ${_cache == null ? "null" : "not null"}. without notifyListeners()');
}
@ -1748,7 +1765,7 @@ class FFI {
connType = ConnType.defaultConn;
canvasModel.id = id;
imageModel.id = id;
cursorModel.id = id;
cursorModel.peerId = id;
}
// If tabWindowId != null, this session is a "tab -> window" one.
// Else this session is a new one.