renderer: Have the viewport meta element establish the initial zoom of new pages (#37315)

This patch contains 2 components: 

1. Instead of passing `self.pinch_zoom_level().get()` while checking
`zoom_result`, initialize it in `combined_magnification`. Ideally, this
part shouldn't have any effect on behavior.

2. Separates the logic for PinchZoom and ViewportZoom. So, when a new
page is opened, it will start with its own viewport zoom scale (rather
than the previous scale multiples).
i.e `self.pinch_zoom_level().get() * 1.0 * magnification`
```rust
        let mut combined_magnification = 1.0;
        ... 
                ScrollZoomEvent::ViewportZoom(magnification) => {
                    combined_magnification *= magnification
                },
        ...        
        let pinch_zoom_result = match self.set_pinch_zoom_level(self.pinch_zoom_level().get() * combined_magnification)
``` 





Testing: This change adds a new WPT test.
Fixes: #37314

---------

Signed-off-by: Shubham Gupta <shubham13297@gmail.com>
This commit is contained in:
Shubham Gupta 2025-07-15 21:54:05 +08:00 committed by GitHub
parent 547ce67514
commit 34829dfce7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 83 additions and 11 deletions

View file

@ -44,8 +44,8 @@ struct ScrollEvent {
enum ScrollZoomEvent {
/// A pinch zoom event that magnifies the view by the given factor.
PinchZoom(f32),
/// A zoom event that magnifies the view by the factor parsed from meta tag.
ViewportZoom(f32),
/// A zoom event that establishes the initial zoom from the viewport meta tag.
InitialViewportZoom(f32),
/// A scroll event that scrolls the scroll node at the given location by the
/// given amount.
Scroll(ScrollEvent),
@ -799,13 +799,16 @@ impl WebViewRenderer {
// Batch up all scroll events into one, or else we'll do way too much painting.
let mut combined_scroll_event: Option<ScrollEvent> = None;
let mut base_page_zoom = self.pinch_zoom_level().get();
let mut combined_magnification = 1.0;
for scroll_event in self.pending_scroll_zoom_events.drain(..) {
match scroll_event {
ScrollZoomEvent::PinchZoom(magnification) |
ScrollZoomEvent::ViewportZoom(magnification) => {
ScrollZoomEvent::PinchZoom(magnification) => {
combined_magnification *= magnification
},
ScrollZoomEvent::InitialViewportZoom(magnification) => {
base_page_zoom = magnification
},
ScrollZoomEvent::Scroll(scroll_event_info) => {
let combined_event = match combined_scroll_event.as_mut() {
None => {
@ -862,12 +865,11 @@ impl WebViewRenderer {
);
}
let pinch_zoom_result = match self
.set_pinch_zoom_level(self.pinch_zoom_level().get() * combined_magnification)
{
true => PinchZoomResult::DidPinchZoom,
false => PinchZoomResult::DidNotPinchZoom,
};
let pinch_zoom_result =
match self.set_pinch_zoom_level(base_page_zoom * combined_magnification) {
true => PinchZoomResult::DidPinchZoom,
false => PinchZoomResult::DidNotPinchZoom,
};
(pinch_zoom_result, scroll_result)
}
@ -1035,7 +1037,7 @@ impl WebViewRenderer {
pub fn set_viewport_description(&mut self, viewport_description: ViewportDescription) {
self.pending_scroll_zoom_events
.push(ScrollZoomEvent::ViewportZoom(
.push(ScrollZoomEvent::InitialViewportZoom(
viewport_description
.clone()
.clamp_zoom(viewport_description.initial_scale.get()),

View file

@ -373460,6 +373460,21 @@
}
}
},
"visual-viewport": {
"viewport-apply-initial-scale-after-navigation.html": [
"ec03c380d6d27ed0b486a26203d441dc101fd39f",
[
null,
[
[
"/visual-viewport/viewport-apply-initial-scale-after-navigation-ref.html",
"=="
]
],
{}
]
]
},
"web-animations": {
"animation-model": {
"keyframe-effects": {
@ -522286,6 +522301,16 @@
"c036b16ec87bc7e562c4040ad1923c5a8b483cec",
[]
],
"resource": {
"viewport-apply-initial-scale-after-navigation-inner.html": [
"edbf5dbb70aa916363ff32eab847f2d03562d4f5",
[]
]
},
"viewport-apply-initial-scale-after-navigation-ref.html": [
"904d370d6b464ef526b79e3974532d3f2c57d13b",
[]
],
"viewport_support.js": [
"a82bd2b028010e053199e55bd7bb357361581e6f",
[]

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<title>Viewport: Apply initial-scale after Navigation</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="/common/reftest-wait.js"></script>
<script>
onload = takeScreenshot;
</script>
</head>
<body>
<h1>Viewport: Apply initial-scale after Navigation</h1>
<p>Test passes if page opens with own initial-scale of 1.0</p>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Viewport: Apply initial-scale after Navigation</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>Viewport: Apply initial-scale after Navigation</h1>
<p>Test passes if page opens with own initial-scale of 1.0</p>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<title>Viewport: Apply initial-scale after Navigation</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=2.0">
<link rel="match" href="viewport-apply-initial-scale-after-navigation-ref.html">
<script src="/common/reftest-wait.js"></script>
<script>
function runTest() {
const url = "resource/viewport-apply-initial-scale-after-navigation-inner.html";
window.location.replace(new URL(url, window.location));
}
onload = () => runTest();
</script>
</head>
</html>