diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 4be4430e9..78612f48e 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -1101,6 +1101,9 @@ class _ImagePaintState extends State { final m = Provider.of(context); var c = Provider.of(context); final s = c.scale; + // CanvasModel caches the DPR and only refreshes it when the view style + // changes, so read it live to follow the window across monitors. + final dpr = MediaQuery.devicePixelRatioOf(context); bool isViewAdaptive() => c.viewStyle.style == kRemoteViewStyleAdaptive; bool isViewOriginal() => c.viewStyle.style == kRemoteViewStyleOriginal; @@ -1122,7 +1125,7 @@ class _ImagePaintState extends State { // pixels, so an unzoomed cursor must be shrunk by the DPR to // keep 1 remote px == 1 physical px, the size Original view // already renders it at. - cursorScale = 1.0 / c.devicePixelRatio; + cursorScale = 1.0 / dpr; } } return cursorScale; @@ -1420,8 +1423,17 @@ class CursorPaint extends StatelessWidget { scale = c.scale; } else if (!isWindows) { // Keep the painted cursor the same physical size as the native one - // built by getCursorScale() above. - scale = 1.0 / c.devicePixelRatio; + // built by getCursorScale() above, including its min-size clamp. + scale = 1.0 / MediaQuery.devicePixelRatioOf(context); + final image = m.image ?? preDefaultCursor.image; + if (scale != 1.0 && + image != null && + ((image.width * scale).toInt() < kMinCursorSize || + (image.height * scale).toInt() < kMinCursorSize)) { + final sw = kMinCursorSize / image.width; + final sh = kMinCursorSize / image.height; + scale = sw < sh ? sh : sw; + } x = (m.x * c.scale + cx) / scale - hotx; y = (m.y * c.scale + cy) / scale - hoty; }