diff options
Diffstat (limited to 'gfx/layers/apz/public')
-rw-r--r-- | gfx/layers/apz/public/APZInputBridge.h | 297 | ||||
-rw-r--r-- | gfx/layers/apz/public/APZPublicUtils.h | 82 | ||||
-rw-r--r-- | gfx/layers/apz/public/APZSampler.h | 154 | ||||
-rw-r--r-- | gfx/layers/apz/public/APZUpdater.h | 236 | ||||
-rw-r--r-- | gfx/layers/apz/public/CompositorController.h | 33 | ||||
-rw-r--r-- | gfx/layers/apz/public/GeckoContentController.h | 187 | ||||
-rw-r--r-- | gfx/layers/apz/public/GeckoContentControllerTypes.h | 68 | ||||
-rw-r--r-- | gfx/layers/apz/public/IAPZCTreeManager.h | 150 | ||||
-rw-r--r-- | gfx/layers/apz/public/MatrixMessage.h | 64 |
9 files changed, 1271 insertions, 0 deletions
diff --git a/gfx/layers/apz/public/APZInputBridge.h b/gfx/layers/apz/public/APZInputBridge.h new file mode 100644 index 0000000000..07ed39548d --- /dev/null +++ b/gfx/layers/apz/public/APZInputBridge.h @@ -0,0 +1,297 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_APZInputBridge_h +#define mozilla_layers_APZInputBridge_h + +#include "Units.h" // for LayoutDeviceIntPoint +#include "mozilla/EventForwards.h" // for WidgetInputEvent, nsEventStatus +#include "mozilla/layers/APZPublicUtils.h" // for APZWheelAction +#include "mozilla/layers/LayersTypes.h" // for ScrollDirections +#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid + +namespace mozilla { + +class InputData; + +namespace layers { + +class APZInputBridgeParent; +class AsyncPanZoomController; +class InputBlockState; +class TouchBlockState; +struct ScrollableLayerGuid; +struct TargetConfirmationFlags; +struct PointerEventsConsumableFlags; + +enum class APZHandledPlace : uint8_t { + Unhandled = 0, // we know for sure that the event will not be handled + // by either the root APZC or others + HandledByRoot = 1, // we know for sure that the event will be handled + // by the root content APZC + HandledByContent = 2, // we know for sure it will be handled by a non-root + // APZC or by an event listener using preventDefault() + // in a document + Invalid = 3, + Last = Invalid +}; + +struct APZHandledResult { + APZHandledPlace mPlace = APZHandledPlace::Invalid; + SideBits mScrollableDirections = SideBits::eNone; + ScrollDirections mOverscrollDirections = ScrollDirections(); + + APZHandledResult() = default; + // A constructor for cases where we have the target of the input block this + // event is part of, the target might be adjusted to be the root in the + // ScrollingDownWillMoveDynamicToolbar case. + // + // NOTE: There's a case where |aTarget| is the APZC for the root content but + // |aPlace| has to be `HandledByContent`, for example, the root content has + // an event handler using preventDefault() in the callback, so call sites of + // this function should be responsible to set a proper |aPlace|. + APZHandledResult(APZHandledPlace aPlace, + const AsyncPanZoomController* aTarget); + APZHandledResult(APZHandledPlace aPlace, SideBits aScrollableDirections, + ScrollDirections aOverscrollDirections) + : mPlace(aPlace), + mScrollableDirections(aScrollableDirections), + mOverscrollDirections(aOverscrollDirections) {} + + bool IsHandledByContent() const { + return mPlace == APZHandledPlace::HandledByContent; + } + bool IsHandledByRoot() const { + return mPlace == APZHandledPlace::HandledByRoot; + } + bool operator==(const APZHandledResult& aOther) const { + return mPlace == aOther.mPlace && + mScrollableDirections == aOther.mScrollableDirections && + mOverscrollDirections == aOther.mOverscrollDirections; + } +}; + +/** + * Represents the outcome of APZ receiving and processing an input event. + * This is returned from APZInputBridge::ReceiveInputEvent() and related APIs. + */ +struct APZEventResult { + /** + * Creates a default result with a status of eIgnore, no block ID, and empty + * target guid. + */ + APZEventResult(); + + /** + * Creates a result with a status of eIgnore, no block ID, the guid of the + * given initial target, and an APZHandledResult if we are sure the event + * is not going to be dispatched to contents. + */ + APZEventResult(const RefPtr<AsyncPanZoomController>& aInitialTarget, + TargetConfirmationFlags aFlags); + + void SetStatusAsConsumeNoDefault() { + mStatus = nsEventStatus_eConsumeNoDefault; + } + + void SetStatusAsIgnore() { mStatus = nsEventStatus_eIgnore; } + + // Set mStatus to nsEventStatus_eConsumeDoDefault and set mHandledResult + // depending on |aTarget|. + void SetStatusAsConsumeDoDefault( + const RefPtr<AsyncPanZoomController>& aTarget); + + // Set mStatus to nsEventStatus_eConsumeDoDefault, unlike above + // SetStatusAsConsumeDoDefault(const RefPtr<AsyncPanZoomController>&) this + // function doesn't mutate mHandledResult. + void SetStatusAsConsumeDoDefault() { + mStatus = nsEventStatus_eConsumeDoDefault; + } + + // Set mStatus to nsEventStatus_eConsumeDoDefault and set mHandledResult + // depending on |aBlock|'s target APZC. + void SetStatusAsConsumeDoDefault(const InputBlockState& aBlock); + // Set mStatus and mHandledResult for a touch event which is not dropped + // altogether (i.e. the status is not eConsumeNoDefault). + void SetStatusForTouchEvent(const InputBlockState& aBlock, + TargetConfirmationFlags aFlags, + PointerEventsConsumableFlags aConsumableFlags, + const AsyncPanZoomController* aTarget); + + // Set mStatus and mHandledResult during in a stat of fast fling. + void SetStatusForFastFling(const TouchBlockState& aBlock, + TargetConfirmationFlags aFlags, + PointerEventsConsumableFlags aConsumableFlags, + const AsyncPanZoomController* aTarget); + + // DO NOT USE THIS UpdateStatus DIRECTLY. THIS FUNCTION IS ONLY FOR + // SERIALIZATION / DESERIALIZATION OF THIS STRUCT IN IPC. + void UpdateStatus(nsEventStatus aStatus) { mStatus = aStatus; } + nsEventStatus GetStatus() const { return mStatus; }; + + // DO NOT USE THIS UpdateHandledResult DIRECTLY. THIS FUNCTION IS ONLY FOR + // SERIALIZATION / DESERIALIZATION OF THIS STRUCT IN IPC. + void UpdateHandledResult(const Maybe<APZHandledResult>& aHandledResult) { + mHandledResult = aHandledResult; + } + const Maybe<APZHandledResult>& GetHandledResult() const { + return mHandledResult; + } + + bool WillHaveDelayedResult() const { + return GetStatus() != nsEventStatus_eConsumeNoDefault && + !GetHandledResult(); + } + + private: + void UpdateHandledResult(const InputBlockState& aBlock, + PointerEventsConsumableFlags aConsumableFlags, + const AsyncPanZoomController* aTarget, + bool aDispatchToContent); + + /** + * A status flag indicated how APZ handled the event. + * The interpretation of each value is as follows: + * + * nsEventStatus_eConsumeNoDefault is returned to indicate the + * APZ is consuming this event and the caller should discard the event with + * extreme prejudice. The exact scenarios under which this is returned is + * implementation-dependent and may vary. + * nsEventStatus_eIgnore is returned to indicate that the APZ code didn't + * use this event. This might be because it was directed at a point on + * the screen where there was no APZ, or because the thing the user was + * trying to do was not allowed. (For example, attempting to pan a + * non-pannable document). + * nsEventStatus_eConsumeDoDefault is returned to indicate that the APZ + * code may have used this event to do some user-visible thing. Note that + * in some cases CONSUMED is returned even if the event was NOT used. This + * is because we cannot always know at the time of event delivery whether + * the event will be used or not. So we err on the side of sending + * CONSUMED when we are uncertain. + */ + nsEventStatus mStatus; + + /** + * This is: + * - set to HandledByRoot if we know for sure that the event will be handled + * by the root content APZC; + * - set to HandledByContent if we know for sure it will not be; + * - left empty if we are unsure. + */ + Maybe<APZHandledResult> mHandledResult; + + public: + /** + * The guid of the APZC initially targeted by this event. + * This will usually be the APZC that handles the event, but in cases + * where the event is dispatched to content, it may end up being + * handled by a different APZC. + */ + ScrollableLayerGuid mTargetGuid; + /** + * If this event started or was added to an input block, the id of that + * input block, otherwise InputBlockState::NO_BLOCK_ID. + */ + uint64_t mInputBlockId; +}; + +/** + * This class lives in the main process, and is accessed via the controller + * thread (which is the process main thread for desktop, and the Java UI + * thread for Android). This class exposes a synchronous API to deliver + * incoming input events to APZ and modify them in-place to unapply the APZ + * async transform. If there is a GPU process, then this class does sync IPC + * calls over to the GPU process in order to accomplish this. Otherwise, + * APZCTreeManager overrides and implements these methods directly. + */ +class APZInputBridge { + public: + using InputBlockCallback = std::function<void( + uint64_t aInputBlockId, const APZHandledResult& aHandledResult)>; + + /** + * General handler for incoming input events. Manipulates the frame metrics + * based on what type of input it is. For example, a PinchGestureEvent will + * cause scaling. This should only be called externally to this class, and + * must be called on the controller thread. + * + * This function transforms |aEvent| to have its coordinates in DOM space. + * This is so that the event can be passed through the DOM and content can + * handle them. The event may need to be converted to a WidgetInputEvent + * by the caller if it wants to do this. + * + * @param aEvent input event object; is modified in-place + * @param aCallback an optional callback to be invoked when the input block is + * ready for handling, + * @return The result of processing the event. Refer to the documentation of + * APZEventResult and its field. + */ + virtual APZEventResult ReceiveInputEvent( + InputData& aEvent, + InputBlockCallback&& aCallback = InputBlockCallback()) = 0; + + /** + * WidgetInputEvent handler. Transforms |aEvent| (which is assumed to be an + * already-existing instance of an WidgetInputEvent which may be an + * WidgetTouchEvent) to have its coordinates in DOM space. This is so that the + * event can be passed through the DOM and content can handle them. + * + * NOTE: Be careful of invoking the WidgetInputEvent variant. This can only be + * called on the main thread. See widget/InputData.h for more information on + * why we have InputData and WidgetInputEvent separated. If this function is + * used, the controller thread must be the main thread, or undefined behaviour + * may occur. + * NOTE: On unix, mouse events are treated as touch and are forwarded + * to the appropriate apz as such. + * + * See documentation for other ReceiveInputEvent above. + */ + APZEventResult ReceiveInputEvent( + WidgetInputEvent& aEvent, + InputBlockCallback&& aCallback = InputBlockCallback()); + + // Returns the kind of wheel event action, if any, that will be (or was) + // performed by APZ. If this returns true, the event must not perform a + // synchronous scroll. + // + // Even if this returns Nothing(), all wheel events in APZ-aware widgets must + // be sent through APZ so they are transformed correctly for BrowserParent. + static Maybe<APZWheelAction> ActionForWheelEvent(WidgetWheelEvent* aEvent); + + protected: + friend class APZInputBridgeParent; + + // Methods to help process WidgetInputEvents (or manage conversion to/from + // InputData) + + virtual void ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint, + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutFocusSequenceNumber, + LayersId* aOutLayersId) = 0; + + virtual void UpdateWheelTransaction( + LayoutDeviceIntPoint aRefPoint, EventMessage aEventMessage, + const Maybe<ScrollableLayerGuid>& aTargetGuid) = 0; + + virtual ~APZInputBridge() = default; +}; + +std::ostream& operator<<(std::ostream& aOut, + const APZHandledResult& aHandledResult); + +// This enum class is used for communicating between APZ and the browser gesture +// support code. APZ needs to wait for the browser to send this response just +// like APZ waits for the content's response if there's an APZ ware event +// listener in the content process. +enum class BrowserGestureResponse : bool { + NotConsumed = 0, // Representing the browser doesn't consume the gesture + Consumed = 1, // Representing the browser has started consuming the gesture. +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_APZInputBridge_h diff --git a/gfx/layers/apz/public/APZPublicUtils.h b/gfx/layers/apz/public/APZPublicUtils.h new file mode 100644 index 0000000000..6433008b4c --- /dev/null +++ b/gfx/layers/apz/public/APZPublicUtils.h @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_APZPublicUtils_h +#define mozilla_layers_APZPublicUtils_h + +// This file is for APZ-related utilities that need to be consumed from outside +// of gfx/layers. For internal utilities, prefer APZUtils.h. + +#include <stdint.h> +#include <utility> +#include "ScrollAnimationBezierPhysics.h" +#include "Units.h" +#include "mozilla/DefineEnum.h" +#include "mozilla/ScrollOrigin.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/ScrollTypes.h" + +namespace mozilla { + +namespace layers { + +struct FrameMetrics; + +// clang-format off +MOZ_DEFINE_ENUM_CLASS_WITH_BASE(APZWheelAction, uint8_t, ( + Scroll, + PinchZoom +)) +// clang-format on + +namespace apz { + +/** + * Initializes the global state used in AsyncPanZoomController. + * This is normally called when it is first needed in the constructor + * of APZCTreeManager, but can be called manually to force it to be + * initialized earlier. + */ +void InitializeGlobalState(); + +/** + * See AsyncPanZoomController::CalculatePendingDisplayPort. This + * function simply delegates to that one, so that non-layers code + * never needs to include AsyncPanZoomController.h + */ +const ScreenMargin CalculatePendingDisplayPort( + const FrameMetrics& aFrameMetrics, const ParentLayerPoint& aVelocity); + +/** + * Returns a width and height multiplier, each of which is a power of two + * between 1 and 8 inclusive. The multiplier is chosen based on the provided + * base size, such that multiplier is larger when the base size is larger. + * The exact details are somewhat arbitrary and tuned by hand. + * This function is intended to only be used with WebRender, because that is + * the codepath that wants to use a larger displayport alignment, because + * moving the displayport is relatively expensive with WebRender. + */ +gfx::IntSize GetDisplayportAlignmentMultiplier(const ScreenSize& aBaseSize); + +/** + * Calculate the physics parameters for smooth scroll animations for the + * given origin, based on pref values. + */ +ScrollAnimationBezierPhysicsSettings ComputeBezierAnimationSettingsForOrigin( + ScrollOrigin aOrigin); + +/** + * Calculate if the scrolling should be instant or smooth based based on + * preferences and the origin + */ +ScrollMode GetScrollModeForOrigin(ScrollOrigin origin); + +} // namespace apz + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_APZPublicUtils_h diff --git a/gfx/layers/apz/public/APZSampler.h b/gfx/layers/apz/public/APZSampler.h new file mode 100644 index 0000000000..a870c2d688 --- /dev/null +++ b/gfx/layers/apz/public/APZSampler.h @@ -0,0 +1,154 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_APZSampler_h +#define mozilla_layers_APZSampler_h + +#include <unordered_map> + +#include "apz/src/APZCTreeManager.h" +#include "base/platform_thread.h" // for PlatformThreadId +#include "mozilla/layers/APZUtils.h" +#include "mozilla/layers/SampleTime.h" +#include "mozilla/StaticMutex.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/webrender/WebRenderTypes.h" +#include "Units.h" +#include "VsyncSource.h" + +namespace mozilla { + +class TimeStamp; + +namespace wr { +struct Transaction; +class TransactionWrapper; +struct WrWindowId; +} // namespace wr + +namespace layers { + +struct ScrollbarData; + +/** + * This interface exposes APZ methods related to "sampling" (i.e. reading the + * async transforms produced by APZ). These methods should all be called on + * the sampler thread. + */ +class APZSampler { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZSampler) + + public: + APZSampler(const RefPtr<APZCTreeManager>& aApz, bool aIsUsingWebRender); + + // Whoever creates this sampler is responsible for calling Destroy() on it + // before releasing the owning refptr. + void Destroy(); + + void SetWebRenderWindowId(const wr::WindowId& aWindowId); + + /** + * This function is invoked from rust on the render backend thread when it + * is created. It effectively tells the APZSampler "the current thread is + * the sampler thread for this window id" and allows APZSampler to remember + * which thread it is. + */ + static void SetSamplerThread(const wr::WrWindowId& aWindowId); + static void SampleForWebRender(const wr::WrWindowId& aWindowId, + const uint64_t* aGeneratedFrameId, + wr::Transaction* aTransaction); + + void SetSampleTime(const SampleTime& aSampleTime); + void SampleForWebRender(const Maybe<VsyncId>& aGeneratedFrameId, + wr::TransactionWrapper& aTxn); + + /** + * Similar to above GetCurrentAsyncTransform, but get the current transform + * with LayersId and ViewID. + * NOTE: This function should NOT be called on the compositor thread. + */ + AsyncTransform GetCurrentAsyncTransform( + const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId, + AsyncTransformComponents aComponents, + const MutexAutoLock& aProofOfMapLock) const; + + /** + * Returns the composition bounds of the APZC corresponding to the pair of + * |aLayersId| and |aScrollId|. + */ + ParentLayerRect GetCompositionBounds( + const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId, + const MutexAutoLock& aProofOfMapLock) const; + + struct ScrollOffsetAndRange { + CSSPoint mOffset; + CSSRect mRange; + }; + /** + * Returns the scroll offset and scroll range of the APZC corresponding to the + * pair of |aLayersId| and |aScrollId| + * + * Note: This is called from OMTA Sampler thread, or Compositor thread for + * testing. + */ + Maybe<ScrollOffsetAndRange> GetCurrentScrollOffsetAndRange( + const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId, + const MutexAutoLock& aProofOfMapLock) const; + + /** + * This can be used to assert that the current thread is the + * sampler thread (which samples the async transform). + * This does nothing if thread assertions are disabled. + */ + void AssertOnSamplerThread() const; + + /** + * Returns true if currently on the APZSampler's "sampler thread". + */ + bool IsSamplerThread() const; + + template <typename Callback> + void CallWithMapLock(Callback& aCallback) { + mApz->CallWithMapLock(aCallback); + } + + protected: + virtual ~APZSampler(); + + static already_AddRefed<APZSampler> GetSampler( + const wr::WrWindowId& aWindowId); + + private: + RefPtr<APZCTreeManager> mApz; + bool mIsUsingWebRender; + + // Used to manage the mapping from a WR window id to APZSampler. These are + // only used if WebRender is enabled. Both sWindowIdMap and mWindowId should + // only be used while holding the sWindowIdLock. Note that we use a + // StaticAutoPtr wrapper on sWindowIdMap to avoid a static initializer for the + // unordered_map. This also avoids the initializer/memory allocation in cases + // where we're not using WebRender. + static StaticMutex sWindowIdLock MOZ_UNANNOTATED; + static StaticAutoPtr<std::unordered_map<uint64_t, RefPtr<APZSampler>>> + sWindowIdMap; + Maybe<wr::WrWindowId> mWindowId; + + // Lock used to protected mSamplerThreadId + mutable Mutex mThreadIdLock MOZ_UNANNOTATED; + // If WebRender is enabled, this holds the thread id of the render backend + // thread (which is the sampler thread) for the compositor associated with + // this APZSampler instance. + Maybe<PlatformThreadId> mSamplerThreadId; + + Mutex mSampleTimeLock MOZ_UNANNOTATED; + // Can only be accessed or modified while holding mSampleTimeLock. + SampleTime mSampleTime; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_APZSampler_h diff --git a/gfx/layers/apz/public/APZUpdater.h b/gfx/layers/apz/public/APZUpdater.h new file mode 100644 index 0000000000..66d040b356 --- /dev/null +++ b/gfx/layers/apz/public/APZUpdater.h @@ -0,0 +1,236 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_APZUpdater_h +#define mozilla_layers_APZUpdater_h + +#include <deque> +#include <unordered_map> + +#include "base/platform_thread.h" // for PlatformThreadId +#include "LayersTypes.h" +#include "mozilla/layers/APZTestData.h" +#include "mozilla/layers/WebRenderScrollData.h" +#include "mozilla/StaticMutex.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/webrender/WebRenderTypes.h" +#include "nsThreadUtils.h" +#include "Units.h" + +namespace mozilla { + +namespace layers { + +class APZCTreeManager; +class FocusTarget; +class WebRenderScrollData; + +/** + * This interface is used to send updates or otherwise mutate APZ internal + * state. These functions is usually called from the compositor thread in + * response to IPC messages. The method implementations internally redispatch + * themselves to the updater thread in the case where the compositor thread + * is not the updater thread. + */ +class APZUpdater { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZUpdater) + + public: + APZUpdater(const RefPtr<APZCTreeManager>& aApz, bool aConnectedToWebRender); + + bool HasTreeManager(const RefPtr<APZCTreeManager>& aApz); + void SetWebRenderWindowId(const wr::WindowId& aWindowId); + + /** + * This function is invoked from rust on the scene builder thread when it + * is created. It effectively tells the APZUpdater "the current thread is + * the updater thread for this window id" and allows APZUpdater to remember + * which thread it is. + */ + static void SetUpdaterThread(const wr::WrWindowId& aWindowId); + static void PrepareForSceneSwap(const wr::WrWindowId& aWindowId); + static void CompleteSceneSwap(const wr::WrWindowId& aWindowId, + const wr::WrPipelineInfo& aInfo); + static void ProcessPendingTasks(const wr::WrWindowId& aWindowId); + + void ClearTree(LayersId aRootLayersId); + void UpdateFocusState(LayersId aRootLayerTreeId, + LayersId aOriginatingLayersId, + const FocusTarget& aFocusTarget); + /** + * This should be called (in the WR-enabled case) when the compositor receives + * a new WebRenderScrollData for a layers id. The |aScrollData| parameter is + * the scroll data for |aOriginatingLayersId| and |aEpoch| is the + * corresponding epoch for the transaction that transferred the scroll data. + * This function will store the new scroll data and update the focus state and + * hit-testing tree. + */ + void UpdateScrollDataAndTreeState(LayersId aRootLayerTreeId, + LayersId aOriginatingLayersId, + const wr::Epoch& aEpoch, + WebRenderScrollData&& aScrollData); + /** + * This is called in the WR-enabled case when we get an empty transaction that + * has some scroll offset updates (from paint-skipped scrolling on the content + * side). This function will update the stored scroll offsets and the + * hit-testing tree. + */ + void UpdateScrollOffsets(LayersId aRootLayerTreeId, + LayersId aOriginatingLayersId, + ScrollUpdatesMap&& aUpdates, + uint32_t aPaintSequenceNumber); + + void NotifyLayerTreeAdopted(LayersId aLayersId, + const RefPtr<APZUpdater>& aOldUpdater); + void NotifyLayerTreeRemoved(LayersId aLayersId); + + bool GetAPZTestData(LayersId aLayersId, APZTestData* aOutData); + + void SetTestAsyncScrollOffset(LayersId aLayersId, + const ScrollableLayerGuid::ViewID& aScrollId, + const CSSPoint& aOffset); + void SetTestAsyncZoom(LayersId aLayersId, + const ScrollableLayerGuid::ViewID& aScrollId, + const LayerToParentLayerScale& aZoom); + + // This can only be called on the updater thread. + const WebRenderScrollData* GetScrollData(LayersId aLayersId) const; + + /** + * This can be used to assert that the current thread is the + * updater thread (which samples the async transform). + * This does nothing if thread assertions are disabled. + */ + void AssertOnUpdaterThread() const; + + /** + * Runs the given task on the APZ "updater thread" for this APZUpdater. If + * this function is called from the updater thread itself then the task is + * run immediately without getting queued. + * + * The layers id argument should be the id of the layer tree that is + * requesting this task to be run. Conceptually each layer tree has a separate + * task queue, so that if one layer tree is blocked waiting for a scene build + * then tasks for the other layer trees can still be processed. + */ + void RunOnUpdaterThread(LayersId aLayersId, already_AddRefed<Runnable> aTask); + + /** + * Returns true if currently on the APZUpdater's "updater thread". + */ + bool IsUpdaterThread() const; + + /** + * Dispatches the given task to the APZ "controller thread", but does it + * *from* the updater thread. That is, if the thread on which this function is + * called is not the updater thread, the task is first dispatched to the + * updater thread. When the updater thread runs it (or if this is called + * directly on the updater thread), that is when the task gets dispatched to + * the controller thread. The controller thread then actually runs the task. + * + * See the RunOnUpdaterThread method for details on the layers id argument. + */ + void RunOnControllerThread(LayersId aLayersId, + already_AddRefed<Runnable> aTask); + + void MarkAsDetached(LayersId aLayersId); + + protected: + virtual ~APZUpdater(); + + // Return true if the APZUpdater is connected to WebRender and is + // using a WebRender scene builder thread as its updater thread. + // This is only false during GTests, and a shutdown codepath during + // which we create a dummy APZUpdater. + bool IsConnectedToWebRender() const; + + static already_AddRefed<APZUpdater> GetUpdater( + const wr::WrWindowId& aWindowId); + + void ProcessQueue(); + + private: + RefPtr<APZCTreeManager> mApz; + bool mDestroyed; + bool mConnectedToWebRender; + + // Map from layers id to WebRenderScrollData. This can only be touched on + // the updater thread. + std::unordered_map<LayersId, WebRenderScrollData, LayersId::HashFn> + mScrollData; + + // Stores epoch state for a particular layers id. This structure is only + // accessed on the updater thread. + struct EpochState { + // The epoch for the most recent scroll data sent from the content side. + wr::Epoch mRequired; + // The epoch for the most recent scene built and swapped in on the WR side. + Maybe<wr::Epoch> mBuilt; + // True if and only if the layers id is the root layers id for the + // compositor + bool mIsRoot; + + EpochState(); + + // Whether or not the state for this layers id is such that it blocks + // processing of tasks for the layer tree. This happens if the root layers + // id or a "visible" layers id has scroll data for an epoch newer than what + // has been built. A "visible" layers id is one that is attached to the full + // layer tree (i.e. there is a chain of reflayer items from the root layer + // tree to the relevant layer subtree). This is not always the case; for + // instance a content process may send the compositor layers for a document + // before the chrome has attached the remote iframe to the root document. + // Since WR only builds pipelines for "visible" layers ids, |mBuilt| being + // populated means that the layers id is "visible". + bool IsBlocked() const; + }; + + // Map from layers id to epoch state. + // This data structure can only be touched on the updater thread. + std::unordered_map<LayersId, EpochState, LayersId::HashFn> mEpochData; + + // Used to manage the mapping from a WR window id to APZUpdater. These are + // only used if WebRender is enabled. Both sWindowIdMap and mWindowId should + // only be used while holding the sWindowIdLock. Note that we use a + // StaticAutoPtr wrapper on sWindowIdMap to avoid a static initializer for the + // unordered_map. This also avoids the initializer/memory allocation in cases + // where we're not using WebRender. + static StaticMutex sWindowIdLock MOZ_UNANNOTATED; + static StaticAutoPtr<std::unordered_map<uint64_t, APZUpdater*>> sWindowIdMap; + Maybe<wr::WrWindowId> mWindowId; + + // Lock used to protected mUpdaterThreadId; + mutable Mutex mThreadIdLock MOZ_UNANNOTATED; + // If WebRender and async scene building are enabled, this holds the thread id + // of the scene builder thread (which is the updater thread) for the + // compositor associated with this APZUpdater instance. It may be populated + // even if async scene building is not enabled, but in that case we don't + // care about the contents. + Maybe<PlatformThreadId> mUpdaterThreadId; + + // Helper struct that pairs each queued runnable with the layers id that it is + // associated with. This allows us to easily implement the conceptual + // separation of mUpdaterQueue into independent queues per layers id. + struct QueuedTask { + LayersId mLayersId; + RefPtr<Runnable> mRunnable; + }; + + // Lock used to protect mUpdaterQueue + Mutex mQueueLock MOZ_UNANNOTATED; + // Holds a queue of tasks to be run on the updater thread, when the updater + // thread is a WebRender thread, since it won't have a message loop we can + // dispatch to. Note that although this is a single queue it is conceptually + // separated into multiple ones, one per layers id. Tasks for a given layers + // id will always run in FIFO order, but there is no guaranteed ordering for + // tasks with different layers ids. + std::deque<QueuedTask> mUpdaterQueue; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_APZUpdater_h diff --git a/gfx/layers/apz/public/CompositorController.h b/gfx/layers/apz/public/CompositorController.h new file mode 100644 index 0000000000..ad71a8faf5 --- /dev/null +++ b/gfx/layers/apz/public/CompositorController.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_CompositorController_h +#define mozilla_layers_CompositorController_h + +#include "nsISupportsImpl.h" // for NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING +#include "mozilla/Maybe.h" +#include "mozilla/webrender/WebRenderTypes.h" + +namespace mozilla { +namespace layers { + +class CompositorController { + public: + NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING + + /** + * Ask the compositor to schedule a new composite. + */ + virtual void ScheduleRenderOnCompositorThread(wr::RenderReasons aReasons) = 0; + + protected: + virtual ~CompositorController() = default; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_CompositorController_h diff --git a/gfx/layers/apz/public/GeckoContentController.h b/gfx/layers/apz/public/GeckoContentController.h new file mode 100644 index 0000000000..abfef68caa --- /dev/null +++ b/gfx/layers/apz/public/GeckoContentController.h @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_GeckoContentController_h +#define mozilla_layers_GeckoContentController_h + +#include "GeckoContentControllerTypes.h" +#include "InputData.h" // for PinchGestureInput +#include "LayersTypes.h" // for ScrollDirection +#include "Units.h" // for CSSPoint, CSSRect, etc +#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 +#include "mozilla/Attributes.h" // for MOZ_CAN_RUN_SCRIPT +#include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM +#include "mozilla/EventForwards.h" // for Modifiers +#include "mozilla/layers/APZThreadUtils.h" +#include "mozilla/layers/MatrixMessage.h" // for MatrixMessage +#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid, etc +#include "nsISupportsImpl.h" + +namespace mozilla { + +class Runnable; + +namespace layers { + +struct RepaintRequest; + +class GeckoContentController { + public: + using APZStateChange = GeckoContentController_APZStateChange; + using TapType = GeckoContentController_TapType; + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GeckoContentController) + + /** + * Notifies the content side of the most recently computed transforms for + * each layers subtree to the root. The nsTArray will contain one + * MatrixMessage for each layers id in the current APZ tree, along with the + * corresponding transform. + */ + virtual void NotifyLayerTransforms(nsTArray<MatrixMessage>&& aTransforms) = 0; + + /** + * Requests a paint of the given RepaintRequest |aRequest| from Gecko. + * Implementations per-platform are responsible for actually handling this. + * + * This method must always be called on the repaint thread, which depends + * on the GeckoContentController. For ChromeProcessController it is the + * Gecko main thread, while for RemoteContentController it is the compositor + * thread where it can send IPDL messages. + */ + virtual void RequestContentRepaint(const RepaintRequest& aRequest) = 0; + + /** + * Requests handling of a tap event. |aPoint| is in LD pixels, relative to the + * current scroll offset. + */ + MOZ_CAN_RUN_SCRIPT + virtual void HandleTap(TapType aType, const LayoutDevicePoint& aPoint, + Modifiers aModifiers, const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) = 0; + + /** + * When the apz.allow_zooming pref is set to false, the APZ will not + * translate pinch gestures to actual zooming. Instead, it will call this + * method to notify gecko of the pinch gesture, and allow it to deal with it + * however it wishes. Note that this function is not called if the pinch is + * prevented by content calling preventDefault() on the touch events, or via + * use of the touch-action property. + * @param aType One of PINCHGESTURE_START, PINCHGESTURE_SCALE, + * PINCHGESTURE_FINGERLIFTED, or PINCHGESTURE_END, indicating the phase + * of the pinch. + * @param aGuid The guid of the APZ that is detecting the pinch. This is + * generally the root APZC for the layers id. + * @param aFocusPoint The focus point of the pinch event. + * @param aSpanChange For the START or END event, this is always 0. + * For a SCALE event, this is the difference in span between the + * previous state and the new state. + * @param aModifiers The keyboard modifiers depressed during the pinch. + */ + virtual void NotifyPinchGesture(PinchGestureInput::PinchGestureType aType, + const ScrollableLayerGuid& aGuid, + const LayoutDevicePoint& aFocusPoint, + LayoutDeviceCoord aSpanChange, + Modifiers aModifiers) = 0; + + /** + * Schedules a runnable to run on the controller thread at some time + * in the future. + * This method must always be called on the controller thread. + */ + virtual void PostDelayedTask(already_AddRefed<Runnable> aRunnable, + int aDelayMs) { + APZThreadUtils::DelayedDispatch(std::move(aRunnable), aDelayMs); + } + + /** + * Returns true if we are currently on the thread that can send repaint + * requests. + */ + virtual bool IsRepaintThread() = 0; + + /** + * Runs the given task on the "repaint" thread. + */ + virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) = 0; + + /** + * General notices of APZ state changes for consumers. + * |aGuid| identifies the APZC originating the state change. + * |aChange| identifies the type of state change + * |aArg| is used by some state changes to pass extra information (see + * the documentation for each state change above) + * |aInputBlockId| is populated for the |eStartTouch| and |eEndTouch| + * state changes and identifies the input block of the + * gesture that triggers the state change. + */ + virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, + APZStateChange aChange, int aArg = 0, + Maybe<uint64_t> aInputBlockId = Nothing()) { + } + + /** + * Notify content of a MozMouseScrollFailed event. + */ + virtual void NotifyMozMouseScrollEvent( + const ScrollableLayerGuid::ViewID& aScrollId, const nsString& aEvent) {} + + /** + * Notify content that the repaint requests have been flushed. + */ + virtual void NotifyFlushComplete() = 0; + + /** + * If the async scrollbar-drag initiation code kicks in on the APZ side, then + * we need to let content know that we are dragging the scrollbar. Otherwise, + * by the time the mousedown events is handled by content, the scrollthumb + * could already have been moved via a RequestContentRepaint message at a + * new scroll position, and the mousedown might end up triggering a click-to- + * scroll on where the thumb used to be. + */ + virtual void NotifyAsyncScrollbarDragInitiated( + uint64_t aDragBlockId, const ScrollableLayerGuid::ViewID& aScrollId, + ScrollDirection aDirection) = 0; + virtual void NotifyAsyncScrollbarDragRejected( + const ScrollableLayerGuid::ViewID& aScrollId) = 0; + + virtual void NotifyAsyncAutoscrollRejected( + const ScrollableLayerGuid::ViewID& aScrollId) = 0; + + virtual void CancelAutoscroll(const ScrollableLayerGuid& aGuid) = 0; + + virtual void NotifyScaleGestureComplete(const ScrollableLayerGuid& aGuid, + float aScale) = 0; + + virtual void UpdateOverscrollVelocity(const ScrollableLayerGuid& aGuid, + float aX, float aY, + bool aIsRootContent) {} + virtual void UpdateOverscrollOffset(const ScrollableLayerGuid& aGuid, + float aX, float aY, bool aIsRootContent) { + } + + GeckoContentController() = default; + + /** + * Needs to be called on the main thread. + */ + virtual void Destroy() {} + + /** + * Whether this is RemoteContentController. + */ + virtual bool IsRemote() { return false; } + + virtual PresShell* GetTopLevelPresShell() const { return nullptr; }; + + protected: + // Protected destructor, to discourage deletion outside of Release(): + virtual ~GeckoContentController() = default; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_GeckoContentController_h diff --git a/gfx/layers/apz/public/GeckoContentControllerTypes.h b/gfx/layers/apz/public/GeckoContentControllerTypes.h new file mode 100644 index 0000000000..8ab478eab5 --- /dev/null +++ b/gfx/layers/apz/public/GeckoContentControllerTypes.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_GeckoContentControllerTypes_h +#define mozilla_layers_GeckoContentControllerTypes_h + +#include "mozilla/DefineEnum.h" + +namespace mozilla { +namespace layers { + +// clang-format off +MOZ_DEFINE_ENUM_CLASS(GeckoContentController_APZStateChange, ( + /** + * APZ started modifying the view (including panning, zooming, and fling). + */ + eTransformBegin, + /** + * APZ finished modifying the view. + */ + eTransformEnd, + /** + * APZ started a touch. + * |aArg| is 1 if touch can be a pan, 0 otherwise. + */ + eStartTouch, + /** + * APZ started a pan. + */ + eStartPanning, + /** + * APZ finished processing a touch. + * |aArg| is 1 if touch was a click, 0 otherwise. + */ + eEndTouch +)); +// clang-format on + +/** + * Different types of tap-related events that can be sent in + * the HandleTap function. The names should be relatively self-explanatory. + * Note that the eLongTapUp will always be preceded by an eLongTap, but not + * all eLongTap notifications will be followed by an eLongTapUp (for instance, + * if the user moves their finger after triggering the long-tap but before + * lifting it). + * The difference between eDoubleTap and eSecondTap is subtle - the eDoubleTap + * is for an actual double-tap "gesture" while eSecondTap is for the same user + * input but where a double-tap gesture is not allowed. This is used to fire + * a click event with detail=2 to web content (similar to what a mouse double- + * click would do). + */ +// clang-format off +MOZ_DEFINE_ENUM_CLASS(GeckoContentController_TapType, ( + eSingleTap, + eDoubleTap, + eSecondTap, + eLongTap, + eLongTapUp +)); +// clang-format on + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_GeckoContentControllerTypes_h diff --git a/gfx/layers/apz/public/IAPZCTreeManager.h b/gfx/layers/apz/public/IAPZCTreeManager.h new file mode 100644 index 0000000000..cd0859d34d --- /dev/null +++ b/gfx/layers/apz/public/IAPZCTreeManager.h @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_IAPZCTreeManager_h +#define mozilla_layers_IAPZCTreeManager_h + +#include <stdint.h> // for uint64_t, uint32_t + +#include "mozilla/layers/LayersTypes.h" // for TouchBehaviorFlags +#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid, etc +#include "mozilla/layers/ZoomConstraints.h" // for ZoomConstraints +#include "nsTArrayForwardDeclare.h" // for nsTArray, nsTArray_Impl, etc +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc +#include "Units.h" // for CSSRect, etc + +namespace mozilla { +namespace layers { + +class APZInputBridge; +class KeyboardMap; +struct ZoomTarget; + +enum AllowedTouchBehavior { + NONE = 0, + VERTICAL_PAN = 1 << 0, + HORIZONTAL_PAN = 1 << 1, + PINCH_ZOOM = 1 << 2, + ANIMATING_ZOOM = 1 << 3, + UNKNOWN = 1 << 4 +}; + +enum ZoomToRectBehavior : uint32_t { + DEFAULT_BEHAVIOR = 0, + DISABLE_ZOOM_OUT = 1 << 0, + PAN_INTO_VIEW_ONLY = 1 << 1, + ONLY_ZOOM_TO_DEFAULT_SCALE = 1 << 2, +}; + +enum class BrowserGestureResponse : bool; + +class AsyncDragMetrics; +struct APZHandledResult; + +class IAPZCTreeManager { + NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(IAPZCTreeManager) + + public: + /** + * Set the keyboard shortcuts to use for translating keyboard events. + */ + virtual void SetKeyboardMap(const KeyboardMap& aKeyboardMap) = 0; + + /** + * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom + * in. The actual animation is done on the sampler thread after being set + * up. |aRect| must be given in CSS pixels, relative to the document. + * |aFlags| is a combination of the ZoomToRectBehavior enum values. + */ + virtual void ZoomToRect(const ScrollableLayerGuid& aGuid, + const ZoomTarget& aZoomTarget, + const uint32_t aFlags = DEFAULT_BEHAVIOR) = 0; + + /** + * If we have touch listeners, this should always be called when we know + * definitively whether or not content has preventDefaulted any touch events + * that have come in. If |aPreventDefault| is true, any touch events in the + * queue will be discarded. This function must be called on the controller + * thread. + */ + virtual void ContentReceivedInputBlock(uint64_t aInputBlockId, + bool aPreventDefault) = 0; + + /** + * When the event regions code is enabled, this function should be invoked to + * to confirm the target of the input block. This is only needed in cases + * where the initial input event of the block hit a dispatch-to-content region + * but is safe to call for all input blocks. This function should always be + * invoked on the controller thread. + * The different elements in the array of targets correspond to the targets + * for the different touch points. In the case where the touch point has no + * target, or the target is not a scrollable frame, the target's |mScrollId| + * should be set to ScrollableLayerGuid::NULL_SCROLL_ID. + */ + virtual void SetTargetAPZC(uint64_t aInputBlockId, + const nsTArray<ScrollableLayerGuid>& aTargets) = 0; + + /** + * Updates any zoom constraints contained in the <meta name="viewport"> tag. + * If the |aConstraints| is Nothing() then previously-provided constraints for + * the given |aGuid| are cleared. + */ + virtual void UpdateZoomConstraints( + const ScrollableLayerGuid& aGuid, + const Maybe<ZoomConstraints>& aConstraints) = 0; + + virtual void SetDPI(float aDpiValue) = 0; + + /** + * Sets allowed touch behavior values for current touch-session for specific + * input block (determined by aInputBlock). + * Should be invoked by the widget. Each value of the aValues arrays + * corresponds to the different touch point that is currently active. + * Must be called after receiving the TOUCH_START event that starts the + * touch-session. + * This must be called on the controller thread. + */ + virtual void SetAllowedTouchBehavior( + uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aValues) = 0; + + virtual void SetBrowserGestureResponse(uint64_t aInputBlockId, + BrowserGestureResponse aResponse) = 0; + + virtual void StartScrollbarDrag(const ScrollableLayerGuid& aGuid, + const AsyncDragMetrics& aDragMetrics) = 0; + + virtual bool StartAutoscroll(const ScrollableLayerGuid& aGuid, + const ScreenPoint& aAnchorLocation) = 0; + + virtual void StopAutoscroll(const ScrollableLayerGuid& aGuid) = 0; + + /** + * Function used to disable LongTap gestures. + * + * On slow running tests, drags and touch events can be misinterpreted + * as a long tap. This allows tests to disable long tap gesture detection. + */ + virtual void SetLongTapEnabled(bool aTapGestureEnabled) = 0; + + /** + * Returns an APZInputBridge interface that can be used to send input + * events to APZ in a synchronous manner. This will always be non-null, and + * the returned object's lifetime will match the lifetime of this + * IAPZCTreeManager implementation. + * It is only valid to call this function in the UI process. + */ + virtual APZInputBridge* InputBridge() = 0; + + protected: + // Discourage destruction outside of decref + + virtual ~IAPZCTreeManager() = default; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_IAPZCTreeManager_h diff --git a/gfx/layers/apz/public/MatrixMessage.h b/gfx/layers/apz/public/MatrixMessage.h new file mode 100644 index 0000000000..45050f7406 --- /dev/null +++ b/gfx/layers/apz/public/MatrixMessage.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_layers_MatrixMessage_h +#define mozilla_layers_MatrixMessage_h + +#include "mozilla/Maybe.h" +#include "mozilla/gfx/Matrix.h" +#include "mozilla/layers/LayersTypes.h" +#include "Units.h" // for ScreenRect +#include "UnitTransforms.h" + +namespace mozilla { +namespace layers { +class MatrixMessage { + public: + // Don't use this one directly + MatrixMessage() = default; + + MatrixMessage(const Maybe<LayerToScreenMatrix4x4>& aMatrix, + const ScreenRect& aTopLevelViewportVisibleRectInBrowserCoords, + const LayersId& aLayersId) + : mMatrix(ToUnknownMatrix(aMatrix)), + mTopLevelViewportVisibleRectInBrowserCoords( + aTopLevelViewportVisibleRectInBrowserCoords), + mLayersId(aLayersId) {} + + inline Maybe<LayerToScreenMatrix4x4> GetMatrix() const { + return LayerToScreenMatrix4x4::FromUnknownMatrix(mMatrix); + } + + inline ScreenRect GetTopLevelViewportVisibleRectInBrowserCoords() const { + return mTopLevelViewportVisibleRectInBrowserCoords; + } + + inline const LayersId& GetLayersId() const { return mLayersId; } + + bool operator==(const MatrixMessage& aOther) const { + return aOther.mMatrix == mMatrix && + aOther.mTopLevelViewportVisibleRectInBrowserCoords == + mTopLevelViewportVisibleRectInBrowserCoords && + aOther.mLayersId == mLayersId; + } + + bool operator!=(const MatrixMessage& aOther) const { + return !(*this == aOther); + } + // Fields are public for IPC. Don't access directly + // elsewhere. + // Transform matrix to convert this layer to screen coordinate. + Maybe<gfx::Matrix4x4> mMatrix; // Untyped for IPC + // The remote iframe document rectangle corresponding to this layer. + // The rectangle is the result of clipped out by ancestor async scrolling so + // that the rectangle will be empty if it's completely scrolled out of view. + ScreenRect mTopLevelViewportVisibleRectInBrowserCoords; + LayersId mLayersId; +}; +}; // namespace layers +}; // namespace mozilla + +#endif // mozilla_layers_MatrixMessage_h |