From f4328c5b39c6ee68d48f829114731618de33a4bf Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Fri, 24 May 2013 09:43:36 +0800 Subject: [PATCH] Bug 868047 - Use a PresShell ID to eliminate stale APZC events; r=roc,benwa --- CLOBBER | 2 +- dom/base/nsDOMWindowUtils.cpp | 15 +++++++++++++++ dom/interfaces/base/nsIDOMWindowUtils.idl | 2 ++ dom/ipc/TabChild.cpp | 16 +++++++++++++++- dom/ipc/TabChild.h | 1 + gfx/layers/FrameMetrics.h | 11 +++++++++-- ipc/glue/IPCMessageUtils.h | 4 +++- layout/base/nsDisplayList.cpp | 2 ++ layout/base/nsIPresShell.h | 4 ++++ layout/base/nsPresShell.cpp | 2 ++ 10 files changed, 54 insertions(+), 5 deletions(-) diff --git a/CLOBBER b/CLOBBER index 2caf9cc1ad9..eee30009a47 100644 --- a/CLOBBER +++ b/CLOBBER @@ -17,7 +17,7 @@ # # Modifying this file will now automatically clobber the buildbot machines \o/ # -Bug 874640 touched webidl, so Windows needs to clobber +Bug 868047 - Adding a field to FrameMetrics affects ContainerLayer class size Alternative to clobber is to run ./config.status from the objdir and to touch the CLOBBER file in the objdir. diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 32f3002b38a..ff8d6225578 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -522,6 +522,21 @@ nsDOMWindowUtils::GetIsFirstPaint(bool *aIsFirstPaint) return NS_ERROR_FAILURE; } +NS_IMETHODIMP +nsDOMWindowUtils::GetPresShellId(uint32_t *aPresShellId) +{ + if (!nsContentUtils::IsCallerChrome()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsIPresShell* presShell = GetPresShell(); + if (presShell) { + *aPresShellId = presShell->GetPresShellId(); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + /* static */ mozilla::widget::Modifiers nsDOMWindowUtils::GetWidgetModifiers(int32_t aModifiers) diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 13118f89616..2842d964ec0 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -195,6 +195,8 @@ interface nsIDOMWindowUtils : nsISupports { */ attribute boolean isFirstPaint; + void getPresShellId(out uint32_t aPresShellId); + /** * Following modifiers are for sent*Event() except sendNative*Event(). * NOTE: MODIFIER_ALT, MODIFIER_CONTROL, MODIFIER_SHIFT and MODIFIER_META diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index c1de40981e1..7e3feb404a0 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -633,7 +633,7 @@ TabChild::HandlePossibleViewportChange() // Force a repaint with these metrics. This, among other things, sets the // displayport, so we start with async painting. - RecvUpdateFrame(metrics); + ProcessUpdateFrame(metrics); } nsresult @@ -1454,6 +1454,20 @@ ScrollWindowTo(nsIDOMWindow* aWindow, const mozilla::gfx::Point& aPoint) bool TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics) { + nsCOMPtr utils(GetDOMWindowUtils()); + + uint32_t presShellId; + nsresult rv = utils->GetPresShellId(&presShellId); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + if (NS_SUCCEEDED(rv) && aFrameMetrics.mPresShellId != presShellId) { + return true; + } + return ProcessUpdateFrame(aFrameMetrics); +} + +bool +TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics) + { if (!mCx || !mTabChildGlobal) { return true; } diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index b0ab4af12ea..2a9fdc89d56 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -366,6 +366,7 @@ private: bool InitRenderingState(); void DestroyWindow(); void SetProcessNameToAppName(); + bool ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics); // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow(). void DoFakeShow(); diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 9fa44f5e00c..72e2b51165a 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -42,6 +42,7 @@ public: , mZoom(1, 1) , mDevPixelsPerCSSPixel(1) , mMayHaveTouchListeners(false) + , mPresShellId(-1) {} // Default copy ctor and operator= are fine @@ -58,7 +59,8 @@ public: mScrollableRect.IsEqualEdges(aOther.mScrollableRect) && mResolution == aOther.mResolution && mDevPixelsPerCSSPixel == aOther.mDevPixelsPerCSSPixel && - mMayHaveTouchListeners == aOther.mMayHaveTouchListeners; + mMayHaveTouchListeners == aOther.mMayHaveTouchListeners && + mPresShellId == aOther.mPresShellId; } bool operator!=(const FrameMetrics& aOther) const { @@ -67,7 +69,10 @@ public: bool IsDefault() const { - return (FrameMetrics() == *this); + FrameMetrics def; + + def.mPresShellId = mPresShellId; + return (def == *this); } bool IsRootScrollable() const @@ -241,6 +246,8 @@ public: // Whether or not this frame may have touch listeners. bool mMayHaveTouchListeners; + + uint32_t mPresShellId; }; } diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index 369fa7a2ac3..61885b94b71 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -1044,6 +1044,7 @@ struct ParamTraits WriteParam(aMsg, aParam.mZoom); WriteParam(aMsg, aParam.mDevPixelsPerCSSPixel); WriteParam(aMsg, aParam.mMayHaveTouchListeners); + WriteParam(aMsg, aParam.mPresShellId); } static bool Read(const Message* aMsg, void** aIter, paramType* aResult) @@ -1059,7 +1060,8 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mResolution) && ReadParam(aMsg, aIter, &aResult->mZoom) && ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) && - ReadParam(aMsg, aIter, &aResult->mMayHaveTouchListeners)); + ReadParam(aMsg, aIter, &aResult->mMayHaveTouchListeners) && + ReadParam(aMsg, aIter, &aResult->mPresShellId)); } }; diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 820c6d79438..04dc4d9cc28 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -695,6 +695,8 @@ static void RecordFrameMetrics(nsIFrame* aForFrame, widget->GetBounds(metrics.mCompositionBounds); } + metrics.mPresShellId = presShell->GetPresShellId(); + aRoot->SetFrameMetrics(metrics); } diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 4eaaf273ff3..fb9cf0dc5a3 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1229,6 +1229,8 @@ public: */ bool GetIsFirstPaint() const { return mIsFirstPaint; } + uint32_t GetPresShellId() { return mPresShellId; } + /** * Dispatch a mouse move event based on the most recent mouse position if * this PresShell is visible. This is used when the contents of the page @@ -1527,6 +1529,8 @@ protected: bool mSuppressInterruptibleReflows : 1; bool mScrollPositionClampingScrollPortSizeSet : 1; + uint32_t mPresShellId; + // List of subtrees rooted at style scope roots that need to be restyled. // When a change to a scoped style sheet is made, we add the style scope // root to this array rather than setting mStylesHaveChanged = true, since diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 75ccfb38c62..d0bfd627628 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -687,6 +687,7 @@ nsIPresShell::FrameSelection() //---------------------------------------------------------------------- static bool sSynthMouseMove = true; +static uint32_t sNextPresShellId; PresShell::PresShell() : mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) @@ -713,6 +714,7 @@ PresShell::PresShell() #else mIsFirstPaint = true; #endif + mPresShellId = sNextPresShellId++; mFrozen = false; #ifdef DEBUG mPresArenaAllocCount = 0;