Files
cromite/build/patches/Android-Pixel-Perfect-Mode.patch

2601 lines
130 KiB
Diff

From: uazo <uazo@users.noreply.github.com>
Date: Mon, 25 Aug 2025 10:50:06 +0000
Subject: Android Pixel Perfect Mode
Eliminate conversions between dpi and pixels in Blink.
The goal (not yet achieved) is to mask the display geometry of Android devices and to make
the various devices identical for canvas and rect fingerprinting.
This patch is WIP, it is incomplete and contains visual glitch, do not activate.
This version contains points of interest marked in the code, which will be removed once the patch is complete.
License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
---
android_webview/browser/aw_contents.cc | 2 +-
cc/input/input_handler.cc | 2 +-
cc/input/scrollbar_controller.cc | 2 +-
cc/layers/viewport.cc | 4 +-
cc/mojo_embedder/viz_layer_context.cc | 2 +-
cc/trees/commit_state.cc | 1 +
cc/trees/commit_state.h | 1 +
cc/trees/layer_tree_host.cc | 5 +-
cc/trees/layer_tree_host.h | 4 ++
cc/trees/layer_tree_host_impl.cc | 4 +-
cc/trees/layer_tree_impl.cc | 30 ++++++++----
cc/trees/layer_tree_impl.h | 7 ++-
cc/trees/property_tree.cc | 4 +-
.../java/res/xml/developer_preferences.xml | 4 ++
.../chrome/browser/WarmupManager.java | 2 +-
.../chrome/browser/app/ChromeActivity.java | 23 ++++++++-
.../compositor/CompositorViewHolder.java | 4 +-
.../overlay_panel/OverlayPanelContent.java | 2 +-
.../chromium/chrome/browser/tab/TabImpl.java | 2 +-
.../tracing/settings/DeveloperSettings.java | 10 ++++
.../android/compositor/tab_content_manager.cc | 6 ++-
.../overlay_panel/overlay_panel_content.cc | 2 +-
.../browser/flags/cromite/sPixelPerfect.java | 33 +++++++++++++
.../settings/ChromeBaseSettingsFragment.java | 4 ++
.../Pixel-perfect-mode.grdp | 9 ++++
components/input/BUILD.gn | 2 +
components/input/android_input_helper.cc | 2 +-
components/input/child_frame_input_helper.cc | 2 +-
components/input/input_router_impl.cc | 2 +-
.../render_widget_host_input_event_router.cc | 5 +-
.../input/render_widget_host_view_input.cc | 3 ++
components/input/render_widget_targeter.cc | 4 +-
.../thin_webview/internal/thin_webview.cc | 2 +-
components/viz/service/input/input_manager.cc | 2 +-
.../render_input_router_support_android.cc | 2 +-
...render_input_router_support_child_frame.cc | 2 +-
.../viz/service/layers/layer_context_impl.cc | 2 +-
.../selection/selection_popup_controller.cc | 5 +-
.../cross_process_frame_connector.cc | 10 ++--
.../renderer_host/delegated_frame_host.cc | 2 +-
...selection_controller_client_child_frame.cc | 2 +-
.../renderer_host/render_frame_host_impl.cc | 2 +-
.../renderer_host/render_widget_host_impl.cc | 30 ++++++++++--
.../render_widget_host_view_android.cc | 17 +++++--
.../render_widget_host_view_android.h | 1 +
.../render_widget_host_view_base.cc | 6 ++-
.../render_widget_host_view_base.h | 2 +
.../render_widget_host_view_child_frame.cc | 4 ++
.../render_widget_host_view_child_frame.h | 1 +
.../web_contents/web_contents_android.cc | 7 ++-
.../web_contents/web_contents_android.h | 2 +-
content/child/runtime_features.cc | 6 ++-
.../SelectionPopupControllerImpl.java | 5 +-
.../browser/webcontents/WebContentsImpl.java | 6 +--
.../content_public/browser/WebContents.java | 2 +-
content/public/common/content_features.cc | 4 ++
.../browser/test/mock/MockWebContents.java | 2 +-
.../about_flags_cc/Pixel-perfect-mode.inc | 7 +++
.../Pixel-perfect-mode.inc | 1 +
.../content_features_h/Pixel-perfect-mode.inc | 1 +
.../mojom/compositing/layer_context.mojom | 1 +
.../blink/common/widget/visual_properties.cc | 4 ++
.../widget/visual_properties_mojom_traits.cc | 3 ++
.../public/common/widget/visual_properties.h | 4 ++
.../widget/visual_properties_mojom_traits.h | 11 +++++
.../mojom/widget/visual_properties.mojom | 4 ++
third_party/blink/public/web/web_view.h | 1 +
.../blink/renderer/core/css/media_values.cc | 4 +-
.../renderer/core/exported/web_view_impl.cc | 41 ++++++++++++----
.../renderer/core/exported/web_view_impl.h | 5 ++
.../renderer/core/frame/local_frame_view.cc | 5 +-
.../renderer/core/frame/visual_viewport.cc | 39 ++++++++++++++-
.../renderer/core/frame/visual_viewport.h | 7 ++-
.../core/frame/web_frame_widget_impl.cc | 36 ++++++++++++--
.../core/frame/web_frame_widget_impl.h | 1 +
.../core/frame/web_local_frame_impl.cc | 4 +-
.../core/html/canvas/html_canvas_element.cc | 1 +
.../renderer/core/input/event_handler.cc | 2 +-
.../inspector/inspector_emulation_agent.cc | 3 +-
third_party/blink/renderer/core/page/page.cc | 4 ++
.../core/page/viewport_description.cc | 2 +-
.../canvas2d/base_rendering_context_2d.cc | 5 +-
.../platform/runtime_enabled_features.json5 | 4 ++
.../widget/input/input_handler_proxy.cc | 48 +++++++++++++------
.../renderer/platform/widget/widget_base.cc | 26 +++++-----
.../renderer/platform/widget/widget_base.h | 2 +-
ui/android/delegated_frame_host_android.cc | 2 +-
ui/android/event_forwarder.cc | 14 +++---
.../ui/base/UiAndroidFeatureList.java | 6 +++
.../ui/display/PhysicalDisplayAndroid.java | 10 ++++
ui/android/view_android.cc | 27 ++++++++---
ui/android/view_android.h | 9 +++-
ui/display/mojom/screen_info.mojom | 1 +
ui/display/mojom/screen_info_mojom_traits.cc | 1 +
ui/display/mojom/screen_info_mojom_traits.h | 4 ++
ui/display/screen_info.h | 1 +
ui/events/blink/blink_event_util.cc | 2 +-
97 files changed, 530 insertions(+), 138 deletions(-)
create mode 100644 chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/cromite/sPixelPerfect.java
create mode 100644 chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Pixel-perfect-mode.grdp
create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Pixel-perfect-mode.inc
create mode 100644 cromite_flags/content/public/common/content_features_cc/Pixel-perfect-mode.inc
create mode 100644 cromite_flags/content/public/common/content_features_h/Pixel-perfect-mode.inc
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -1017,7 +1017,7 @@ void AwContents::OnSizeChanged(JNIEnv* env, int w, int h, int ow, int oh) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
gfx::Size size(w, h);
web_contents_->GetNativeView()->OnPhysicalBackingSizeChanged(size);
- web_contents_->GetNativeView()->OnSizeChanged(w, h);
+ web_contents_->GetNativeView()->OnSizeChanged(w, h, w, h);
browser_view_renderer_.OnSizeChanged(w, h);
AwBrowserProcess::GetInstance()
->visibility_metrics_logger()
diff --git a/cc/input/input_handler.cc b/cc/input/input_handler.cc
--- a/cc/input/input_handler.cc
+++ b/cc/input/input_handler.cc
@@ -759,7 +759,7 @@ InputHandlerPointerResult InputHandler::MouseMoveAt(
return result;
}
-PointerResultType InputHandler::HitTest(const gfx::PointF& viewport_point) {
+PointerResultType InputHandler::HitTest(const gfx::PointF& viewport_point) { // POI
return scrollbar_controller_->HitTest(viewport_point)
? PointerResultType::kScrollbarScroll
: PointerResultType::kUnhandled;
diff --git a/cc/input/scrollbar_controller.cc b/cc/input/scrollbar_controller.cc
--- a/cc/input/scrollbar_controller.cc
+++ b/cc/input/scrollbar_controller.cc
@@ -671,7 +671,7 @@ InputHandlerPointerResult ScrollbarController::HandlePointerUp(
}
// Returns the layer that is hit by the position_in_widget.
-LayerImpl* ScrollbarController::GetLayerHitByPoint(
+LayerImpl* ScrollbarController::GetLayerHitByPoint( // POI
const gfx::PointF position_in_widget) const {
LayerTreeImpl* active_tree = layer_tree_host_impl_->active_tree();
gfx::Point viewport_point(position_in_widget.x(), position_in_widget.y());
diff --git a/cc/layers/viewport.cc b/cc/layers/viewport.cc
--- a/cc/layers/viewport.cc
+++ b/cc/layers/viewport.cc
@@ -38,7 +38,7 @@ void Viewport::Pan(const gfx::Vector2dF& delta) {
host_impl_->active_tree());
}
-Viewport::ScrollResult Viewport::ScrollBy(const gfx::Vector2dF& physical_delta,
+Viewport::ScrollResult Viewport::ScrollBy(const gfx::Vector2dF& physical_delta, // POI
const gfx::Point& viewport_point,
bool is_direct_manipulation,
bool affect_browser_controls,
@@ -123,7 +123,7 @@ void Viewport::SnapIfNeeded() {
ScrollBy(delta, gfx::Point(), false, false, true);
}
-gfx::Vector2dF Viewport::ComputeClampedDelta(
+gfx::Vector2dF Viewport::ComputeClampedDelta( // POI
const gfx::Vector2dF& scroll_delta) const {
// When clamping for the outer viewport, we need to distribute the scroll
// between inner and outer to get the clamped value. The returned values
diff --git a/cc/mojo_embedder/viz_layer_context.cc b/cc/mojo_embedder/viz_layer_context.cc
--- a/cc/mojo_embedder/viz_layer_context.cc
+++ b/cc/mojo_embedder/viz_layer_context.cc
@@ -1372,7 +1372,7 @@ void VizLayerContext::SetTargetLocalSurfaceId(
service_->SetTargetLocalSurfaceId(target_local_surface_id);
}
-base::TimeTicks VizLayerContext::UpdateDisplayTreeFrom(
+base::TimeTicks VizLayerContext::UpdateDisplayTreeFrom( // POI
LayerTreeImpl& tree,
viz::ClientResourceProvider& resource_provider,
gpu::SharedImageInterface* shared_image_interface,
diff --git a/cc/trees/commit_state.cc b/cc/trees/commit_state.cc
--- a/cc/trees/commit_state.cc
+++ b/cc/trees/commit_state.cc
@@ -27,6 +27,7 @@ CommitState::CommitState(const CommitState& prev)
page_scale_factor_limits_set(prev.page_scale_factor_limits_set),
max_page_scale_factor(prev.max_page_scale_factor),
min_page_scale_factor(prev.min_page_scale_factor),
+ browser_control_scale_factor(prev.browser_control_scale_factor),
page_scale_factor(prev.page_scale_factor),
painted_device_scale_factor(prev.painted_device_scale_factor),
top_controls_shown_ratio(prev.top_controls_shown_ratio),
diff --git a/cc/trees/commit_state.h b/cc/trees/commit_state.h
--- a/cc/trees/commit_state.h
+++ b/cc/trees/commit_state.h
@@ -96,6 +96,7 @@ struct CC_EXPORT CommitState {
bool page_scale_factor_limits_set = false;
float max_page_scale_factor = 1.f;
float min_page_scale_factor = 1.f;
+ float browser_control_scale_factor = 1.f;
float page_scale_factor = 1.f;
float painted_device_scale_factor = 1.f;
float top_controls_shown_ratio = 0.f;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1466,7 +1466,7 @@ void LayerTreeHost::SetEventListenerProperties(
SetNeedsCommit();
}
-void LayerTreeHost::SetViewportRectAndScale(
+void LayerTreeHost::SetViewportRectAndScale( // POI
const gfx::Rect& device_viewport_rect,
float device_scale_factor,
const viz::LocalSurfaceId& local_surface_id_from_parent) {
@@ -1577,10 +1577,12 @@ void LayerTreeHost::SetOverscrollBehavior(const OverscrollBehavior& behavior) {
void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor,
float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor) {
if (pending_commit_state()->page_scale_factor_limits_set &&
pending_commit_state()->page_scale_factor == page_scale_factor &&
pending_commit_state()->min_page_scale_factor == min_page_scale_factor &&
+ pending_commit_state()->browser_control_scale_factor == browser_control_scale_factor &&
pending_commit_state()->max_page_scale_factor == max_page_scale_factor) {
return;
}
@@ -1605,6 +1607,7 @@ void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor,
pending_commit_state()->page_scale_factor_limits_set = true;
pending_commit_state()->page_scale_factor = page_scale_factor;
pending_commit_state()->min_page_scale_factor = min_page_scale_factor;
+ pending_commit_state()->browser_control_scale_factor = browser_control_scale_factor;
pending_commit_state()->max_page_scale_factor = max_page_scale_factor;
SetPropertyTreesNeedRebuild();
SetNeedsCommit();
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -583,6 +583,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void SetPageScaleFactorAndLimits(float page_scale_factor,
float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor);
float page_scale_factor() const {
return pending_commit_state()->page_scale_factor;
@@ -590,6 +591,9 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
float min_page_scale_factor() const {
return pending_commit_state()->min_page_scale_factor;
}
+ float browser_control_scale_factor() const {
+ return pending_commit_state()->browser_control_scale_factor;
+ }
float max_page_scale_factor() const {
return pending_commit_state()->max_page_scale_factor;
}
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2748,7 +2748,7 @@ viz::RegionCaptureBounds LayerTreeHostImpl::CollectRegionCaptureBounds() {
return bounds;
}
-viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() {
+viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() { // POI
viz::CompositorFrameMetadata metadata;
if (settings().trees_in_viz_in_viz_process) {
// In TreesInViz mode, this function is called in client process already,
@@ -2911,7 +2911,7 @@ viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() {
return metadata;
}
-RenderFrameMetadata LayerTreeHostImpl::MakeRenderFrameMetadata(
+RenderFrameMetadata LayerTreeHostImpl::MakeRenderFrameMetadata( // POI
FrameData* frame) {
RenderFrameMetadata metadata;
metadata.root_scroll_offset = active_tree_->TotalScrollOffset();
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -162,6 +162,7 @@ LayerTreeImpl::LayerTreeImpl(
background_color_(SkColors::kTransparent),
page_scale_factor_(page_scale_factor),
min_page_scale_factor_(1.f),
+ browser_control_scale_factor_(0),
max_page_scale_factor_(1.f),
external_page_scale_factor_(1.f),
device_scale_factor_(1.f),
@@ -452,7 +453,7 @@ void LayerTreeImpl::InvalidateRasterInducingScrolls(
}
}
-void LayerTreeImpl::UpdateViewportContainerSizes() {
+void LayerTreeImpl::UpdateViewportContainerSizes() { // POI
if (!InnerViewportScrollNode())
return;
@@ -521,8 +522,13 @@ void LayerTreeImpl::UpdateViewportContainerSizes() {
// Adjust the outer viewport container as well, since adjusting only the
// inner may cause its bounds to exceed those of the outer, causing scroll
// clamping.
- gfx::Vector2dF scaled_bounds_delta =
- gfx::ScaleVector2d(bounds_delta, 1.f / min_page_scale_factor());
+ gfx::Vector2dF scaled_bounds_delta;
+ if (browser_control_scale_factor() != 1.f) {
+ scaled_bounds_delta =
+ gfx::ScaleVector2d(bounds_delta, 1.f / browser_control_scale_factor());
+ } else {
+ scaled_bounds_delta = gfx::ScaleVector2d(bounds_delta, 1.f / min_page_scale_factor());
+ }
property_trees->SetOuterViewportContainerBoundsDelta(scaled_bounds_delta);
// outer_viewport_container_bounds_delta and
@@ -862,6 +868,7 @@ void LayerTreeImpl::PullLayerTreePropertiesFrom(CommitState& commit_state) {
PushPageScaleFromMainThread(commit_state.page_scale_factor,
commit_state.min_page_scale_factor,
+ commit_state.browser_control_scale_factor,
commit_state.max_page_scale_factor,
commit_state.page_scale_factor_limits_set);
@@ -986,6 +993,7 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
// Active tree already shares the page_scale_factor object with pending
// tree so only the limits need to be provided.
target_tree->PushPageScaleFactorAndLimits(nullptr, min_page_scale_factor(),
+ browser_control_scale_factor(),
max_page_scale_factor(),
page_scale_factor_limits_set_);
target_tree->SetExternalPageScaleFactor(external_page_scale_factor_);
@@ -1424,19 +1432,21 @@ void LayerTreeImpl::SetPageScaleOnActiveTree(float active_page_scale) {
void LayerTreeImpl::PushPageScaleFromMainThread(float page_scale_factor,
float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor,
bool limits_set) {
- PushPageScaleFactorAndLimits(&page_scale_factor, min_page_scale_factor,
+ PushPageScaleFactorAndLimits(&page_scale_factor, min_page_scale_factor, browser_control_scale_factor,
max_page_scale_factor, limits_set);
}
void LayerTreeImpl::SetPageScaleFactorAndLimitsForDisplayTree(
float page_scale_factor,
float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor) {
DCHECK(settings().trees_in_viz_in_viz_process);
bool changed_page_scale = page_scale_factor_->SetCurrent(page_scale_factor);
- changed_page_scale |= SetPageScaleFactorLimits(min_page_scale_factor,
+ changed_page_scale |= SetPageScaleFactorLimits(min_page_scale_factor, browser_control_scale_factor,
max_page_scale_factor, true);
if (changed_page_scale) {
@@ -1446,13 +1456,14 @@ void LayerTreeImpl::SetPageScaleFactorAndLimitsForDisplayTree(
void LayerTreeImpl::PushPageScaleFactorAndLimits(const float* page_scale_factor,
float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor,
bool limits_set) {
DCHECK(page_scale_factor || IsActiveTree());
bool changed_page_scale = false;
changed_page_scale |= SetPageScaleFactorLimits(
- min_page_scale_factor, max_page_scale_factor, limits_set);
+ min_page_scale_factor, browser_control_scale_factor, max_page_scale_factor, limits_set);
if (page_scale_factor) {
DCHECK(!IsActiveTree() || !host_impl_->pending_tree());
@@ -1557,6 +1568,7 @@ void LayerTreeImpl::PushBrowserControls(
}
bool LayerTreeImpl::SetPageScaleFactorLimits(float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor,
bool limits_set) {
DCHECK_GT(min_page_scale_factor, 0.f);
@@ -1564,12 +1576,14 @@ bool LayerTreeImpl::SetPageScaleFactorLimits(float min_page_scale_factor,
if (page_scale_factor_limits_set_ == limits_set &&
min_page_scale_factor == min_page_scale_factor_ &&
+ browser_control_scale_factor == browser_control_scale_factor_ &&
max_page_scale_factor == max_page_scale_factor_) {
return false;
}
page_scale_factor_limits_set_ = limits_set;
min_page_scale_factor_ = min_page_scale_factor;
+ browser_control_scale_factor_ = browser_control_scale_factor;
max_page_scale_factor_ = max_page_scale_factor;
return true;
@@ -2470,7 +2484,7 @@ ScrollbarSet LayerTreeImpl::ScrollbarsFor(ElementId scroll_element_id) const {
return scrollbars;
}
-static bool PointHitsRect(
+static bool PointHitsRect( // POI
const gfx::PointF& screen_space_point,
const gfx::Transform& local_space_to_screen_space_transform,
const gfx::Rect& local_space_rect,
@@ -3107,7 +3121,7 @@ static gfx::SelectionBound ComputeViewportSelectionBound(
return viewport_bound;
}
-void LayerTreeImpl::GetViewportSelection(
+void LayerTreeImpl::GetViewportSelection( // POI
viz::Selection<gfx::SelectionBound>* selection) {
DCHECK(selection);
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -387,6 +387,7 @@ class CC_EXPORT LayerTreeImpl {
void SetPageScaleOnActiveTree(float active_page_scale);
void PushPageScaleFromMainThread(float page_scale_factor,
float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor,
bool limits_set = true);
const LayerSelection& selection() const { return selection_; }
@@ -395,7 +396,7 @@ class CC_EXPORT LayerTreeImpl {
}
float min_page_scale_factor() const { return min_page_scale_factor_; }
float max_page_scale_factor() const { return max_page_scale_factor_; }
-
+ float browser_control_scale_factor() const { return browser_control_scale_factor_; }
float page_scale_delta() const { return page_scale_factor()->Delta(); }
SyncedScale* page_scale_factor();
@@ -856,6 +857,7 @@ class CC_EXPORT LayerTreeImpl {
void SetPageScaleFactorAndLimitsForDisplayTree(float page_scale_factor,
float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor);
LayerTreeHostImpl* host_impl() { return host_impl_; }
@@ -880,9 +882,11 @@ class CC_EXPORT LayerTreeImpl {
float ClampPageScaleFactorToLimits(float page_scale_factor) const;
void PushPageScaleFactorAndLimits(const float* page_scale_factor,
float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor,
bool limits_set);
bool SetPageScaleFactorLimits(float min_page_scale_factor,
+ float browser_control_scale_factor,
float max_page_scale_factor,
bool limits_set);
void DidUpdatePageScale();
@@ -926,6 +930,7 @@ class CC_EXPORT LayerTreeImpl {
// set.
bool page_scale_factor_limits_set_ = false;
float min_page_scale_factor_;
+ float browser_control_scale_factor_;
float max_page_scale_factor_;
float external_page_scale_factor_;
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -1822,7 +1822,7 @@ void ScrollTree::clear() {
#endif
}
-gfx::PointF ScrollTree::MaxScrollOffset(int scroll_node_id) const {
+gfx::PointF ScrollTree::MaxScrollOffset(int scroll_node_id) const { //
const ScrollNode* scroll_node = Node(scroll_node_id);
gfx::SizeF scroll_bounds = this->scroll_bounds(scroll_node_id);
@@ -2375,7 +2375,7 @@ gfx::Vector2dF ScrollTree::ScrollBy(const ScrollNode& scroll_node,
return old_offset + scroll - new_offset;
}
-gfx::PointF ScrollTree::ClampScrollOffsetToLimits(
+gfx::PointF ScrollTree::ClampScrollOffsetToLimits( // POI
gfx::PointF offset,
const ScrollNode& scroll_node) const {
offset.SetToMin(MaxScrollOffset(scroll_node.id));
diff --git a/chrome/android/java/res/xml/developer_preferences.xml b/chrome/android/java/res/xml/developer_preferences.xml
--- a/chrome/android/java/res/xml/developer_preferences.xml
+++ b/chrome/android/java/res/xml/developer_preferences.xml
@@ -45,4 +45,8 @@ found in the LICENSE file.
android:summary="@string/android_fonts_fingerprinting_mitigation_summary"
app:featureName="android-fonts-fingerprinting-mitigation"
app:needRestart="true" />
+ <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
+ android:key="pixel_perfect_mode"
+ android:title="@string/android_pixel_perfect_mode_title"
+ android:summary="@string/android_pixel_perfect_mode_summary" />
</PreferenceScreen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
@@ -303,7 +303,7 @@ public class WarmupManager {
int height = bounds.bottom - bounds.top;
webContents = tab.getWebContents();
assumeNonNull(webContents);
- webContents.setSize(width, height);
+ webContents.setSize(width, height, 0);
// Reparent the tab to detach it from the current activity.
ReparentingTask.from(tab).detach();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -43,6 +43,9 @@ import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import android.util.DisplayMetrics;
+import org.chromium.chrome.browser.flags.cromite.sPixelPerfect;
+
import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.Callback;
@@ -555,7 +558,25 @@ public abstract class ChromeActivity extends AsyncInitializationActivity
// Ensure that mConfig is initialized before tablet mode changes.
mConfig = getResources().getConfiguration();
-
+ if (sPixelPerfect.getInstance().isEnabled()) {
+ DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+ Log.i("","Pixel Perfect Mode Enabled:"
+ + " density=" + displayMetrics.density
+ + " densityDpi=" + mConfig.densityDpi
+ + " xdpi=" + displayMetrics.xdpi
+ + " ydpi=" + displayMetrics.ydpi
+ + " widthPixels=" + displayMetrics.widthPixels
+ + " heightPixels=" + displayMetrics.heightPixels
+ + " screenWidthDp=" + mConfig.screenWidthDp
+ + " screenHeightDp=" + mConfig.screenHeightDp);
+ if (displayMetrics.widthPixels < displayMetrics.heightPixels)
+ mConfig.densityDpi = (int)(mConfig.densityDpi / 412.0 * displayMetrics.widthPixels / displayMetrics.density);
+ else
+ mConfig.densityDpi = (int)(mConfig.densityDpi / 412.0 * displayMetrics.heightPixels / displayMetrics.density);
+ displayMetrics.densityDpi = mConfig.densityDpi;
+ Log.i("PixelPerfect","Setting new densityDpi to " + mConfig.densityDpi);
+ getResources().updateConfiguration(mConfig, displayMetrics);
+ }
// Make sure the root coordinator is created prior to calling super to ensure all
// the activity lifecycle events are called.
mRootUiCoordinator = createRootUiCoordinator();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -1055,7 +1055,7 @@ public class CompositorViewHolder extends FrameLayout
int verticalViewportInsets = controlsInsets + keyboardInset;
if (isAttachedToWindow(view)) {
- webContents.setSize(width - horizontalViewportInsets, height - verticalViewportInsets);
+ webContents.setSize(width - horizontalViewportInsets, height - verticalViewportInsets, verticalViewportInsets);
// Dispatch the geometrychange JavaScript event to the page.
// TODO(bokan): This doesn't belong in updateWebContentsSize. Ideally the content/ layer
@@ -1077,7 +1077,7 @@ public class CompositorViewHolder extends FrameLayout
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
webContents.setSize(
view.getWidth() - horizontalViewportInsets,
- view.getHeight() - verticalViewportInsets);
+ view.getHeight() - verticalViewportInsets, verticalViewportInsets);
requestRender();
}
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlay_panel/OverlayPanelContent.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlay_panel/OverlayPanelContent.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlay_panel/OverlayPanelContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlay_panel/OverlayPanelContent.java
@@ -638,7 +638,7 @@ public class OverlayPanelContent {
OverlayPanelContentJni.get()
.onPhysicalBackingSizeChanged(
mNativeOverlayPanelContentPtr, webContents, mContentViewWidth, viewHeight);
- assumeNonNull(mWebContents).setSize(mContentViewWidth, viewHeight);
+ assumeNonNull(mWebContents).setSize(mContentViewWidth, viewHeight, (mSubtractBarHeight ? mBarHeightPx : 0));
}
/** Destroy the native component of this class. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -2433,7 +2433,7 @@ class TabImpl implements Tab {
View compositorView =
assumeNonNull(getActivity()).getCompositorViewHolderSupplier().get();
assumeNonNull(compositorView);
- webContents.setSize(compositorView.getWidth(), compositorView.getHeight());
+ webContents.setSize(compositorView.getWidth(), compositorView.getHeight(), 0);
mWebContentsState.destroy();
mWebContentsState = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
@@ -27,12 +27,14 @@ import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import org.chromium.components.browser_ui.settings.search.SettingsIndexData;
import org.chromium.chrome.browser.util.PlatformUtil;
+import org.chromium.chrome.browser.flags.CromiteNativeUtils;
/** Settings fragment containing preferences aimed at Chrome and web developers. */
@NullMarked
public class DeveloperSettings extends ChromeBaseSettingsFragment implements EmbeddableSettingsPage {
private static final String UI_PREF_BETA_STABLE_HINT = "beta_stable_hint";
private static final String TEST_GWP_ASAN_KEY = "test_gwp_asan";
+ private static final String PIXEL_PERFECT_MODE_KEY = "pixel_perfect_mode";
// Non-translated strings:
private static final String MSG_DEVELOPER_OPTIONS_TITLE = "Developer options";
@@ -84,6 +86,14 @@ public class DeveloperSettings extends ChromeBaseSettingsFragment implements Emb
// handle the click so the default action isn't triggered.
return true;
});
+
+ Preference mPixelPerfect = findPreference(PIXEL_PERFECT_MODE_KEY);
+ mPixelPerfect.setOnPreferenceChangeListener((preference, newValue) -> {
+ CromiteNativeUtils.setFlagEnabled("AndroidPixelPerfect", (boolean)newValue);
+ CromiteNativeUtils.setFlagEnabled("pixel-perfect-mode", (boolean)newValue);
+ getRequestRestartDelegateSupplier().get().RequireRestart();
+ return true;
+ });
}
private static boolean shouldRemoveBetaStableHint() {
diff --git a/chrome/browser/android/compositor/tab_content_manager.cc b/chrome/browser/android/compositor/tab_content_manager.cc
--- a/chrome/browser/android/compositor/tab_content_manager.cc
+++ b/chrome/browser/android/compositor/tab_content_manager.cc
@@ -30,6 +30,7 @@
#include "chrome/browser/android/tab_android.h"
#include "chrome/browser/thumbnail/cc/thumbnail.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "content/public/common/content_features.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
@@ -131,7 +132,10 @@ class TabContentManager::TabReadbackRequest : public RetryableTask {
std::move(result_callback).Run(content::CopyFromSurfaceResult());
return;
}
- gfx::Rect source_rect = gfx::Rect(view_size_in_pixels);
+ float scale = rwhv->GetNativeView()->GetDipScale();
+ if (!base::FeatureList::IsEnabled(features::kPixelPerfect))
+ scale = 1;
+ gfx::Rect source_rect = gfx::Rect(view_size_in_pixels.width() / scale, view_size_in_pixels.height() / scale);
gfx::Size thumbnail_size(
gfx::ScaleToCeiledSize(view_size_in_pixels, thumbnail_scale_));
rwhv->CopyFromSurface(source_rect, thumbnail_size, kTabReadbackTimeout,
diff --git a/chrome/browser/android/overlay_panel/overlay_panel_content.cc b/chrome/browser/android/overlay_panel/overlay_panel_content.cc
--- a/chrome/browser/android/overlay_panel/overlay_panel_content.cc
+++ b/chrome/browser/android/overlay_panel/overlay_panel_content.cc
@@ -52,7 +52,7 @@ void OverlayPanelContent::OnPhysicalBackingSizeChanged(
int32_t height) {
gfx::Size size(width, height);
web_contents->GetNativeView()->OnPhysicalBackingSizeChanged(size);
- web_contents->GetNativeView()->OnSizeChanged(width, height);
+ web_contents->GetNativeView()->OnSizeChanged(width, height, width, height);
}
void OverlayPanelContent::SetWebContents(
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/cromite/sPixelPerfect.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/cromite/sPixelPerfect.java
new file mode 100644
--- /dev/null
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/cromite/sPixelPerfect.java
@@ -0,0 +1,33 @@
+/*
+ This file is part of Cromite.
+
+ Cromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Cromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Cromite. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+package org.chromium.chrome.browser.flags.cromite;
+
+import org.chromium.components.cached_flags.CachedFlag;
+import org.chromium.chrome.browser.flags.ChromeFeatureMap;
+
+public class sPixelPerfect {
+ private static final CachedFlag sInstance =
+ new CachedFlag(ChromeFeatureMap.getInstance(),
+ "AndroidPixelPerfect", false);
+
+ private sPixelPerfect() {}
+
+ public static CachedFlag getInstance() {
+ return sInstance;
+ }
+}
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeBaseSettingsFragment.java b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeBaseSettingsFragment.java
--- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeBaseSettingsFragment.java
+++ b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeBaseSettingsFragment.java
@@ -53,6 +53,10 @@ public abstract class ChromeBaseSettingsFragment extends PreferenceFragmentCompa
mRequireRestartDelegateSupplier = delegate;
}
+ protected Supplier<ChromeBaseSettingsFragment.RequireRestartDelegate> getRequestRestartDelegateSupplier() {
+ return mRequireRestartDelegateSupplier;
+ }
+
public void onCreatePreferencesCromite(Bundle savedInstanceState, String rootKey) {
}
diff --git a/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Pixel-perfect-mode.grdp b/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Pixel-perfect-mode.grdp
new file mode 100644
--- /dev/null
+++ b/chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Pixel-perfect-mode.grdp
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_ANDROID_PIXEL_PERFECT_MODE_TITLE" desc="Text for 'Android Pixel Perfect Mode' settings option.">
+ Pixel Perfect Mode
+ </message>
+ <message name="IDS_ANDROID_PIXEL_PERFECT_MODE_SUMMARY" desc="Summary text for 'Android Pixel Perfect Mode' settings option.">
+ Eliminate conversions between dpi and pixels in Blink
+ </message>
+</grit-part>
diff --git a/components/input/BUILD.gn b/components/input/BUILD.gn
--- a/components/input/BUILD.gn
+++ b/components/input/BUILD.gn
@@ -98,6 +98,8 @@ component("input") {
"//ui/events:gesture_detection",
"//ui/events/blink",
"//ui/events/gestures/blink",
+ "//content/public/common:buildflags",
+ "//tools/v8_context_snapshot:buildflags",
]
if (use_aura) {
sources += [ "native_web_keyboard_event_aura.cc" ]
diff --git a/components/input/android_input_helper.cc b/components/input/android_input_helper.cc
--- a/components/input/android_input_helper.cc
+++ b/components/input/android_input_helper.cc
@@ -144,7 +144,7 @@ void AndroidInputHelper::ProcessAckedTouchEvent(
}
}
-bool AndroidInputHelper::TransformPointToCoordSpaceForView(
+bool AndroidInputHelper::TransformPointToCoordSpaceForView( // POI
const gfx::PointF& point,
input::RenderWidgetHostViewInput* target_view,
gfx::PointF* transformed_point) {
diff --git a/components/input/child_frame_input_helper.cc b/components/input/child_frame_input_helper.cc
--- a/components/input/child_frame_input_helper.cc
+++ b/components/input/child_frame_input_helper.cc
@@ -153,7 +153,7 @@ bool ChildFrameInputHelper::TransformPointToCoordSpaceForView(
point, target_view, view_->GetFrameSinkId(), transformed_point);
}
-bool ChildFrameInputHelper::TransformPointToCoordSpaceForView(
+bool ChildFrameInputHelper::TransformPointToCoordSpaceForView( // POI
const gfx::PointF& point,
input::RenderWidgetHostViewInput* target_view,
const viz::FrameSinkId& local_frame_sink_id,
diff --git a/components/input/input_router_impl.cc b/components/input/input_router_impl.cc
--- a/components/input/input_router_impl.cc
+++ b/components/input/input_router_impl.cc
@@ -622,7 +622,7 @@ bool InputRouterImpl::IsAutoscrollInProgress() {
return client_->IsAutoscrollInProgress();
}
-void InputRouterImpl::FilterAndSendWebInputEvent(
+void InputRouterImpl::FilterAndSendWebInputEvent( // POI
const WebInputEvent& input_event,
const ui::LatencyInfo& latency_info,
blink::mojom::WidgetInputHandler::DispatchEventCallback callback,
diff --git a/components/input/render_widget_host_input_event_router.cc b/components/input/render_widget_host_input_event_router.cc
--- a/components/input/render_widget_host_input_event_router.cc
+++ b/components/input/render_widget_host_input_event_router.cc
@@ -16,6 +16,7 @@
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "content/public/common/content_features.h"
#include "components/input/cursor_manager.h"
#include "components/input/features.h"
#include "components/input/touch_emulator.h"
@@ -581,6 +582,8 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
return {root_view, /*should_query_view=*/false, *transformed_point};
}
float device_scale_factor = root_view->GetDeviceScaleFactor();
+ if (base::FeatureList::IsEnabled(::features::kPixelPerfect))
+ device_scale_factor = 1;
DCHECK_GT(device_scale_factor, 0.0f);
gfx::PointF point_in_pixels =
gfx::ConvertPointToPixels(point, device_scale_factor);
@@ -1579,7 +1582,7 @@ bool IsPinchCurrentlyAllowedInTarget(RenderWidgetHostViewInput* target) {
} // namespace
-void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
+void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent( // POI
RenderWidgetHostViewInput* root_view,
RenderWidgetHostViewInput* target,
const blink::WebGestureEvent& gesture_event,
diff --git a/components/input/render_widget_host_view_input.cc b/components/input/render_widget_host_view_input.cc
--- a/components/input/render_widget_host_view_input.cc
+++ b/components/input/render_widget_host_view_input.cc
@@ -5,6 +5,7 @@
#include "components/input/render_widget_host_view_input.h"
#include "base/notreached.h"
+#include "content/public/common/content_features.h"
#include "components/input/render_widget_host_input_event_router.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -328,6 +329,8 @@ bool RenderWidgetHostViewInput::TransformPointToTargetCoordSpace(
}
float device_scale_factor = original_view->GetDeviceScaleFactor();
+ if (base::FeatureList::IsEnabled(::features::kPixelPerfect))
+ device_scale_factor = 1;
CHECK_GT(device_scale_factor, 0.0f);
// HitTestQuery requires |point_in_pixels| to be in the coordinate space of
// the root surface. See crbug.com/41460959 for context.
diff --git a/components/input/render_widget_targeter.cc b/components/input/render_widget_targeter.cc
--- a/components/input/render_widget_targeter.cc
+++ b/components/input/render_widget_targeter.cc
@@ -67,7 +67,7 @@ RenderWidgetTargetResult::RenderWidgetTargetResult(
RenderWidgetTargetResult::~RenderWidgetTargetResult() = default;
-RenderWidgetTargeter::TargetingRequest::TargetingRequest(
+RenderWidgetTargeter::TargetingRequest::TargetingRequest( // POI
base::WeakPtr<RenderWidgetHostViewInput> root_view,
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency) {
@@ -179,7 +179,7 @@ void RenderWidgetTargeter::FindTargetAndCallback(
ResolveTargetingRequest(std::move(request));
}
-void RenderWidgetTargeter::ResolveTargetingRequest(TargetingRequest request) {
+void RenderWidgetTargeter::ResolveTargetingRequest(TargetingRequest request) { // POI
if (request_in_flight_) {
requests_.push(std::move(request));
return;
diff --git a/components/thin_webview/internal/thin_webview.cc b/components/thin_webview/internal/thin_webview.cc
--- a/components/thin_webview/internal/thin_webview.cc
+++ b/components/thin_webview/internal/thin_webview.cc
@@ -119,7 +119,7 @@ void ThinWebView::ResizeWebContents(const gfx::Size& size) {
}
web_contents_->GetNativeView()->OnPhysicalBackingSizeChanged(size);
- web_contents_->GetNativeView()->OnSizeChanged(size.width(), size.height());
+ web_contents_->GetNativeView()->OnSizeChanged(size.width(), size.height(), size.width(), size.height());
}
} // namespace android
diff --git a/components/viz/service/input/input_manager.cc b/components/viz/service/input/input_manager.cc
--- a/components/viz/service/input/input_manager.cc
+++ b/components/viz/service/input/input_manager.cc
@@ -408,7 +408,7 @@ const DisplayHitTestQueryMap& InputManager::GetDisplayHitTestQuery() const {
return frame_sink_manager_->GetDisplayHitTestQuery();
}
-float InputManager::GetDeviceScaleFactorForId(
+float InputManager::GetDeviceScaleFactorForId( // POI
const FrameSinkId& frame_sink_id) {
auto* support = frame_sink_manager_->GetFrameSinkForId(frame_sink_id);
CHECK(support);
diff --git a/components/viz/service/input/render_input_router_support_android.cc b/components/viz/service/input/render_input_router_support_android.cc
--- a/components/viz/service/input/render_input_router_support_android.cc
+++ b/components/viz/service/input/render_input_router_support_android.cc
@@ -117,7 +117,7 @@ SurfaceId RenderInputRouterSupportAndroid::GetCurrentSurfaceId() const {
NOTREACHED();
}
-bool RenderInputRouterSupportAndroid::TransformPointToCoordSpaceForView(
+bool RenderInputRouterSupportAndroid::TransformPointToCoordSpaceForView( // POI
const gfx::PointF& point,
input::RenderWidgetHostViewInput* target_view,
gfx::PointF* transformed_point) {
diff --git a/components/viz/service/input/render_input_router_support_child_frame.cc b/components/viz/service/input/render_input_router_support_child_frame.cc
--- a/components/viz/service/input/render_input_router_support_child_frame.cc
+++ b/components/viz/service/input/render_input_router_support_child_frame.cc
@@ -86,7 +86,7 @@ gfx::PointF RenderInputRouterSupportChildFrame::TransformPointToRootCoordSpaceF(
return input_helper_->TransformPointToRootCoordSpaceF(point);
}
-bool RenderInputRouterSupportChildFrame::TransformPointToCoordSpaceForView(
+bool RenderInputRouterSupportChildFrame::TransformPointToCoordSpaceForView( // POI
const gfx::PointF& point,
input::RenderWidgetHostViewInput* target_view,
gfx::PointF* transformed_point) {
diff --git a/components/viz/service/layers/layer_context_impl.cc b/components/viz/service/layers/layer_context_impl.cc
--- a/components/viz/service/layers/layer_context_impl.cc
+++ b/components/viz/service/layers/layer_context_impl.cc
@@ -2009,7 +2009,7 @@ base::expected<void, std::string> LayerContextImpl::DoUpdateDisplayTree(
return base::unexpected("Invalid page scale factors");
}
layers.SetPageScaleFactorAndLimitsForDisplayTree(
- update->page_scale_factor, update->min_page_scale_factor,
+ update->page_scale_factor, update->min_page_scale_factor, update->browser_control_scale_factor,
update->max_page_scale_factor);
if (update->external_page_scale_factor <= 0 ||
diff --git a/content/browser/android/selection/selection_popup_controller.cc b/content/browser/android/selection/selection_popup_controller.cc
--- a/content/browser/android/selection/selection_popup_controller.cc
+++ b/content/browser/android/selection/selection_popup_controller.cc
@@ -190,7 +190,7 @@ void SelectionPopupController::MoveRangeSelectionExtent(
web_contents_impl->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
}
-void SelectionPopupController::SelectBetweenCoordinates(
+void SelectionPopupController::SelectBetweenCoordinates( // POI
const gfx::PointF& base,
const gfx::PointF& extent) {
auto* web_contents_impl = static_cast<WebContentsImpl*>(web_contents());
@@ -326,7 +326,8 @@ bool SelectionPopupController::ShowSelectionMenu(
can_select_all, can_edit_richly, should_suggest,
static_cast<int>(params.source_type),
render_frame_host->GetJavaRenderFrameHost(),
- menu_model_bridge_->GetJavaObject());
+ menu_model_bridge_->GetJavaObject(),
+ base::FeatureList::IsEnabled(features::kPixelPerfect));
return true;
}
diff --git a/content/browser/renderer_host/cross_process_frame_connector.cc b/content/browser/renderer_host/cross_process_frame_connector.cc
--- a/content/browser/renderer_host/cross_process_frame_connector.cc
+++ b/content/browser/renderer_host/cross_process_frame_connector.cc
@@ -21,6 +21,7 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/common/features.h"
+#include "content/public/common/content_features.h"
#include "third_party/blink/public/common/frame/frame_visual_properties.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom.h"
@@ -221,9 +222,12 @@ void CrossProcessFrameConnector::SynchronizeVisualProperties(
render_widget_host->SetAutoResize(visual_properties.auto_resize_enabled,
visual_properties.min_size_for_auto_resize,
visual_properties.max_size_for_auto_resize);
+ auto compositing_scale_factor = visual_properties.compositing_scale_factor;
+ if (base::FeatureList::IsEnabled(features::kPixelPerfect))
+ compositing_scale_factor = 4;
render_widget_host->SetVisualPropertiesFromParentFrame(
visual_properties.page_scale_factor,
- visual_properties.compositing_scale_factor,
+ compositing_scale_factor,
visual_properties.is_pinch_gesture_active,
visual_properties.visible_viewport_size,
visual_properties.compositor_viewport,
@@ -512,7 +516,7 @@ void CrossProcessFrameConnector::SetVisibilityForChildViews(bool visible) {
current_child_frame_host()->SetVisibilityForChildViews(visible);
}
-void CrossProcessFrameConnector::SetLocalFrameSize(
+void CrossProcessFrameConnector::SetLocalFrameSize( // POI
const gfx::Size& local_frame_size) {
has_size_ = true;
const float dsf = screen_infos_.current().device_scale_factor;
@@ -521,7 +525,7 @@ void CrossProcessFrameConnector::SetLocalFrameSize(
gfx::ScaleToRoundedSize(local_frame_size, 1.f / dsf);
}
-void CrossProcessFrameConnector::SetRectInParentView(
+void CrossProcessFrameConnector::SetRectInParentView( // POI
const gfx::Rect& rect_in_parent_view) {
gfx::Rect old_rect = rect_in_parent_view_in_dip_;
const float dsf = screen_infos_.current().device_scale_factor;
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -192,7 +192,7 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceAsTexture(
base::TimeDelta(), std::move(callback));
}
-void DelegatedFrameHost::CopyFromCompositingSurfaceInternal(
+void DelegatedFrameHost::CopyFromCompositingSurfaceInternal( // POI
const gfx::Rect& src_subrect,
const gfx::Size& output_size,
const viz::SurfaceId& surface_id,
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
--- a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
@@ -53,7 +53,7 @@ void TouchSelectionControllerClientChildFrame::OnHitTestRegionUpdated() {
}
void TouchSelectionControllerClientChildFrame::
- TransformSelectionBoundsAndUpdate() {
+ TransformSelectionBoundsAndUpdate() { // POI
gfx::SelectionBound transformed_selection_start(selection_start_);
gfx::SelectionBound transformed_selection_end(selection_end_);
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -9683,7 +9683,7 @@ void RenderFrameHostImpl::ShowPopupMenu(
#endif
}
-void RenderFrameHostImpl::ShowContextMenu(
+void RenderFrameHostImpl::ShowContextMenu( // POI
mojo::PendingAssociatedRemote<blink::mojom::ContextMenuClient>
context_menu_client,
const blink::UntrustworthyContextMenuParams& params) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1020,7 +1020,20 @@ blink::VisualProperties RenderWidgetHostImpl::GetVisualProperties() {
blink::VisualProperties visual_properties;
visual_properties.screen_infos = GetScreenInfos();
auto& current_screen_info = visual_properties.screen_infos.mutable_current();
-
+ float browser_controls_scale_factor = 1;
+ if (base::FeatureList::IsEnabled(features::kPixelPerfect)) {
+ browser_controls_scale_factor = current_screen_info.device_scale_factor_original;
+ if (browser_controls_scale_factor == 0)
+ browser_controls_scale_factor = current_screen_info.device_scale_factor;
+ if (browser_controls_scale_factor == 0)
+ browser_controls_scale_factor = 1;
+ current_screen_info.rect = gfx::Rect(view_->GetRequestedRendererSizeDevicePx());
+ current_screen_info.available_rect = current_screen_info.rect;
+ current_screen_info.device_scale_factor_original = browser_controls_scale_factor;
+ current_screen_info.device_scale_factor = 1.f;
+ } else {
+ current_screen_info.device_scale_factor_original = current_screen_info.device_scale_factor;
+ }
// For testing, override the raster color profile.
// Note: this needs to be done here and not earlier in the pipeline because
// Mac uses the display color space to update an NSSurface and this setting
@@ -1125,6 +1138,13 @@ blink::VisualProperties RenderWidgetHostImpl::GetVisualProperties() {
visual_properties.compositing_scale_factor =
properties_from_parent_local_root_.compositing_scale_factor;
+ visual_properties.browser_controls_scale_factor = 1;
+ if (is_topmost_widget) {
+ visual_properties.browser_controls_scale_factor = browser_controls_scale_factor;
+ visual_properties.compositor_viewport_pixel_rect_real =
+ gfx::Rect(view_->GetCompositorViewportRealPixelSize());
+ }
+
#if BUILDFLAG(IS_MAC)
// Only macOS cursor scaling affects CSS custom cursor images for now.
visual_properties.cursor_accessibility_scale_factor =
@@ -1305,8 +1325,10 @@ bool RenderWidgetHostImpl::SynchronizeVisualProperties(
}
}
- GetRenderInputRouter()->SetDeviceScaleFactor(
- visual_properties->screen_infos.current().device_scale_factor);
+ auto device_scale_factor = visual_properties->screen_infos.current().device_scale_factor;
+ if (base::FeatureList::IsEnabled(features::kPixelPerfect))
+ device_scale_factor = 2.f;
+ GetRenderInputRouter()->SetDeviceScaleFactor(device_scale_factor);
// If we do not have a valid viz::LocalSurfaceId then we are a child frame
// waiting on the id to be propagated from our parent. We cannot create a hash
@@ -4026,7 +4048,7 @@ void RenderWidgetHostImpl::IntrinsicSizingInfoChanged(
// porting drag-and-drop calls to Mojo, so that RenderWidgetHostImpl bypasses
// RenderWidget to talk the the WebFrameWidget and needs to perform the scale
// operation itself.
-gfx::PointF RenderWidgetHostImpl::ConvertWindowPointToViewport(
+gfx::PointF RenderWidgetHostImpl::ConvertWindowPointToViewport( // POI
const gfx::PointF& window_point) {
gfx::PointF viewport_point = window_point;
viewport_point.Scale(GetScaleFactorForView(GetView()));
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -91,6 +91,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/content_features.h"
#include "third_party/blink/public/mojom/input/input_handler.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/track.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -987,7 +988,7 @@ void RenderWidgetHostViewAndroid::OnRenderFrameMetadataChangedBeforeActivation(
? SK_ColorTRANSPARENT
: metadata.root_background_color.toSkColor());
- if (overscroll_controller_) {
+ if (overscroll_controller_) { // POI
overscroll_controller_->OnFrameMetadataUpdated(
metadata.page_scale_factor, metadata.device_scale_factor,
metadata.scrollable_viewport_size, metadata.root_layer_size,
@@ -1289,6 +1290,12 @@ gfx::Size RenderWidgetHostViewAndroid::GetRequestedRendererSizeDevicePx() {
default_bounds_dip_.height() * scale_factor);
}
+ if (base::FeatureList::IsEnabled(features::kPixelPerfect)) {
+ auto size = view_.GetSizeDIPs();
+ // this is also the viewport width
+ DCHECK(size.width() == 0 || size.width() == 412 || size.height() == 412);
+ return size;
+ }
const float scale_factor = GetDeviceScaleFactor() / view_.GetDipScale();
return gfx::ScaleToCeiledSize(view_.GetSizeDevicePx(), scale_factor);
}
@@ -1314,6 +1321,10 @@ void RenderWidgetHostViewAndroid::SetInsets(const gfx::Insets& insets) {
NOTREACHED();
}
+gfx::Size RenderWidgetHostViewAndroid::GetCompositorViewportRealPixelSize() {
+ return view_.GetSizeReal();
+}
+
gfx::Size RenderWidgetHostViewAndroid::GetCompositorViewportPixelSize() {
if (!view_.parent()) {
if (default_bounds_dip_.IsEmpty()) {
@@ -1466,7 +1477,7 @@ viz::SurfaceId RenderWidgetHostViewAndroid::GetCurrentSurfaceId() const {
: viz::SurfaceId();
}
-bool RenderWidgetHostViewAndroid::TransformPointToCoordSpaceForView(
+bool RenderWidgetHostViewAndroid::TransformPointToCoordSpaceForView( // POI
const gfx::PointF& point,
RenderWidgetHostViewInput* target_view,
gfx::PointF* transformed_point) {
@@ -1890,7 +1901,7 @@ bool RenderWidgetHostViewAndroid::HasFallbackSurface() const {
return delegated_frame_host_->HasFallbackSurface();
}
-void RenderWidgetHostViewAndroid::CopyFromSurface(
+void RenderWidgetHostViewAndroid::CopyFromSurface( // POI
const gfx::Rect& src_subrect,
const gfx::Size& output_size,
base::TimeDelta timeout,
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -171,6 +171,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
gfx::Size GetRequestedRendererSizeDevicePx() override;
gfx::Size GetVisibleViewportSize() override;
gfx::Size GetVisibleViewportSizeDevicePx() override;
+ gfx::Size GetCompositorViewportRealPixelSize() override;
void SetInsets(const gfx::Insets& insets) override;
gfx::Size GetCompositorViewportPixelSize() override;
bool IsSurfaceAvailableForCopy() override;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -116,6 +116,10 @@ gfx::Size RenderWidgetHostViewBase::GetCompositorViewportPixelSize() {
GetDeviceScaleFactor());
}
+gfx::Size RenderWidgetHostViewBase::GetCompositorViewportRealPixelSize() {
+ return gfx::Size();
+}
+
void RenderWidgetHostViewBase::SelectionBoundsChanged(
const gfx::Rect& anchor_rect,
base::i18n::TextDirection anchor_dir,
@@ -628,7 +632,7 @@ display::ScreenInfos RenderWidgetHostViewBase::GetScreenInfos() const {
void RenderWidgetHostViewBase::ResetGestureDetection() {}
-float RenderWidgetHostViewBase::GetDeviceScaleFactor() const {
+float RenderWidgetHostViewBase::GetDeviceScaleFactor() const { // POI
return GetScreenInfos().current().device_scale_factor;
}
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -290,6 +290,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// The size of the view's backing surface in non-DPI-adjusted pixels.
virtual gfx::Size GetCompositorViewportPixelSize();
+ virtual gfx::Size GetCompositorViewportRealPixelSize();
+
virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget();
virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible();
virtual gfx::NativeViewAccessible
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -444,6 +444,10 @@ void RenderWidgetHostViewChildFrame::RequestInputBackForDragAndDrop(
}
#endif
+gfx::Size RenderWidgetHostViewChildFrame::GetCompositorViewportRealPixelSize() {
+ return gfx::Size();
+}
+
RenderWidgetHostViewBase* RenderWidgetHostViewChildFrame::GetRootView() {
return frame_connector_ ? frame_connector_->GetRootRenderWidgetHostView()
: nullptr;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -120,6 +120,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
RenderWidgetHostViewBase* GetRootView() override;
uint32_t GetCaptureSequenceNumber() const override;
gfx::Size GetCompositorViewportPixelSize() override;
+ gfx::Size GetCompositorViewportRealPixelSize() override;
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds,
const gfx::Rect& anchor_rect) override;
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -826,8 +826,11 @@ WebContentsAndroid::GetFullscreenVideoSize(JNIEnv* env) {
return Java_WebContentsImpl_createSize(env, size.width(), size.height());
}
-void WebContentsAndroid::SetSize(JNIEnv* env, int32_t width, int32_t height) {
- web_contents_->GetNativeView()->OnSizeChanged(width, height);
+void WebContentsAndroid::SetSize(JNIEnv* env, int32_t width, int32_t height, jint viewport_insets) {
+ int fixed_width = width;
+ int fixed_height = height;
+ web_contents_->GetNativeView()->OnSizeChanged(
+ fixed_width, fixed_height, width, height);
}
int WebContentsAndroid::GetWidth(JNIEnv* env) {
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h
--- a/content/browser/web_contents/web_contents_android.h
+++ b/content/browser/web_contents/web_contents_android.h
@@ -188,7 +188,7 @@ class CONTENT_EXPORT WebContentsAndroid {
base::android::ScopedJavaLocalRef<jobject> GetFullscreenVideoSize(
JNIEnv* env);
- void SetSize(JNIEnv* env, int32_t width, int32_t height);
+ void SetSize(JNIEnv* env, int32_t width, int32_t height, jint viewport_insets);
int GetWidth(JNIEnv* env);
int GetHeight(JNIEnv* env);
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -510,7 +510,11 @@ void SetCustomizedRuntimeFeaturesFromCombinedArgs(
!command_line.HasSwitch(switches::kFingerprintingCanvasImageDataNoise));
// CAUTION: Only add custom enabling logic here if it cannot
// be covered by the other functions.
-
+ if (base::FeatureList::IsEnabled(features::kPixelPerfect)) {
+ WebRuntimeFeatures::EnableFingerprintingCanvasMeasureTextNoise(false);
+ WebRuntimeFeatures::EnableFingerprintingCanvasImageDataNoise(false);
+ WebRuntimeFeatures::EnablePixelPerfect(true);
+ }
// These checks are custom wrappers around base::FeatureList::IsEnabled
// They're moved here to distinguish them from actual base checks
#if !BUILDFLAG(IS_CHROMEOS)
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
--- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
@@ -548,7 +548,8 @@ public class SelectionPopupControllerImpl extends ActionModeCallbackHelper
boolean shouldSuggest,
int sourceType,
RenderFrameHost renderFrameHost,
- MenuModelBridge menuModelBridge) {
+ MenuModelBridge menuModelBridge,
+ boolean pixelPerfectEnabled) {
mMenuModelBridge = menuModelBridge;
RecordHistogram.recordEnumeratedHistogram(
"Android.ShowSelectionMenuSourceType", sourceType, MenuSourceType.MAX_VALUE);
@@ -558,6 +559,8 @@ public class SelectionPopupControllerImpl extends ActionModeCallbackHelper
mXDip = xDip;
mYDip = yDip;
mSelectionRect.set(left, top, right, offsetBottom);
+ if (pixelPerfectEnabled)
+ mSelectionRect.set(left, mYDip, right, offsetBottom);
mEditable = isEditable;
mLastSelectedText = selectionText;
mLastSelectionOffset = selectionStartOffset;
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -1015,9 +1015,9 @@ public class WebContentsImpl
}
@Override
- public void setSize(int width, int height) {
+ public void setSize(int width, int height, int viewportInsets) {
checkNotDestroyed();
- WebContentsImplJni.get().setSize(mNativeWebContentsAndroid, width, height);
+ WebContentsImplJni.get().setSize(mNativeWebContentsAndroid, width, height, viewportInsets);
}
@Override
@@ -1508,7 +1508,7 @@ public class WebContentsImpl
Rect getFullscreenVideoSize(long nativeWebContentsAndroid);
- void setSize(long nativeWebContentsAndroid, int width, int height);
+ void setSize(long nativeWebContentsAndroid, int width, int height, int viewportInsets);
int getWidth(long nativeWebContentsAndroid);
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
--- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -547,7 +547,7 @@ public interface WebContents extends Parcelable {
* @param width The width of the view.
* @param height The height of the view.
*/
- void setSize(int width, int height);
+ void setSize(int width, int height, int viewport_insets);
/**
* Gets the view size width of the WebContents.
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -22,6 +22,10 @@
namespace features {
+CROMITE_FEATURE(kPixelPerfect,
+ "AndroidPixelPerfect",
+ base::FEATURE_DISABLED_BY_DEFAULT);
+
// All features in alphabetical order.
// Marks navigations as aborted when the NavigationHandle is destroyed mid
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockWebContents.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockWebContents.java
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockWebContents.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockWebContents.java
@@ -341,7 +341,7 @@ public class MockWebContents implements WebContents, WebContentsObserver.Observa
public void setHasPersistentVideo(boolean value) {}
@Override
- public void setSize(int width, int height) {}
+ public void setSize(int width, int height, int offset) {}
@Override
public int getWidth() {
diff --git a/cromite_flags/chrome/browser/about_flags_cc/Pixel-perfect-mode.inc b/cromite_flags/chrome/browser/about_flags_cc/Pixel-perfect-mode.inc
new file mode 100644
--- /dev/null
+++ b/cromite_flags/chrome/browser/about_flags_cc/Pixel-perfect-mode.inc
@@ -0,0 +1,7 @@
+#ifdef FLAG_SECTION
+
+ {"pixel-perfect-mode", "Pixel Perfect Mode",
+ "Enable Pixel Perfect Mode", kOsAndroid,
+ FEATURE_VALUE_TYPE(features::kPixelPerfect)},
+
+#endif
diff --git a/cromite_flags/content/public/common/content_features_cc/Pixel-perfect-mode.inc b/cromite_flags/content/public/common/content_features_cc/Pixel-perfect-mode.inc
new file mode 100644
--- /dev/null
+++ b/cromite_flags/content/public/common/content_features_cc/Pixel-perfect-mode.inc
@@ -0,0 +1 @@
+// empty for now
diff --git a/cromite_flags/content/public/common/content_features_h/Pixel-perfect-mode.inc b/cromite_flags/content/public/common/content_features_h/Pixel-perfect-mode.inc
new file mode 100644
--- /dev/null
+++ b/cromite_flags/content/public/common/content_features_h/Pixel-perfect-mode.inc
@@ -0,0 +1 @@
+CONTENT_EXPORT BASE_DECLARE_FEATURE(kPixelPerfect);
diff --git a/services/viz/public/mojom/compositing/layer_context.mojom b/services/viz/public/mojom/compositing/layer_context.mojom
--- a/services/viz/public/mojom/compositing/layer_context.mojom
+++ b/services/viz/public/mojom/compositing/layer_context.mojom
@@ -83,6 +83,7 @@ struct LayerTreeUpdate {
// The page scale factors set by the tree's client. All must be positive,
// non-zero.
float page_scale_factor;
+ float browser_control_scale_factor;
float min_page_scale_factor;
float max_page_scale_factor;
float external_page_scale_factor;
diff --git a/third_party/blink/common/widget/visual_properties.cc b/third_party/blink/common/widget/visual_properties.cc
--- a/third_party/blink/common/widget/visual_properties.cc
+++ b/third_party/blink/common/widget/visual_properties.cc
@@ -22,6 +22,10 @@ bool VisualProperties::operator==(const VisualProperties& other) const {
new_size_device_px == other.new_size_device_px &&
visible_viewport_size_device_px ==
other.visible_viewport_size_device_px &&
+ compositor_viewport_pixel_rect_real ==
+ other.compositor_viewport_pixel_rect_real &&
+ browser_controls_scale_factor ==
+ other.browser_controls_scale_factor &&
compositor_viewport_pixel_rect ==
other.compositor_viewport_pixel_rect &&
browser_controls_params == other.browser_controls_params &&
diff --git a/third_party/blink/common/widget/visual_properties_mojom_traits.cc b/third_party/blink/common/widget/visual_properties_mojom_traits.cc
--- a/third_party/blink/common/widget/visual_properties_mojom_traits.cc
+++ b/third_party/blink/common/widget/visual_properties_mojom_traits.cc
@@ -21,6 +21,8 @@ bool StructTraits<
!data.ReadNewSizeDevicePx(&out->new_size_device_px) ||
!data.ReadVisibleViewportSizeDevicePx(
&out->visible_viewport_size_device_px) ||
+ !data.ReadCompositorViewportPixelRectReal(
+ &out->compositor_viewport_pixel_rect_real) ||
!data.ReadCompositorViewportPixelRect(
&out->compositor_viewport_pixel_rect) ||
!data.ReadBrowserControlsParams(&out->browser_controls_params) ||
@@ -39,6 +41,7 @@ bool StructTraits<
out->is_fullscreen_granted = data.is_fullscreen_granted();
out->display_mode = data.display_mode();
out->capture_sequence_number = data.capture_sequence_number();
+ out->browser_controls_scale_factor = data.browser_controls_scale_factor();
out->zoom_level = data.zoom_level();
out->css_zoom_factor = data.css_zoom_factor();
out->page_scale_factor = data.page_scale_factor();
diff --git a/third_party/blink/public/common/widget/visual_properties.h b/third_party/blink/public/common/widget/visual_properties.h
--- a/third_party/blink/public/common/widget/visual_properties.h
+++ b/third_party/blink/public/common/widget/visual_properties.h
@@ -75,6 +75,10 @@ struct BLINK_COMMON_EXPORT VisualProperties {
// the widget, such as with an on-screen keyboard.
gfx::Size visible_viewport_size_device_px;
+ gfx::Rect compositor_viewport_pixel_rect_real;
+
+ float browser_controls_scale_factor = 1.f;
+
// The rect of compositor's viewport in device pixels. Note that for top level
// widgets this is the same as |new_size| (when UseDevicePixelsForWidgetSizing
// is on; otherwise different by device pixel ratio) except that on Android
diff --git a/third_party/blink/public/common/widget/visual_properties_mojom_traits.h b/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
--- a/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
+++ b/third_party/blink/public/common/widget/visual_properties_mojom_traits.h
@@ -50,6 +50,17 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::VisualPropertiesDataView,
return r.visible_viewport_size_device_px;
}
+ static const gfx::Rect& compositor_viewport_pixel_rect_real(
+ const blink::VisualProperties& r) {
+ return r.compositor_viewport_pixel_rect_real;
+ }
+
+ static float browser_controls_scale_factor(
+ const blink::VisualProperties& r) {
+ DCHECK_GE(r.browser_controls_scale_factor, 1.f);
+ return r.browser_controls_scale_factor;
+ }
+
static const gfx::Rect& compositor_viewport_pixel_rect(
const blink::VisualProperties& r) {
return r.compositor_viewport_pixel_rect;
diff --git a/third_party/blink/public/mojom/widget/visual_properties.mojom b/third_party/blink/public/mojom/widget/visual_properties.mojom
--- a/third_party/blink/public/mojom/widget/visual_properties.mojom
+++ b/third_party/blink/public/mojom/widget/visual_properties.mojom
@@ -40,6 +40,10 @@ struct VisualProperties {
// as with an on-screen keyboard.
gfx.mojom.Size visible_viewport_size_device_px;
+ gfx.mojom.Rect compositor_viewport_pixel_rect_real;
+
+ float browser_controls_scale_factor;
+
// The rect of compositor's viewport in pixels. Note that for top level
// widgets this is roughly the DSF scaled new_size put into a rect. For child
// frame widgets it is a pixel-perfect bounds of the visible region of the
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h
--- a/third_party/blink/public/web/web_view.h
+++ b/third_party/blink/public/web/web_view.h
@@ -238,6 +238,7 @@ class BLINK_EXPORT WebView {
// Minimum and Maximum as computed as a combination of default, page defined,
// UA, etc. constraints.
virtual float MinimumPageScaleFactor() const = 0;
+ virtual float BrowserControlScaleFactor() const = 0;
virtual float MaximumPageScaleFactor() const = 0;
// Sets the offset of the visual viewport within the main frame, in
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc
--- a/third_party/blink/renderer/core/css/media_values.cc
+++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -162,7 +162,7 @@ double MediaValues::CalculateDynamicViewportHeight(LocalFrame* frame) {
return frame->View()->DynamicViewportSizeForViewportUnits().height();
}
-int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
+int MediaValues::CalculateDeviceWidth(LocalFrame* frame) { // POI
DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
const display::ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
@@ -174,7 +174,7 @@ int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
return device_width;
}
-int MediaValues::CalculateDeviceHeight(LocalFrame* frame) {
+int MediaValues::CalculateDeviceHeight(LocalFrame* frame) { // POI
DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
const display::ScreenInfo& screen_info =
frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1225,8 +1225,19 @@ void WebViewImpl::UpdateICBAndResizeViewport(
if (GetBrowserControls().PermittedState() ==
cc::BrowserControlsState::kBoth &&
!GetBrowserControls().ShrinkViewport()) {
- icb_size.Enlarge(0, -(GetBrowserControls().TotalHeight() -
- GetBrowserControls().TotalMinHeight()));
+ int bc = -(GetBrowserControls().TotalHeight() -
+ GetBrowserControls().TotalMinHeight());
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled()) {
+ bc = std::floor(bc / BrowserControlScaleFactor());
+ bc = bc / 2 * 2;
+ if (bc >= -60 && bc <= -50) bc = -56;
+ if (bc >= -110 && bc <= -90) bc = -104;
+ // the browser controls size must be 56 (only bc) or 104 (bc + tab strip)
+ // (TODO) this is a fingerprint value that must be removed (also in chromium),
+ // tab strip must always be visible
+ DCHECK(bc == -56 || bc == -104);
+ }
+ icb_size.Enlarge(0, bc);
}
GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(icb_size);
@@ -1306,7 +1317,8 @@ void WebViewImpl::DidUpdateBrowserControls() {
ResizeViewportAnchor::ResizeScope resize_scope(*resize_viewport_anchor_);
visual_viewport.SetBrowserControlsAdjustment(
- GetBrowserControls().UnreportedSizeAdjustment());
+ GetBrowserControls().UnreportedSizeAdjustment(),
+ BrowserControlScaleFactor());
}
}
@@ -1370,7 +1382,7 @@ void WebViewImpl::ResizeWithBrowserControls(
float bottom_controls_height,
bool browser_controls_shrink_layout) {
ResizeWithBrowserControls(
- new_size, new_size,
+ new_size, new_size, gfx::Size(), browser_controls_scale_factor_,
{top_controls_height, GetBrowserControls().TopMinHeight(),
bottom_controls_height, GetBrowserControls().BottomMinHeight(),
GetBrowserControls().AnimateHeightChanges(),
@@ -1380,6 +1392,8 @@ void WebViewImpl::ResizeWithBrowserControls(
void WebViewImpl::ResizeWithBrowserControls(
const gfx::Size& main_frame_widget_size,
const gfx::Size& visible_viewport_size,
+ const gfx::Size& compositor_viewport_pixel_rect_real,
+ float browser_controls_scale_factor,
cc::BrowserControlsParams browser_controls_params) {
if (should_auto_resize_) {
// When auto-resizing only the viewport size comes from the browser, while
@@ -1388,6 +1402,11 @@ void WebViewImpl::ResizeWithBrowserControls(
return;
}
+ if (GetPage()->MainFrame()) {
+ browser_controls_scale_factor_ = browser_controls_scale_factor;
+ GetPage()->GetVisualViewport().SetSizeReal(compositor_viewport_pixel_rect_real);
+ }
+
if (size_ == main_frame_widget_size &&
GetPage()->GetVisualViewport().Size() == visible_viewport_size &&
GetBrowserControls().Params() == browser_controls_params)
@@ -2076,7 +2095,7 @@ void WebViewImpl::DidAttachLocalMainFrame() {
web_preferences_.prefers_reduced_motion);
MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
viewport.Scale(), viewport.IsPinchGestureActive(),
- MinimumPageScaleFactor(), MaximumPageScaleFactor());
+ MinimumPageScaleFactor(), BrowserControlScaleFactor(), MaximumPageScaleFactor());
// Prevent main frame updates while the main frame is loading until enough
// progress is made and BeginMainFrames are explicitly asked for.
scoped_defer_main_frame_update_ =
@@ -2923,7 +2942,7 @@ void WebViewImpl::RefreshPageScaleFactor() {
auto& viewport = GetPage()->GetVisualViewport();
MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
viewport.Scale(), viewport.IsPinchGestureActive(),
- MinimumPageScaleFactor(), MaximumPageScaleFactor());
+ MinimumPageScaleFactor(), BrowserControlScaleFactor(), MaximumPageScaleFactor());
}
}
@@ -3003,7 +3022,7 @@ void WebViewImpl::UpdatePageDefinedViewportConstraints(
TextAutosizer::UpdatePageInfoInAllFrames(GetPage()->MainFrame());
}
-void WebViewImpl::UpdateMainFrameLayoutSize() {
+void WebViewImpl::UpdateMainFrameLayoutSize() { // POI
if (should_auto_resize_ || !MainFrameImpl())
return;
@@ -3378,6 +3397,10 @@ float WebViewImpl::MinimumPageScaleFactor() const {
return GetPageScaleConstraintsSet().FinalConstraints().minimum_scale;
}
+float WebViewImpl::BrowserControlScaleFactor() const {
+ return browser_controls_scale_factor_;
+}
+
float WebViewImpl::MaximumPageScaleFactor() const {
return GetPageScaleConstraintsSet().FinalConstraints().maximum_scale;
}
@@ -3432,7 +3455,7 @@ void WebViewImpl::SendResizeEventForMainFrame() {
auto& viewport = GetPage()->GetVisualViewport();
MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
viewport.Scale(), viewport.IsPinchGestureActive(),
- MinimumPageScaleFactor(), MaximumPageScaleFactor());
+ MinimumPageScaleFactor(), BrowserControlScaleFactor(), MaximumPageScaleFactor());
}
}
@@ -3984,7 +4007,7 @@ void WebViewImpl::PageScaleFactorChanged() {
DCHECK(viewport.IsActiveViewport());
MainFrameImpl()->FrameWidgetImpl()->SetPageScaleStateAndLimits(
viewport.Scale(), viewport.IsPinchGestureActive(),
- MinimumPageScaleFactor(), MaximumPageScaleFactor());
+ MinimumPageScaleFactor(), BrowserControlScaleFactor(), MaximumPageScaleFactor());
local_main_frame_host_remote_->ScaleFactorChanged(viewport.Scale());
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -169,6 +169,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void AdvanceFocus(bool reverse) override;
float PageScaleFactor() const override;
float MinimumPageScaleFactor() const override;
+ float BrowserControlScaleFactor() const override;
float MaximumPageScaleFactor() const override;
void SetDefaultPageScaleLimits(float min_scale, float max_scale) override;
void SetInitialPageScaleOverride(float) override;
@@ -282,6 +283,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// includes all browser controls params such as the min heights.
void ResizeWithBrowserControls(const gfx::Size& main_frame_widget_size,
const gfx::Size& visible_viewport_size,
+ const gfx::Size& compositor_viewport_pixel_rect_real,
+ float browser_controls_scale_factor,
cc::BrowserControlsParams);
// Requests a page-scale animation based on the specified point/rect.
@@ -846,6 +849,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// The upper bound on the size when auto-resizing.
gfx::Size max_auto_size_;
+ float browser_controls_scale_factor_ = 1.f;
+
// An object that can be used to manipulate m_page->settings() without linking
// against WebCore. This is lazily allocated the first time GetWebSettings()
// is called.
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1883,8 +1883,11 @@ void LocalFrameView::PerformPostLayoutTasks(bool visual_viewport_size_changed) {
}
float LocalFrameView::InputEventsScaleFactor() const {
+ float scale_factor = 1;
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled())
+ scale_factor = 2;
float page_scale = frame_->GetPage()->GetVisualViewport().Scale();
- return page_scale *
+ return page_scale * scale_factor *
frame_->GetPage()->GetChromeClient().InputEventsScaleForEmulation();
}
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.cc b/third_party/blink/renderer/core/frame/visual_viewport.cc
--- a/third_party/blink/renderer/core/frame/visual_viewport.cc
+++ b/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -41,6 +41,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/frame/browser_controls.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -97,6 +98,7 @@ VisualViewport::VisualViewport(Page& owner)
scale_(1),
is_pinch_gesture_active_(false),
browser_controls_adjustment_(0),
+ browser_controls_scale_(0),
needs_paint_property_update_(true),
overscroll_type_(ComputeOverscrollType()) {
UniqueObjectId unique_id = NewUniqueObjectId();
@@ -392,6 +394,33 @@ void VisualViewport::EnqueueResizeEvent() {
document->EnqueueVisualViewportResizeEvent();
}
+void VisualViewport::SetSizeReal(const gfx::Size& size) {
+ if (!RuntimeEnabledFeatures::PixelPerfectEnabled())
+ return;
+
+ auto scale = ScaleFromDIP();
+ auto size_dpi = gfx::Size(size.width() * scale, size.height() * scale);
+ if (size_real_ == size_dpi)
+ return;
+
+ size_real_ = size_dpi;
+
+ if (!IsActiveViewport())
+ return;
+
+ needs_paint_property_update_ = true;
+
+ // Need to re-compute sizes for the overlay scrollbars.
+ if (scrollbar_layer_horizontal_ && LocalMainFrame().View()) {
+ DCHECK(scrollbar_layer_vertical_);
+ UpdateScrollbarLayer(kHorizontalScrollbar);
+ UpdateScrollbarLayer(kVerticalScrollbar);
+ LocalMainFrame().View()->SetVisualViewportOrOverlayNeedsRepaint();
+ }
+
+ EnqueueResizeEvent();
+}
+
void VisualViewport::SetSize(const gfx::Size& size) {
if (size_ == size)
return;
@@ -447,7 +476,10 @@ gfx::RectF VisualViewport::VisibleRect(
if (scrollbar_inclusion == kExcludeScrollbars)
visible_size = gfx::SizeF(ExcludeScrollbars(size_));
- visible_size.Enlarge(0, browser_controls_adjustment_);
+ int value = browser_controls_adjustment_;
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled())
+ value = browser_controls_adjustment_ / browser_controls_scale_ * ScaleFromDIP();
+ visible_size.Enlarge(0, value);
visible_size.Scale(1 / scale_);
return gfx::RectF(ScrollPosition(), visible_size);
@@ -902,10 +934,13 @@ gfx::Point VisualViewport::ClampDocumentOffsetAtScale(const gfx::Point& offset,
return clamped;
}
-void VisualViewport::SetBrowserControlsAdjustment(float adjustment) {
+void VisualViewport::SetBrowserControlsAdjustment(float adjustment, float browser_controls_scale) {
DCHECK(IsActiveViewport());
DCHECK(LocalMainFrame().IsOutermostMainFrame());
+ browser_controls_scale_ = browser_controls_scale;
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled())
+ adjustment = ceilf(adjustment / browser_controls_scale);
if (browser_controls_adjustment_ == adjustment)
return;
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.h b/third_party/blink/renderer/core/frame/visual_viewport.h
--- a/third_party/blink/renderer/core/frame/visual_viewport.h
+++ b/third_party/blink/renderer/core/frame/visual_viewport.h
@@ -123,7 +123,9 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
// The size of the Blink viewport area. See size_ for precise
// definition.
void SetSize(const gfx::Size&);
+ void SetSizeReal(const gfx::Size&);
gfx::Size Size() const { return size_; }
+ gfx::Size SizeReal() const { return size_real_; }
// The area of the layout viewport rect visible in the visual viewport,
// relative to the layout viewport's top-left corner. i.e. As the page scale
@@ -165,7 +167,7 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
// scrollability aspect from LocalFrameView, we use this method to let
// VisualViewport make the necessary adjustments so that we don't incorrectly
// clamp scroll offsets coming from the compositor. crbug.com/422328
- void SetBrowserControlsAdjustment(float);
+ void SetBrowserControlsAdjustment(float, float browser_controls_scale);
float BrowserControlsAdjustment() const;
// Adjust the viewport's offset so that it remains bounded by the outer
@@ -187,6 +189,7 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
gfx::Point RootFrameToViewport(const gfx::Point&) const;
// ScrollableArea implementation
+ //ScrollOffset ClampScrollOffset(const ScrollOffset&) const override;
ChromeClient* GetChromeClient() const override;
PhysicalRect ScrollIntoView(
const PhysicalRect&,
@@ -387,12 +390,14 @@ class CORE_EXPORT VisualViewport : public GarbageCollected<VisualViewport>,
// the changed visible content area. The transient URL bar-caused change to
// the visible content area is tracked in browser_controls_adjustment.
gfx::Size size_;
+ gfx::Size size_real_;
// Blink is only resized as a result of showing/hiding the URL bar once
// they're fully committed (all the way hidden or shown). While they're
// animating or being dragged, browser_controls_adjustment_ tracks the amount
// they expand or shrink the visible content height.
float browser_controls_adjustment_;
+ float browser_controls_scale_;
// For page scale animation on page_scale_node_.
CompositorElementId page_scale_element_id_;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -1877,6 +1877,9 @@ void WebFrameWidgetImpl::UpdateVisualProperties(
// All non-top-level Widgets (child local-root frames, GuestViews,
// etc.) propagate and consume the page scale factor as "external", meaning
// that it comes from the top level widget's page scale.
+ float compositing_scale_factor = visual_properties.compositing_scale_factor;
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled())
+ compositing_scale_factor = 2.f;
if (!ForTopMostMainFrame()) {
// The main frame controls the page scale factor, from blink. For other
// frame widgets, the page scale from pinch zoom and compositing scale is
@@ -1884,7 +1887,7 @@ void WebFrameWidgetImpl::UpdateVisualProperties(
// blink doesn't need to know this page scale factor outside the main frame,
// the compositor does in order to produce its output at the correct scale.
float combined_scale_factor = visual_properties.page_scale_factor *
- visual_properties.compositing_scale_factor;
+ compositing_scale_factor;
widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
combined_scale_factor, visual_properties.is_pinch_gesture_active);
@@ -1897,7 +1900,7 @@ void WebFrameWidgetImpl::UpdateVisualProperties(
// Ensure the external scale factor in top-level widgets is reset as it may
// be leftover from when a widget was nested and was promoted to top level.
widget_base_->LayerTreeHost()->SetExternalPageScaleFactor(
- 1.f,
+ compositing_scale_factor,
/*is_pinch_gesture_active=*/false);
}
@@ -1941,6 +1944,18 @@ void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
new_compositor_viewport_pixel_rect,
device_scale_factor_for_testing_ / non_testing_device_scale_factor_);
}
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled() && ForMainFrame()) {
+ int fixed_width = visual_properties.new_size_device_px.width();
+ int fixed_height = visual_properties.new_size_device_px.height();
+ if (fixed_width <= fixed_height)
+ fixed_width = 412;
+ else
+ fixed_height = 412;
+ new_size = gfx::Size(fixed_width, fixed_height);
+
+ new_compositor_viewport_pixel_rect =
+ gfx::Rect(0, 0, fixed_width * 2, fixed_height * 2);
+ }
if (ForMainFrame()) {
if (size_ != new_size) {
@@ -1958,6 +1973,8 @@ void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
size_.value(),
widget_base_->DIPsToCeiledBlinkSpace(
widget_base_->VisibleViewportSize()),
+ visual_properties.compositor_viewport_pixel_rect_real.size(),
+ visual_properties.browser_controls_scale_factor,
visual_properties.browser_controls_params);
return;
}
@@ -1991,6 +2008,8 @@ void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
View()->ResizeWithBrowserControls(
size_.value(), widget_base_->VisibleViewportSize(),
+ visual_properties.compositor_viewport_pixel_rect_real.size(),
+ visual_properties.browser_controls_scale_factor,
visual_properties.browser_controls_params);
}
@@ -2375,6 +2394,8 @@ void WebFrameWidgetImpl::SetZoomInternal(double zoom_level,
View()->ZoomFactorForViewportLayout() *
static_cast<float>(View()->ZoomLevelToZoomFactor(zoom_level)) *
static_cast<float>(css_zoom_factor);
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled())
+ DCHECK(layout_zoom_factor == 1.f);
if (zoom_changed) {
// Set the layout shift exclusion window for the zoom level change.
if (LocalFrameView* view = document->View()) {
@@ -3436,6 +3457,7 @@ void WebFrameWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
// be needed in setting the raster scale.
SetPageScaleStateAndLimits(1.f, false /* is_pinch_gesture_active */,
View()->MinimumPageScaleFactor(),
+ View()->BrowserControlScaleFactor(),
View()->MaximumPageScaleFactor());
}
@@ -4883,9 +4905,10 @@ void WebFrameWidgetImpl::SetPageScaleStateAndLimits(
float page_scale_factor,
bool is_pinch_gesture_active,
float minimum,
+ float browser_control_scale_factor,
float maximum) {
widget_base_->LayerTreeHost()->SetPageScaleFactorAndLimits(page_scale_factor,
- minimum, maximum);
+ minimum, browser_control_scale_factor, maximum);
// Only propagate page scale from the main frame.
if (ForMainFrame()) {
@@ -5009,7 +5032,10 @@ void WebFrameWidgetImpl::OrientationChanged() {
void WebFrameWidgetImpl::DidUpdateSurfaceAndScreen(
const display::ScreenInfos& previous_original_screen_infos) {
display::ScreenInfo screen_info = widget_base_->GetScreenInfo();
- View()->SetZoomFactorForDeviceScaleFactor(screen_info.device_scale_factor);
+ float device_scale_factor = screen_info.device_scale_factor;
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled())
+ device_scale_factor = 1;
+ View()->SetZoomFactorForDeviceScaleFactor(device_scale_factor);
if (ShouldAutoDetermineCompositingToLCDTextSetting()) {
// This causes compositing state to be modified which dirties the
@@ -5219,7 +5245,7 @@ void WebFrameWidgetImpl::SetDeviceScaleFactorForTesting(float factor) {
if (!device_scale_factor_for_testing_) {
non_testing_device_scale_factor_ =
- widget_base_->GetOriginalDeviceScaleFactor();
+ widget_base_->GetOriginalDeviceScaleFactor(false);
}
// Stash the window size before we adjust the scale factor, as subsequent
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -661,6 +661,7 @@ class CORE_EXPORT WebFrameWidgetImpl
void SetPageScaleStateAndLimits(float page_scale_factor,
bool is_pinch_gesture_active,
float minimum,
+ float browser_control_scale_factor,
float maximum);
void UpdateViewportDescription(
const ViewportDescription& viewport_description);
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -2578,7 +2578,7 @@ void WebLocalFrameImpl::PaintDevToolsOverlays(GraphicsContext& context) {
dev_tools_agent_->PaintOverlays(context);
}
-void WebLocalFrameImpl::CreateFrameView() {
+void WebLocalFrameImpl::CreateFrameView() { // POI
TRACE_EVENT0("blink", "WebLocalFrameImpl::createFrameView");
DCHECK(GetFrame()); // If frame() doesn't exist, we probably didn't init
@@ -3070,7 +3070,7 @@ void WebLocalFrameImpl::ShowContextMenuFromExternal(
std::move(context_menu_client), params);
}
-void WebLocalFrameImpl::ShowContextMenu(
+void WebLocalFrameImpl::ShowContextMenu( // POI
mojo::PendingAssociatedRemote<mojom::blink::ContextMenuClient> client,
const blink::ContextMenuData& data,
const std::optional<gfx::Point>& host_context_menu_location) {
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -1510,6 +1510,7 @@ bool HTMLCanvasElement::PushFrame(scoped_refptr<CanvasResource>&& image) {
}
bool HTMLCanvasElement::ShouldAccelerate() const {
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled()) return false;
if (context_ && !IsRenderingContext2D())
return false;
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -2115,7 +2115,7 @@ GestureEventWithHitTestResults EventHandler::HitTestResultForGestureEvent(
hit_test_result);
}
-void EventHandler::ApplyTouchAdjustment(WebGestureEvent* gesture_event,
+void EventHandler::ApplyTouchAdjustment(WebGestureEvent* gesture_event, // POI
HitTestLocation& location,
HitTestResult& hit_test_result) {
TouchAdjustmentCandidateType touch_adjustment_candiate_type =
diff --git a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
--- a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
@@ -1090,7 +1090,8 @@ InspectorEmulationAgent::setSmallViewportHeightDifferenceOverride(
// Ensure the override is applied immediately without having to wait for
// `WebFrameWidgetImpl::UpdateVisualProperties()` to be called.
GetWebViewImpl()->ResizeWithBrowserControls(
- GetWebViewImpl()->Size(), viewport_size, browser_controls_params);
+ GetWebViewImpl()->Size(), viewport_size,
+ gfx::Size(), GetWebViewImpl()->BrowserControlScaleFactor(), browser_controls_params);
return protocol::Response::Success();
}
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -1301,6 +1301,10 @@ void Page::CalculateEmulatedScreenSetting(LocalFrame* frame, bool force) {
|| disable_screen_emulated_) {
isEnabled = false;
}
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled()) {
+ isEnabled = false;
+ force = false;
+ }
if (isEnabled || force) {
// this is the maximum (and minimum) value which in percentage
// corresponds to +- 0.03%
diff --git a/third_party/blink/renderer/core/page/viewport_description.cc b/third_party/blink/renderer/core/page/viewport_description.cc
--- a/third_party/blink/renderer/core/page/viewport_description.cc
+++ b/third_party/blink/renderer/core/page/viewport_description.cc
@@ -80,7 +80,7 @@ float ViewportDescription::ResolveViewportLength(
NOTREACHED();
}
-PageScaleConstraints ViewportDescription::Resolve(
+PageScaleConstraints ViewportDescription::Resolve( // POI
const gfx::SizeF& initial_viewport_size,
const ViewportLength& legacy_fallback_width) const {
float result_width = kValueAuto;
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -471,16 +471,17 @@ ImageData* BaseRenderingContext2D::getImageDataInternal(
}
}
+ bool pixelPerfect = RuntimeEnabledFeatures::PixelPerfectEnabled();
// The default behavior before the willReadFrequently feature existed:
// Accelerated canvases fall back to CPU when there is a readback.
- if (will_read_frequently_value ==
+ if (pixelPerfect || will_read_frequently_value ==
CanvasContextCreationAttributesCore::WillReadFrequently::kUndefined) {
// GetImageData is faster in Unaccelerated canvases.
// In Desynchronized canvas disabling the acceleration will break
// putImageData: crbug.com/1112060.
if (IsAccelerated() && !IsDesynchronized()) {
read_count_++;
- if (read_count_ >= kFallbackToCPUAfterReadbacks ||
+ if (pixelPerfect || read_count_ >= kFallbackToCPUAfterReadbacks ||
ShouldDisableAccelerationBecauseOfReadback()) {
DisableAcceleration();
base::UmaHistogramEnumeration("Blink.Canvas.GPUFallbackToCPU",
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -6813,5 +6813,9 @@
// crbug.com/435623334.
name: "XSLTSpecialTrial",
},
+ {
+ name: "PixelPerfect",
+ public: true,
+ },
],
}
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
--- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
+++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
@@ -38,6 +38,7 @@
#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#include "third_party/blink/public/common/input/web_pointer_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h"
#include "third_party/blink/renderer/platform/widget/input/cursor_control_handler.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
@@ -57,6 +58,20 @@ namespace {
using ::perfetto::protos::pbzero::ChromeLatencyInfo2;
using ::perfetto::protos::pbzero::TrackEvent;
+gfx::PointF ScalePoint(const gfx::PointF& point) {
+ gfx::PointF point_scaled = point;
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled())
+ point_scaled.Scale(.5f);
+ return point_scaled;
+}
+
+gfx::Point ScalePoint(const gfx::Point& point) {
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled())
+ return gfx::Point(point.x() / 2, point.y() / 2);
+ else
+ return point;
+}
+
cc::ScrollStateData CreateScrollStateDataForGesture(
const WebGestureEvent& event) {
cc::ScrollStateData scroll_state_data;
@@ -65,8 +80,8 @@ cc::ScrollStateData CreateScrollStateDataForGesture(
}
switch (event.GetType()) {
case WebInputEvent::Type::kGestureScrollBegin:
- scroll_state_data.position_x = event.PositionInWidget().x();
- scroll_state_data.position_y = event.PositionInWidget().y();
+ scroll_state_data.position_x = ScalePoint(event.PositionInWidget()).x();
+ scroll_state_data.position_y = ScalePoint(event.PositionInWidget()).y();
scroll_state_data.delta_x_hint = -event.data.scroll_begin.delta_x_hint;
scroll_state_data.delta_y_hint = -event.data.scroll_begin.delta_y_hint;
scroll_state_data.is_beginning = true;
@@ -888,7 +903,7 @@ InputHandlerProxy::RouteToTypeSpecificHandler(
const WebGestureEvent& gesture_event =
static_cast<const WebGestureEvent&>(event);
input_handler_->PinchGestureBegin(
- gfx::ToFlooredPoint(gesture_event.PositionInWidget()),
+ gfx::ToFlooredPoint(ScalePoint(gesture_event.PositionInWidget())),
GestureScrollInputType(gesture_event.SourceDevice()));
gesture_pinch_in_progress_ = true;
return DID_HANDLE;
@@ -900,7 +915,7 @@ InputHandlerProxy::RouteToTypeSpecificHandler(
const WebGestureEvent& gesture_event =
static_cast<const WebGestureEvent&>(event);
input_handler_->PinchGestureEnd(
- gfx::ToFlooredPoint(gesture_event.PositionInWidget()));
+ gfx::ToFlooredPoint(ScalePoint(gesture_event.PositionInWidget())));
return DID_HANDLE;
}
@@ -910,7 +925,7 @@ InputHandlerProxy::RouteToTypeSpecificHandler(
static_cast<const WebGestureEvent&>(event);
input_handler_->PinchGestureUpdate(
gesture_event.data.pinch_update.scale,
- gfx::ToFlooredPoint(gesture_event.PositionInWidget()));
+ gfx::ToFlooredPoint(ScalePoint(gesture_event.PositionInWidget())));
return DID_HANDLE;
}
@@ -933,7 +948,7 @@ InputHandlerProxy::RouteToTypeSpecificHandler(
// TODO(crbug.com/40106459): Pass in the modifier instead of a bool
// once the refactor is done. For details, see
// crbug.com/1016955.
- HandlePointerDown(event_with_callback, mouse_event.PositionInWidget());
+ HandlePointerDown(event_with_callback, ScalePoint(mouse_event.PositionInWidget()));
}
return DID_NOT_HANDLE;
@@ -944,7 +959,7 @@ InputHandlerProxy::RouteToTypeSpecificHandler(
static_cast<const WebMouseEvent&>(event);
CHECK(input_handler_);
if (mouse_event.button == WebMouseEvent::Button::kLeft)
- HandlePointerUp(event_with_callback, mouse_event.PositionInWidget());
+ HandlePointerUp(event_with_callback, ScalePoint(mouse_event.PositionInWidget()));
return DID_NOT_HANDLE;
}
case WebInputEvent::Type::kMouseMove: {
@@ -959,7 +974,7 @@ InputHandlerProxy::RouteToTypeSpecificHandler(
(mouse_event.button == WebPointerProperties::Button::kNoButton &&
!(mouse_event.GetModifiers() &
WebInputEvent::Modifiers::kRelativeMotionEvent));
- HandlePointerMove(event_with_callback, mouse_event.PositionInWidget(),
+ HandlePointerMove(event_with_callback, ScalePoint(mouse_event.PositionInWidget()),
should_cancel_scrollbar_drag);
return DID_NOT_HANDLE;
}
@@ -998,12 +1013,14 @@ WebInputEventAttribution InputHandlerProxy::PerformEventAttribution(
// to check pointer lock state
gfx::PointF point =
static_cast<const WebMouseEvent&>(event).PositionInWidget();
+ point = ScalePoint(point);
return WebInputEventAttribution(
WebInputEventAttribution::kTargetedFrame,
input_handler_->FindFrameElementIdAtPoint(point));
} else if (WebInputEvent::IsGestureEventType(event.GetType())) {
gfx::PointF point =
static_cast<const WebGestureEvent&>(event).PositionInWidget();
+ point = ScalePoint(point);
return WebInputEventAttribution(
WebInputEventAttribution::kTargetedFrame,
input_handler_->FindFrameElementIdAtPoint(point));
@@ -1018,6 +1035,7 @@ WebInputEventAttribution InputHandlerProxy::PerformEventAttribution(
// how the renderer host performs touch event dispatch.
// https://cs.chromium.org/chromium/src/content/browser/renderer_host/render_widget_host_input_event_router.cc?l=808&rcl=10fe9d0a725d4ed7b69266a5936c525f0a5b26d3
gfx::PointF point = touch_event.touches[0].PositionInWidget();
+ point = ScalePoint(point);
const cc::ElementId targeted_element =
input_handler_->FindFrameElementIdAtPoint(point);
@@ -1124,7 +1142,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel(
}
}
- gfx::PointF position_in_widget = wheel_event.PositionInWidget();
+ gfx::PointF position_in_widget = ScalePoint(wheel_event.PositionInWidget());
if (input_handler_->HasBlockingWheelEventHandlerAt(
gfx::Point(position_in_widget.x(), position_in_widget.y()))) {
result = DID_NOT_HANDLE;
@@ -1319,7 +1337,7 @@ InputHandlerProxy::HandleGestureScrollUpdate(
scroll_data->set_unused_delta_y(scroll_result.unused_scroll_delta.y());
});
- HandleOverscroll(gesture_event.PositionInWidget(), scroll_result,
+ HandleOverscroll(ScalePoint(gesture_event.PositionInWidget()), scroll_result,
gesture_event.SourceDevice());
if (elastic_overscroll_controller_) {
@@ -1420,8 +1438,8 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HitTestTouchEvent(
}
cc::TouchAction touch_action = cc::TouchAction::kAuto;
- const gfx::Point point(touch_event.touches[i].PositionInWidget().x(),
- touch_event.touches[i].PositionInWidget().y());
+ const gfx::Point point(ScalePoint(gfx::Point(touch_event.touches[i].PositionInWidget().x(),
+ touch_event.touches[i].PositionInWidget().y())));
// TODO(crbug.com/355578906): This is just some rough math for now. The main
// thread counterpart is AdjustPointerEvent. The buffer math on the main and
// cc thread(s) need to match.
@@ -1536,7 +1554,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchStart(
touch_event.touches_length == 1) {
DCHECK(touch_event.touches[0].state == WebTouchPoint::State::kStatePressed);
cc::InputHandlerPointerResult pointer_result = HandlePointerDown(
- event_with_callback, touch_event.touches[0].PositionInWidget());
+ event_with_callback, ScalePoint(touch_event.touches[0].PositionInWidget()));
if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
client_->SetAllowedTouchAction(allowed_touch_action);
return DID_HANDLE;
@@ -1599,7 +1617,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchMove(
touch_event.touch_start_or_first_touch_move);
if (touch_event.touches_length == 1) {
cc::InputHandlerPointerResult pointer_result = HandlePointerMove(
- event_with_callback, touch_event.touches[0].PositionInWidget(),
+ event_with_callback, ScalePoint(touch_event.touches[0].PositionInWidget()),
false /* should_cancel_scrollbar_drag */);
if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
return DID_HANDLE;
@@ -1642,7 +1660,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchEnd(
touch_event.touches_length);
if (touch_event.touches_length == 1) {
cc::InputHandlerPointerResult pointer_result = HandlePointerUp(
- event_with_callback, touch_event.touches[0].PositionInWidget());
+ event_with_callback, ScalePoint(touch_event.touches[0].PositionInWidget()));
if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
return DID_HANDLE;
}
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -1667,7 +1667,9 @@ void WidgetBase::RequestAnimationAfterDelayTimerFired(TimerBase*) {
client_->ScheduleAnimation(/*urgent=*/urgent_for_input);
}
-float WidgetBase::GetOriginalDeviceScaleFactor() const {
+float WidgetBase::GetOriginalDeviceScaleFactor(bool real) const {
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled() && real)
+ return 1.0f;
return client_->GetOriginalScreenInfos().current().device_scale_factor;
}
@@ -1701,7 +1703,7 @@ void WidgetBase::UpdateSurfaceAndScreenInfo(
// Note carefully that the DSF specified in |new_screen_info| is not the
// DSF used by the compositor during device emulation!
LayerTreeHost()->SetViewportRectAndScale(compositor_viewport_pixel_rect,
- GetOriginalDeviceScaleFactor(),
+ GetOriginalDeviceScaleFactor(false),
local_surface_id_from_parent_);
// The VisualDeviceViewportIntersectionRect derives from the LayerTreeView's
// viewport size, which is set above.
@@ -1831,56 +1833,56 @@ void WidgetBase::CountDroppedPointerDownForEventTiming(unsigned count) {
gfx::PointF WidgetBase::DIPsToBlinkSpace(const gfx::PointF& point) {
// TODO(danakj): Should this use non-original scale factor so it changes under
// emulation?
- return gfx::ScalePoint(point, GetOriginalDeviceScaleFactor());
+ return gfx::ScalePoint(point, GetOriginalDeviceScaleFactor(true));
}
gfx::Point WidgetBase::DIPsToRoundedBlinkSpace(const gfx::Point& point) {
// TODO(danakj): Should this use non-original scale factor so it changes under
// emulation?
- return gfx::ScaleToRoundedPoint(point, GetOriginalDeviceScaleFactor());
+ return gfx::ScaleToRoundedPoint(point, GetOriginalDeviceScaleFactor(true));
}
gfx::PointF WidgetBase::BlinkSpaceToDIPs(const gfx::PointF& point) {
// TODO(danakj): Should this use non-original scale factor so it changes under
// emulation?
- return gfx::ScalePoint(point, 1.f / GetOriginalDeviceScaleFactor());
+ return gfx::ScalePoint(point, 1.f / GetOriginalDeviceScaleFactor(true));
}
gfx::Point WidgetBase::BlinkSpaceToFlooredDIPs(const gfx::Point& point) {
// TODO(danakj): Should this use non-original scale factor so it changes under
// emulation?
- float reverse = 1 / GetOriginalDeviceScaleFactor();
+ float reverse = 1 / GetOriginalDeviceScaleFactor(true);
return gfx::ScaleToFlooredPoint(point, reverse);
}
gfx::Size WidgetBase::DIPsToCeiledBlinkSpace(const gfx::Size& size) {
- return gfx::ScaleToCeiledSize(size, GetOriginalDeviceScaleFactor());
+ return gfx::ScaleToCeiledSize(size, GetOriginalDeviceScaleFactor(false));
}
gfx::RectF WidgetBase::DIPsToBlinkSpace(const gfx::RectF& rect) {
// TODO(danakj): Should this use non-original scale factor so it changes under
// emulation?
- return gfx::ScaleRect(rect, GetOriginalDeviceScaleFactor());
+ return gfx::ScaleRect(rect, GetOriginalDeviceScaleFactor(true));
}
float WidgetBase::DIPsToBlinkSpace(float scalar) {
// TODO(danakj): Should this use non-original scale factor so it changes under
// emulation?
- return GetOriginalDeviceScaleFactor() * scalar;
+ return GetOriginalDeviceScaleFactor(true) * scalar;
}
gfx::Size WidgetBase::BlinkSpaceToFlooredDIPs(const gfx::Size& size) {
- float reverse = 1 / GetOriginalDeviceScaleFactor();
+ float reverse = 1 / GetOriginalDeviceScaleFactor(false);
return gfx::ScaleToFlooredSize(size, reverse);
}
gfx::Rect WidgetBase::BlinkSpaceToEnclosedDIPs(const gfx::Rect& rect) {
- float reverse = 1 / GetOriginalDeviceScaleFactor();
+ float reverse = 1 / GetOriginalDeviceScaleFactor(false);
return gfx::ScaleToEnclosedRect(rect, reverse);
}
gfx::RectF WidgetBase::BlinkSpaceToDIPs(const gfx::RectF& rect) {
- float reverse = 1 / GetOriginalDeviceScaleFactor();
+ float reverse = 1 / GetOriginalDeviceScaleFactor(false);
return gfx::ScaleRect(rect, reverse);
}
diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h
--- a/third_party/blink/renderer/platform/widget/widget_base.h
+++ b/third_party/blink/renderer/platform/widget/widget_base.h
@@ -405,7 +405,7 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
void OnDevToolsSessionConnectionChanged(bool attached);
// Helper to get the non-emulated device scale factor.
- float GetOriginalDeviceScaleFactor() const;
+ float GetOriginalDeviceScaleFactor(bool real) const;
// Indicates a change in scheduling needs that should be forwarded to viz.
void RequestEfficientScheduling(
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -161,7 +161,7 @@ const viz::FrameSinkId& DelegatedFrameHostAndroid::GetFrameSinkId() const {
return frame_sink_id_;
}
-void DelegatedFrameHostAndroid::CopyFromCompositingSurface(
+void DelegatedFrameHostAndroid::CopyFromCompositingSurface( // POI
const gfx::Rect& src_subrect,
const gfx::Size& output_size,
base::TimeDelta timeout,
diff --git a/ui/android/event_forwarder.cc b/ui/android/event_forwarder.cc
--- a/ui/android/event_forwarder.cc
+++ b/ui/android/event_forwarder.cc
@@ -144,7 +144,7 @@ bool EventForwarder::OnTouchEvent(JNIEnv* env,
JNI_MotionEvent::Java_MotionEvent_getDownTime(env, motion_event));
auto event = ui::MotionEventAndroidFactory::CreateFromJava(
env, /*event=*/motion_event,
- /*pix_to_dip=*/1.f / view_->GetDipScale(),
+ /*pix_to_dip=*/1.f / view_->GetDipScaleFactor(),
/*ticks_x=*/0.f,
/*ticks_y=*/0.f,
/*tick_multiplier=*/0.f,
@@ -198,7 +198,7 @@ void EventForwarder::OnMouseEvent(
/*tool_type=*/android_tool_type);
auto event = ui::MotionEventAndroidFactory::CreateFromJava(
env, /*event=*/motion_event,
- /*pix_to_dip=*/1.f / view_->GetDipScale(),
+ /*pix_to_dip=*/1.f / view_->GetDipScaleFactor(),
/*ticks_x=*/0.f,
/*ticks_y=*/0.f,
/*tick_multiplier=*/0.f,
@@ -232,7 +232,7 @@ void EventForwarder::OnDragEvent(JNIEnv* env,
const JavaRef<jstring>& j_text,
const JavaRef<jstring>& j_html,
const JavaRef<jstring>& j_url) {
- float dip_scale = view_->GetDipScale();
+ float dip_scale = view_->GetDipScaleFactor();
gfx::PointF location(x / dip_scale, y / dip_scale);
gfx::PointF root_location(screen_x / dip_scale, screen_y / dip_scale);
std::vector<std::u16string> mime_types;
@@ -247,7 +247,7 @@ bool EventForwarder::OnGestureEvent(JNIEnv* env,
int32_t type,
int64_t time_ms,
float scale) {
- float dip_scale = view_->GetDipScale();
+ float dip_scale = view_->GetDipScaleFactor();
auto size = view_->GetSizeDIPs();
float x = size.width() / 2;
float y = size.height() / 2;
@@ -277,7 +277,7 @@ bool EventForwarder::OnGenericMotionEvent(JNIEnv* env,
base::TimeTicks down_time = base::TimeTicks::FromUptimeMillis(down_time_ms);
auto event = ui::MotionEventAndroidFactory::CreateFromJava(
env, /*event=*/motion_event,
- /*pix_to_dip=*/1.f / view_->GetDipScale(),
+ /*pix_to_dip=*/1.f / view_->GetDipScaleFactor(),
/*ticks_x=*/0.f,
/*ticks_y=*/0.f,
/*tick_multiplier=*/0.f,
@@ -360,7 +360,7 @@ void EventForwarder::DoubleTap(JNIEnv* env,
int64_t time_ms,
int32_t x,
int32_t y) {
- float dip_scale = view_->GetDipScale();
+ float dip_scale = view_->GetDipScaleFactor();
view_->OnGestureEvent(GestureEventAndroid(
GESTURE_EVENT_TYPE_DOUBLE_TAP, gfx::PointF(x / dip_scale, y / dip_scale),
gfx::PointF(), time_ms, ui::GestureDeviceType::DEVICE_TOUCHSCREEN, 0, 0,
@@ -379,7 +379,7 @@ void EventForwarder::StartFling(JNIEnv* env,
if (velocity_x == 0 && velocity_y == 0)
return;
- float dip_scale = view_->GetDipScale();
+ float dip_scale = view_->GetDipScaleFactor();
ui::GestureDeviceType source =
is_touchpad_event ? ui::GestureDeviceType::DEVICE_TOUCHPAD
: ui::GestureDeviceType::DEVICE_TOUCHSCREEN;
diff --git a/ui/android/java/src/org/chromium/ui/base/UiAndroidFeatureList.java b/ui/android/java/src/org/chromium/ui/base/UiAndroidFeatureList.java
--- a/ui/android/java/src/org/chromium/ui/base/UiAndroidFeatureList.java
+++ b/ui/android/java/src/org/chromium/ui/base/UiAndroidFeatureList.java
@@ -70,6 +70,12 @@ public class UiAndroidFeatureList {
newMutableFlagWithSafeDefault(
UiAndroidFeatures.SUPPORT_KEYBOARD, /* defaultValue= */ true);
+ public static final CachedFlag sPixelPerfect =
+ newCachedFlag(
+ "AndroidPixelPerfect",
+ /* defaultValue= */ false,
+ /* defaultValueInTests= */ false);
+
public static final List<CachedFlag> sFlagsCachedUiAndroid =
List.of(
sAndroidUseDisplayTopology,
diff --git a/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java b/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java
--- a/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java
+++ b/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java
@@ -36,6 +36,7 @@ import org.chromium.base.StrictModeContext;
import org.chromium.base.ThreadUtils;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
+import org.chromium.ui.base.UiAndroidFeatureList;
import java.util.Arrays;
import java.util.List;
@@ -402,6 +403,15 @@ import java.util.function.Consumer;
float xdpi,
float ydpi,
Display display) {
+ if (UiAndroidFeatureList.sPixelPerfect.isEnabled()) {
+ if (bounds.right < bounds.bottom) {
+ density = (float)(Math.round(bounds.right / 412.0 * 1000.0) / 1000.0);
+ bounds = new Rect(bounds.left, bounds.top, 412, bounds.bottom);
+ } else {
+ density = (float)(Math.round(bounds.bottom / 412.0 * 1000.0) / 1000.0);
+ bounds = new Rect(bounds.left, bounds.top, bounds.right, 412);
+ }
+ }
boolean isWideColorGamut = display.isWideColorGamut();
int pixelFormatId = PixelFormat.RGBA_8888;
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc
--- a/ui/android/view_android.cc
+++ b/ui/android/view_android.cc
@@ -144,6 +144,10 @@ float ViewAndroid::GetDipScale() {
return ui::GetScaleFactorForNativeView(this);
}
+float ViewAndroid::GetDipScaleFactor() {
+ return ui::GetScaleFactorForNativeView(this);
+}
+
ScopedJavaLocalRef<jobject> ViewAndroid::GetEventForwarder() {
if (!event_forwarder_) {
DCHECK(!RootPathHasEventForwarder(parent_))
@@ -179,7 +183,7 @@ void ViewAndroid::AddChild(ViewAndroid* child) {
// spurious events with empty size from being sent down.
if (child->match_parent() && !bounds_device_px_.IsEmpty() &&
child->GetSizeDevicePx() != bounds_device_px_.size()) {
- child->OnSizeChangedInternal(bounds_device_px_.size());
+ child->OnSizeChangedInternal(bounds_device_px_.size(), bounds_real_.size());
child->DispatchOnSizeChanged();
}
@@ -529,7 +533,7 @@ void ViewAndroid::OnVerticalScrollDirectionChanged(bool direction_up,
env, delegate, direction_up, current_scroll_ratio);
}
-void ViewAndroid::OnSizeChanged(int width, int height) {
+void ViewAndroid::OnSizeChanged(int width, int height, int real_width, int real_height) {
// Match-parent view must not receive size events.
DCHECK(!match_parent());
@@ -539,13 +543,15 @@ void ViewAndroid::OnSizeChanged(int width, int height) {
return;
}
- OnSizeChangedInternal(size_device_px);
+ gfx::Size bounds(real_width, real_height);
+ OnSizeChangedInternal(size_device_px, bounds);
// Signal resize event after all the views in the tree get the updated size.
DispatchOnSizeChanged();
}
-void ViewAndroid::OnSizeChangedInternal(const gfx::Size& size_device_px) {
+void ViewAndroid::OnSizeChangedInternal(const gfx::Size& size_device_px, const gfx::Size& size_real) {
+ bounds_real_.set_size(size_real);
if (bounds_device_px_.size() == size_device_px) {
return;
}
@@ -553,12 +559,15 @@ void ViewAndroid::OnSizeChangedInternal(const gfx::Size& size_device_px) {
bounds_device_px_.set_size(size_device_px);
float scale = GetDipScale();
- bounds_dips_.set_size(gfx::Size(std::ceil(size_device_px.width() / scale),
- std::ceil(size_device_px.height() / scale)));
+ int w = std::ceil(size_device_px.width() / scale);
+ int h = std::ceil(size_device_px.height() / scale);
+ if (w >= 411 && w <= 413) w = 412;
+ if (h >= 411 && h <= 413) h = 412;
+ bounds_dips_.set_size(gfx::Size(w, h));
for (ViewAndroid* child : children_) {
if (child->match_parent())
- child->OnSizeChangedInternal(size_device_px);
+ child->OnSizeChangedInternal(size_device_px, size_real);
}
}
@@ -619,6 +628,10 @@ gfx::Size ViewAndroid::GetSizeDevicePx() const {
return bounds_device_px_.size();
}
+gfx::Size ViewAndroid::GetSizeReal() const {
+ return bounds_real_.size();
+}
+
bool ViewAndroid::OnDragEvent(const DragEventAndroid& event) {
return HitTest(base::BindRepeating(&ViewAndroid::SendDragEventToHandler),
event, event.location());
diff --git a/ui/android/view_android.h b/ui/android/view_android.h
--- a/ui/android/view_android.h
+++ b/ui/android/view_android.h
@@ -123,6 +123,8 @@ class UI_ANDROID_EXPORT ViewAndroid {
// Virtual for testing.
virtual float GetDipScale();
+ float GetDipScaleFactor();
+
cc::slim::Layer* GetLayer() const;
void SetLayer(scoped_refptr<cc::slim::Layer> layer);
@@ -167,10 +169,11 @@ class UI_ANDROID_EXPORT ViewAndroid {
gfx::Size GetPhysicalBackingSize() const;
gfx::Size GetSizeDIPs() const;
+ gfx::Size GetSizeReal() const;
gfx::Size GetSizeDevicePx() const;
// |width| and |height| are in device pixels.
- void OnSizeChanged(int width, int height);
+ void OnSizeChanged(int width, int height, int real_width, int real_height);
// |deadline_override| if not nullopt will be used as the cc::DeadlinePolicy
// timeout for this resize.
void OnPhysicalBackingSizeChanged(
@@ -321,7 +324,7 @@ class UI_ANDROID_EXPORT ViewAndroid {
// each leaf of subtree.
static bool SubtreeHasEventForwarder(ViewAndroid* view);
- void OnSizeChangedInternal(const gfx::Size& size_device_px);
+ void OnSizeChangedInternal(const gfx::Size& size_device_px, const gfx::Size& size_real);
void DispatchOnSizeChanged();
// Returns the Java delegate for this view. This is used to delegate work
@@ -343,6 +346,8 @@ class UI_ANDROID_EXPORT ViewAndroid {
// Same as above, but before dividing by the device scale factor.
gfx::Rect bounds_device_px_;
+ gfx::Rect bounds_real_;
+
const LayoutType layout_type_;
// In physical pixel.
diff --git a/ui/display/mojom/screen_info.mojom b/ui/display/mojom/screen_info.mojom
--- a/ui/display/mojom/screen_info.mojom
+++ b/ui/display/mojom/screen_info.mojom
@@ -17,6 +17,7 @@ struct ScreenInfo {
// Device scale factor. Specifies the ratio between physical and logical
// pixels.
float device_scale_factor = 1;
+ float device_scale_factor_original = 0;
// The color spaces and buffer formats that this screen will use for various
// content types.
diff --git a/ui/display/mojom/screen_info_mojom_traits.cc b/ui/display/mojom/screen_info_mojom_traits.cc
--- a/ui/display/mojom/screen_info_mojom_traits.cc
+++ b/ui/display/mojom/screen_info_mojom_traits.cc
@@ -19,6 +19,7 @@ bool StructTraits<display::mojom::ScreenInfoDataView, display::ScreenInfo>::
}
out->device_scale_factor = data.device_scale_factor();
+ out->device_scale_factor_original = data.device_scale_factor_original();
out->depth = data.depth();
out->handwriting_radius = data.handwriting_radius();
out->depth_per_component = data.depth_per_component();
diff --git a/ui/display/mojom/screen_info_mojom_traits.h b/ui/display/mojom/screen_info_mojom_traits.h
--- a/ui/display/mojom/screen_info_mojom_traits.h
+++ b/ui/display/mojom/screen_info_mojom_traits.h
@@ -19,6 +19,10 @@ struct COMPONENT_EXPORT(DISPLAY_SHARED_MOJOM_TRAITS)
return r.device_scale_factor;
}
+ static float device_scale_factor_original(const display::ScreenInfo& r) {
+ return r.device_scale_factor_original;
+ }
+
static const gfx::DisplayColorSpaces& display_color_spaces(
const display::ScreenInfo& r) {
return r.display_color_spaces;
diff --git a/ui/display/screen_info.h b/ui/display/screen_info.h
--- a/ui/display/screen_info.h
+++ b/ui/display/screen_info.h
@@ -22,6 +22,7 @@ struct DISPLAY_EXPORT ScreenInfo {
// Device scale factor. Specifies the ratio between physical and logical
// pixels.
float device_scale_factor = 1.f;
+ float device_scale_factor_original = 0;
// The color spaces used by output display for various content types.
gfx::DisplayColorSpaces display_color_spaces;
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc
--- a/ui/events/blink/blink_event_util.cc
+++ b/ui/events/blink/blink_event_util.cc
@@ -165,7 +165,7 @@ WebPointerProperties::Button ToWebPointerButton(int android_button_state) {
return WebPointerProperties::Button::kNoButton;
}
-WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
+WebTouchPoint CreateWebTouchPoint(const MotionEvent& event, // POI
size_t pointer_index) {
WebTouchPoint touch;
--