mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
a3916a4e4e
This commit changes ScrollAnchorContainer to store the offset between the scroll anchoring bounding rect start edge and the scroll-port start edge in the block axis of the scroll frame. The logic to clamp the negative portions of scroll anchor bounding rect is also amended to only clamp the portion that is beyond the border start edge in the block axis of the scroll frame. Differential Revision: https://phabricator.services.mozilla.com/D16757 --HG-- extra : rebase_source : 43b5bc4ece7f90cb38e3a7186a764d9cddac90f9 extra : source : f26d953d76fcfb02a5fa46cb62e389f852592fe9
153 lines
5.2 KiB
C++
153 lines
5.2 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef mozilla_layout_ScrollAnchorContainer_h_
|
|
#define mozilla_layout_ScrollAnchorContainer_h_
|
|
|
|
#include "nsPoint.h"
|
|
|
|
class nsIFrame;
|
|
namespace mozilla {
|
|
class ScrollFrameHelper;
|
|
} // namespace mozilla
|
|
|
|
namespace mozilla {
|
|
namespace layout {
|
|
|
|
/**
|
|
* A scroll anchor container finds a descendent element of a scrollable frame
|
|
* to be an anchor node. After every reflow, the scroll anchor will apply
|
|
* scroll adjustments to keep the anchor node in the same relative position.
|
|
*
|
|
* See: https://drafts.csswg.org/css-scroll-anchoring/
|
|
*/
|
|
class ScrollAnchorContainer final {
|
|
public:
|
|
explicit ScrollAnchorContainer(ScrollFrameHelper* aScrollFrame);
|
|
~ScrollAnchorContainer();
|
|
|
|
/**
|
|
* Returns the nearest scroll anchor container that could select aFrame as an
|
|
* anchor node.
|
|
*/
|
|
static ScrollAnchorContainer* FindFor(nsIFrame* aFrame);
|
|
|
|
/**
|
|
* Returns the frame that is the selected anchor node or null if no anchor
|
|
* is selected.
|
|
*/
|
|
nsIFrame* AnchorNode() const { return mAnchorNode; }
|
|
|
|
/**
|
|
* Returns the frame that owns this scroll anchor container. This is always
|
|
* non-null.
|
|
*/
|
|
nsIFrame* Frame() const;
|
|
|
|
/**
|
|
* Returns the frame that owns this scroll anchor container as a scrollable
|
|
* frame. This is always non-null.
|
|
*/
|
|
nsIScrollableFrame* ScrollableFrame() const;
|
|
|
|
/**
|
|
* Find a suitable anchor node among the descendants of the scrollable frame.
|
|
* This should only be called after the scroll anchor has been invalidated.
|
|
*/
|
|
void SelectAnchor();
|
|
|
|
/**
|
|
* Notify the scroll anchor container that its scroll frame has been
|
|
* scrolled by a user and should invalidate itself.
|
|
*/
|
|
void UserScrolled();
|
|
|
|
/**
|
|
* Notify the scroll anchor container that a reflow has happened and it
|
|
* should query its anchor to see if a scroll adjustment needs to occur.
|
|
*/
|
|
void ApplyAdjustments();
|
|
|
|
/**
|
|
* Notify the scroll anchor container that it should suppress any scroll
|
|
* adjustment that may happen after the next layout flush.
|
|
*/
|
|
void SuppressAdjustments();
|
|
|
|
/**
|
|
* Notify this scroll anchor container that its anchor node should be
|
|
* invalidated and recomputed at the next available opportunity.
|
|
*/
|
|
void InvalidateAnchor();
|
|
|
|
/**
|
|
* Notify this scroll anchor container that it will be destroyed along with
|
|
* its parent frame.
|
|
*/
|
|
void Destroy();
|
|
|
|
private:
|
|
// Represents an assessment of a frame's suitability as a scroll anchor,
|
|
// from the scroll-anchoring spec's "candidate examination algorithm":
|
|
// https://drafts.csswg.org/css-scroll-anchoring-1/#candidate-examination
|
|
enum class ExamineResult {
|
|
// The frame is an excluded subtree or fully clipped and should be ignored.
|
|
// This corresponds with step 1 in the algorithm.
|
|
Exclude,
|
|
// This frame is an anonymous or inline box and its descendants should be
|
|
// searched to find an anchor node. If none are found, then continue
|
|
// searching. This is implied by the prologue of the algorithm, and
|
|
// should be made explicit in the spec [1].
|
|
//
|
|
// [1] https://github.com/w3c/csswg-drafts/issues/3489
|
|
PassThrough,
|
|
// The frame is partially visible and its descendants should be searched to
|
|
// find an anchor node. If none are found then this frame should be
|
|
// selected. This corresponds with step 3 in the algorithm.
|
|
Traverse,
|
|
// The frame is fully visible and should be selected as an anchor node. This
|
|
// corresponds with step 2 in the algorithm.
|
|
Accept,
|
|
};
|
|
|
|
ExamineResult ExamineAnchorCandidate(nsIFrame* aPrimaryFrame) const;
|
|
|
|
// Search a frame's children to find an anchor node. Returns the frame for a
|
|
// valid anchor node, if one was found in the frames descendants, or null
|
|
// otherwise.
|
|
nsIFrame* FindAnchorIn(nsIFrame* aFrame) const;
|
|
|
|
// Search a child list to find an anchor node. Returns the frame for a valid
|
|
// anchor node, if one was found in this child list, or null otherwise.
|
|
nsIFrame* FindAnchorInList(const nsFrameList& aFrameList) const;
|
|
|
|
// The owner of this scroll anchor container
|
|
ScrollFrameHelper* mScrollFrame;
|
|
|
|
// The anchor node that we will scroll to keep in the same relative position
|
|
// after reflows. This may be null if we were not able to select a valid
|
|
// scroll anchor
|
|
nsIFrame* mAnchorNode;
|
|
|
|
// The last offset of the scroll anchor node's scrollable overflow rect start
|
|
// edge relative to the scroll-port start edge, in the block axis of the
|
|
// scroll frame. This is used for calculating the distance to scroll to keep
|
|
// the anchor node in the same relative position
|
|
nscoord mLastAnchorOffset;
|
|
|
|
// True if we should recalculate our anchor node at the next chance
|
|
bool mAnchorNodeIsDirty : 1;
|
|
// True if we are applying a scroll anchor adjustment
|
|
bool mApplyingAnchorAdjustment : 1;
|
|
// True if we should suppress anchor adjustments
|
|
bool mSuppressAnchorAdjustment : 1;
|
|
};
|
|
|
|
} // namespace layout
|
|
} // namespace mozilla
|
|
|
|
#endif // mozilla_layout_ScrollAnchorContainer_h_
|