Bug 1137944 - Add support for hiding plugin windows during async dom scroll operations managed in the content process. r=roc

This commit is contained in:
Jim Mathies 2015-10-06 14:23:24 -05:00
parent 84b34afc13
commit 8b1beff09d
4 changed files with 85 additions and 0 deletions

View File

@ -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 <mozilla/layers/AxisPhysicsModel.h>
#include <mozilla/layers/AxisPhysicsMSDModel.h>
#include <algorithm>
@ -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<nsIContent> 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);

View File

@ -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.

View File

@ -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;

View File

@ -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<nsRootPresContext> mRootPresContextRegisteredWith;
// Tracks windowed plugin visibility during scroll operations. See
// SetScrollVisibility.
bool mIsHiddenDueToScroll;
};
class nsDisplayPlugin : public nsDisplayItem {