Bug 1157941 - If the current PresShell is suppressed, paint the old one if it is available r=tn,Enn

This commit is contained in:
George Wright 2015-07-21 21:09:02 -04:00
Родитель 7094b286b4
Коммит f12a9fe441
9 изменённых файлов: 100 добавлений и 32 удалений

Просмотреть файл

@ -18,36 +18,21 @@ function getFocusedLocalName(browser) {
} }
add_task(function* () { add_task(function* () {
gBrowser.selectedTab = gBrowser.addTab(URL); let testTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let browser = gBrowser.selectedBrowser;
yield BrowserTestUtils.browserLoaded(browser); let browser = testTab.linkedBrowser;
is((yield getFocusedLocalName(browser)), "button", "button is focused"); is((yield getFocusedLocalName(browser)), "button", "button is focused");
let promiseFocused = ContentTask.spawn(browser, null, function* () { let blankTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
return new Promise(resolve => {
content.addEventListener("focus", function onFocus({target}) {
if (String(target.location).startsWith("data:")) {
content.removeEventListener("focus", onFocus);
resolve();
}
});
});
});
// The test page loaded, so open an empty tab, select it, then restore yield BrowserTestUtils.switchTab(gBrowser, testTab);
// the test tab. This causes the test page's focused element to be removed
// from its document.
gBrowser.selectedTab = gBrowser.addTab("about:blank");
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
gBrowser.removeCurrentTab();
// Wait until the original tab is focused again.
yield promiseFocused;
// Make sure focus is given to the window because the element is now gone. // Make sure focus is given to the window because the element is now gone.
is((yield getFocusedLocalName(browser)), "body", "body is focused"); is((yield getFocusedLocalName(browser)), "body", "body is focused");
// Cleanup. // Cleanup.
gBrowser.removeTab(blankTab);
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();
}); });

Просмотреть файл

@ -90,6 +90,10 @@ nsView::~nsView()
mParent->RemoveChild(this); mParent->RemoveChild(this);
} }
if (mPreviousWindow) {
mPreviousWindow->SetPreviouslyAttachedWidgetListener(nullptr);
}
// Destroy and release the widget // Destroy and release the widget
DestroyWidget(); DestroyWidget();
@ -722,6 +726,18 @@ nsresult nsView::DetachFromTopLevelWidget()
NS_PRECONDITION(mWindow, "null mWindow for DetachFromTopLevelWidget!"); NS_PRECONDITION(mWindow, "null mWindow for DetachFromTopLevelWidget!");
mWindow->SetAttachedWidgetListener(nullptr); mWindow->SetAttachedWidgetListener(nullptr);
nsIWidgetListener* listener = mWindow->GetPreviouslyAttachedWidgetListener();
if (listener && listener->GetView()) {
// Ensure the listener doesn't think it's being used anymore
listener->GetView()->SetPreviousWidget(nullptr);
}
// If the new view's frame is paint suppressed then the window
// will want to use us instead until that's done
mWindow->SetPreviouslyAttachedWidgetListener(this);
mPreviousWindow = mWindow;
mWindow = nullptr; mWindow = nullptr;
mWidgetIsTopLevel = false; mWidgetIsTopLevel = false;
@ -1096,3 +1112,9 @@ nsView::HandleEvent(WidgetGUIEvent* aEvent,
return result; return result;
} }
bool
nsView::IsPrimaryFramePaintSuppressed()
{
return mFrame ? mFrame->PresContext()->PresShell()->IsPaintingSuppressed() : false;
}

Просмотреть файл

@ -281,6 +281,14 @@ public:
*/ */
nsIWidget* GetWidget() const { return mWindow; } nsIWidget* GetWidget() const { return mWindow; }
/**
* The widget which we have attached a listener to can also have a "previous"
* listener set on it. This is to keep track of the last nsView when navigating
* to a new one so that we can continue to paint that if the new one isn't ready
* yet.
*/
void SetPreviousWidget(nsIWidget* aWidget) { mPreviousWindow = aWidget; }
/** /**
* Returns true if the view has a widget associated with it. * Returns true if the view has a widget associated with it.
*/ */
@ -383,6 +391,8 @@ public:
nsPoint GetOffsetTo(const nsView* aOther, const int32_t aAPD) const; nsPoint GetOffsetTo(const nsView* aOther, const int32_t aAPD) const;
nsIWidget* GetNearestWidget(nsPoint* aOffset, const int32_t aAPD) const; nsIWidget* GetNearestWidget(nsPoint* aOffset, const int32_t aAPD) const;
bool IsPrimaryFramePaintSuppressed();
private: private:
explicit nsView(nsViewManager* aViewManager = nullptr, explicit nsView(nsViewManager* aViewManager = nullptr,
nsViewVisibility aVisibility = nsViewVisibility_kShow); nsViewVisibility aVisibility = nsViewVisibility_kShow);
@ -450,6 +460,7 @@ private:
nsViewManager *mViewManager; nsViewManager *mViewManager;
nsView *mParent; nsView *mParent;
nsCOMPtr<nsIWidget> mWindow; nsCOMPtr<nsIWidget> mWindow;
nsCOMPtr<nsIWidget> mPreviousWindow;
nsView *mNextSibling; nsView *mNextSibling;
nsView *mFirstChild; nsView *mFirstChild;
nsIFrame *mFrame; nsIFrame *mFrame;

