Merge pull request #5901 from fufesou/fix/cursor_hotxy_mismatch
fix, cursor (hotx,hoty) mismatch sometimes
This commit is contained in:
		
						commit
						a723518346
					
				@ -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