Fix native cursor display selection during local movement

This commit is contained in:
fufesou
2026-09-12 21:46:28 +08:00
parent 4d064a8445
commit 371e5e8f2d
3 changed files with 285 additions and 4 deletions

View File

@@ -1120,7 +1120,8 @@ class _ImagePaintState extends State<ImagePaint> {
// Density metadata is optional. Keep the legacy path for hosts that
// omit it so capture-backend upgrades are not a client prerequisite.
final imageScale = isViewScaled() && zoomCursor.value
? _cursorImageScale(widget.ffi, cursor) : s;
? _cursorImageScale(widget.ffi, cursor, useLocalPointer: true)
: s;
var cursorScale = 1.0;
if (isWindows) {
// debug win10
@@ -1477,7 +1478,8 @@ class CursorPaint extends StatelessWidget {
// Match physical video pixels, independently of the cursor's density metadata:
// a single DRM output keeps physical desktop coordinates even at high DPI.
double _cursorImageScale(FFI ffi, CursorModel cursor) {
double _cursorImageScale(FFI ffi, CursorModel cursor,
{bool useLocalPointer = false}) {
final canvas = ffi.canvasModel;
final peer = ffi.ffiModel;
if (!peer.isPeerLinux) return canvas.scale;
@@ -1491,7 +1493,11 @@ double _cursorImageScale(FFI ffi, CursorModel cursor) {
if (displays.length == 1) return canvas.scale / displays.first.scale;
final rect = peer.rect;
if (rect != null) {
final position = Offset(cursor.x + rect.left, cursor.y + rect.top);
// Local input drives native sizing; host positions still drive the overlay.
// Before the first local movement, retain the existing position source.
final position =
(useLocalPointer ? ffi.inputModel.remotePointerPosition.value : null) ??
Offset(cursor.x + rect.left, cursor.y + rect.top);
for (final display in displays) {
if (Rect.fromLTWH(display.x, display.y, display.width / display.scale,
display.height / display.scale).contains(position)) {

View File

@@ -449,6 +449,8 @@ class InputModel {
final isPhysicalMouse = false.obs;
int _lastButtons = 0;
Offset lastMousePos = Offset.zero;
// Host position echoes may be absent; keep locally mapped input separately.
final remotePointerPosition = Rxn<Offset>();
int _lastWheelTsUs = 0;
// Wheel acceleration thresholds.
@@ -1954,7 +1956,7 @@ class InputModel {
canvasModel.updateLocalCursor(x, y);
}
return _handlePointerDevicePos(
final point = _handlePointerDevicePos(
kind,
x,
y,
@@ -1965,6 +1967,20 @@ class InputModel {
onExit: onExit,
buttons: buttons,
);
_rememberRemotePointer(point, isMove);
return point;
}
void _rememberRemotePointer(Point? point, bool isMove) {
final peer = parent.target!.ffiModel;
if (point == null ||
!isMove ||
!(isDesktop || isWebDesktop) ||
peer.pi.currentDisplay != kAllDisplayValue ||
!peer.isPeerLinux) {
return;
}
remotePointerPosition.value = Offset(point.x.toDouble(), point.y.toDouble());
}
bool _isInCurrentWindow(double x, double y) {