diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 842ef1173b5c..ad88ce6b8a24 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -92,9 +92,6 @@ [] - - null - [] @@ -4926,28 +4923,7 @@ 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 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 diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index cbdc0008397d..2194cc5e7a1c 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -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 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() { diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index c953cde5dc09..8892b7ed9a41 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -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 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> mLiveResizeListeners; + #ifdef DEBUG protected: static nsAutoString debug_GuiEventToString(mozilla::WidgetGUIEvent* aGuiEvent); diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 06765f22da84..29bd1b3e8666 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -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 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 observerService = mozilla::services::GetObserverService(); - if (observerService) { - observerService->NotifyObservers(nullptr, "live-resize-end", nullptr); - } + NotifyLiveResizeStopped(); } mResizeState = aNewState; ForcePresent(); diff --git a/xpfe/appshell/LiveResizeListener.h b/xpfe/appshell/LiveResizeListener.h new file mode 100644 index 000000000000..f41dcfaea97d --- /dev/null +++ b/xpfe/appshell/LiveResizeListener.h @@ -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 diff --git a/xpfe/appshell/moz.build b/xpfe/appshell/moz.build index 5cfe4192481f..089580b6aea0 100644 --- a/xpfe/appshell/moz.build +++ b/xpfe/appshell/moz.build @@ -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') \ No newline at end of file +include('/ipc/chromium/chromium-config.mozbuild') diff --git a/xpfe/appshell/nsIXULWindow.idl b/xpfe/appshell/nsIXULWindow.idl index ceeb7f1b4d90..27468df825c1 100644 --- a/xpfe/appshell/nsIXULWindow.idl +++ b/xpfe/appshell/nsIXULWindow.idl @@ -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>); + [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 diff --git a/xpfe/appshell/nsXULWindow.cpp b/xpfe/appshell/nsXULWindow.cpp index c9c0dc9ad134..1b18966df36a 100644 --- a/xpfe/appshell/nsXULWindow.cpp +++ b/xpfe/appshell/nsXULWindow.cpp @@ -344,6 +344,17 @@ nsXULWindow::GetPrimaryTabParent(nsITabParent** aTab) return NS_OK; } +nsTArray> +nsXULWindow::GetLiveResizeListeners() +{ + nsTArray> listeners; + if (mPrimaryTabParent) { + TabParent* parent = static_cast(mPrimaryTabParent.get()); + listeners.AppendElement(parent); + } + return listeners; +} + NS_IMETHODIMP nsXULWindow::AddChildWindow(nsIXULWindow *aChild) { // we're not really keeping track of this right now