Просмотреть файл

@ -440,11 +440,20 @@ nsViewManager::ProcessPendingUpdatesPaint(nsIWidget* aWidget)
} }
} }
nsView* view = nsView::GetViewFor(aWidget); nsView* view = nsView::GetViewFor(aWidget);
if (!view) { if (!view) {
NS_ERROR("FlushDelayedResize destroyed the nsView?"); NS_ERROR("FlushDelayedResize destroyed the nsView?");
return; return;
} }
nsIWidgetListener* previousListener = aWidget->GetPreviouslyAttachedWidgetListener();
if (previousListener &&
previousListener != view &&
view->IsPrimaryFramePaintSuppressed()) {
return;
}
if (mPresShell) { if (mPresShell) {
#ifdef MOZ_DUMP_PAINTING #ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
@ -1149,3 +1158,4 @@ nsViewManager::InvalidateHierarchy()
} }
} }
} }

Просмотреть файл

@ -217,7 +217,14 @@ PuppetWidget::Resize(double aWidth,
InvalidateRegion(this, dirty); InvalidateRegion(this, dirty);
} }
// call WindowResized() on both the current listener, and possibly
// also the previous one if we're in a state where we're drawing that one
// because the current one is paint suppressed
if (!oldBounds.IsEqualEdges(mBounds) && mAttachedWidgetListener) { if (!oldBounds.IsEqualEdges(mBounds) && mAttachedWidgetListener) {
if (GetCurrentWidgetListener() &&
GetCurrentWidgetListener() != mAttachedWidgetListener) {
GetCurrentWidgetListener()->WindowResized(this, mBounds.width, mBounds.height);
}
mAttachedWidgetListener->WindowResized(this, mBounds.width, mBounds.height); mAttachedWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
} }
@ -313,8 +320,8 @@ PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
aStatus = nsEventStatus_eIgnore; aStatus = nsEventStatus_eIgnore;
if (mAttachedWidgetListener) { if (GetCurrentWidgetListener()) {
aStatus = mAttachedWidgetListener->HandleEvent(event, mUseAttachedEvents); aStatus = GetCurrentWidgetListener()->HandleEvent(event, mUseAttachedEvents);
} }
return NS_OK; return NS_OK;
@ -912,7 +919,7 @@ PuppetWidget::Paint()
{ {
MOZ_ASSERT(!mDirtyRegion.IsEmpty(), "paint event logic messed up"); MOZ_ASSERT(!mDirtyRegion.IsEmpty(), "paint event logic messed up");
if (!mAttachedWidgetListener) if (!GetCurrentWidgetListener())
return NS_OK; return NS_OK;
nsIntRegion region = mDirtyRegion; nsIntRegion region = mDirtyRegion;
@ -921,9 +928,9 @@ PuppetWidget::Paint()
mDirtyRegion.SetEmpty(); mDirtyRegion.SetEmpty();
mPaintTask.Revoke(); mPaintTask.Revoke();
mAttachedWidgetListener->WillPaintWindow(this); GetCurrentWidgetListener()->WillPaintWindow(this);
if (mAttachedWidgetListener) { if (GetCurrentWidgetListener()) {
#ifdef DEBUG #ifdef DEBUG
debug_DumpPaintEvent(stderr, this, region, debug_DumpPaintEvent(stderr, this, region,
nsAutoCString("PuppetWidget"), 0); nsAutoCString("PuppetWidget"), 0);
@ -940,15 +947,15 @@ PuppetWidget::Paint()
ctx->Clip(); ctx->Clip();
AutoLayerManagerSetup setupLayerManager(this, ctx, AutoLayerManagerSetup setupLayerManager(this, ctx,
BufferMode::BUFFER_NONE); BufferMode::BUFFER_NONE);
mAttachedWidgetListener->PaintWindow(this, region); GetCurrentWidgetListener()->PaintWindow(this, region);
if (mTabChild) { if (mTabChild) {
mTabChild->NotifyPainted(); mTabChild->NotifyPainted();
} }
} }
} }
if (mAttachedWidgetListener) { if (GetCurrentWidgetListener()) {
mAttachedWidgetListener->DidPaintWindow(); GetCurrentWidgetListener()->DidPaintWindow();
} }
return NS_OK; return NS_OK;
@ -1250,5 +1257,20 @@ PuppetScreenManager::GetSystemDefaultScale(float *aDefaultScale)
return NS_OK; return NS_OK;
} }
nsIWidgetListener*
PuppetWidget::GetCurrentWidgetListener()
{
if (!mPreviouslyAttachedWidgetListener ||
!mAttachedWidgetListener) {
return mAttachedWidgetListener;
}
if (mAttachedWidgetListener->GetView()->IsPrimaryFramePaintSuppressed()) {
return mPreviouslyAttachedWidgetListener;
}
return mAttachedWidgetListener;
}
} // namespace widget } // namespace widget
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -274,6 +274,8 @@ private:
bool GetCaretRect(mozilla::LayoutDeviceIntRect& aCaretRect, uint32_t aCaretOffset); bool GetCaretRect(mozilla::LayoutDeviceIntRect& aCaretRect, uint32_t aCaretOffset);
uint32_t GetCaretOffset(); uint32_t GetCaretOffset();
nsIWidgetListener* GetCurrentWidgetListener();
class PaintTask : public nsRunnable { class PaintTask : public nsRunnable {
public: public:
NS_DECL_NSIRUNNABLE NS_DECL_NSIRUNNABLE

Просмотреть файл

@ -147,6 +147,7 @@ NS_IMPL_ISUPPORTS(nsBaseWidget, nsIWidget, nsISupportsWeakReference)
nsBaseWidget::nsBaseWidget() nsBaseWidget::nsBaseWidget()
: mWidgetListener(nullptr) : mWidgetListener(nullptr)
, mAttachedWidgetListener(nullptr) , mAttachedWidgetListener(nullptr)
, mPreviouslyAttachedWidgetListener(nullptr)
, mLayerManager(nullptr) , mLayerManager(nullptr)
, mCompositorVsyncDispatcher(nullptr) , mCompositorVsyncDispatcher(nullptr)
, mCursor(eCursor_standard) , mCursor(eCursor_standard)
@ -399,6 +400,16 @@ nsIWidgetListener* nsBaseWidget::GetAttachedWidgetListener()
return mAttachedWidgetListener; return mAttachedWidgetListener;
} }
nsIWidgetListener* nsBaseWidget::GetPreviouslyAttachedWidgetListener()
{
return mPreviouslyAttachedWidgetListener;
}
void nsBaseWidget::SetPreviouslyAttachedWidgetListener(nsIWidgetListener* aListener)
{
mPreviouslyAttachedWidgetListener = aListener;
}
void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener* aListener) void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener* aListener)
{ {
mAttachedWidgetListener = aListener; mAttachedWidgetListener = aListener;

Просмотреть файл

@ -236,6 +236,8 @@ public:
NS_IMETHOD AttachViewToTopLevel(bool aUseAttachedEvents) override; NS_IMETHOD AttachViewToTopLevel(bool aUseAttachedEvents) override;
virtual nsIWidgetListener* GetAttachedWidgetListener() override; virtual nsIWidgetListener* GetAttachedWidgetListener() override;
virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) override; virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) override;
virtual nsIWidgetListener* GetPreviouslyAttachedWidgetListener() override;
virtual void SetPreviouslyAttachedWidgetListener(nsIWidgetListener* aListener) override;
NS_IMETHOD_(TextEventDispatcher*) GetTextEventDispatcher() override final; NS_IMETHOD_(TextEventDispatcher*) GetTextEventDispatcher() override final;
// Helper function for dispatching events which are not processed by APZ, // Helper function for dispatching events which are not processed by APZ,
@ -489,6 +491,7 @@ protected:
nsIWidgetListener* mWidgetListener; nsIWidgetListener* mWidgetListener;
nsIWidgetListener* mAttachedWidgetListener; nsIWidgetListener* mAttachedWidgetListener;
nsIWidgetListener* mPreviouslyAttachedWidgetListener;
nsRefPtr<LayerManager> mLayerManager; nsRefPtr<LayerManager> mLayerManager;
nsRefPtr<CompositorChild> mCompositorChild; nsRefPtr<CompositorChild> mCompositorChild;
nsRefPtr<CompositorParent> mCompositorParent; nsRefPtr<CompositorParent> mCompositorParent;

