Repository navigation
[web] Let the browser handle Control+wheel zoom outside of macOS - #193362
diegolopezrm wants to merge 6 commits into
Conversation
Browsers report trackpad pinch gestures as wheel events with ctrlKey set, and since flutter-team-archive/engine#36348 every such event is turned into a scale signal and cancelled. That also swallows the user holding the Control key and turning the mouse wheel, which is the browser's zoom shortcut on Windows, Linux and ChromeOS, so those pages could no longer be zoomed. Tell the two apart the same way the macOS code path already does: a pinch never involves a physical Control key press. When the key is held, leave the event to the browser instead of forwarding or cancelling it. Fixes flutter#129933
There was a problem hiding this comment.
Code Review
This pull request updates the web engine's pointer binding to identify browser zoom shortcuts (Control+wheel) on platforms outside of macOS and iOS, allowing the browser to handle the zoom instead of forwarding the event to the framework. A test is added to verify this behavior. The review feedback suggests resetting ui.PlatformDispatcher.instance.onPointerDataPacket to null at the end of the new test to prevent test pollution.
flutter-zl
left a comment
There was a problem hiding this comment.
Verified on Linux Chrome with before/after builds:
Before: https://flutter-demo-81-before.web.app (master engine): Control+wheel does not zoom, Flutter receives PointerScaleEvents.
After: https://flutter-demo-81-after.web.app (this PR's engine): Control+wheel zooms the page, Flutter receives nothing. Plain wheel still scrolls.
LGTM.
Optional nit: isMacOrIOS from browser_detection.dart could replace the two enum comparisons in _isBrowserZoomShortcut.
|
autosubmit label was removed for flutter/flutter/193362, because - The status or check suite ci.yaml validation has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/193362, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/193362, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/193362, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/193362, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
Hi @diegolopezrm , there is a test failure: Analyzing flutter... info - lib/web_ui/test/engine/pointer_binding_test.dart:1369:16 - Omit the type annotation on a local variable when the type is obvious. Try removing the type annotation. - omit_obvious_local_variable_types 1 issue found. |
0e270cc
|
Thanks @flutter-zl, fixed in 0e270cc: the loop variable no longer repeats its type. Could you add CICD and autosubmit back when you get a chance? |
|
autosubmit label was removed for flutter/flutter/193362, because This PR has not met approval requirements for merging. The PR author is not a member of flutter-hackers and needs 1 more review(s) in order to merge this PR.
|
|
Thanks @flutter-zl! The bot says it needs a second approval since I'm not in flutter-hackers. @mdebbar, would you have a minute to take a look? |
The problem
On Windows and Linux, holding Control and turning the mouse wheel zooms the page in every browser. In a Flutter web app it does nothing: the page does not zoom and the app does not react either. Control+Plus and Control+Minus still work, as the reporter noted, which makes the wheel feel broken rather than deliberately disabled.
Issue: #129933
Root cause
Browsers report a trackpad pinch as a
wheelevent withctrlKeyset. Since flutter-team-archive/engine#36348 (Flutter 3.10) the web engine turns everywheelevent withctrlKeyinto aPointerSignalKind.scaleand callspreventDefault()on it, so thatInteractiveViewerand friends can zoom on pinch. That is right for a pinch. But a user holding the Control key and turning the wheel produces exactly the same event, and gets swallowed with it.Before that change
_handleWheelEventhad this:The macOS path already knows how to tell the two apart: it asks the keyboard converter whether a physical Control key is held, because a pinch never involves a key press. Windows and Linux never got that check, which is how they lost browser zoom.
The fix
_isBrowserZoomShortcutapplies the same physical-key check on every platform except macOS and iOS. When the user is holding Control and turning the wheel,_handleWheelEventreturns before forwarding the event to the framework and without cancelling it, so the browser zooms the page the way it does on any other site. A pinch still reaches the framework as a scale signal and is still cancelled, so nothing changes forInteractiveViewer.macOS keeps its current behaviour on purpose: Control+wheel does not zoom the browser there, and the existing code already reports it as a plain scroll.
ctrlKey, no key held)The one behavioural change is for an app that relied on getting a
PointerScaleEventfrom a mouse wheel with Control held on Windows or Linux. That never worked on macOS, did not work before 3.10, and it competes with the browser's own shortcut, so restoring the pre-3.10 behaviour looks like the right call to me. If the team would rather keep delivering the event and only skippreventDefault(), I am happy to change it.Testing
leaves Control+wheel to the browser outside of macOSinpointer_binding_test.dartcovers Windows and Linux: a pinch is delivered as a scale and cancelled, a wheel with Control physically held is neither delivered nor cancelled, and releasing the key brings scrolling back.felt test --gcs-prod --compiler dart2js test/engine/pointer_binding_test.dartpasses (73 tests), and I checked that the new test fails without the fix.does choose scroll vs scale based on ctrlKeytest still passes, so the macOS path is unchanged.Pre-launch Checklist
///).Notes on the checklist: the only behaviour that changes is described in the table above, and it restores what the engine did before 3.10. There is no API change, so no Data Driven Fixes apply.