paint: Use viewport meta tag's min-scale and max-scale to clamp pinch zoom#40098
Conversation
I compared the behavior on Android and OHOS device, they use viewport values and restrict the pinch zoom accordingly. cc: @xiaochengh |
mrobinson
left a comment
There was a problem hiding this comment.
This just needs a bit of justification:
| if let Some(viewport) = self.viewport_description.as_ref() { | ||
| requested_pinch_zoom = viewport.clamp_page_zoom(requested_pinch_zoom); | ||
| } | ||
|
|
||
| let old_zoom = | ||
| std::mem::replace(&mut self.pinch_zoom, PinchZoomFactor::new(new_pinch_zoom)); | ||
| let old_zoom = std::mem::replace( | ||
| &mut self.pinch_zoom, | ||
| PinchZoomFactor::new(requested_pinch_zoom), | ||
| ); |
There was a problem hiding this comment.
What happens when you combine pinch zoom and page zoom on these devices? Where in the specification does it mention that this should the non-layout viewport? Failing that, can you somehow explain the reasoning used by the other browsers and what their general strategy is with clamping values from the viewport metatag (an internal bug report or link to the code would suffice to)?
There was a problem hiding this comment.
Splitting the scenarios observed on Chrome:
- Mobile Devices: Supports Viewport Meta via pref, and when pinch zoom it is clamped as per meta viewport. When page zoomed using zoom option aka desktop zoom, it has range from 50% to 300% using slider.
- Desktop Devices: Doesn't support Viewport Meta via pref, no pinch zoom only desktop zoom using preset values range from 25% to 500%.
- Desktop Devices (with touch screen): Doesn't support Viewport Meta via pref, when pinch zoom, since no viewport meta parsed it gets clamped in default range and when desktop style zoom applied, it uses preset value range from 25% to 500%.
@mrobinson I have added the table for more clarity. Tell me know if you have any other concerns.
There was a problem hiding this comment.
@shubhamg13 Some clarification:
When I ask how pinch zoom / page zoom interact here. I mean to ask whether or not combining pinch zoom and page zoom affect the clamping. For instance if page zoom is 2x, does that mean that we should clamp pinch zoom to [min_zoom / 2, max_zoom / 2]? If you first apply a page zoom, does it change the range of available pinch zoom values?
In addition, I'm looking for some justification to explain why this change is necessary. FWIW, I believe you that it is, but it just needs to reasoned so that it does not regress again. For example, the viewport meta tag was changed to only affect the page zoom viewport in #40055 and this change undoes some of that work. You also proposed a related change, so I'm pretty confused. We just need to be clear on what viewport it should affect. It seems quite odd that parts of the meta tag affect the layout viewport and others the visual viewport.
So we either need:
- Specification text that describes how this is supposed to work.
- In the case that this is underspecified either:
- A link to a bug from another browser where the implementation and what viewport it affects is discussed.
- A link to the code which shows how this works in other browsers.
There was a problem hiding this comment.
When I ask how pinch zoom / page zoom interact here. I mean to ask whether or not combining pinch zoom and page zoom affect the clamping. For instance if page zoom is 2x, does that mean that we should clamp pinch zoom to
[min_zoom / 2, max_zoom / 2]? If you first apply a page zoom, does it change the range of available pinch zoom values?
No they aren't combined. They are applied irrespective of each other having their separate clamping range.
And this change is required due to inconsistency observed as compared to Chrome.
P.S: I'll try to find some reference.
There was a problem hiding this comment.
2. A link to the code which shows how this works in other browsers.
- Here, In chromium PinchZoom is applied by first fetching the current
page_scale, and applyingmagnify_deltaover that. - Inside, it is clamped here.
- And I further backtracked, its range comes from viewport_description
There was a problem hiding this comment.
What you call "Desktop Zoom" in the table above is typically called "page zoom" and that's what we call it in Servo. I'm not sure how you were able to test this in the mobile version of Chrome as it no longer seems to be enabled in the Chrome browser. What did you do to test this? I am skeptical that it would be adjust the pinch zoom as these are very different concepts. Maybe whatever you were doing to test was adjusting the pinch zoom?
Safari for iOS does support reflowing style page zoom. I can try to see what its behavior is.
There was a problem hiding this comment.
I'm not sure how you were able to test this in the mobile version of Chrome as it no longer seems to be enabled in the Chrome browser. What did you do to test this?
Updated table headings, PTAL.
- Zoom (using menu): Click on More Menu (⋮) -> Zoom
- Zoom (using keyboard) on Mobile: Connect Bluetooth Keyboard
Let me know what scenarios steps you are suspicious about.
Safari for iOS does support reflowing style page zoom. I can try to see what its behavior is.
-
Safari and Chrome on iOS uses WebKit.
-
On the other hand Chrome Desktop and Chrome Android use Blink.
IMHO our comparison should be with Blink Engine, right?
There was a problem hiding this comment.
@mrobinson Chrome even provides an override switch to zoom where websites prevent zoom.
Reference 1
-
To zoom in on pages that prevent zoom, turn on Force enable zoom.
Reference 2
- Websites can only control via
<viewport> meta - They control pinch-zoom via this toogle switch.
When user enabled force enable zoom, we should always allow pinch-zoom [1]
bfb13e7 to
bf203f5
Compare
bfc53e1 to
c36a956
Compare
c36a956 to
95a2320
Compare
ddb132d to
398c14e
Compare
|
Please help to review |
a303c1a to
bf8e887
Compare
|
|
||
| /// Constrains a zoom value within the allowed scale range | ||
| pub fn clamp_page_zoom(&self, zoom: f32) -> f32 { | ||
| pub fn clamp_zoom(&self, zoom: f32) -> f32 { |
There was a problem hiding this comment.
Please name this to be explicit ie clamp_pinch_zoom.
There was a problem hiding this comment.
I am using it for both the zooms now.
There was a problem hiding this comment.
Where in the specification does it say that it should be used to clamp both values? Everything that I have read suggests that it should be used to clamp the visual viewport (pinch zoom / page scale). If you clamp both values separately, I do not think this will have the correct behavior when both a page zoom and pinch zoom are applied -- which was my original question.
There was a problem hiding this comment.
I just use the fallback behavior for clamping by using DEFAULT. Yes they should be different indeed.
In Chrome they have page Zoom Range of 0.25 to 50.0. But In Servo our Range was 0.1 and 10.0 as you didn't agree for this here.
There was a problem hiding this comment.
If they should be separate, let's separate these concepts fully. If we still need to clamp the page zoom range via a hardcoded set of values create two new constants:
MINIMUM_PAGE_ZOOMMAXIMUM_PAGE_ZOOM
in the code unit that needs to clamp page zoom. Then we can stop clamping page zoom at all using the ViewportDescription.
There was a problem hiding this comment.
Sure will do, What range do you suggest for this...
There was a problem hiding this comment.
I think we should just maintain the current behavior for page zooms.
There was a problem hiding this comment.
Sure. Reverting changes for I made with page zoom.
There was a problem hiding this comment.
Everything that I have read suggests that it should be used to clamp the visual viewport (pinch zoom / page scale).
With this conclusion of yours and coming to sole and primary goal of this PR. Please take a look and review
P.S: Sorry for lot of back and forth changes. I removed all the unrelated changes.
| let new_page_zoom = self | ||
| .viewport_description | ||
| .unwrap_or_default() | ||
| .clamp_zoom(new_page_zoom); |
There was a problem hiding this comment.
Why are you clamping page zoom here as this change is about making the viewport metatag clamp pinch zoom. Why would it clamp both values? If page zoom needs to be clamped it should certain be a separate set of values as these concepts are distinct aren't they?
There was a problem hiding this comment.
Basically it does same thing,
- For Desktop (Meta not Parsed):, use Defualt Values
- For Mobile (Meta Parsed): use Meta Values
Same as Chrome and ChromeAndroid
There was a problem hiding this comment.
I'm pretty unconvinced by this, but I would change my mind if you could justify this choice by helping my understand how the specification says we should do this.
There was a problem hiding this comment.
Please take a look over the table for observed behavior in Chrome (Firefox also has same behavior)
There seems no explicit specs for this, I found inconsistent behavior with chrome that's it.
There was a problem hiding this comment.
If there is no specification, let's keep this simple. Can we only use the <meta viewport> tag to clamp pinch zoom and nothing else?
There was a problem hiding this comment.
Yes, that's the goal.
| let new_factor = self | ||
| .viewport_description | ||
| .unwrap_or_default() | ||
| .clamp_zoom(factor * new_pinch_zoom.zoom_factor().get()); |
There was a problem hiding this comment.
You are clamping each individual pinch zoom delta here rather than the final value. This will lead to incorrect results. You need to figure out what the final value will be and clamp that.
There was a problem hiding this comment.
I am clamping delta*existing_zoom_factor
There was a problem hiding this comment.
I see. I think you were on the right track before clamping inside of PinchZoom. Theoretically there could be some other caller to PinchZoom::zoom() and the behavior should be consistent.
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
@mrobinson And coming to sole and only purpose of this PR. Please take a look and review. P.S: Sorry for lot of back and forth changes. I removed all the unrelated changes. |
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
|
✍ Updated existing upstream WPT pull request (web-platform-tests/wpt#58805) title and body. |
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
3 similar comments
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
| <script> promise_test(async () => { | ||
| const x = 200, y = 200; | ||
| const initialScale = window.visualViewport.scale; | ||
| // Perform pinch zoom |
There was a problem hiding this comment.
Are there other tests that perform a pinch zoom like this? If so this is probably fine, but otherwise this should likely be a Servo-only test.
There was a problem hiding this comment.
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
|
✍ Updated existing upstream WPT pull request (web-platform-tests/wpt#58805) title and body. |
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
| @@ -1,3 +1,7 @@ | |||
| [pointerevent_touch-action_two-finger_interaction.html] | |||
| expected: TIMEOUT | |||
There was a problem hiding this comment.
IMO this was false positive as Servo doesn't support touch-action due to which this was removed from MQ.
There was a problem hiding this comment.
Any idea why the test starts to fail now though? It doesn't seem to be using the viewport metatag, so it seems that this change if modifying the behavior of Servo even when the viewport metatag isn't used -- which seems wrong.
There was a problem hiding this comment.
With this PR the clamp range is 0.1 to 10.0 so this is affecting the test. Adding the workaround back.
There was a problem hiding this comment.
We should not allow pinch zooming to values below 1 by default.
There was a problem hiding this comment.
Yeah, when I enable it in here #43688. I will add a check for same.
Signed-off-by: Shubham Gupta <[email protected]>
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
|
🔨 Triggering try run (#23936449766) for Linux (WPT) |
|
Test results for linux-wpt from try job (#23936449766): Flaky unexpected result (29)
Stable unexpected results that are known to be intermittent (19)
|
|
✨ Try run (#23936449766) succeeded. |
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
Signed-off-by: Shubham Gupta <[email protected]>
Signed-off-by: Shubham Gupta <[email protected]>
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#58805). |
| if new_factor <= 1.0 { | ||
| self.zoom_factor = 1.0; // Update the zoom factor to 1.0 to avoid precision issues when zooming back in after zooming out fully. | ||
| self.transform = Transform2D::identity(); | ||
| return; |
There was a problem hiding this comment.
This does seem like it will cause an issue in the case that the ViewportDescription does say that we should be able to pinch zoom to values below 1.0. Would it make sense to change the default minimum zoom in ViewportDescription to be 1.0?
There was a problem hiding this comment.
There are some websites that have initial-scale as 0.5. We should support entire range from 0.1 to 10.0, but selectively modify depending on platforms.
There was a problem hiding this comment.
In those cases it seems that the ViewportDescription will no longer be the default one and so when you call clamp on the new value it will be clamped properly to [0.5, ...].
There was a problem hiding this comment.
Yes, that's what exactly I am doing ( in PR where I support for scale less than 1, yet to push or I can add separate PR if you say)
Note: Targeting Mobile devices only.
Clamp Pinch Zoom factor using
viewport' scale range parsed from<meta>tag.Behavior in Servo with this PR
Observed behavior in Chrome:
References from Chromium:
Testing: New WPT Test Added:
wpt/visual-viewport/viewport-scale-clamped.htmlFixes: #40390 (Observed Inconsistent behavior with Chrome Android)