Backed out changeset a7a2744670a7 (bug 1860328) for causing bc failures in nsDisplayList.cpp CLOSED TREE

This commit is contained in:
Cristian Tuns 2024-01-10 14:50:34 -05:00
parent c8bacdf683
commit 649cd5a87f
6 changed files with 64 additions and 42 deletions

View File

@ -398,10 +398,6 @@ nsIFrame* nsCaret::GetGeometry(const Selection* aSelection, nsRect* aRect) {
}
void nsCaret::SchedulePaint(Selection* aSelection) {
if (mLastCaretFrame) {
mLastCaretFrame->MarkNeedsDisplayItemRebuild();
}
Selection* selection;
if (aSelection) {
selection = aSelection;
@ -413,15 +409,14 @@ void nsCaret::SchedulePaint(Selection* aSelection) {
nsIFrame* frame = GetFrameAndOffset(selection, mOverrideContent,
mOverrideOffset, &frameOffset);
if (!frame) {
mLastCaretFrame = nullptr;
return;
}
if (nsIFrame* cb = GetContainingBlockIfNeeded(frame)) {
frame = cb;
cb->SchedulePaint();
} else {
frame->SchedulePaint();
}
frame->SchedulePaint();
}
void nsCaret::SetVisibilityDuringSelection(bool aVisibility) {
@ -560,9 +555,6 @@ void nsCaret::PaintCaret(DrawTarget& aDrawTarget, nsIFrame* aForFrame,
NS_IMETHODIMP
nsCaret::NotifySelectionChanged(Document*, Selection* aDomSel, int16_t aReason,
int32_t aAmount) {
if (mLastCaretFrame) {
mLastCaretFrame->MarkNeedsDisplayItemRebuild();
}
// Note that aDomSel, per the comment below may not be the same as our
// selection, but that's OK since if that is the case, it wouldn't have
// mattered what IsVisible() returns here, so we just opt for checking

View File

@ -12,7 +12,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/Selection.h"
#include "nsCoord.h"
#include "nsIFrame.h"
#include "nsISelectionListener.h"
#include "nsIWeakReferenceUtils.h"
#include "nsPoint.h"
@ -197,10 +196,6 @@ class nsCaret final : public nsISelectionListener {
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
void SetLastCaretFrame(nsIFrame* aLastCaretFrame) {
mLastCaretFrame = aLastCaretFrame;
}
protected:
static void CaretBlinkCallback(nsITimer* aTimer, void* aClosure);
@ -284,11 +279,6 @@ class nsCaret final : public nsISelectionListener {
* it's in non-user-modifiable content.
*/
bool mIgnoreUserModify;
/**
* mLastCaretFrame is the last caret frame that was scheduled to paint.
*/
WeakFrame mLastCaretFrame;
};
#endif // nsCaret_h__

View File

@ -1302,6 +1302,23 @@ bool RetainedDisplayListBuilder::ShouldBuildPartial(
return true;
}
void RetainedDisplayListBuilder::InvalidateCaretFramesIfNeeded() {
if (mPreviousCaret == mBuilder.GetCaretFrame()) {
// The current caret frame is the same as the previous one.
return;
}
if (mPreviousCaret) {
mPreviousCaret->MarkNeedsDisplayItemRebuild();
}
if (mBuilder.GetCaretFrame()) {
mBuilder.GetCaretFrame()->MarkNeedsDisplayItemRebuild();
}
mPreviousCaret = mBuilder.GetCaretFrame();
}
class AutoClearFramePropsArray {
public:
explicit AutoClearFramePropsArray(size_t aCapacity) : mFrames(aCapacity) {}
@ -1557,6 +1574,8 @@ PartialUpdateResult RetainedDisplayListBuilder::AttemptPartialUpdate(
MarkFramesWithItemsAndImagesModified(&mList);
}
InvalidateCaretFramesIfNeeded();
// We set the override dirty regions during ComputeRebuildRegion or in
// DisplayPortUtils::InvalidateForDisplayPortChange. The display port change
// also marks the frame modified, so those regions are cleared here as well.

View File

@ -272,6 +272,7 @@ class RetainedDisplayListBuilder {
nsDisplayListBuilder mBuilder;
RetainedDisplayList mList;
WeakFrame mPreviousCaret;
RetainedDisplayListMetrics mMetrics;
RetainedDisplayListData mData;
};

View File

@ -653,6 +653,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mCurrentContainerASR(nullptr),
mCurrentFrame(aReferenceFrame),
mCurrentReferenceFrame(aReferenceFrame),
mCaretFrame(nullptr),
mScrollInfoItemsForHoisting(nullptr),
mFirstClipChainToDestroy(nullptr),
mTableBackgroundSet(nullptr),
@ -720,6 +721,21 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mRetainingDisplayList && StaticPrefs::layout_display_list_retain_sc();
}
static PresShell* GetFocusedPresShell() {
nsPIDOMWindowOuter* focusedWnd =
nsFocusManager::GetFocusManager()->GetFocusedWindow();
if (!focusedWnd) {
return nullptr;
}
nsCOMPtr<nsIDocShell> focusedDocShell = focusedWnd->GetDocShell();
if (!focusedDocShell) {
return nullptr;
}
return focusedDocShell->GetPresShell();
}
void nsDisplayListBuilder::BeginFrame() {
nsCSSRendering::BeginFrameTreesLocked();
@ -729,6 +745,26 @@ void nsDisplayListBuilder::BeginFrame() {
mInTransform = false;
mInFilter = false;
mSyncDecodeImages = false;
if (!mBuildCaret) {
return;
}
RefPtr<PresShell> presShell = GetFocusedPresShell();
if (presShell) {
RefPtr<nsCaret> caret = presShell->GetCaret();
mCaretFrame = caret->GetPaintGeometry(&mCaretRect);
// The focused pres shell may not be in the document that we're
// painting, or be in a popup. Check if the display root for
// the caret matches the display root that we're painting, and
// only use it if it matches.
if (mCaretFrame &&
nsLayoutUtils::GetDisplayRootFrame(mCaretFrame) !=
nsLayoutUtils::GetDisplayRootFrame(mReferenceFrame)) {
mCaretFrame = nullptr;
}
}
}
void nsDisplayListBuilder::AddEffectUpdate(dom::RemoteBrowser* aBrowser,
@ -768,6 +804,7 @@ void nsDisplayListBuilder::EndFrame() {
FreeClipChains();
FreeTemporaryItems();
nsCSSRendering::EndFrameTreesLocked();
mCaretFrame = nullptr;
}
void nsDisplayListBuilder::MarkFrameForDisplay(nsIFrame* aFrame,
@ -1102,28 +1139,11 @@ void nsDisplayListBuilder::EnterPresShell(const nsIFrame* aReferenceFrame,
return;
}
RefPtr<nsCaret> caret = state->mPresShell->GetCaret();
// This code run for each pres shell and caret->GetPaintGeometry
// will return nullptr for invisible caret. So only one caret
// can be painted at a time.
state->mCaretFrame = caret->GetPaintGeometry(&mCaretRect);
// Check if the display root for the caret matches the display
// root that we're painting, and only use it if it matches. Likely
// we only need this for popup.
if (state->mCaretFrame &&
nsLayoutUtils::GetDisplayRootFrame(state->mCaretFrame) !=
nsLayoutUtils::GetDisplayRootFrame(aReferenceFrame)) {
state->mCaretFrame = nullptr;
}
// Caret frames add visual area to their frame, but we don't update the
// overflow area. Use flags to make sure we build display items for that frame
// instead.
if (state->mCaretFrame) {
MOZ_ASSERT(state->mCaretFrame->PresShell() == state->mPresShell);
caret->SetLastCaretFrame(state->mCaretFrame);
MarkFrameForDisplay(state->mCaretFrame, aReferenceFrame);
if (mCaretFrame && mCaretFrame->PresShell() == state->mPresShell) {
MarkFrameForDisplay(mCaretFrame, aReferenceFrame);
}
}

View File

@ -656,7 +656,7 @@ class nsDisplayListBuilder {
* Get the frame that the caret is supposed to draw in.
* If the caret is currently invisible, this will be null.
*/
nsIFrame* GetCaretFrame() { return CurrentPresShellState()->mCaretFrame; }
nsIFrame* GetCaretFrame() { return mCaretFrame; }
/**
* Get the rectangle we're supposed to draw the caret into.
*/
@ -1726,7 +1726,6 @@ class nsDisplayListBuilder {
bool mInsidePointerEventsNoneDoc;
bool mTouchEventPrefEnabledDoc;
nsIFrame* mPresShellIgnoreScrollFrame;
nsIFrame* mCaretFrame = nullptr;
};
PresShellState* CurrentPresShellState() {
@ -1761,6 +1760,7 @@ class nsDisplayListBuilder {
// The reference frame for mCurrentFrame.
const nsIFrame* mCurrentReferenceFrame;
nsIFrame* mCaretFrame;
// A temporary list that we append scroll info items to while building
// display items for the contents of frames with SVG effects.
// Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.