Bug 1907808, part 1 - Text Fragments: Use ScrollSelectionIntoView() to scroll text directive into view. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D226813
This commit is contained in:
Jan-Niklas Jaeschke
2024-10-28 08:31:37 +00:00
parent 262f78c07f
commit 4ea484f7f2
3 changed files with 43 additions and 25 deletions

View File

@@ -1231,7 +1231,7 @@ class MOZ_RAII AutoHideSelectionChanges final {
constexpr bool IsValidRawSelectionType(RawSelectionType aRawSelectionType) {
return aRawSelectionType >= nsISelectionController::SELECTION_NONE &&
aRawSelectionType <= nsISelectionController::SELECTION_URLSTRIKEOUT;
aRawSelectionType <= nsISelectionController::SELECTION_TARGET_TEXT;
}
constexpr SelectionType ToSelectionType(RawSelectionType aRawSelectionType) {

View File

@@ -772,7 +772,6 @@ PresShell::PresShell(Document* aDocument)
: mDocument(aDocument),
mViewManager(nullptr),
mAutoWeakFrames(nullptr),
mLastAnchorVerticalScrollViewPosition(WhereToScroll::Start),
#ifdef ACCESSIBILITY
mDocAccessible(nullptr),
#endif // ACCESSIBILITY
@@ -3187,24 +3186,35 @@ nsresult PresShell::GoToAnchor(const nsAString& aAnchorName,
// From "Monkeypatching HTML §7.4.6.3 Scrolling to a fragment:"
// 3.9 Let blockPosition be "center" if scrollTarget is a range, "start"
// otherwise.
const auto verticalScrollPosition =
thereIsATextFragment ? WhereToScroll(WhereToScroll::Center)
: WhereToScroll(WhereToScroll::Start);
// Implementation note: Use `ScrollSelectionIntoView` for text fragment,
// since the text fragment is stored as a `eTargetText` selection.
//
// 3.3. TODO: Run the ancestor details revealing algorithm on target.
// 3.4. Scroll target into view, with behavior set to "auto", block set to
// "start", and inline set to "nearest".
// FIXME(emilio): Not all callers pass ScrollSmoothAuto (but we use auto
// smooth scroll for `top` regardless below, so maybe they should!).
ScrollingInteractionContext scrollToAnchorContext(true);
MOZ_TRY(ScrollContentIntoView(
target, ScrollAxis(verticalScrollPosition, WhenToScroll::Always),
ScrollAxis(),
ScrollFlags::AnchorScrollFlags | aAdditionalScrollFlags));
if (thereIsATextFragment) {
MOZ_TRY(ScrollSelectionIntoView(
SelectionType::eTargetText,
nsISelectionController::SELECTION_ANCHOR_REGION,
ScrollAxis(WhereToScroll::Center, WhenToScroll::Always),
ScrollAxis(),
ScrollFlags::AnchorScrollFlags | aAdditionalScrollFlags,
SelectionScrollMode::SyncFlush));
} else {
MOZ_TRY(ScrollContentIntoView(
target, ScrollAxis(WhereToScroll::Start, WhenToScroll::Always),
ScrollAxis(),
ScrollFlags::AnchorScrollFlags | aAdditionalScrollFlags));
}
if (ScrollContainerFrame* rootScroll = GetRootScrollContainerFrame()) {
mLastAnchorScrolledTo = target;
mLastAnchorScrollPositionY = rootScroll->GetScrollPosition().y;
mLastAnchorVerticalScrollViewPosition = verticalScrollPosition;
mLastAnchorScrollType = thereIsATextFragment
? AnchorScrollType::TextDirective
: AnchorScrollType::Anchor;
}
}
@@ -3300,21 +3310,28 @@ nsresult PresShell::GoToAnchor(const nsAString& aAnchorName,
}
nsresult PresShell::ScrollToAnchor() {
nsCOMPtr<nsIContent> lastAnchor = std::move(mLastAnchorScrolledTo);
if (!lastAnchor) {
return NS_OK;
NS_ASSERTION(mDidInitialize, "should have done initial reflow by now");
if (mLastAnchorScrollType == AnchorScrollType::Anchor) {
nsCOMPtr<nsIContent> lastAnchor = std::move(mLastAnchorScrolledTo);
if (!lastAnchor) {
return NS_OK;
}
ScrollContainerFrame* rootScroll = GetRootScrollContainerFrame();
if (!rootScroll ||
mLastAnchorScrollPositionY != rootScroll->GetScrollPosition().y) {
return NS_OK;
}
return ScrollContentIntoView(
lastAnchor, ScrollAxis(WhereToScroll::Start, WhenToScroll::Always),
ScrollAxis(), ScrollFlags::AnchorScrollFlags);
}
NS_ASSERTION(mDidInitialize, "should have done initial reflow by now");
ScrollContainerFrame* rootScroll = GetRootScrollContainerFrame();
if (!rootScroll ||
mLastAnchorScrollPositionY != rootScroll->GetScrollPosition().y) {
return NS_OK;
}
return ScrollContentIntoView(
lastAnchor,
ScrollAxis(mLastAnchorVerticalScrollViewPosition, WhenToScroll::Always),
ScrollAxis(), ScrollFlags::AnchorScrollFlags);
return ScrollSelectionIntoView(
SelectionType::eTargetText,
nsISelectionController::SELECTION_ANCHOR_REGION,
ScrollAxis(WhereToScroll::Center, WhenToScroll::Always), ScrollAxis(),
ScrollFlags::AnchorScrollFlags, SelectionScrollMode::SyncFlush);
}
/*

View File

@@ -3049,7 +3049,8 @@ class PresShell final : public nsStubDocumentObserver,
// Text directives are supposed to be scrolled to the center of the viewport.
// Since `ScrollToAnchor()` might get called after `GoToAnchor()` during a
// load, the vertical view position should be preserved.
WhereToScroll mLastAnchorVerticalScrollViewPosition;
enum class AnchorScrollType : bool { Anchor, TextDirective };
AnchorScrollType mLastAnchorScrollType = AnchorScrollType::Anchor;
// Information needed to properly handle scrolling content into view if the
// pre-scroll reflow flush can be interrupted. mContentToScrollTo is non-null