зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1328066 - Don't broadcast the live-resize events to all browser windows unnecessarily. r=mstange
The machinery for suppressing the displayport during live resizes was using the Observer service. However, in the case of multiple browser windows, this meant that all the open browser windows would have their displayport suppressed if *any* of the browser windows was being resized. This was mostly ok, as the displayport suppression would be turned off once the resize ended. However, the code to kick off a repaint with the unsuppressed displayport would only get triggered on one of the windows (whichever happened to process the unsuppress message last). This patch stops using the Observer service for the implementation machinery, and instead locates the active TabParent of the relevant nsWindow, and invokes the displayport suppression directly on that. This fixes the repainting bug and also avoids unnecessarily broadcasting the suppression/unsuppression notification to windows that don't neccessarily need it. MozReview-Commit-ID: LBHOgOW9KUp
This commit is contained in:
Родитель
c8192bce58
Коммит
cf091ea0eb
|
@ -92,9 +92,6 @@
|
|||
<field name="mProgressListeners">
|
||||
[]
|
||||
</field>
|
||||
<field name="mActiveResizeDisplayportSuppression">
|
||||
null
|
||||
</field>
|
||||
<field name="mTabsProgressListeners">
|
||||
[]
|
||||
</field>
|
||||
|
@ -4926,28 +4923,7 @@
|
|||
<parameter name="aTopic"/>
|
||||
<parameter name="aData"/>
|
||||
<body><![CDATA[
|
||||
let browser;
|
||||
switch (aTopic) {
|
||||
case "live-resize-start": {
|
||||
browser = this.mCurrentTab.linkedBrowser;
|
||||
let fl = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
|
||||
if (fl && fl.tabParent && !this.mActiveResizeDisplayportSuppression) {
|
||||
fl.tabParent.suppressDisplayport(true);
|
||||
this.mActiveResizeDisplayportSuppression = browser;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "live-resize-end": {
|
||||
browser = this.mActiveResizeDisplayportSuppression;
|
||||
if (browser) {
|
||||
let fl = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
|
||||
if (fl && fl.tabParent) {
|
||||
fl.tabParent.suppressDisplayport(false);
|
||||
this.mActiveResizeDisplayportSuppression = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "contextual-identity-updated": {
|
||||
for (let tab of this.tabs) {
|
||||
if (tab.getAttribute("usercontextid") == aData) {
|
||||
|
@ -4970,8 +4946,6 @@
|
|||
this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser");
|
||||
this.mCurrentBrowser.permanentKey = {};
|
||||
|
||||
Services.obs.addObserver(this, "live-resize-start", false);
|
||||
Services.obs.addObserver(this, "live-resize-end", false);
|
||||
Services.obs.addObserver(this, "contextual-identity-updated", false);
|
||||
|
||||
this.mCurrentTab = this.tabContainer.firstChild;
|
||||
|
@ -5074,8 +5048,6 @@
|
|||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
Services.obs.removeObserver(this, "live-resize-start");
|
||||
Services.obs.removeObserver(this, "live-resize-end");
|
||||
Services.obs.removeObserver(this, "contextual-identity-updated");
|
||||
|
||||
for (let tab of this.tabs) {
|
||||
|
|
|
@ -3296,6 +3296,18 @@ TabParent::RecvRequestCrossBrowserNavigation(const uint32_t& aGlobalIndex)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::LiveResizeStarted()
|
||||
{
|
||||
SuppressDisplayport(true);
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::LiveResizeStopped()
|
||||
{
|
||||
SuppressDisplayport(false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define mozilla_tabs_TabParent_h
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "LiveResizeListener.h"
|
||||
#include "mozilla/ContentCache.h"
|
||||
#include "mozilla/dom/AudioChannelBinding.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
|
@ -91,6 +92,7 @@ class TabParent final : public PBrowserParent
|
|||
, public TabContext
|
||||
, public nsAPostRefreshObserver
|
||||
, public nsIWebBrowserPersistable
|
||||
, public LiveResizeListener
|
||||
{
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
|
||||
|
@ -593,6 +595,10 @@ public:
|
|||
|
||||
mozilla::ipc::IPCResult RecvEnsureLayersConnected() override;
|
||||
|
||||
// LiveResizeListener implementation
|
||||
void LiveResizeStarted() override;
|
||||
void LiveResizeStopped() override;
|
||||
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
|
|
|
@ -3653,24 +3653,24 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
|
||||
- (void)viewWillStartLiveResize
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
|
||||
if (!observerService) {
|
||||
return;
|
||||
nsCocoaWindow* windowWidget = mGeckoChild ? mGeckoChild->GetXULWindowWidget() : nullptr;
|
||||
if (windowWidget) {
|
||||
windowWidget->NotifyLiveResizeStarted();
|
||||
}
|
||||
|
||||
observerService->NotifyObservers(nullptr, "live-resize-start", nullptr);
|
||||
}
|
||||
|
||||
- (void)viewDidEndLiveResize
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
|
||||
if (!observerService) {
|
||||
return;
|
||||
// mGeckoChild may legitimately be null here. It should also have been null
|
||||
// in viewWillStartLiveResize, so there's no problem. However if we run into
|
||||
// cases where the windowWidget was non-null in viewWillStartLiveResize but
|
||||
// is null here, that might be problematic because we might get stuck with
|
||||
// a content process that has the displayport suppressed. If that scenario
|
||||
// arises (I'm not sure that it does) we will need to handle it gracefully.
|
||||
nsCocoaWindow* windowWidget = mGeckoChild ? mGeckoChild->GetXULWindowWidget() : nullptr;
|
||||
if (windowWidget) {
|
||||
windowWidget->NotifyLiveResizeStopped();
|
||||
}
|
||||
|
||||
observerService->NotifyObservers(nullptr, "live-resize-end", nullptr);
|
||||
}
|
||||
|
||||
- (NSColor*)vibrancyFillColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "LiveResizeListener.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -249,6 +250,7 @@ WidgetShutdownObserver::Unregister()
|
|||
void
|
||||
nsBaseWidget::Shutdown()
|
||||
{
|
||||
NotifyLiveResizeStopped();
|
||||
RevokeTransactionIdAllocator();
|
||||
DestroyCompositor();
|
||||
FreeShutdownObserver();
|
||||
|
@ -2093,6 +2095,41 @@ nsBaseWidget::UpdateSynthesizedTouchState(MultiTouchInput* aState,
|
|||
return inputToDispatch;
|
||||
}
|
||||
|
||||
void
|
||||
nsBaseWidget::NotifyLiveResizeStarted()
|
||||
{
|
||||
// If we have mLiveResizeListeners already non-empty, we should notify those
|
||||
// listeners that the resize stopped before starting anew. In theory this
|
||||
// should never happen because we shouldn't get nested live resize actions.
|
||||
NotifyLiveResizeStopped();
|
||||
MOZ_ASSERT(mLiveResizeListeners.IsEmpty());
|
||||
|
||||
// If we can get the active tab parent for the current widget, suppress
|
||||
// the displayport on it during the live resize.
|
||||
if (!mWidgetListener) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIXULWindow> xulWindow = mWidgetListener->GetXULWindow();
|
||||
if (!xulWindow) {
|
||||
return;
|
||||
}
|
||||
mLiveResizeListeners = xulWindow->GetLiveResizeListeners();
|
||||
for (uint32_t i = 0; i < mLiveResizeListeners.Length(); i++) {
|
||||
mLiveResizeListeners[i]->LiveResizeStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBaseWidget::NotifyLiveResizeStopped()
|
||||
{
|
||||
if (!mLiveResizeListeners.IsEmpty()) {
|
||||
for (uint32_t i = 0; i < mLiveResizeListeners.Length(); i++) {
|
||||
mLiveResizeListeners[i]->LiveResizeStopped();
|
||||
}
|
||||
mLiveResizeListeners.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBaseWidget::RegisterPluginWindowForRemoteUpdates()
|
||||
{
|
||||
|
|
|
@ -37,6 +37,8 @@ class gfxContext;
|
|||
|
||||
namespace mozilla {
|
||||
class CompositorVsyncDispatcher;
|
||||
class LiveResizeListener;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
namespace a11y {
|
||||
class Accessible;
|
||||
|
@ -398,6 +400,13 @@ public:
|
|||
uint64_t CreateScrollCaptureContainer() override;
|
||||
#endif
|
||||
|
||||
// These functions should be called at the start and end of a "live" widget
|
||||
// resize (i.e. when the window contents are repainting during the resize,
|
||||
// such as when the user drags a window border). It will suppress the
|
||||
// displayport during the live resize to avoid unneccessary overpainting.
|
||||
void NotifyLiveResizeStarted();
|
||||
void NotifyLiveResizeStopped();
|
||||
|
||||
protected:
|
||||
// These are methods for CompositorWidgetWrapper, and should only be
|
||||
// accessed from that class. Derived widgets can choose which methods to
|
||||
|
@ -709,6 +718,11 @@ protected:
|
|||
|
||||
mozilla::Maybe<InitialZoomConstraints> mInitialZoomConstraints;
|
||||
|
||||
// This points to the resize listeners who have been notified that a live
|
||||
// resize is in progress. This should always be empty when a live-resize is
|
||||
// not in progress.
|
||||
nsTArray<RefPtr<mozilla::LiveResizeListener>> mLiveResizeListeners;
|
||||
|
||||
#ifdef DEBUG
|
||||
protected:
|
||||
static nsAutoString debug_GuiEventToString(mozilla::WidgetGUIEvent* aGuiEvent);
|
||||
|
|
|
@ -5644,13 +5644,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
// within a ENTERSIZEMOVE to consider this a live resize event.
|
||||
if (mResizeState == IN_SIZEMOVE) {
|
||||
mResizeState = RESIZING;
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
|
||||
if (observerService) {
|
||||
observerService->NotifyObservers(nullptr, "live-resize-start",
|
||||
nullptr);
|
||||
}
|
||||
NotifyLiveResizeStarted();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -6077,10 +6071,7 @@ void
|
|||
nsWindow::FinishLiveResizing(ResizeState aNewState)
|
||||
{
|
||||
if (mResizeState == RESIZING) {
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->NotifyObservers(nullptr, "live-resize-end", nullptr);
|
||||
}
|
||||
NotifyLiveResizeStopped();
|
||||
}
|
||||
mResizeState = aNewState;
|
||||
ForcePresent();
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_LiveResizeListener_h
|
||||
#define mozilla_LiveResizeListener_h
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class LiveResizeListener {
|
||||
public:
|
||||
virtual void LiveResizeStarted() = 0;
|
||||
virtual void LiveResizeStopped() = 0;
|
||||
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
|
||||
protected:
|
||||
virtual ~LiveResizeListener() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_LiveResizeListener_h
|
|
@ -19,6 +19,7 @@ XPIDL_SOURCES += [
|
|||
XPIDL_MODULE = 'appshell'
|
||||
|
||||
EXPORTS += [
|
||||
'LiveResizeListener.h',
|
||||
'nsAppShellCID.h',
|
||||
]
|
||||
|
||||
|
@ -39,4 +40,4 @@ LOCAL_INCLUDES += [
|
|||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -13,12 +13,19 @@
|
|||
* notification through the global observer service.
|
||||
*/
|
||||
|
||||
%{C++
|
||||
#include "LiveResizeListener.h"
|
||||
#include "nsTArray.h"
|
||||
%}
|
||||
|
||||
interface nsIDocShell;
|
||||
interface nsIDocShellTreeItem;
|
||||
interface nsIXULBrowserWindow;
|
||||
interface nsITabParent;
|
||||
interface mozIDOMWindowProxy;
|
||||
|
||||
native LiveResizeListenerArray(nsTArray<RefPtr<mozilla::LiveResizeListener>>);
|
||||
|
||||
[scriptable, uuid(d6d7a014-e28d-4c9d-8727-1cf6d870619b)]
|
||||
interface nsIXULWindow : nsISupports
|
||||
{
|
||||
|
@ -51,6 +58,8 @@ interface nsIXULWindow : nsISupports
|
|||
void tabParentAdded(in nsITabParent aTab, in boolean aPrimary);
|
||||
void tabParentRemoved(in nsITabParent aTab);
|
||||
|
||||
[noscript,notxpcom] LiveResizeListenerArray getLiveResizeListeners();
|
||||
|
||||
/**
|
||||
* Tell this window that it has picked up a child XUL window
|
||||
* @param aChild the child window being added
|
||||
|
|
|
@ -344,6 +344,17 @@ nsXULWindow::GetPrimaryTabParent(nsITabParent** aTab)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTArray<RefPtr<mozilla::LiveResizeListener>>
|
||||
nsXULWindow::GetLiveResizeListeners()
|
||||
{
|
||||
nsTArray<RefPtr<mozilla::LiveResizeListener>> listeners;
|
||||
if (mPrimaryTabParent) {
|
||||
TabParent* parent = static_cast<TabParent*>(mPrimaryTabParent.get());
|
||||
listeners.AppendElement(parent);
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXULWindow::AddChildWindow(nsIXULWindow *aChild)
|
||||
{
|
||||
// we're not really keeping track of this right now
|
||||
|
|
Загрузка…
Ссылка в новой задаче