Bug 1354913: Fix nsDeckFrame, nsImageBoxFrame and nsImageFrame so that nsDeckFrame does not tick the refresh driver when its child images are animated and hidden. r=aosmond

Differential Revision: https://phabricator.services.mozilla.com/D24598

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Will Hawkins 2019-03-25 19:11:22 +00:00
parent 0d286523d2
commit b3e38bb341
6 changed files with 91 additions and 0 deletions

View File

@ -2548,6 +2548,38 @@ void nsImageFrame::IconLoad::GetPrefs() {
"browser.display.show_loading_image_placeholder", true);
}
nsresult nsImageFrame::RestartAnimation() {
nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest();
/*
* We cannot count on mContentURLRequestRegistered to make
* the deregistration work. So, we are going to force it.
*/
bool deregister = true;
if (currentRequest && !mContentURLRequestRegistered) {
nsLayoutUtils::RegisterImageRequestIfAnimated(PresContext(), currentRequest,
&deregister);
return currentRequest->StartDecoding(imgIContainer::FLAG_NONE);
}
return NS_OK;
}
nsresult nsImageFrame::StopAnimation() {
nsCOMPtr<imgIRequest> currentRequest = GetCurrentRequest();
/*
* We cannot count on mContentURLRequestRegistered to make
* the deregistration work. So, we are going to force it.
*/
bool deregister = true;
if (currentRequest) {
nsLayoutUtils::DeregisterImageRequest(PresContext(), currentRequest,
&deregister);
return currentRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
}
return NS_OK;
}
NS_IMETHODIMP
nsImageFrame::IconLoad::Notify(imgIRequest* aRequest, int32_t aType,
const nsIntRect* aData) {

View File

@ -134,6 +134,9 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
NS_IF_RELEASE(sIOService);
}
virtual nsresult RestartAnimation();
virtual nsresult StopAnimation();
already_AddRefed<imgIRequest> GetCurrentRequest() const;
nsresult Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData);

View File

@ -28,6 +28,8 @@
#include "nsContainerFrame.h"
#include "nsContentUtils.h"
#include "nsXULPopupManager.h"
#include "nsImageBoxFrame.h"
#include "nsImageFrame.h"
#ifdef ACCESSIBILITY
# include "nsAccessibilityService.h"
@ -72,13 +74,17 @@ void nsDeckFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
mIndex = GetSelectedIndex();
}
void nsDeckFrame::ShowBox(nsIFrame* aBox) { Animate(aBox, true); }
void nsDeckFrame::HideBox(nsIFrame* aBox) {
nsIPresShell::ClearMouseCapture(aBox);
Animate(aBox, false);
}
void nsDeckFrame::IndexChanged() {
// did the index change?
int32_t index = GetSelectedIndex();
if (index == mIndex) return;
// redraw
@ -91,6 +97,8 @@ void nsDeckFrame::IndexChanged() {
mIndex = index;
ShowBox(GetSelectedBox());
#ifdef ACCESSIBILITY
nsAccessibilityService* accService = GetAccService();
if (accService) {
@ -171,6 +179,34 @@ void nsDeckFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
BuildDisplayListForChild(aBuilder, box, set);
}
void nsDeckFrame::Animate(nsIFrame* aParentBox, bool start) {
if (!aParentBox) return;
nsImageBoxFrame* imgBoxFrame = do_QueryFrame(aParentBox);
nsImageFrame* imgFrame = do_QueryFrame(aParentBox);
if (imgBoxFrame) {
if (start)
imgBoxFrame->RestartAnimation();
else
imgBoxFrame->StopAnimation();
}
if (imgFrame) {
if (start)
imgFrame->RestartAnimation();
else
imgFrame->StopAnimation();
}
for (nsIFrame::ChildListIterator childLists(aParentBox); !childLists.IsDone();
childLists.Next()) {
for (nsIFrame* child : childLists.CurrentList()) {
Animate(child, start);
}
}
}
NS_IMETHODIMP
nsDeckFrame::DoXULLayout(nsBoxLayoutState& aState) {
// Make sure we tweak the state so it does not resize our children.

View File

@ -56,10 +56,13 @@ class nsDeckFrame final : public nsBoxFrame {
void IndexChanged();
int32_t GetSelectedIndex();
void HideBox(nsIFrame* aBox);
void ShowBox(nsIFrame* aBox);
private:
int32_t mIndex;
void Animate(nsIFrame*, bool);
}; // class nsDeckFrame
#endif

View File

@ -124,6 +124,9 @@ nsIFrame* NS_NewImageBoxFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle) {
}
NS_IMPL_FRAMEARENA_HELPERS(nsImageBoxFrame)
NS_QUERYFRAME_HEAD(nsImageBoxFrame)
NS_QUERYFRAME_ENTRY(nsImageBoxFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsLeafBoxFrame)
nsresult nsImageBoxFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
@ -195,6 +198,16 @@ void nsImageBoxFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
UpdateImage();
}
void nsImageBoxFrame::RestartAnimation() { UpdateImage(); }
void nsImageBoxFrame::StopAnimation() {
if (mImageRequest && mRequestRegistered) {
nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
&mRequestRegistered);
mImageRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
}
}
void nsImageBoxFrame::UpdateImage() {
nsPresContext* presContext = PresContext();

View File

@ -41,6 +41,7 @@ class nsImageBoxFrame final : public nsLeafBoxFrame {
friend class nsDisplayXULImage;
NS_DECL_FRAMEARENA_HELPERS(nsImageBoxFrame)
NS_DECL_QUERYFRAME
virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
@ -80,6 +81,9 @@ class nsImageBoxFrame final : public nsLeafBoxFrame {
*/
void UpdateLoadFlags();
void RestartAnimation();
void StopAnimation();
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;