pdfrx icon indicating copy to clipboard operation
pdfrx copied to clipboard

Flutter Web on Windows: Ctrl+Wheel event is directly handled by Flutter and results in incorrect boundaryMargin

Open espresso3389 opened this issue 1 month ago • 8 comments

Related: #538

It seems Flutter Web on Windows, it handles Ctrl+Wheel events inside Flutter engine and we didn't receive PointerScrollEvent but PointerScaleEvent inside InteractiveViewer. And it results in incorrect boundaryMargin in scaling if scrollPhysics is specified explicitly.

https://github.com/user-attachments/assets/8feec1b7-6741-49c8-8761-4bdca3f1fee2

So, on such situation, the simple solution is just set scrollPhysics to null on these platforms. But PdfViewerParams.getScrollPhysics, that is normally considered to be "safe automatic mode", does not return null on the situation and it results in such behavior.

@enhancient I think, the behavior of PdfViewerParams.getScrollPhysics seems problematic and it should not be used so far. Basically, I don't understand the design of the function and I think we should not use it. Or changing behavior/design to return null for such cases. How do you think?

espresso3389 avatar Nov 20 '25 17:11 espresso3389

BTW, I think this is the last issue to be fixed on pdfrx 2.0 series. After closing this, we can go for pdfrx 3.0!

espresso3389 avatar Nov 20 '25 17:11 espresso3389

Did 606b39a1b3327aabf4db8148dea63867cf60e981 fix this?

As for getScrollPhysics, the idea is to provide sensible defaults for a PDF reader - Flutter already has a ScrollConfiguration.of(context).getScrollPhysics(context) to determine the platform default, but we wrap that and for Android used a FixedOverscrollPhysics() which is a custom ScrollPhysics that provides some overscroll. A lot of PDF readers on Android try to mimic this kind of iOS overscroll so I think it's a good option.

>   /// A convenience function to get platform-specific default scroll physics.
>   ///
>   /// On iOS/MacOS this is [BouncingScrollPhysics], and on Android this is [FixedOverscrollPhysics], a
>   /// custom [ScrollPhysics] that allows fixed overscroll on pan/zoom and snapback.
>   static ScrollPhysics getScrollPhysics(BuildContext context) {
>     if (isAndroid) {
>       return FixedOverscrollPhysics();
>     } else {
>       return ScrollConfiguration.of(context).getScrollPhysics(context);
>     }
>   }

We definitely need ScrollPhysics to work on all platforms though because for the PageTransition.discrete we need InteractiveViewer to manage boundaries, so relying on a null ScrollPhysics isn't desirable. We default to ClampingScrollPhysics if no ScrollPhysics is defined but pageTransition is defined. If we need different ScrollPhysics behavior on Windows we should consider what this might look like.

enhancient avatar Nov 20 '25 21:11 enhancient

Did https://github.com/espresso3389/pdfrx/commit/606b39a1b3327aabf4db8148dea63867cf60e981 fix this?

No. I could not debug the things deeply but only setting null to scrollPhysics fixes the issue. The same things may happen seems to happen on Flutter Web macOS but I don't know exactly; the problem is that the current pdfrx code has things that assumes scrollPhysics ==|!= null.

espresso3389 avatar Nov 20 '25 22:11 espresso3389

It seems the situation is almost same on Flutter Web on Linux. In theory, setting debugDefaultTargetPlatformOverride = TargetPlatform.windows on Flutter Web will reproduce the issue also on macOS. And it seems I can reproduce it though Ctrl+Wheel could not work reliably on macOS (#538).

Anyway, I've find another issue, it seems that overscroll bouncing does not work if we do wheel-scroll on macOS with scrollPhysics on (not related to TargetPlatform.windows).

It seems that the ultimate cause for these issues are same.

Image

espresso3389 avatar Nov 20 '25 23:11 espresso3389

I can see the issue on Flutter Web on MacOS too. I'm looking into it.

A mouse wheel scroll should not encounter resistance and cause a bounce-back, but be clamped when hitting a boundary.

enhancient avatar Nov 20 '25 23:11 enhancient

I've discovered the issue - the _receivedPointerSignal method in InteractiveViewer used to handle mouse wheel and trackpad events on web was setting the matrix without clamping. I've added a simple fix in #548 to clamp the matrix and now it will not overshoot when using the mouse wheel or trackpad on web.

enhancient avatar Nov 21 '25 01:11 enhancient

#548 fixes the problematic behavior on zoom-out. But there seems still problems on zoom-in. Should I add more clamping code?

https://github.com/user-attachments/assets/13928153-1e43-4569-804d-23e9eadfcad5

espresso3389 avatar Nov 21 '25 02:11 espresso3389

I can't reproduce this - how did you zoom in exactly? For me on macOS web in chrome when I zoom in with the trackpad it re centers.

enhancient avatar Nov 21 '25 03:11 enhancient