fix(cursor): preserve native pixels and hotspots across display scales

Capture actual Mutter and DXGI cursor metadata, preserve Retina artwork, and invalidate cursor identities when physical pixels or DPI change. Keep straight-alpha colors during native cursor resizing and correct the Windows XOR outline offset.

Verified all six Mac/Linux/Windows directions with real pointer movement, arrow/I-beam/crosshair transitions, adaptive zoom off/on/off, Original view, and live DPI changes. Requested debug builds and focused native/Flutter regressions pass.
This commit is contained in:
fufesou
2026-09-11 11:49:04 +08:00
parent f96d00d9d1
commit 72ea38ca4f
16 changed files with 1644 additions and 12 deletions

View File

@@ -3470,6 +3470,13 @@ class CursorModel with ChangeNotifier {
img2.Image imgOrigin = img2.Image.fromBytes(
width: w, height: h, bytes: rgba.buffer, order: img2.ChannelOrder.rgba);
if (isWindows) {
final pixels =
await image.toByteData(format: ui.ImageByteFormat.rawStraightRgba);
if (pixels == null) {
throw StateError('Could not read straight-alpha cursor pixels');
}
imgOrigin = img2.Image.fromBytes(
width: w, height: h, bytes: pixels.buffer, order: img2.ChannelOrder.rgba);
data = imgOrigin.getBytes(order: img2.ChannelOrder.bgra);
} else {
ByteData? imgBytes =
@@ -3478,6 +3485,11 @@ class CursorModel with ChangeNotifier {
return false;
}
data = imgBytes.buffer.asUint8List();
if (isLinux || isMacOS) {
// Preserve the PNG's straight-alpha colors when resizing native cursors.
imgOrigin = img2.decodePng(data) ??
(throw const FormatException('Invalid native cursor PNG'));
}
}
final cache = CursorData(
peerId: peerId,