Merge pull request #5901 from fufesou/fix/cursor_hotxy_mismatch
fix, cursor (hotx,hoty) mismatch sometimes
This commit is contained in:
commit
a723518346
flutter/lib
@ -614,7 +614,7 @@ class _ImagePaintState extends State<ImagePaint> {
|
|||||||
} else {
|
} else {
|
||||||
final key = cache.updateGetKey(scale);
|
final key = cache.updateGetKey(scale);
|
||||||
if (!cursor.cachedKeys.contains(key)) {
|
if (!cursor.cachedKeys.contains(key)) {
|
||||||
debugPrint("Register custom cursor with key $key");
|
debugPrint("Register custom cursor with key $key (${cache.hotx},${cache.hoty})");
|
||||||
// [Safety]
|
// [Safety]
|
||||||
// It's ok to call async registerCursor in current synchronous context,
|
// It's ok to call async registerCursor in current synchronous context,
|
||||||
// because activating the cursor is also an async call and will always
|
// because activating the cursor is also an async call and will always
|
||||||
|
@ -203,10 +203,12 @@ class FfiModel with ChangeNotifier {
|
|||||||
updatePrivacyMode(data.updatePrivacyMode, sessionId, peerId);
|
updatePrivacyMode(data.updatePrivacyMode, sessionId, peerId);
|
||||||
setConnectionType(peerId, data.secure, data.direct);
|
setConnectionType(peerId, data.secure, data.direct);
|
||||||
await handlePeerInfo(data.peerInfo, peerId);
|
await handlePeerInfo(data.peerInfo, peerId);
|
||||||
for (var element in data.cursorDataList) {
|
for (final element in data.cursorDataList) {
|
||||||
|
updateLastCursorId(element);
|
||||||
await handleCursorData(element);
|
await handleCursorData(element);
|
||||||
}
|
}
|
||||||
await handleCursorId(data.lastCursorId);
|
updateLastCursorId(data.lastCursorId);
|
||||||
|
handleCursorId(data.lastCursorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: why called by two position
|
// todo: why called by two position
|
||||||
@ -225,9 +227,11 @@ class FfiModel with ChangeNotifier {
|
|||||||
} else if (name == 'switch_display') {
|
} else if (name == 'switch_display') {
|
||||||
handleSwitchDisplay(evt, sessionId, peerId);
|
handleSwitchDisplay(evt, sessionId, peerId);
|
||||||
} else if (name == 'cursor_data') {
|
} else if (name == 'cursor_data') {
|
||||||
|
updateLastCursorId(evt);
|
||||||
await handleCursorData(evt);
|
await handleCursorData(evt);
|
||||||
} else if (name == 'cursor_id') {
|
} else if (name == 'cursor_id') {
|
||||||
await handleCursorId(evt);
|
updateLastCursorId(evt);
|
||||||
|
handleCursorId(evt);
|
||||||
} else if (name == 'cursor_position') {
|
} else if (name == 'cursor_position') {
|
||||||
await parent.target?.cursorModel.updateCursorPosition(evt, peerId);
|
await parent.target?.cursorModel.updateCursorPosition(evt, peerId);
|
||||||
} else if (name == 'clipboard') {
|
} else if (name == 'clipboard') {
|
||||||
@ -651,9 +655,13 @@ class FfiModel with ChangeNotifier {
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCursorId(Map<String, dynamic> evt) async {
|
updateLastCursorId(Map<String, dynamic> evt) {
|
||||||
|
parent.target?.cursorModel.id = int.parse(evt['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCursorId(Map<String, dynamic> evt) {
|
||||||
cachedPeerData.lastCursorId = evt;
|
cachedPeerData.lastCursorId = evt;
|
||||||
await parent.target?.cursorModel.updateCursorId(evt);
|
parent.target?.cursorModel.updateCursorId(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCursorData(Map<String, dynamic> evt) async {
|
handleCursorData(Map<String, dynamic> evt) async {
|
||||||
@ -1279,6 +1287,7 @@ class CursorModel with ChangeNotifier {
|
|||||||
final _cacheKeys = <String>{};
|
final _cacheKeys = <String>{};
|
||||||
double _x = -10000;
|
double _x = -10000;
|
||||||
double _y = -10000;
|
double _y = -10000;
|
||||||
|
int _id = -1;
|
||||||
double _hotx = 0;
|
double _hotx = 0;
|
||||||
double _hoty = 0;
|
double _hoty = 0;
|
||||||
double _displayOriginX = 0;
|
double _displayOriginX = 0;
|
||||||
@ -1287,7 +1296,7 @@ class CursorModel with ChangeNotifier {
|
|||||||
bool gotMouseControl = true;
|
bool gotMouseControl = true;
|
||||||
DateTime _lastPeerMouse = DateTime.now()
|
DateTime _lastPeerMouse = DateTime.now()
|
||||||
.subtract(Duration(milliseconds: 3000 * kMouseControlTimeoutMSec));
|
.subtract(Duration(milliseconds: 3000 * kMouseControlTimeoutMSec));
|
||||||
String id = '';
|
String peerId = '';
|
||||||
WeakReference<FFI> parent;
|
WeakReference<FFI> parent;
|
||||||
|
|
||||||
ui.Image? get image => _image;
|
ui.Image? get image => _image;
|
||||||
@ -1301,6 +1310,8 @@ class CursorModel with ChangeNotifier {
|
|||||||
double get hotx => _hotx;
|
double get hotx => _hotx;
|
||||||
double get hoty => _hoty;
|
double get hoty => _hoty;
|
||||||
|
|
||||||
|
set id(int id) => _id = id;
|
||||||
|
|
||||||
bool get isPeerControlProtected =>
|
bool get isPeerControlProtected =>
|
||||||
DateTime.now().difference(_lastPeerMouse).inMilliseconds <
|
DateTime.now().difference(_lastPeerMouse).inMilliseconds <
|
||||||
kMouseControlTimeoutMSec;
|
kMouseControlTimeoutMSec;
|
||||||
@ -1439,32 +1450,33 @@ class CursorModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateCursorData(Map<String, dynamic> evt) async {
|
updateCursorData(Map<String, dynamic> evt) async {
|
||||||
var id = int.parse(evt['id']);
|
final id = int.parse(evt['id']);
|
||||||
_hotx = double.parse(evt['hotx']);
|
final hotx = double.parse(evt['hotx']);
|
||||||
_hoty = double.parse(evt['hoty']);
|
final hoty = double.parse(evt['hoty']);
|
||||||
var width = int.parse(evt['width']);
|
final width = int.parse(evt['width']);
|
||||||
var height = int.parse(evt['height']);
|
final height = int.parse(evt['height']);
|
||||||
List<dynamic> colors = json.decode(evt['colors']);
|
List<dynamic> colors = json.decode(evt['colors']);
|
||||||
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
|
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
|
||||||
final image = await img.decodeImageFromPixels(
|
final image = await img.decodeImageFromPixels(
|
||||||
rgba, width, height, ui.PixelFormat.rgba8888);
|
rgba, width, height, ui.PixelFormat.rgba8888);
|
||||||
_image = image;
|
if (await _updateCache(rgba, image, id, hotx, hoty, width, height)) {
|
||||||
if (await _updateCache(rgba, image, id, width, height)) {
|
_images[id] = Tuple3(image, hotx, hoty);
|
||||||
_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');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update last cursor data.
|
||||||
|
// Do not use the previous `image` and `id`, because `_id` may be changed.
|
||||||
|
_updateCurData();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _updateCache(
|
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;
|
Uint8List? data;
|
||||||
img2.Image imgOrigin = img2.Image.fromBytes(
|
img2.Image imgOrigin = img2.Image.fromBytes(
|
||||||
width: w, height: h, bytes: rgba.buffer, order: img2.ChannelOrder.rgba);
|
width: w, height: h, bytes: rgba.buffer, order: img2.ChannelOrder.rgba);
|
||||||
@ -1478,33 +1490,45 @@ class CursorModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
data = imgBytes.buffer.asUint8List();
|
data = imgBytes.buffer.asUint8List();
|
||||||
}
|
}
|
||||||
_cache = CursorData(
|
final cache = CursorData(
|
||||||
peerId: this.id,
|
peerId: peerId,
|
||||||
id: id,
|
id: id,
|
||||||
image: imgOrigin,
|
image: imgOrigin,
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
data: data,
|
data: data,
|
||||||
hotxOrigin: _hotx,
|
hotxOrigin: hotx,
|
||||||
hotyOrigin: _hoty,
|
hotyOrigin: hoty,
|
||||||
width: w,
|
width: w,
|
||||||
height: h,
|
height: h,
|
||||||
);
|
);
|
||||||
_cacheMap[id] = _cache!;
|
_cacheMap[id] = cache;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCursorId(Map<String, dynamic> evt) async {
|
bool _updateCurData() {
|
||||||
final id = int.parse(evt['id']);
|
_cache = _cacheMap[_id];
|
||||||
_cache = _cacheMap[id];
|
final tmp = _images[_id];
|
||||||
final tmp = _images[id];
|
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
_image = tmp.item1;
|
_image = tmp.item1;
|
||||||
_hotx = tmp.item2;
|
_hotx = tmp.item2;
|
||||||
_hoty = tmp.item3;
|
_hoty = tmp.item3;
|
||||||
|
try {
|
||||||
|
// may throw exception, because the listener maybe already dispose
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} else {
|
} catch (e) {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
'WARNING: updateCursorId $id, cache is ${_cache == null ? "null" : "not null"}. without notifyListeners()');
|
'WARNING: updateCursorId $_id, without notifyListeners(). $e');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCursorId(Map<String, dynamic> evt) {
|
||||||
|
if (!_updateCurData()) {
|
||||||
|
debugPrint(
|
||||||
|
'WARNING: updateCursorId $_id, cache is ${_cache == null ? "null" : "not null"}. without notifyListeners()');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1748,7 +1772,7 @@ class FFI {
|
|||||||
connType = ConnType.defaultConn;
|
connType = ConnType.defaultConn;
|
||||||
canvasModel.id = id;
|
canvasModel.id = id;
|
||||||
imageModel.id = id;
|
imageModel.id = id;
|
||||||
cursorModel.id = id;
|
cursorModel.peerId = id;
|
||||||
}
|
}
|
||||||
// If tabWindowId != null, this session is a "tab -> window" one.
|
// If tabWindowId != null, this session is a "tab -> window" one.
|
||||||
// Else this session is a new one.
|
// Else this session is a new one.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user