mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	Depends on D221391 Differential Revision: https://phabricator.services.mozilla.com/D221392
		
			
				
	
	
		
			224 lines
		
	
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* 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/ScrollContainerFrame.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 "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 (ScrollContainerFrame* rootScrollContainerFrame =
 | 
						|
          mPresShell->GetRootScrollContainerFrame()) {
 | 
						|
    return Some(
 | 
						|
        CSSRect::FromAppUnits(nsLayoutUtils::CalculateScrollableRectForFrame(
 | 
						|
            rootScrollContainerFrame, 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->GetRootScrollContainerFrame()),
 | 
						|
      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;
 | 
						|
}
 | 
						|
 | 
						|
bool GeckoMVMContext::IsDocumentFullscreen() const {
 | 
						|
  MOZ_ASSERT(mDocument);
 | 
						|
  return mDocument->Fullscreen();
 | 
						|
}
 | 
						|
 | 
						|
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 (ScrollContainerFrame* root = mPresShell->GetRootScrollContainerFrame()) {
 | 
						|
    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);
 | 
						|
    DisplayPortUtils::CalculateAndSetDisplayPortMargins(
 | 
						|
        root, 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);
 | 
						|
}
 | 
						|
 | 
						|
dom::InteractiveWidget GeckoMVMContext::GetInteractiveWidgetMode() const {
 | 
						|
  return mDocument->InteractiveWidget();
 | 
						|
}
 | 
						|
}  // namespace mozilla
 |