Просмотреть файл

@ -121,8 +121,8 @@ typedef void* nsNativeWidget;
#define NS_NATIVE_PLUGIN_ID 105 #define NS_NATIVE_PLUGIN_ID 105
#define NS_IWIDGET_IID \ #define NS_IWIDGET_IID \
{ 0x22b4504e, 0xddba, 0x4211, \ { 0x483BF75C, 0xF909, 0x45C3, \
{ 0xa1, 0x49, 0x6e, 0x11, 0x73, 0xc4, 0x11, 0x45 } } { 0x95, 0xBE, 0x41, 0x89, 0xDB, 0xCE, 0x2E, 0x13 } };
/* /*
* Window shadow styles * Window shadow styles
@ -1075,6 +1075,8 @@ class nsIWidget : public nsISupports {
*/ */
virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) = 0; virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) = 0;
virtual nsIWidgetListener* GetAttachedWidgetListener() = 0; virtual nsIWidgetListener* GetAttachedWidgetListener() = 0;
virtual void SetPreviouslyAttachedWidgetListener(nsIWidgetListener* aListener) = 0;
virtual nsIWidgetListener* GetPreviouslyAttachedWidgetListener() = 0;
/** /**
* Accessor functions to get and set the listener which handles various * Accessor functions to get and set the listener which handles various