GeckoMVMContext.cpp (7601B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "GeckoMVMContext.h" 6 7 #include "mozilla/DisplayPortUtils.h" 8 #include "mozilla/PresShell.h" 9 #include "mozilla/ScrollContainerFrame.h" 10 #include "mozilla/Services.h" 11 #include "mozilla/dom/Document.h" 12 #include "mozilla/dom/VisualViewport.h" 13 #include "nsCOMPtr.h" 14 #include "nsGlobalWindowInner.h" 15 #include "nsIDOMEventListener.h" 16 #include "nsIFrame.h" 17 #include "nsIObserverService.h" 18 #include "nsLayoutUtils.h" 19 #include "nsPIDOMWindow.h" 20 #include "nsPresContext.h" 21 22 namespace mozilla { 23 24 GeckoMVMContext::GeckoMVMContext(dom::Document* aDocument, 25 PresShell* aPresShell) 26 : mDocument(aDocument), mPresShell(aPresShell) { 27 if (nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow()) { 28 mEventTarget = window->GetChromeEventHandler(); 29 } 30 } 31 32 void GeckoMVMContext::AddEventListener(const nsAString& aType, 33 nsIDOMEventListener* aListener, 34 bool aUseCapture) { 35 if (mEventTarget) { 36 mEventTarget->AddEventListener(aType, aListener, aUseCapture); 37 } 38 } 39 40 void GeckoMVMContext::RemoveEventListener(const nsAString& aType, 41 nsIDOMEventListener* aListener, 42 bool aUseCapture) { 43 if (mEventTarget) { 44 mEventTarget->RemoveEventListener(aType, aListener, aUseCapture); 45 } 46 } 47 48 void GeckoMVMContext::AddObserver(nsIObserver* aObserver, const char* aTopic, 49 bool aOwnsWeak) { 50 if (nsCOMPtr<nsIObserverService> observerService = 51 services::GetObserverService()) { 52 observerService->AddObserver(aObserver, aTopic, aOwnsWeak); 53 } 54 } 55 56 void GeckoMVMContext::RemoveObserver(nsIObserver* aObserver, 57 const char* aTopic) { 58 if (nsCOMPtr<nsIObserverService> observerService = 59 services::GetObserverService()) { 60 observerService->RemoveObserver(aObserver, aTopic); 61 } 62 } 63 64 void GeckoMVMContext::Destroy() { 65 mEventTarget = nullptr; 66 mDocument = nullptr; 67 mPresShell = nullptr; 68 } 69 70 nsViewportInfo GeckoMVMContext::GetViewportInfo( 71 const ScreenIntSize& aDisplaySize) const { 72 MOZ_ASSERT(mDocument); 73 return mDocument->GetViewportInfo(aDisplaySize); 74 } 75 76 CSSToLayoutDeviceScale GeckoMVMContext::CSSToDevPixelScale() const { 77 MOZ_ASSERT(mPresShell); 78 return mPresShell->GetPresContext()->CSSToDevPixelScale(); 79 } 80 81 float GeckoMVMContext::GetResolution() const { 82 MOZ_ASSERT(mPresShell); 83 return mPresShell->GetResolution(); 84 } 85 86 bool GeckoMVMContext::SubjectMatchesDocument(nsISupports* aSubject) const { 87 MOZ_ASSERT(mDocument); 88 return SameCOMIdentity(aSubject, ToSupports(mDocument)); 89 } 90 91 Maybe<CSSRect> GeckoMVMContext::CalculateScrollableRectForRSF() const { 92 MOZ_ASSERT(mPresShell); 93 if (ScrollContainerFrame* rootScrollContainerFrame = 94 mPresShell->GetRootScrollContainerFrame()) { 95 return Some( 96 CSSRect::FromAppUnits(nsLayoutUtils::CalculateScrollableRectForFrame( 97 rootScrollContainerFrame, nullptr))); 98 } 99 return Nothing(); 100 } 101 102 bool GeckoMVMContext::IsResolutionUpdatedByApz() const { 103 MOZ_ASSERT(mPresShell); 104 return mPresShell->IsResolutionUpdatedByApz(); 105 } 106 107 LayoutDeviceMargin 108 GeckoMVMContext::ScrollbarAreaToExcludeFromCompositionBounds() const { 109 MOZ_ASSERT(mPresShell); 110 return LayoutDeviceMargin::FromAppUnits( 111 nsLayoutUtils::ScrollbarAreaToExcludeFromCompositionBoundsFor( 112 mPresShell->GetRootScrollContainerFrame()), 113 mPresShell->GetPresContext()->AppUnitsPerDevPixel()); 114 } 115 116 Maybe<LayoutDeviceIntSize> GeckoMVMContext::GetDocumentViewerSize() const { 117 MOZ_ASSERT(mPresShell); 118 LayoutDeviceIntSize result; 119 if (nsLayoutUtils::GetDocumentViewerSize(mPresShell->GetPresContext(), 120 result)) { 121 return Some(result); 122 } 123 return Nothing(); 124 } 125 126 bool GeckoMVMContext::AllowZoomingForDocument() const { 127 MOZ_ASSERT(mDocument); 128 return nsLayoutUtils::AllowZoomingForDocument(mDocument); 129 } 130 131 bool GeckoMVMContext::IsInReaderMode() const { 132 MOZ_ASSERT(mDocument); 133 nsString uri; 134 if (NS_FAILED(mDocument->GetDocumentURI(uri))) { 135 return false; 136 } 137 static auto readerModeUriPrefix = u"about:reader"_ns; 138 return StringBeginsWith(uri, readerModeUriPrefix); 139 } 140 141 bool GeckoMVMContext::IsDocumentLoading() const { 142 MOZ_ASSERT(mDocument); 143 return mDocument->GetReadyStateEnum() == dom::Document::READYSTATE_LOADING; 144 } 145 146 bool GeckoMVMContext::IsDocumentFullscreen() const { 147 MOZ_ASSERT(mDocument); 148 return mDocument->Fullscreen(); 149 } 150 151 void GeckoMVMContext::SetResolutionAndScaleTo(float aResolution, 152 ResolutionChangeOrigin aOrigin) { 153 MOZ_ASSERT(mPresShell); 154 mPresShell->SetResolutionAndScaleTo(aResolution, aOrigin); 155 } 156 157 void GeckoMVMContext::SetVisualViewportSize(const CSSSize& aSize) { 158 MOZ_ASSERT(mPresShell); 159 mPresShell->SetVisualViewportSize( 160 nsPresContext::CSSPixelsToAppUnits(aSize.width), 161 nsPresContext::CSSPixelsToAppUnits(aSize.height)); 162 } 163 164 void GeckoMVMContext::PostVisualViewportResizeEventByDynamicToolbar() { 165 MOZ_ASSERT(mDocument); 166 167 // We only fire visual viewport events and don't want to cause any explicit 168 // reflows here since in general we don't use the up-to-date visual viewport 169 // size for layout. 170 if (auto* window = nsGlobalWindowInner::Cast(mDocument->GetInnerWindow())) { 171 window->VisualViewport()->PostResizeEvent(); 172 } 173 } 174 175 void GeckoMVMContext::UpdateDisplayPortMargins() { 176 MOZ_ASSERT(mPresShell); 177 if (ScrollContainerFrame* root = mPresShell->GetRootScrollContainerFrame()) { 178 nsIContent* content = root->GetContent(); 179 bool hasDisplayPort = DisplayPortUtils::HasNonMinimalDisplayPort(content); 180 bool hasResolution = mPresShell->GetResolution() != 1.0f; 181 if (!hasDisplayPort && !hasResolution) { 182 // We only want to update the displayport if there is one already, or 183 // add one if there's a resolution on the document (see bug 1225508 184 // comment 1). 185 return; 186 } 187 nsRect displayportBase = nsRect( 188 nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(root)); 189 // We only create MobileViewportManager for root content documents. If that 190 // ever changes we'd need to limit the size of this displayport base rect 191 // because non-toplevel documents have no limit on their size. 192 MOZ_ASSERT( 193 mPresShell->GetPresContext()->IsRootContentDocumentCrossProcess()); 194 DisplayPortUtils::SetDisplayPortBaseIfNotSet(content, displayportBase); 195 DisplayPortUtils::CalculateAndSetDisplayPortMargins( 196 root, DisplayPortUtils::RepaintMode::Repaint); 197 } 198 } 199 200 void GeckoMVMContext::Reflow(const CSSSize& aNewSize) { 201 RefPtr doc = mDocument; 202 RefPtr ps = mPresShell; 203 204 MOZ_ASSERT(doc); 205 MOZ_ASSERT(ps); 206 207 if (ps->ResizeReflowIgnoreOverride(CSSPixel::ToAppUnits(aNewSize))) { 208 doc->FlushPendingNotifications(FlushType::InterruptibleLayout); 209 } 210 } 211 212 ScreenIntCoord GeckoMVMContext::GetDynamicToolbarOffset() { 213 const nsPresContext* presContext = mPresShell->GetPresContext(); 214 return presContext->HasDynamicToolbar() 215 ? presContext->GetDynamicToolbarMaxHeight() - 216 presContext->GetDynamicToolbarHeight() 217 : ScreenIntCoord(0); 218 } 219 220 dom::InteractiveWidget GeckoMVMContext::GetInteractiveWidgetMode() const { 221 return mDocument->InteractiveWidget(); 222 } 223 } // namespace mozilla