Commit 6c7fa9ea authored by Jinfeng Ma's avatar Jinfeng Ma Committed by Commit Bot

CSS @media (width: *px) may not work if devicePixelRatio is greater than 1.

When devicePixelRatio is greater than 1, the viewport size of the CSS media
query may appear as non-integers. This can happen in Chrome for Android if
the UseZoomForDSF flag is enabled.

For example:
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
    @media (width: 393px) {
        p {
            color: red;
        }
    }
</style>
<p>text</p>

If the device width is 1081 physical pixels and devicePixelRatio is 2.75. The
viewport width of the CSS media query will be 393.091px.

Change-Id: I25ee4da1ebdbd57202fa8c5e360138a8058f578f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1695522
Commit-Queue: David Bokan <bokan@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680047}
parent 6a69d6a0
......@@ -1453,6 +1453,7 @@ jumbo_source_set("unit_tests") {
"page/touch_adjustment_test.cc",
"page/viewport_test.cc",
"page/window_features_test.cc",
"page/zoom_test.cc",
"paint/block_painter_test.cc",
"paint/box_paint_invalidator_test.cc",
"paint/box_painter_test.cc",
......
......@@ -990,9 +990,14 @@ FloatSize LocalFrameView::ViewportSizeForViewportUnits() const {
}
FloatSize LocalFrameView::ViewportSizeForMediaQueries() const {
FloatSize viewport_size(GetLayoutSize());
if (!frame_->GetDocument() || !frame_->GetDocument()->Printing())
viewport_size.Scale(1 / GetFrame().PageZoomFactor());
FloatSize viewport_size(layout_size_);
if (!frame_->GetDocument()->Printing()) {
float zoom = GetFrame().PageZoomFactor();
viewport_size.SetWidth(
AdjustForAbsoluteZoom::AdjustInt(layout_size_.Width(), zoom));
viewport_size.SetHeight(
AdjustForAbsoluteZoom::AdjustInt(layout_size_.Height(), zoom));
}
return viewport_size;
}
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
namespace blink {
class FractionalZoomSimTest : public SimTest {};
TEST_F(FractionalZoomSimTest, CheckCSSMediaQueryWidthEqualsWindowInnerWidth) {
WebView().MainFrameWidget()->Resize(WebSize(1081, 1921));
// 1081/2.75 = 393.091
// 1081/2.00 = 540.500
// 1081/1.50 = 720.667
std::vector<float> factors = {2.75f, 2.00f, 1.50f};
for (auto factor : factors) {
WebView().SetZoomFactorForDeviceScaleFactor(factor);
EXPECT_EQ(GetDocument().View()->ViewportSizeForMediaQueries().Width(),
GetDocument().GetFrame()->DomWindow()->innerWidth());
}
}
} // namespace blink
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CSS Test: CSS media query width equals window innerWidth</title>
<link rel="author" title="Jinfeng Ma" href="mailto:majinfeng1@xiaomi.org">
<link rel="help" href="https://www.w3.org/TR/css3-mediaqueries/#width">
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-window-innerwidth">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<!--
It'd be best to programmatically change device scale factor so that the document
width becomes non integral but for now this test is only effective when run on
devices with a fractional device scale factor.
-->
<script type="text/javascript">
'use strict';
test(() => {
assert_true(window.matchMedia('(width: ' + window.innerWidth + 'px)').matches);
}, 'CSS media query width equals window innerWidth.');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment