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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_ResizeObserverController_h 8 #define mozilla_dom_ResizeObserverController_h 9 10 #include "mozilla/dom/Document.h" 11 #include "mozilla/dom/ResizeObserver.h" 12 #include "mozilla/TimeStamp.h" 13 #include "nsRefreshObservers.h" 14 #include "nsTObserverArray.h" 15 16 class nsRefreshDriver; 17 18 namespace mozilla { 19 20 class PresShell; 21 22 namespace dom { 23 24 class ResizeObserverController; 25 26 /** 27 * ResizeObserverNotificationHelper will trigger ResizeObserver notifications 28 * by registering with the Refresh Driver. 29 */ 30 class ResizeObserverNotificationHelper final : public nsARefreshObserver { 31 public: NS_INLINE_DECL_REFCOUNTING(ResizeObserverNotificationHelper,override)32 NS_INLINE_DECL_REFCOUNTING(ResizeObserverNotificationHelper, override) 33 34 explicit ResizeObserverNotificationHelper(ResizeObserverController* aOwner) 35 : mOwner(aOwner), mRegistered(false) { 36 MOZ_ASSERT(mOwner, "Need a non-null owner"); 37 } 38 39 MOZ_CAN_RUN_SCRIPT void WillRefresh(TimeStamp aTime) override; 40 41 nsRefreshDriver* GetRefreshDriver() const; 42 43 void Register(); 44 45 void Unregister(); 46 IsRegistered()47 bool IsRegistered() const { return mRegistered; } 48 DetachFromOwner()49 void DetachFromOwner() { mOwner = nullptr; } 50 51 private: 52 virtual ~ResizeObserverNotificationHelper(); 53 54 ResizeObserverController* mOwner; 55 bool mRegistered; 56 }; 57 58 /** 59 * ResizeObserverController contains the list of ResizeObservers and controls 60 * the flow of notification. 61 */ 62 class ResizeObserverController final { 63 public: ResizeObserverController(Document * aDocument)64 explicit ResizeObserverController(Document* aDocument) 65 : mDocument(aDocument), 66 mResizeObserverNotificationHelper( 67 new ResizeObserverNotificationHelper(this)) { 68 MOZ_ASSERT(mDocument, "Need a non-null document"); 69 } 70 71 void AddSizeOfIncludingThis(nsWindowSizes&) const; 72 73 void ShellDetachedFromDocument(); AddResizeObserver(ResizeObserver & aObserver)74 void AddResizeObserver(ResizeObserver& aObserver) { 75 MOZ_ASSERT(!mResizeObservers.Contains(&aObserver)); 76 mResizeObservers.AppendElement(&aObserver); 77 } 78 RemoveResizeObserver(ResizeObserver & aObserver)79 void RemoveResizeObserver(ResizeObserver& aObserver) { 80 MOZ_ASSERT(mResizeObservers.Contains(&aObserver)); 81 mResizeObservers.RemoveElement(&aObserver); 82 } 83 84 /** 85 * Schedule the notification via ResizeObserverNotificationHelper refresh 86 * observer. 87 */ 88 void ScheduleNotification(); 89 90 /** 91 * Notify all ResizeObservers by gathering and broadcasting all active 92 * observations. 93 */ 94 MOZ_CAN_RUN_SCRIPT void Notify(); 95 GetPresShell()96 PresShell* GetPresShell() const { return mDocument->GetPresShell(); } 97 98 ~ResizeObserverController(); 99 100 private: 101 /** 102 * Calls GatherActiveObservations(aDepth) for all ResizeObservers in this 103 * controller. All observations in each ResizeObserver with element's depth 104 * more than aDepth will be gathered. 105 */ 106 void GatherAllActiveObservations(uint32_t aDepth); 107 108 /** 109 * Calls BroadcastActiveObservations() for all ResizeObservers in this 110 * controller. It also returns the shallowest depth of observed target 111 * elements with active observations from all ResizeObservers or 112 * numeric_limits<uint32_t>::max() if there aren't any active observations 113 * at all. 114 */ 115 MOZ_CAN_RUN_SCRIPT uint32_t BroadcastAllActiveObservations(); 116 117 /** 118 * Returns whether there is any ResizeObserver that has active observations. 119 */ 120 bool HasAnyActiveObservations() const; 121 122 /** 123 * Returns whether there is any ResizeObserver that has skipped observations. 124 */ 125 bool HasAnySkippedObservations() const; 126 127 // Raw pointer is OK because mDocument strongly owns us & hence must outlive 128 // us. 129 Document* const mDocument; 130 131 RefPtr<ResizeObserverNotificationHelper> mResizeObserverNotificationHelper; 132 nsTArray<ResizeObserver*> mResizeObservers; 133 }; 134 135 } // namespace dom 136 } // namespace mozilla 137 138 #endif // mozilla_dom_ResizeObserverController_h 139