Bug 689623. Part 6. Keep a list of visible images on the presshell and code to manage it. r=mats

This commit is contained in:
Timothy Nikkel
2013-02-24 18:59:22 -06:00
parent 69377b4e06
commit b8a752e3e0
4 changed files with 152 additions and 7 deletions

View File

@@ -182,6 +182,7 @@
#include "nsTransitionManager.h"
#include "LayerTreeInvalidation.h"
#include "nsAsyncDOMEvent.h"
#include "nsIImageLoadingContent.h"
#define ANCHOR_SCROLL_FLAGS \
(nsIPresShell::SCROLL_OVERFLOW_HIDDEN | nsIPresShell::SCROLL_NO_PARENT_FRAMES)
@@ -1001,6 +1002,10 @@ PresShell::Destroy()
mSynthMouseMoveEvent.Revoke();
mUpdateImageVisibilityEvent.Revoke();
ClearVisibleImagesList();
if (mCaret) {
mCaret->Terminate();
mCaret = nullptr;
@@ -3613,8 +3618,10 @@ PresShell::UnsuppressAndInvalidate()
if (win)
win->SetReadyForFocus();
if (!mHaveShutDown)
if (!mHaveShutDown) {
SynthesizeMouseMove(false);
ScheduleImageVisibilityUpdate();
}
}
void
@@ -5278,6 +5285,116 @@ PresShell::ProcessSynthMouseMoveEvent(bool aFromScroll)
}
}
/* static */ void
PresShell::MarkImagesInListVisible(const nsDisplayList& aList)
{
for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
nsDisplayList* sublist = item->GetChildren();
if (sublist) {
MarkImagesInListVisible(*sublist);
continue;
}
nsIFrame* f = item->GetUnderlyingFrame();
// We could check the type of the display item, only a handful can hold an
// image loading content.
if (f) {
// dont bother nscomptr here, it is wasteful
nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(f->GetContent()));
if (content) {
// use the presshell containing the image
PresShell* presShell = static_cast<PresShell*>(f->PresContext()->PresShell());
if (presShell) {
content->IncrementVisibleCount();
presShell->mVisibleImages.AppendElement(content);
}
}
}
}
}
void
PresShell::RebuildImageVisibility(const nsDisplayList& aList)
{
nsTArray< nsCOMPtr<nsIImageLoadingContent > > beforeimagelist;
beforeimagelist.SwapElements(mVisibleImages);
MarkImagesInListVisible(aList);
for (uint32_t i = 0; i < beforeimagelist.Length(); ++i) {
beforeimagelist[i]->DecrementVisibleCount();
}
}
void
PresShell::ClearVisibleImagesList()
{
for (uint32_t i = 0; i < mVisibleImages.Length(); ++i) {
mVisibleImages[i]->DecrementVisibleCount();
}
mVisibleImages.Clear();
}
void
PresShell::UpdateImageVisibility()
{
MOZ_ASSERT(!mPresContext || mPresContext->IsRootContentDocument(),
"updating image visibility on a non-root content document?");
mUpdateImageVisibilityEvent.Revoke();
if (mHaveShutDown || mIsDestroying) {
return;
}
// call update on that frame
nsIFrame* rootFrame = GetRootFrame();
if (!rootFrame) {
ClearVisibleImagesList();
return;
}
// We could walk the frame tree directly and skip creating a display list for
// better perf.
nsRect updateRect(nsPoint(0, 0), rootFrame->GetSize());
nsDisplayListBuilder builder(rootFrame, nsDisplayListBuilder::IMAGE_VISIBILITY, true);
builder.IgnorePaintSuppression();
builder.EnterPresShell(rootFrame, updateRect);
nsDisplayList list;
rootFrame->BuildDisplayListForStackingContext(&builder, updateRect, &list);
builder.LeavePresShell(rootFrame, updateRect);
RebuildImageVisibility(list);
list.DeleteAll();
}
void
PresShell::ScheduleImageVisibilityUpdate()
{
if (!mPresContext)
return;
if (!mPresContext->IsRootContentDocument()) {
nsPresContext* presContext = mPresContext->GetToplevelContentDocumentPresContext();
if (!presContext)
return;
MOZ_ASSERT(presContext->IsRootContentDocument(),
"Didn't get a root prescontext from GetToplevelContentDocumentPresContext?");
presContext->PresShell()->ScheduleImageVisibilityUpdate();
return;
}
if (mHaveShutDown || mIsDestroying)
return;
if (mUpdateImageVisibilityEvent.IsPending())
return;
nsRefPtr<nsRunnableMethod<PresShell> > ev =
NS_NewRunnableMethod(this, &PresShell::UpdateImageVisibility);
if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev))) {
mUpdateImageVisibilityEvent = ev;
}
}
class nsAutoNotifyDidPaint
{
public:
@@ -7281,6 +7398,8 @@ FreezeSubDocument(nsIDocument *aDocument, void *aData)
void
PresShell::Freeze()
{
mUpdateImageVisibilityEvent.Revoke();
MaybeReleaseCapturingContent();
mDocument->EnumerateFreezableElements(FreezeElement, nullptr);