diff options
Diffstat (limited to 'layout/base/GeckoMVMContext.cpp')
-rw-r--r-- | layout/base/GeckoMVMContext.cpp | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/layout/base/GeckoMVMContext.cpp b/layout/base/GeckoMVMContext.cpp new file mode 100644 index 0000000000..85bb21b85e --- /dev/null +++ b/layout/base/GeckoMVMContext.cpp @@ -0,0 +1,217 @@ +/* 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/. */ + +#include "GeckoMVMContext.h" + +#include "mozilla/DisplayPortUtils.h" +#include "mozilla/PresShell.h" +#include "mozilla/Services.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/VisualViewport.h" +#include "nsCOMPtr.h" +#include "nsGlobalWindowInner.h" +#include "nsIDOMEventListener.h" +#include "nsIFrame.h" +#include "nsIObserverService.h" +#include "nsIScrollableFrame.h" +#include "nsLayoutUtils.h" +#include "nsPIDOMWindow.h" +#include "nsPresContext.h" + +namespace mozilla { + +GeckoMVMContext::GeckoMVMContext(dom::Document* aDocument, + PresShell* aPresShell) + : mDocument(aDocument), mPresShell(aPresShell) { + if (nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow()) { + mEventTarget = window->GetChromeEventHandler(); + } +} + +void GeckoMVMContext::AddEventListener(const nsAString& aType, + nsIDOMEventListener* aListener, + bool aUseCapture) { + if (mEventTarget) { + mEventTarget->AddEventListener(aType, aListener, aUseCapture); + } +} + +void GeckoMVMContext::RemoveEventListener(const nsAString& aType, + nsIDOMEventListener* aListener, + bool aUseCapture) { + if (mEventTarget) { + mEventTarget->RemoveEventListener(aType, aListener, aUseCapture); + } +} + +void GeckoMVMContext::AddObserver(nsIObserver* aObserver, const char* aTopic, + bool aOwnsWeak) { + if (nsCOMPtr<nsIObserverService> observerService = + services::GetObserverService()) { + observerService->AddObserver(aObserver, aTopic, aOwnsWeak); + } +} + +void GeckoMVMContext::RemoveObserver(nsIObserver* aObserver, + const char* aTopic) { + if (nsCOMPtr<nsIObserverService> observerService = + services::GetObserverService()) { + observerService->RemoveObserver(aObserver, aTopic); + } +} + +void GeckoMVMContext::Destroy() { + mEventTarget = nullptr; + mDocument = nullptr; + mPresShell = nullptr; +} + +nsViewportInfo GeckoMVMContext::GetViewportInfo( + const ScreenIntSize& aDisplaySize) const { + MOZ_ASSERT(mDocument); + return mDocument->GetViewportInfo(aDisplaySize); +} + +CSSToLayoutDeviceScale GeckoMVMContext::CSSToDevPixelScale() const { + MOZ_ASSERT(mPresShell); + return mPresShell->GetPresContext()->CSSToDevPixelScale(); +} + +float GeckoMVMContext::GetResolution() const { + MOZ_ASSERT(mPresShell); + return mPresShell->GetResolution(); +} + +bool GeckoMVMContext::SubjectMatchesDocument(nsISupports* aSubject) const { + MOZ_ASSERT(mDocument); + return SameCOMIdentity(aSubject, ToSupports(mDocument)); +} + +Maybe<CSSRect> GeckoMVMContext::CalculateScrollableRectForRSF() const { + MOZ_ASSERT(mPresShell); + if (nsIScrollableFrame* rootScrollableFrame = + mPresShell->GetRootScrollFrameAsScrollable()) { + return Some( + CSSRect::FromAppUnits(nsLayoutUtils::CalculateScrollableRectForFrame( + rootScrollableFrame, nullptr))); + } + return Nothing(); +} + +bool GeckoMVMContext::IsResolutionUpdatedByApz() const { + MOZ_ASSERT(mPresShell); + return mPresShell->IsResolutionUpdatedByApz(); +} + +LayoutDeviceMargin +GeckoMVMContext::ScrollbarAreaToExcludeFromCompositionBounds() const { + MOZ_ASSERT(mPresShell); + return LayoutDeviceMargin::FromAppUnits( + nsLayoutUtils::ScrollbarAreaToExcludeFromCompositionBoundsFor( + mPresShell->GetRootScrollFrame()), + mPresShell->GetPresContext()->AppUnitsPerDevPixel()); +} + +Maybe<LayoutDeviceIntSize> GeckoMVMContext::GetDocumentViewerSize() const { + MOZ_ASSERT(mPresShell); + LayoutDeviceIntSize result; + if (nsLayoutUtils::GetDocumentViewerSize(mPresShell->GetPresContext(), + result)) { + return Some(result); + } + return Nothing(); +} + +bool GeckoMVMContext::AllowZoomingForDocument() const { + MOZ_ASSERT(mDocument); + return nsLayoutUtils::AllowZoomingForDocument(mDocument); +} + +bool GeckoMVMContext::IsInReaderMode() const { + MOZ_ASSERT(mDocument); + nsString uri; + if (NS_FAILED(mDocument->GetDocumentURI(uri))) { + return false; + } + static auto readerModeUriPrefix = u"about:reader"_ns; + return StringBeginsWith(uri, readerModeUriPrefix); +} + +bool GeckoMVMContext::IsDocumentLoading() const { + MOZ_ASSERT(mDocument); + return mDocument->GetReadyStateEnum() == dom::Document::READYSTATE_LOADING; +} + +void GeckoMVMContext::SetResolutionAndScaleTo(float aResolution, + ResolutionChangeOrigin aOrigin) { + MOZ_ASSERT(mPresShell); + mPresShell->SetResolutionAndScaleTo(aResolution, aOrigin); +} + +void GeckoMVMContext::SetVisualViewportSize(const CSSSize& aSize) { + MOZ_ASSERT(mPresShell); + mPresShell->SetVisualViewportSize( + nsPresContext::CSSPixelsToAppUnits(aSize.width), + nsPresContext::CSSPixelsToAppUnits(aSize.height)); +} + +void GeckoMVMContext::PostVisualViewportResizeEventByDynamicToolbar() { + MOZ_ASSERT(mDocument); + + // We only fire visual viewport events and don't want to cause any explicit + // reflows here since in general we don't use the up-to-date visual viewport + // size for layout. + if (auto* window = nsGlobalWindowInner::Cast(mDocument->GetInnerWindow())) { + window->VisualViewport()->PostResizeEvent(); + } +} + +void GeckoMVMContext::UpdateDisplayPortMargins() { + MOZ_ASSERT(mPresShell); + if (nsIFrame* root = mPresShell->GetRootScrollFrame()) { + nsIContent* content = root->GetContent(); + bool hasDisplayPort = DisplayPortUtils::HasNonMinimalDisplayPort(content); + bool hasResolution = mPresShell->GetResolution() != 1.0f; + if (!hasDisplayPort && !hasResolution) { + // We only want to update the displayport if there is one already, or + // add one if there's a resolution on the document (see bug 1225508 + // comment 1). + return; + } + nsRect displayportBase = nsRect( + nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(root)); + // We only create MobileViewportManager for root content documents. If that + // ever changes we'd need to limit the size of this displayport base rect + // because non-toplevel documents have no limit on their size. + MOZ_ASSERT( + mPresShell->GetPresContext()->IsRootContentDocumentCrossProcess()); + DisplayPortUtils::SetDisplayPortBaseIfNotSet(content, displayportBase); + nsIScrollableFrame* scrollable = do_QueryFrame(root); + DisplayPortUtils::CalculateAndSetDisplayPortMargins( + scrollable, DisplayPortUtils::RepaintMode::Repaint); + } +} + +void GeckoMVMContext::Reflow(const CSSSize& aNewSize) { + RefPtr doc = mDocument; + RefPtr ps = mPresShell; + + MOZ_ASSERT(doc); + MOZ_ASSERT(ps); + + if (ps->ResizeReflowIgnoreOverride(CSSPixel::ToAppUnits(aNewSize.width), + CSSPixel::ToAppUnits(aNewSize.height))) { + doc->FlushPendingNotifications(FlushType::InterruptibleLayout); + } +} + +ScreenIntCoord GeckoMVMContext::GetDynamicToolbarOffset() { + const nsPresContext* presContext = mPresShell->GetPresContext(); + return presContext->HasDynamicToolbar() + ? presContext->GetDynamicToolbarMaxHeight() - + presContext->GetDynamicToolbarHeight() + : ScreenIntCoord(0); +} + +} // namespace mozilla |