MobileViewportManager.h (9389B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MobileViewportManager_h_ 8 #define MobileViewportManager_h_ 9 10 #include "UnitTransforms.h" 11 #include "Units.h" 12 #include "mozilla/Logging.h" 13 #include "mozilla/MVMContext.h" 14 #include "mozilla/Maybe.h" 15 #include "mozilla/PresShellForwards.h" 16 #include "nsCOMPtr.h" 17 #include "nsIDOMEventListener.h" 18 #include "nsIObserver.h" 19 20 class nsViewportInfo; 21 22 namespace mozilla { 23 class MVMContext; 24 namespace dom { 25 class Document; 26 class EventTarget; 27 } // namespace dom 28 } // namespace mozilla 29 30 class MobileViewportManager final : public nsIDOMEventListener, 31 public nsIObserver { 32 public: 33 NS_DECL_ISUPPORTS 34 NS_DECL_NSIDOMEVENTLISTENER 35 NS_DECL_NSIOBSERVER 36 37 /* The MobileViewportManager might be required to handle meta-viewport tags 38 * and changes, or it might not (e.g. if we are in a desktop-zooming setup). 39 * This enum indicates which mode the manager is in. It might make sense to 40 * split these two "modes" into two separate classes but for now they have a 41 * bunch of shared code and it's uncertain if that shared set will expand or 42 * contract. */ 43 enum class ManagerType { VisualAndMetaViewport, VisualViewportOnly }; 44 45 explicit MobileViewportManager(mozilla::MVMContext* aContext, 46 ManagerType aType); 47 void Destroy(); 48 49 ManagerType GetManagerType() { return mManagerType; } 50 51 /* Provide a resolution to use during the first paint instead of the default 52 * resolution computed from the viewport info metadata. This is in the same 53 * "units" as the argument to nsDOMWindowUtils::SetResolutionAndScaleTo. 54 * Also takes the previous display dimensions as they were at the time the 55 * resolution was stored in order to correctly adjust the resolution if the 56 * device was rotated in the meantime. */ 57 void SetRestoreResolution(float aResolution, 58 mozilla::LayoutDeviceIntSize aDisplaySize); 59 60 /* Compute the "intrinsic resolution", which is the smallest resolution at 61 * which the layout viewport fills the visual viewport. (In typical 62 * scenarios, where the aspect ratios of the two viewports match, it's the 63 * resolution at which they are the same size.) 64 * 65 * The returned resolution is suitable for passing to 66 * PresShell::SetResolutionAndScaleTo(). It's not in typed units for 67 * reasons explained at the declaration of FrameMetrics::mPresShellResolution. 68 */ 69 float ComputeIntrinsicResolution() const; 70 71 /* The only direct calls to this should be in test code. 72 * Normally, it gets called by HandleEvent(). 73 */ 74 void HandleDOMMetaAdded(); 75 76 private: 77 void SetRestoreResolution(float aResolution); 78 79 public: 80 /* Notify the MobileViewportManager that a reflow is about to happen. This 81 * triggers the MVM to update its internal notion of display size and CSS 82 * viewport, so that code that queries those during the reflow gets an 83 * up-to-date value. 84 */ 85 void UpdateSizesBeforeReflow(); 86 87 /* Notify the MobileViewportManager that a reflow was requested in the 88 * presShell.*/ 89 void RequestReflow(bool aForceAdjustResolution); 90 91 /* Notify the MobileViewportManager that the resolution on the presShell was 92 * updated, and the visual viewport size needs to be updated. */ 93 void ResolutionUpdated(mozilla::ResolutionChangeOrigin aOrigin); 94 95 /* Called to compute the initial viewport on page load or before-first-paint, 96 * whichever happens first. Also called directly if we are created after the 97 * presShell is initialized. */ 98 void SetInitialViewport(); 99 100 mozilla::LayoutDeviceIntSize DisplaySize() const { 101 return mozilla::ViewAs<mozilla::LayoutDevicePixel>( 102 GetLayoutDisplaySize(), 103 mozilla::PixelCastJustification::LayoutDeviceIsScreenForBounds); 104 }; 105 /* 106 * Shrink the content to fit it to the display width if no initial-scale is 107 * specified and if the content is still wider than the display width. 108 */ 109 void ShrinkToDisplaySizeIfNeeded(); 110 111 /* 112 * Similar to UpdateVisualViewportSize but this should be called only when we 113 * need to update visual viewport size in response to dynamic toolbar 114 * transitions. 115 * This function doesn't cause any reflows, just fires a visual viewport 116 * resize event. 117 */ 118 void UpdateVisualViewportSizeByDynamicToolbar( 119 mozilla::ScreenIntCoord aToolbarHeight); 120 121 nsSize GetVisualViewportSizeUpdatedByDynamicToolbar() const { 122 return mVisualViewportSizeUpdatedByDynamicToolbar; 123 } 124 125 /* 126 * This refreshes the visual viewport size based on the most recently 127 * available information. It is intended to be called in particular after 128 * the root scrollframe does a reflow, which may make scrollbars appear or 129 * disappear if the content changed size. 130 */ 131 void UpdateVisualViewportSizeForPotentialScrollbarChange(); 132 133 /* 134 * Returns the composition size in CSS units when zoomed to the intrinsic 135 * scale. 136 */ 137 mozilla::CSSSize GetIntrinsicCompositionSize() const; 138 139 mozilla::ParentLayerSize GetCompositionSizeWithoutDynamicToolbar() const; 140 141 void UpdateKeyboardHeight(mozilla::ScreenIntCoord aKeyboardHeight); 142 143 static mozilla::LazyLogModule gLog; 144 145 mozilla::CSSToScreenScale GetZoom() const; 146 147 /* Main helper method to update the CSS viewport and any other properties that 148 * need updating. */ 149 void RefreshViewportSize(bool aForceAdjustResolution); 150 151 /* 152 * Returns the visible area for setting nsPresContext's visible area. 153 */ 154 nsRect InitialVisibleArea(); 155 156 mozilla::ScreenIntCoord GetKeyboardHeight() const { return mKeyboardHeight; } 157 158 private: 159 ~MobileViewportManager(); 160 161 /* Secondary main helper method to update just the visual viewport size. */ 162 void RefreshVisualViewportSize(); 163 164 /* Helper to clamp the given zoom by the min/max in the viewport info. */ 165 mozilla::CSSToScreenScale ClampZoom( 166 const mozilla::CSSToScreenScale& aZoom, 167 const nsViewportInfo& aViewportInfo) const; 168 169 /* Helper to update the given zoom according to changed display and viewport 170 * widths. */ 171 mozilla::CSSToScreenScale ScaleZoomWithDisplayWidth( 172 const mozilla::CSSToScreenScale& aZoom, 173 const float& aDisplayWidthChangeRatio, 174 const mozilla::CSSSize& aNewViewport, 175 const mozilla::CSSSize& aOldViewport); 176 177 mozilla::CSSToScreenScale ResolutionToZoom( 178 const mozilla::LayoutDeviceToLayerScale& aResolution) const; 179 mozilla::LayoutDeviceToLayerScale ZoomToResolution( 180 const mozilla::CSSToScreenScale& aZoom) const; 181 182 /* Updates the presShell resolution and the visual viewport size for various 183 * types of changes. */ 184 void UpdateResolutionForFirstPaint(const mozilla::CSSSize& aViewportSize); 185 void UpdateResolutionForViewportSizeChange( 186 const mozilla::CSSSize& aViewportSize, 187 const mozilla::Maybe<float>& aDisplayWidthChangeRatio); 188 void UpdateResolutionForContentSizeChange( 189 const mozilla::CSSSize& aContentSize); 190 191 void ApplyNewZoom(const mozilla::CSSToScreenScale& aNewZoom); 192 193 void UpdateVisualViewportSize(const mozilla::CSSToScreenScale& aZoom); 194 195 /* Updates the displayport margins for the presShell's root scrollable frame 196 */ 197 void UpdateDisplayPortMargins(); 198 199 /* Helper function for ComputeIntrinsicResolution(). */ 200 mozilla::CSSToScreenScale ComputeIntrinsicScale( 201 const nsViewportInfo& aViewportInfo, 202 const mozilla::ScreenIntSize& aDisplaySize, 203 const mozilla::CSSSize& aViewportOrContentSize) const; 204 205 /* 206 * Returns the screen size subtracted the scrollbar sizes from |aDisplaySize|. 207 */ 208 mozilla::ScreenIntSize GetCompositionSize( 209 const mozilla::ScreenIntSize& aDisplaySize) const; 210 211 /* 212 * Returns the display size for layout. It varies depending on the 213 * interactive-widget value. 214 */ 215 mozilla::ScreenIntSize GetLayoutDisplaySize() const; 216 217 /* 218 * Returns the display size for visual viewport events. It varies depending on 219 * the interactive-widget value. The size doesn't match above 220 * GetLayoutDisplaySize() in the case of resizes-visual. 221 */ 222 mozilla::ScreenIntSize GetDisplaySizeForVisualViewport() const; 223 224 RefPtr<mozilla::MVMContext> mContext; 225 ManagerType mManagerType; 226 bool mIsFirstPaint; 227 bool mPainted; 228 // True if this MobileViewportManager needs to update the visual viewport size 229 // even if the layout viewport size is unchanged. 230 bool mInvalidViewport; 231 mozilla::LayoutDeviceIntSize mDisplaySize; 232 mozilla::CSSSize mMobileViewportSize; 233 mozilla::Maybe<float> mRestoreResolution; 234 mozilla::Maybe<mozilla::ScreenIntSize> mRestoreDisplaySize; 235 /* 236 * The visual viewport size updated by the dynamic toolbar transitions. This 237 * is typically used for the VisualViewport width/height APIs. 238 * NOTE: If you want to use this value, you should make sure to flush 239 * position:fixed elements layout and update 240 * FrameMetrics.mFixedLayerMargins to conform with this value. 241 */ 242 nsSize mVisualViewportSizeUpdatedByDynamicToolbar; 243 244 /* 245 * The software keyboard height. 246 */ 247 mozilla::ScreenIntCoord mKeyboardHeight; 248 mozilla::Maybe<mozilla::ScreenIntCoord> mPendingKeyboardHeight; 249 }; 250 251 #endif