From 8b1beff09d8e62cd2943c1cf1b2513ad8bb5aada Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Tue, 6 Oct 2015 14:23:24 -0500 Subject: [PATCH] Bug 1137944 - Add support for hiding plugin windows during async dom scroll operations managed in the content process. r=roc --- layout/generic/nsGfxScrollFrame.cpp | 38 +++++++++++++++++++++++++++++ layout/generic/nsGfxScrollFrame.h | 8 ++++++ layout/generic/nsPluginFrame.cpp | 29 ++++++++++++++++++++++ layout/generic/nsPluginFrame.h | 10 ++++++++ 4 files changed, 85 insertions(+) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index f82d587d4c6..ebca12c9ca0 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -45,6 +45,7 @@ #include "nsSMILKeySpline.h" #include "nsSubDocumentFrame.h" #include "nsSVGOuterSVGFrame.h" +#include "nsIObjectLoadingContent.h" #include "mozilla/Attributes.h" #include "ScrollbarActivity.h" #include "nsRefreshDriver.h" @@ -57,6 +58,7 @@ #include "gfxPrefs.h" #include "AsyncScrollBase.h" #include "UnitTransforms.h" +#include "nsPluginFrame.h" #include #include #include @@ -1852,6 +1854,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, , mTransformingByAPZ(false) , mZoomableByAPZ(false) , mVelocityQueue(aOuter->PresContext()) + , mAsyncScrollEvent(END) { if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) { mScrollbarActivity = new ScrollbarActivity(do_QueryFrame(aOuter)); @@ -1958,6 +1961,8 @@ ScrollFrameHelper::AsyncScrollCallback(ScrollFrameHelper* aInstance, void ScrollFrameHelper::CompleteAsyncScroll(const nsRect &aRange, nsIAtom* aOrigin) { + NotifyPluginFrames(END); + // Apply desired destination range since this is the last step of scrolling. mAsyncSmoothMSDScroll = nullptr; mAsyncScroll = nullptr; @@ -1971,6 +1976,38 @@ ScrollFrameHelper::CompleteAsyncScroll(const nsRect &aRange, nsIAtom* aOrigin) mDestination = GetScrollPosition(); } +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) +static void +NotifyPluginFramesCallback(nsISupports* aSupports, void* aFlag) +{ + nsCOMPtr content = do_QueryInterface(aSupports); + if (content) { + nsIFrame *frame = content->GetPrimaryFrame(); + if (frame) { + nsPluginFrame* plugin = do_QueryFrame(frame); + if (plugin) { + plugin->SetScrollVisibility(aFlag != nullptr); + } + } + } +} +#endif + +void +ScrollFrameHelper::NotifyPluginFrames(AsyncScrollEventType aEvent) +{ +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) + if (XRE_IsContentProcess()) { + if (aEvent != mAsyncScrollEvent) { + nsPresContext* presContext = mOuter->PresContext(); + presContext->Document()->EnumerateActivityObservers(NotifyPluginFramesCallback, + (void*)(aEvent == BEGIN)); + mAsyncScrollEvent = aEvent; + } + } +#endif +} + void ScrollFrameHelper::ScrollToCSSPixels(const CSSIntPoint& aScrollPosition, nsIScrollableFrame::ScrollMode aMode) @@ -2125,6 +2162,7 @@ ScrollFrameHelper::ScrollToWithOrigin(nsPoint aScrollPosition, mAsyncScroll->mIsSmoothScroll = isSmoothScroll; if (isSmoothScroll) { + NotifyPluginFrames(BEGIN); mAsyncScroll->InitSmoothScroll(now, mDestination, aOrigin, range, currentVelocity); } else { mAsyncScroll->Init(range); diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 6bcb51d0834..b6b44fdce5a 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -558,6 +558,14 @@ protected: void CompleteAsyncScroll(const nsRect &aRange, nsIAtom* aOrigin = nullptr); + /* + * Helper that notifies plugins about async smooth scroll operations managed + * by nsGfxScrollFrame. + */ + enum AsyncScrollEventType { BEGIN, END }; + void NotifyPluginFrames(AsyncScrollEventType aEvent); + AsyncScrollEventType mAsyncScrollEvent; + static void EnsureImageVisPrefsCached(); static bool sImageVisPrefsCached; // The number of scrollports wide/high to expand when looking for images. diff --git a/layout/generic/nsPluginFrame.cpp b/layout/generic/nsPluginFrame.cpp index 81f248f893f..37bfbdfc2ac 100644 --- a/layout/generic/nsPluginFrame.cpp +++ b/layout/generic/nsPluginFrame.cpp @@ -157,6 +157,7 @@ nsPluginFrame::nsPluginFrame(nsStyleContext* aContext) : nsPluginFrameSuper(aContext) , mInstanceOwner(nullptr) , mReflowCallbackPosted(false) + , mIsHiddenDueToScroll(false) { MOZ_LOG(GetObjectFrameLog(), LogLevel::Debug, ("Created new nsPluginFrame %p\n", this)); @@ -764,6 +765,23 @@ nsPluginFrame::IsHidden(bool aCheckVisibilityStyle) const return false; } +// Clips windowed plugin frames during remote content scroll operations managed +// by nsGfxScrollFrame. +void +nsPluginFrame::SetScrollVisibility(bool aState) +{ + // Limit this setting to windowed plugins by checking if we have a widget + if (mWidget) { + bool changed = mIsHiddenDueToScroll != aState; + mIsHiddenDueToScroll = aState; + // Force a paint so plugin window visibility gets flushed via + // the compositor. + if (changed) { + SchedulePaint(); + } + } +} + mozilla::LayoutDeviceIntPoint nsPluginFrame::GetRemoteTabChromeOffset() { @@ -1098,6 +1116,11 @@ nsPluginFrame::DidSetWidgetGeometry() bool nsPluginFrame::IsOpaque() const { + // Insure underlying content gets painted when we clip windowed plugins + // during remote content scroll operations managed by nsGfxScrollFrame. + if (mIsHiddenDueToScroll) { + return false; + } #if defined(XP_MACOSX) return false; #elif defined(MOZ_WIDGET_ANDROID) @@ -1143,6 +1166,12 @@ nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { + // Clip windowed plugin frames from the list during remote content scroll + // operations managed by nsGfxScrollFrame. + if (mIsHiddenDueToScroll) { + return; + } + // XXX why are we painting collapsed object frames? if (!IsVisibleOrCollapsedForPainting(aBuilder)) return; diff --git a/layout/generic/nsPluginFrame.h b/layout/generic/nsPluginFrame.h index 611839ca724..32556026daa 100644 --- a/layout/generic/nsPluginFrame.h +++ b/layout/generic/nsPluginFrame.h @@ -24,6 +24,7 @@ #undef GetClassName #undef GetBinaryType #undef RemoveDirectory +#undef LoadIcon #endif class nsPresContext; @@ -199,6 +200,11 @@ public: void SetInstanceOwner(nsPluginInstanceOwner* aOwner); + /** + * Helper for hiding windowed plugins during non-apz scroll operations. + */ + void SetScrollVisibility(bool aState); + protected: explicit nsPluginFrame(nsStyleContext* aContext); virtual ~nsPluginFrame(); @@ -302,6 +308,10 @@ private: // This is only non-null while we have a plugin registered for geometry // updates. nsRefPtr mRootPresContextRegisteredWith; + + // Tracks windowed plugin visibility during scroll operations. See + // SetScrollVisibility. + bool mIsHiddenDueToScroll; }; class nsDisplayPlugin : public nsDisplayItem {