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:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user