зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1157941 - If the current PresShell is suppressed, paint the old one if it is available r=tn,Enn
This commit is contained in:
Родитель
7094b286b4
Коммит
f12a9fe441
|
@ -18,36 +18,21 @@ function getFocusedLocalName(browser) {
|
|||
}
|
||||
|
||||
add_task(function* () {
|
||||
gBrowser.selectedTab = gBrowser.addTab(URL);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
let testTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
|
||||
|
||||
let browser = testTab.linkedBrowser;
|
||||
|
||||
is((yield getFocusedLocalName(browser)), "button", "button is focused");
|
||||
|
||||
let promiseFocused = ContentTask.spawn(browser, null, function* () {
|
||||
return new Promise(resolve => {
|
||||
content.addEventListener("focus", function onFocus({target}) {
|
||||
if (String(target.location).startsWith("data:")) {
|
||||
content.removeEventListener("focus", onFocus);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
let blankTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
|
||||
|
||||
// The test page loaded, so open an empty tab, select it, then restore
|
||||
// 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;
|
||||
yield BrowserTestUtils.switchTab(gBrowser, testTab);
|
||||
|
||||
// Make sure focus is given to the window because the element is now gone.
|
||||
is((yield getFocusedLocalName(browser)), "body", "body is focused");
|
||||
|
||||
// Cleanup.
|
||||
gBrowser.removeTab(blankTab);
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
});
|
||||
|
|
|
@ -90,6 +90,10 @@ nsView::~nsView()
|
|||
mParent->RemoveChild(this);
|
||||
}
|
||||
|
||||
if (mPreviousWindow) {
|
||||
mPreviousWindow->SetPreviouslyAttachedWidgetListener(nullptr);
|
||||
}
|
||||
|
||||
// Destroy and release the widget
|
||||
DestroyWidget();
|
||||
|
||||
|
@ -722,6 +726,18 @@ nsresult nsView::DetachFromTopLevelWidget()
|
|||
NS_PRECONDITION(mWindow, "null mWindow for DetachFromTopLevelWidget!");
|
||||
|
||||
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;
|
||||
|
||||
mWidgetIsTopLevel = false;
|
||||
|
@ -1096,3 +1112,9 @@ nsView::HandleEvent(WidgetGUIEvent* aEvent,
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
nsView::IsPrimaryFramePaintSuppressed()
|
||||
{
|
||||
return mFrame ? mFrame->PresContext()->PresShell()->IsPaintingSuppressed() : false;
|
||||
}
|
||||
|
|
|
@ -281,6 +281,14 @@ public:
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -383,6 +391,8 @@ public:
|
|||
nsPoint GetOffsetTo(const nsView* aOther, const int32_t aAPD) const;
|
||||
nsIWidget* GetNearestWidget(nsPoint* aOffset, const int32_t aAPD) const;
|
||||
|
||||
bool IsPrimaryFramePaintSuppressed();
|
||||
|
||||
private:
|
||||
explicit nsView(nsViewManager* aViewManager = nullptr,
|
||||
nsViewVisibility aVisibility = nsViewVisibility_kShow);
|
||||
|
@ -450,6 +460,7 @@ private:
|
|||
nsViewManager *mViewManager;
|
||||
nsView *mParent;
|
||||
nsCOMPtr<nsIWidget> mWindow;
|
||||
nsCOMPtr<nsIWidget> mPreviousWindow;
|
||||
nsView *mNextSibling;
|
||||
nsView *mFirstChild;
|
||||
nsIFrame *mFrame;
|
||||
|
|
|
@ -440,11 +440,20 @@ nsViewManager::ProcessPendingUpdatesPaint(nsIWidget* aWidget)
|
|||
}
|
||||
}
|
||||
nsView* view = nsView::GetViewFor(aWidget);
|
||||
|
||||
if (!view) {
|
||||
NS_ERROR("FlushDelayedResize destroyed the nsView?");
|
||||
return;
|
||||
}
|
||||
|
||||
nsIWidgetListener* previousListener = aWidget->GetPreviouslyAttachedWidgetListener();
|
||||
|
||||
if (previousListener &&
|
||||
previousListener != view &&
|
||||
view->IsPrimaryFramePaintSuppressed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPresShell) {
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
|
@ -1149,3 +1158,4 @@ nsViewManager::InvalidateHierarchy()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,7 +217,14 @@ PuppetWidget::Resize(double aWidth,
|
|||
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 (GetCurrentWidgetListener() &&
|
||||
GetCurrentWidgetListener() != mAttachedWidgetListener) {
|
||||
GetCurrentWidgetListener()->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;
|
||||
|
||||
if (mAttachedWidgetListener) {
|
||||
aStatus = mAttachedWidgetListener->HandleEvent(event, mUseAttachedEvents);
|
||||
if (GetCurrentWidgetListener()) {
|
||||
aStatus = GetCurrentWidgetListener()->HandleEvent(event, mUseAttachedEvents);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -912,7 +919,7 @@ PuppetWidget::Paint()
|
|||
{
|
||||
MOZ_ASSERT(!mDirtyRegion.IsEmpty(), "paint event logic messed up");
|
||||
|
||||
if (!mAttachedWidgetListener)
|
||||
if (!GetCurrentWidgetListener())
|
||||
return NS_OK;
|
||||
|
||||
nsIntRegion region = mDirtyRegion;
|
||||
|
@ -921,9 +928,9 @@ PuppetWidget::Paint()
|
|||
mDirtyRegion.SetEmpty();
|
||||
mPaintTask.Revoke();
|
||||
|
||||
mAttachedWidgetListener->WillPaintWindow(this);
|
||||
GetCurrentWidgetListener()->WillPaintWindow(this);
|
||||
|
||||
if (mAttachedWidgetListener) {
|
||||
if (GetCurrentWidgetListener()) {
|
||||
#ifdef DEBUG
|
||||
debug_DumpPaintEvent(stderr, this, region,
|
||||
nsAutoCString("PuppetWidget"), 0);
|
||||
|
@ -940,15 +947,15 @@ PuppetWidget::Paint()
|
|||
ctx->Clip();
|
||||
AutoLayerManagerSetup setupLayerManager(this, ctx,
|
||||
BufferMode::BUFFER_NONE);
|
||||
mAttachedWidgetListener->PaintWindow(this, region);
|
||||
GetCurrentWidgetListener()->PaintWindow(this, region);
|
||||
if (mTabChild) {
|
||||
mTabChild->NotifyPainted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mAttachedWidgetListener) {
|
||||
mAttachedWidgetListener->DidPaintWindow();
|
||||
if (GetCurrentWidgetListener()) {
|
||||
GetCurrentWidgetListener()->DidPaintWindow();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1250,5 +1257,20 @@ PuppetScreenManager::GetSystemDefaultScale(float *aDefaultScale)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIWidgetListener*
|
||||
PuppetWidget::GetCurrentWidgetListener()
|
||||
{
|
||||
if (!mPreviouslyAttachedWidgetListener ||
|
||||
!mAttachedWidgetListener) {
|
||||
return mAttachedWidgetListener;
|
||||
}
|
||||
|
||||
if (mAttachedWidgetListener->GetView()->IsPrimaryFramePaintSuppressed()) {
|
||||
return mPreviouslyAttachedWidgetListener;
|
||||
}
|
||||
|
||||
return mAttachedWidgetListener;
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -274,6 +274,8 @@ private:
|
|||
bool GetCaretRect(mozilla::LayoutDeviceIntRect& aCaretRect, uint32_t aCaretOffset);
|
||||
uint32_t GetCaretOffset();
|
||||
|
||||
nsIWidgetListener* GetCurrentWidgetListener();
|
||||
|
||||
class PaintTask : public nsRunnable {
|
||||
public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
|
|
@ -147,6 +147,7 @@ NS_IMPL_ISUPPORTS(nsBaseWidget, nsIWidget, nsISupportsWeakReference)
|
|||
nsBaseWidget::nsBaseWidget()
|
||||
: mWidgetListener(nullptr)
|
||||
, mAttachedWidgetListener(nullptr)
|
||||
, mPreviouslyAttachedWidgetListener(nullptr)
|
||||
, mLayerManager(nullptr)
|
||||
, mCompositorVsyncDispatcher(nullptr)
|
||||
, mCursor(eCursor_standard)
|
||||
|
@ -399,6 +400,16 @@ nsIWidgetListener* nsBaseWidget::GetAttachedWidgetListener()
|
|||
return mAttachedWidgetListener;
|
||||
}
|
||||
|
||||
nsIWidgetListener* nsBaseWidget::GetPreviouslyAttachedWidgetListener()
|
||||
{
|
||||
return mPreviouslyAttachedWidgetListener;
|
||||
}
|
||||
|
||||
void nsBaseWidget::SetPreviouslyAttachedWidgetListener(nsIWidgetListener* aListener)
|
||||
{
|
||||
mPreviouslyAttachedWidgetListener = aListener;
|
||||
}
|
||||
|
||||
void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener* aListener)
|
||||
{
|
||||
mAttachedWidgetListener = aListener;
|
||||
|
|
|
@ -236,6 +236,8 @@ public:
|
|||
NS_IMETHOD AttachViewToTopLevel(bool aUseAttachedEvents) override;
|
||||
virtual nsIWidgetListener* GetAttachedWidgetListener() override;
|
||||
virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) override;
|
||||
virtual nsIWidgetListener* GetPreviouslyAttachedWidgetListener() override;
|
||||
virtual void SetPreviouslyAttachedWidgetListener(nsIWidgetListener* aListener) override;
|
||||
NS_IMETHOD_(TextEventDispatcher*) GetTextEventDispatcher() override final;
|
||||
|
||||
// Helper function for dispatching events which are not processed by APZ,
|
||||
|
@ -489,6 +491,7 @@ protected:
|
|||
|
||||
nsIWidgetListener* mWidgetListener;
|
||||
nsIWidgetListener* mAttachedWidgetListener;
|
||||
nsIWidgetListener* mPreviouslyAttachedWidgetListener;
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
nsRefPtr<CompositorChild> mCompositorChild;
|
||||
nsRefPtr<CompositorParent> mCompositorParent;
|
||||
|
|
|
@ -121,8 +121,8 @@ typedef void* nsNativeWidget;
|
|||
#define NS_NATIVE_PLUGIN_ID 105
|
||||
|
||||
#define NS_IWIDGET_IID \
|
||||
{ 0x22b4504e, 0xddba, 0x4211, \
|
||||
{ 0xa1, 0x49, 0x6e, 0x11, 0x73, 0xc4, 0x11, 0x45 } }
|
||||
{ 0x483BF75C, 0xF909, 0x45C3, \
|
||||
{ 0x95, 0xBE, 0x41, 0x89, 0xDB, 0xCE, 0x2E, 0x13 } };
|
||||
|
||||
/*
|
||||
* Window shadow styles
|
||||
|
@ -1075,6 +1075,8 @@ class nsIWidget : public nsISupports {
|
|||
*/
|
||||
virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener) = 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
|
||||
|
|
Загрузка…
Ссылка в новой задаче