tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit fe16ae088c03b008d8af634302d5b3ae4f9b7cec
parent 40fae03a754652c2f50e582698646bd2fb3563a1
Author: Hiroyuki Ikezoe <hikezoe.birchill@mozilla.com>
Date:   Tue,  2 Dec 2025 09:49:20 +0000

Bug 1999432 - Focibly use WhereToScroll::Nearest for zoom-to-focused-input for position:fixed elements. r=layout-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D272119

Diffstat:
Mdom/base/nsDOMWindowUtils.cpp | 2+-
Agfx/layers/apz/test/mochitest/helper_zoomToFocusedInput_for_position_fixed.html | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mgfx/layers/apz/test/mochitest/test_group_zoomToFocusedInput.html | 3+++
Mlayout/base/PresShell.cpp | 18++++++++++++------
Mlayout/base/PresShellForwards.h | 3++-
5 files changed, 92 insertions(+), 8 deletions(-)

diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp @@ -3165,7 +3165,7 @@ nsDOMWindowUtils::ZoomToFocusedInput() { caretInfo.frame, caretInfo.caretRectRelativeToTextFrame, ScrollAxis(WhereToScroll::Center, WhenToScroll::IfNotVisible), ScrollAxis(WhereToScroll::Center, WhenToScroll::IfNotVisible), - ScrollFlags::ScrollOverflowHidden); + ScrollFlags::ScrollOverflowHidden | ScrollFlags::ForZoomToFocusedInput); } RefPtr<Document> document = presShell->GetDocument(); diff --git a/gfx/layers/apz/test/mochitest/helper_zoomToFocusedInput_for_position_fixed.html b/gfx/layers/apz/test/mochitest/helper_zoomToFocusedInput_for_position_fixed.html @@ -0,0 +1,74 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>Tests that zoomToFocuedInput doesn't align position:fixed elements at the center of the visual viewport</title> + <script src="apz_test_utils.js"></script> + <script src="/tests/SimpleTest/paint_listener.js"></script> +</head> +<style> +@font-face { + font-family: Ahem; + src: url("/tests/layout/base/tests/Ahem.ttf"); +} +body { + margin: 0px; + padding: 0px; +} +input { + width: 100%; + height: 40px; + border: none; + padding: 0px; + position: fixed; + bottom: 0px; + /* + * Use the same size of the element height to easily calculate expected + position since zoom-to-focused-input tries to align the caret position + rather than the input element. + */ + font: 40px/1 Ahem; +} +</style> +<body> +<div style="width: 100vw; height: 100vh; background: blue;"></div> +<input id="target" type="text"/> +<div style="width: 100vw; height: 200vh; background: green;"></div> +<script> +async function test() { + is(window.scrollY, 0, "The initial scroll offset should be 0"); + is(visualViewport.scale, 2.0, "The document should get scaled by 2.0"); + is(visualViewport.pageLeft, 0, "The initial visual viewport pageLeft should be 0"); + + const input = document.querySelector("#target"); + const inputRect = input.getBoundingClientRect(); + + // Focus to the input element without scrolling. + const focusPromise = new Promise(resolve => { + input.addEventListener("focus", resolve); + }); + input.focus({ preventScroll: true }); + await focusPromise; + + // Invoke zoom-to-focused-input. + const utils = SpecialPowers.getDOMWindowUtils(window); + utils.zoomToFocusedInput(); + + await promiseApzFlushedRepaints(); + + // Calculate the expected position. + const centerOfTarget = inputRect.y + inputRect.height; + const expected = centerOfTarget - visualViewport.height; + + isfuzzy(visualViewport.pageTop, expected, 1.0, + "The input element is aligned at the bottom of the visual viewport"); +} + +SpecialPowers.getDOMWindowUtils(window).setResolutionAndScaleTo(2.0); +waitUntilApzStable() +.then(test) +.then(subtestDone, subtestFailed); +</script> +</body> +</html> diff --git a/gfx/layers/apz/test/mochitest/test_group_zoomToFocusedInput.html b/gfx/layers/apz/test/mochitest/test_group_zoomToFocusedInput.html @@ -38,6 +38,9 @@ var subtests = [ }, {"file": "helper_zoomToFocusedInput_content_visibility_auto.html", prefs}, {"file": "helper_zoomToFocusedInput_to_cursor.html", prefs}, + {"file": "helper_zoomToFocusedInput_for_position_fixed.html", + "prefs": [...prefs, + ["layout.scroll_fixed_content_into_view_visually", true]]}, ]; // These tests rely on mobile viewport sizing, so only run them on diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp @@ -3810,13 +3810,19 @@ void PresShell::ScrollFrameIntoVisualViewport( nscoord unusedRangeMinOutparam; nscoord unusedRangeMaxOutparam; nscoord x = ComputeWhereToScroll( - aHorizontal.mWhereToScroll, layoutOffset.x, aPositionFixedRect.x, - aPositionFixedRect.XMost(), visibleRect.x, visibleRect.XMost(), - &unusedRangeMinOutparam, &unusedRangeMaxOutparam); + aScrollFlags & ScrollFlags::ForZoomToFocusedInput + ? WhereToScroll::Nearest + : aHorizontal.mWhereToScroll, + layoutOffset.x, aPositionFixedRect.x, aPositionFixedRect.XMost(), + visibleRect.x, visibleRect.XMost(), &unusedRangeMinOutparam, + &unusedRangeMaxOutparam); nscoord y = ComputeWhereToScroll( - aVertical.mWhereToScroll, layoutOffset.y, aPositionFixedRect.y, - aPositionFixedRect.YMost(), visibleRect.y, visibleRect.YMost(), - &unusedRangeMinOutparam, &unusedRangeMaxOutparam); + aScrollFlags & ScrollFlags::ForZoomToFocusedInput + ? WhereToScroll::Nearest + : aVertical.mWhereToScroll, + layoutOffset.y, aPositionFixedRect.y, aPositionFixedRect.YMost(), + visibleRect.y, visibleRect.YMost(), &unusedRangeMinOutparam, + &unusedRangeMaxOutparam); layoutOffset.x += x; layoutOffset.y += y; diff --git a/layout/base/PresShellForwards.h b/layout/base/PresShellForwards.h @@ -147,11 +147,12 @@ enum class ScrollFlags : uint8_t { ScrollSmoothAuto = 1 << 4, TriggeredByScript = 1 << 5, AxesAreLogical = 1 << 6, + ForZoomToFocusedInput = 1 << 7, // NOTE: `Anchor` means here is "scrolling to an anchor", not "CSS scroll // anchoring". AnchorScrollFlags = ScrollOverflowHidden | ScrollNoParentFrames | TriggeredByScript, - ALL_BITS = (1 << 7) - 1, + ALL_BITS = (1 << 8) - 1, }; MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ScrollFlags)