зеркало из 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* () {
|
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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче