summaryrefslogtreecommitdiffstats
path: root/layout/base/PresShell.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/base/PresShell.h')
-rw-r--r--layout/base/PresShell.h3287
1 files changed, 3287 insertions, 0 deletions
diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h
new file mode 100644
index 0000000000..c6a965e81e
--- /dev/null
+++ b/layout/base/PresShell.h
@@ -0,0 +1,3287 @@
+/* -*- 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/. */
+
+/* a presentation of a document, part 2 */
+
+#ifndef mozilla_PresShell_h
+#define mozilla_PresShell_h
+
+#include "DepthOrderedFrameList.h"
+#include "mozilla/PresShellForwards.h"
+
+#include <stdio.h> // for FILE definition
+#include "FrameMetrics.h"
+#include "LayoutConstants.h"
+#include "TouchManager.h"
+#include "Units.h"
+#include "Visibility.h"
+#include "mozilla/ArenaObjectID.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/FlushType.h"
+#include "mozilla/Logging.h"
+#include "mozilla/MemoryReporting.h"
+#include "mozilla/ScrollTypes.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/WeakPtr.h"
+#include "mozilla/dom/DocumentBinding.h"
+#include "mozilla/layers/FocusTarget.h"
+#include "mozilla/layout/LayoutTelemetryTools.h"
+#include "mozilla/widget/ThemeChangeKind.h"
+#include "nsColor.h"
+#include "nsCOMArray.h"
+#include "nsCoord.h"
+#include "nsDOMNavigationTiming.h"
+#include "nsFrameManager.h"
+#include "nsFrameState.h"
+#include "nsIContent.h"
+#include "nsIObserver.h"
+#include "nsISelectionController.h"
+#include "nsQueryFrame.h"
+#include "nsPresArena.h"
+#include "nsPresContext.h"
+#include "nsRect.h"
+#include "nsRefreshObservers.h"
+#include "nsStringFwd.h"
+#include "nsStubDocumentObserver.h"
+#include "nsTHashSet.h"
+#include "nsThreadUtils.h"
+#include "nsWeakReference.h"
+#ifdef ACCESSIBILITY
+# include "nsAccessibilityService.h"
+#endif
+
+class AutoPointerEventTargetUpdater;
+class AutoWeakFrame;
+class gfxContext;
+class MobileViewportManager;
+class nsAutoCauseReflowNotifier;
+class nsCanvasFrame;
+class nsCaret;
+class nsCSSFrameConstructor;
+class nsDocShell;
+class nsFrameSelection;
+class nsIDocShell;
+class nsIFrame;
+class nsILayoutHistoryState;
+class nsINode;
+class nsPageSequenceFrame;
+class nsIReflowCallback;
+class nsIScrollableFrame;
+class nsITimer;
+class nsPIDOMWindowOuter;
+class nsPresShellEventCB;
+class nsRange;
+class nsRefreshDriver;
+class nsRegion;
+class nsView;
+class nsViewManager;
+class nsWindowSizes;
+struct RangePaintInfo;
+#ifdef MOZ_REFLOW_PERF
+class ReflowCountMgr;
+#endif
+class WeakFrame;
+class nsTextFrame;
+class ZoomConstraintsClient;
+
+struct nsCallbackEventRequest;
+
+namespace mozilla {
+class nsDisplayList;
+class nsDisplayListBuilder;
+class FallbackRenderer;
+
+class AccessibleCaretEventHub;
+class GeckoMVMContext;
+class OverflowChangedTracker;
+class StyleSheet;
+
+class ProfileChunkedBuffer;
+
+#ifdef ACCESSIBILITY
+namespace a11y {
+class DocAccessible;
+} // namespace a11y
+#endif
+
+namespace dom {
+class BrowserParent;
+class Element;
+class Event;
+class HTMLSlotElement;
+class Selection;
+class PerformanceMainThread;
+} // namespace dom
+
+namespace gfx {
+class SourceSurface;
+} // namespace gfx
+
+namespace layers {
+class LayerManager;
+struct LayersId;
+} // namespace layers
+
+namespace layout {
+class ScrollAnchorContainer;
+} // namespace layout
+
+// 039d8ffc-fa55-42d7-a53a-388cb129b052
+#define NS_PRESSHELL_IID \
+ { \
+ 0x039d8ffc, 0xfa55, 0x42d7, { \
+ 0xa5, 0x3a, 0x38, 0x8c, 0xb1, 0x29, 0xb0, 0x52 \
+ } \
+ }
+
+#undef NOISY_INTERRUPTIBLE_REFLOW
+
+/**
+ * Presentation shell. Presentation shells are the controlling point for
+ * managing the presentation of a document. The presentation shell holds a
+ * live reference to the document, the presentation context, the style
+ * manager, the style set and the root frame.
+ *
+ * When this object is Release'd, it will release the document, the
+ * presentation context, the style manager, the style set and the root frame.
+ */
+
+class PresShell final : public nsStubDocumentObserver,
+ public nsISelectionController,
+ public nsIObserver,
+ public nsSupportsWeakReference {
+ typedef dom::Document Document;
+ typedef dom::Element Element;
+ typedef gfx::SourceSurface SourceSurface;
+ typedef layers::FocusTarget FocusTarget;
+ typedef layers::FrameMetrics FrameMetrics;
+ typedef layers::LayerManager LayerManager;
+
+ // A set type for tracking visible frames, for use by the visibility code in
+ // PresShell. The set contains nsIFrame* pointers.
+ typedef nsTHashSet<nsIFrame*> VisibleFrames;
+
+ public:
+ explicit PresShell(Document* aDocument);
+
+ // nsISupports
+ NS_DECL_ISUPPORTS
+
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_PRESSHELL_IID)
+
+ static bool AccessibleCaretEnabled(nsIDocShell* aDocShell);
+
+ /**
+ * Return the active content currently capturing the mouse if any.
+ */
+ static nsIContent* GetCapturingContent() {
+ return sCapturingContentInfo.mContent;
+ }
+
+ /**
+ */
+ static dom::BrowserParent* GetCapturingRemoteTarget() {
+ MOZ_ASSERT(XRE_IsParentProcess());
+ return sCapturingContentInfo.mRemoteTarget;
+ }
+
+ /**
+ * Allow or disallow mouse capturing.
+ */
+ static void AllowMouseCapture(bool aAllowed) {
+ sCapturingContentInfo.mAllowed = aAllowed;
+ }
+
+ /**
+ * Returns true if there is an active mouse capture that wants to prevent
+ * drags.
+ */
+ static bool IsMouseCapturePreventingDrag() {
+ return sCapturingContentInfo.mPreventDrag && sCapturingContentInfo.mContent;
+ }
+
+ static void ClearMouseCaptureOnView(nsView* aView);
+
+ // Clear the capture content if it exists in this process.
+ static void ClearMouseCapture();
+
+ // If a frame in the subtree rooted at aFrame is capturing the mouse then
+ // clears that capture.
+ //
+ // NOTE(emilio): This is needed only so that mouse events captured by a remote
+ // frame don't remain being captured by the frame while hidden, see
+ // dom/events/test/browser_mouse_enterleave_switch_tab.js, which is the only
+ // test that meaningfully exercises this code path.
+ //
+ // We could consider maybe removing this, since the capturing content gets
+ // reset on mouse/pointerdown? Or maybe exposing an API so that the front-end
+ // does this.
+ static void ClearMouseCapture(nsIFrame* aFrame);
+
+#ifdef ACCESSIBILITY
+ /**
+ * Return the document accessible for this PresShell if there is one.
+ */
+ a11y::DocAccessible* GetDocAccessible() const { return mDocAccessible; }
+
+ /**
+ * Set the document accessible for this PresShell.
+ */
+ void SetDocAccessible(a11y::DocAccessible* aDocAccessible) {
+ mDocAccessible = aDocAccessible;
+ }
+#endif // #ifdef ACCESSIBILITY
+
+ /**
+ * See `mLastOverWindowPointerLocation`.
+ */
+ const nsPoint& GetLastOverWindowPointerLocation() const {
+ return mLastOverWindowPointerLocation;
+ }
+
+ MOZ_CAN_RUN_SCRIPT void Init(nsPresContext*, nsViewManager*);
+
+ /**
+ * All callers are responsible for calling |Destroy| after calling
+ * |EndObservingDocument|. It needs to be separate only because form
+ * controls incorrectly store their data in the frames rather than the
+ * content model and printing calls |EndObservingDocument| multiple
+ * times to make form controls behave nicely when printed.
+ */
+ void Destroy();
+
+ bool IsDestroying() { return mIsDestroying; }
+
+ /**
+ * All frames owned by the shell are allocated from an arena. They
+ * are also recycled using free lists. Separate free lists are
+ * maintained for each frame type (aID), which must always correspond
+ * to the same aSize value. AllocateFrame is infallible and will abort
+ * on out-of-memory.
+ */
+ void* AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) {
+#define FRAME_ID(classname, ...) \
+ static_assert(size_t(nsQueryFrame::FrameIID::classname##_id) == \
+ size_t(eArenaObjectID_##classname), \
+ "");
+#define ABSTRACT_FRAME_ID(classname) \
+ static_assert(size_t(nsQueryFrame::FrameIID::classname##_id) == \
+ size_t(eArenaObjectID_##classname), \
+ "");
+#include "mozilla/FrameIdList.h"
+#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
+ return AllocateByObjectID(ArenaObjectID(size_t(aID)), aSize);
+ }
+
+ void FreeFrame(nsQueryFrame::FrameIID aID, void* aPtr) {
+ return FreeByObjectID(ArenaObjectID(size_t(aID)), aPtr);
+ }
+
+ void* AllocateByObjectID(ArenaObjectID aID, size_t aSize) {
+ void* result = mFrameArena.Allocate(aID, aSize);
+ RecordAlloc(result);
+ return result;
+ }
+
+ void FreeByObjectID(ArenaObjectID aID, void* aPtr) {
+ RecordFree(aPtr);
+ if (!mIsDestroying) {
+ mFrameArena.Free(aID, aPtr);
+ }
+ }
+
+ Document* GetDocument() const { return mDocument; }
+
+ nsPresContext* GetPresContext() const { return mPresContext; }
+
+ nsViewManager* GetViewManager() const { return mViewManager; }
+
+ nsRefreshDriver* GetRefreshDriver() const;
+
+ nsCSSFrameConstructor* FrameConstructor() const {
+ return mFrameConstructor.get();
+ }
+
+ /**
+ * FrameSelection will return the Frame based selection API.
+ * You cannot go back and forth anymore with QI between nsIDOM sel and
+ * nsIFrame sel.
+ */
+ already_AddRefed<nsFrameSelection> FrameSelection();
+
+ /**
+ * ConstFrameSelection returns an object which methods are safe to use for
+ * example in nsIFrame code.
+ */
+ const nsFrameSelection* ConstFrameSelection() const { return mSelection; }
+
+ // Start receiving notifications from our document. If called after Destroy,
+ // this will be ignored.
+ void BeginObservingDocument();
+
+ // Stop receiving notifications from our document. If called after Destroy,
+ // this will be ignored.
+ void EndObservingDocument();
+
+ bool IsObservingDocument() const { return mIsObservingDocument; }
+
+ /**
+ * Return whether Initialize() was previously called.
+ */
+ bool DidInitialize() const { return mDidInitialize; }
+
+ /**
+ * Perform initialization. Constructs the frame for the root content
+ * object and then enqueues a reflow of the frame model.
+ *
+ * Callers of this method must hold a reference to this shell that
+ * is guaranteed to survive through arbitrary script execution.
+ * Calling Initialize can execute arbitrary script.
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult Initialize();
+
+ /**
+ * Schedule a reflow for the frame model into a new width and height. The
+ * coordinates for aWidth and aHeight must be in standard nscoord's.
+ *
+ * Returns whether layout might have changed.
+ */
+ MOZ_CAN_RUN_SCRIPT void ResizeReflow(
+ nscoord aWidth, nscoord aHeight,
+ ResizeReflowOptions = ResizeReflowOptions::NoOption);
+ MOZ_CAN_RUN_SCRIPT bool ResizeReflowIgnoreOverride(
+ nscoord aWidth, nscoord aHeight,
+ ResizeReflowOptions = ResizeReflowOptions::NoOption);
+ MOZ_CAN_RUN_SCRIPT void ForceResizeReflowWithCurrentDimensions();
+
+ /**
+ * Add this pres shell to the refresh driver to be observed for resize
+ * event if applicable.
+ */
+ void AddResizeEventFlushObserverIfNeeded();
+
+ /**
+ * Returns true if the document hosted by this presShell is in a devtools
+ * Responsive Design Mode browsing context.
+ */
+ bool InRDMPane();
+
+#if defined(MOZ_WIDGET_ANDROID)
+ /**
+ * If the dynamic toolbar is not expanded, notify the app to do so.
+ */
+ void MaybeNotifyShowDynamicToolbar();
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+ void RefreshZoomConstraintsForScreenSizeChange();
+
+ private:
+ /**
+ * This is what ResizeReflowIgnoreOverride does when not shrink-wrapping (that
+ * is, when ResizeReflowOptions::BSizeLimit is not specified).
+ */
+ bool SimpleResizeReflow(nscoord aWidth, nscoord aHeight);
+
+ bool CanHandleUserInputEvents(WidgetGUIEvent* aGUIEvent);
+
+ public:
+ /**
+ * Updates pending layout, assuming reasonable (up-to-date, or mid-update for
+ * container queries) styling of the page. Returns whether a reflow did not
+ * get interrupted (and thus layout should be considered fully up-to-date).
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY bool DoFlushLayout(bool aInterruptible);
+
+ /**
+ * Note that the assumptions that determine whether we need a mobile viewport
+ * manager may have changed.
+ */
+ MOZ_CAN_RUN_SCRIPT void MaybeRecreateMobileViewportManager(
+ bool aAfterInitialization);
+
+ /**
+ * Returns true if this document uses mobile viewport sizing (including
+ * processing of <meta name="viewport"> tags).
+ *
+ * Note that having a MobileViewportManager does not necessarily mean using
+ * mobile viewport sizing, as with desktop zooming we can have a
+ * MobileViewportManager on desktop, but we only want to do mobile viewport
+ * sizing on mobile. (TODO: Rename MobileViewportManager to reflect its more
+ * general role.)
+ */
+ bool UsesMobileViewportSizing() const;
+
+ /**
+ * Get the MobileViewportManager used to manage the document's mobile
+ * viewport. Will return null in situations where we don't have a mobile
+ * viewport, and for documents that are not the root content document.
+ */
+ RefPtr<MobileViewportManager> GetMobileViewportManager() const;
+
+ /**
+ * Return true if the presshell expects layout flush.
+ */
+ bool IsLayoutFlushObserver();
+
+ /**
+ * Called when document load completes.
+ */
+ void LoadComplete();
+ /**
+ * This calls through to the frame manager to get the root frame.
+ */
+ nsIFrame* GetRootFrame() const { return mFrameManager->GetRootFrame(); }
+
+ /*
+ * Get root scroll frame from FrameManager()->GetRootFrame().
+ */
+ nsIFrame* GetRootScrollFrame() const;
+
+ /*
+ * The same as GetRootScrollFrame, but returns an nsIScrollableFrame
+ */
+ nsIScrollableFrame* GetRootScrollFrameAsScrollable() const;
+
+ /**
+ * Get the current focused content or DOM selection that should be the
+ * target for scrolling.
+ */
+ already_AddRefed<nsIContent> GetContentForScrolling() const;
+
+ /**
+ * Get the DOM selection that should be the target for scrolling, if there
+ * is no focused content.
+ */
+ already_AddRefed<nsIContent> GetSelectedContentForScrolling() const;
+
+ /**
+ * Gets nearest scrollable frame from the specified content node. The frame
+ * is scrollable with overflow:scroll or overflow:auto in some direction when
+ * aDirection is eEither. Otherwise, this returns a nearest frame that is
+ * scrollable in the specified direction.
+ */
+ nsIScrollableFrame* GetScrollableFrameToScrollForContent(
+ nsIContent* aContent, layers::ScrollDirections aDirections);
+
+ /**
+ * Gets nearest scrollable frame from current focused content or DOM
+ * selection if there is no focused content. The frame is scrollable with
+ * overflow:scroll or overflow:auto in some direction when aDirection is
+ * eEither. Otherwise, this returns a nearest frame that is scrollable in
+ * the specified direction.
+ */
+ nsIScrollableFrame* GetScrollableFrameToScroll(
+ layers::ScrollDirections aDirections);
+
+ /**
+ * Returns the page sequence frame associated with the frame hierarchy.
+ * Returns nullptr if not a paginated view.
+ */
+ nsPageSequenceFrame* GetPageSequenceFrame() const;
+
+ /**
+ * Returns the canvas frame associated with the frame hierarchy.
+ * Returns nullptr if is XUL document.
+ */
+ nsCanvasFrame* GetCanvasFrame() const;
+
+ void PostPendingScrollAnchorSelection(
+ layout::ScrollAnchorContainer* aContainer);
+ void FlushPendingScrollAnchorSelections();
+ void PostPendingScrollAnchorAdjustment(
+ layout::ScrollAnchorContainer* aContainer);
+
+ void PostPendingScrollResnap(nsIScrollableFrame* aScrollableFrame);
+ void FlushPendingScrollResnap();
+
+ void CancelAllPendingReflows();
+
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void NotifyCounterStylesAreDirty();
+
+ bool FrameIsAncestorOfDirtyRoot(nsIFrame* aFrame) const;
+
+ /**
+ * Destroy the frames for aElement, and reconstruct them asynchronously if
+ * needed.
+ *
+ * Note that this may destroy frames for an arbitrary ancestor, depending on
+ * the frame tree structure.
+ */
+ void DestroyFramesForAndRestyle(Element* aElement);
+
+ /**
+ * Called when a ShadowRoot will be attached to an element (and thus the flat
+ * tree children will go away).
+ */
+ void ShadowRootWillBeAttached(Element& aElement);
+
+ /**
+ * Handles all the layout stuff needed when the slot assignment for an element
+ * is about to change.
+ *
+ * Only called when the slot attribute of the element changes, the rest of
+ * the changes should be handled in ShadowRoot.
+ */
+ void SlotAssignmentWillChange(Element& aElement,
+ dom::HTMLSlotElement* aOldSlot,
+ dom::HTMLSlotElement* aNewSlot);
+
+ void PostRecreateFramesFor(Element*);
+ void RestyleForAnimation(Element*, RestyleHint);
+
+ /**
+ * Determine if it is safe to flush all pending notifications.
+ */
+ bool IsSafeToFlush() const;
+
+ /**
+ * Informs the document's FontFaceSet that the refresh driver ticked,
+ * flushing style and layout.
+ */
+ void NotifyFontFaceSetOnRefresh();
+
+ // Removes ourself from the list of layout / style / and resize refresh driver
+ // observers.
+ //
+ // Right now this is only used for documents in the BFCache, so if you want to
+ // use this for anything else you need to ensure we don't end up in those
+ // lists after calling this, but before calling StartObservingRefreshDriver
+ // again.
+ //
+ // That is handled by the mDocument->GetBFCacheEntry checks in
+ // DoObserve*Flushes functions, though that could conceivably become a boolean
+ // member in the shell if needed.
+ //
+ // Callers are responsible of manually calling StartObservingRefreshDriver
+ // again.
+ void StopObservingRefreshDriver();
+ void StartObservingRefreshDriver();
+
+ bool ObservingStyleFlushes() const { return mObservingStyleFlushes; }
+ bool ObservingLayoutFlushes() const { return mObservingLayoutFlushes; }
+
+ void ObserveStyleFlushes() {
+ if (!ObservingStyleFlushes()) {
+ DoObserveStyleFlushes();
+ }
+ }
+
+ /**
+ * Callbacks will be called even if reflow itself fails for
+ * some reason.
+ */
+ nsresult PostReflowCallback(nsIReflowCallback* aCallback);
+ void CancelReflowCallback(nsIReflowCallback* aCallback);
+
+ void ScheduleBeforeFirstPaint();
+ void UnsuppressAndInvalidate();
+
+ void ClearFrameRefs(nsIFrame* aFrame);
+
+ // Clears the selection of the older focused frame selection if any.
+ void FrameSelectionWillTakeFocus(nsFrameSelection&);
+
+ // Clears and repaint mFocusedFrameSelection if it matches the argument.
+ void FrameSelectionWillLoseFocus(nsFrameSelection&);
+
+ /**
+ * Get a reference rendering context. This is a context that should not
+ * be rendered to, but is suitable for measuring text and performing
+ * other non-rendering operations. Guaranteed to return non-null.
+ */
+ mozilla::UniquePtr<gfxContext> CreateReferenceRenderingContext();
+
+ /**
+ * Scrolls the view of the document so that the given area of a frame
+ * is visible, if possible. Layout is not flushed before scrolling.
+ *
+ * @param aRect Relative to aTargetFrame. If none, the bounding box of
+ * aTargetFrame will be used. The rect edges will be respected even if the
+ * rect is empty.
+ * @param aVertical see ScrollContentIntoView and ScrollAxis
+ * @param aHorizontal see ScrollContentIntoView and ScrollAxis
+ * @param aScrollFlags if ScrollFirstAncestorOnly is set, only the
+ * nearest scrollable ancestor is scrolled, otherwise all
+ * scrollable ancestors may be scrolled if necessary
+ * if ScrollOverflowHidden is set then we may scroll in a direction
+ * even if overflow:hidden is specified in that direction; otherwise
+ * we will not scroll in that direction when overflow:hidden is
+ * set for that direction
+ * If ScrollNoParentFrames is set then we only scroll
+ * nodes in this document, not in any parent documents which
+ * contain this document in a iframe or the like.
+ * @return true if any scrolling happened, false if no scrolling happened
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool ScrollFrameIntoView(nsIFrame* aTargetFrame,
+ const Maybe<nsRect>& aKnownRectRelativeToTarget,
+ ScrollAxis aVertical, ScrollAxis aHorizontal,
+ ScrollFlags aScrollFlags);
+
+ /**
+ * Suppress notification of the frame manager that frames are
+ * being destroyed.
+ */
+ void SetIgnoreFrameDestruction(bool aIgnore);
+
+ /**
+ * Get the AccessibleCaretEventHub, if it exists. AddRefs it.
+ */
+ already_AddRefed<AccessibleCaretEventHub> GetAccessibleCaretEventHub() const;
+
+ /**
+ * Get the caret, if it exists. AddRefs it.
+ */
+ already_AddRefed<nsCaret> GetCaret() const;
+
+ /**
+ * Set the current caret to a new caret. To undo this, call RestoreCaret.
+ */
+ void SetCaret(nsCaret* aNewCaret);
+
+ /**
+ * Restore the caret to the original caret that this pres shell was created
+ * with.
+ */
+ void RestoreCaret();
+
+ dom::Selection* GetCurrentSelection(SelectionType aSelectionType);
+
+ /**
+ * Gets the last selection that took focus in this document. This is basically
+ * the frame selection that's visible to the user.
+ */
+ nsFrameSelection* GetLastFocusedFrameSelection();
+
+ /**
+ * Interface to dispatch events via the presshell
+ * @note The caller must have a strong reference to the PresShell.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEventWithTarget(WidgetEvent* aEvent, nsIFrame* aFrame,
+ nsIContent* aContent,
+ nsEventStatus* aEventStatus,
+ bool aIsHandlingNativeEvent = false,
+ nsIContent** aTargetContent = nullptr,
+ nsIContent* aOverrideClickTarget = nullptr) {
+ MOZ_ASSERT(aEvent);
+ EventHandler eventHandler(*this);
+ return eventHandler.HandleEventWithTarget(
+ aEvent, aFrame, aContent, aEventStatus, aIsHandlingNativeEvent,
+ aTargetContent, aOverrideClickTarget);
+ }
+
+ /**
+ * Dispatch event to content only (NOT full processing)
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleDOMEventWithTarget(nsIContent* aTargetContent,
+ WidgetEvent* aEvent,
+ nsEventStatus* aStatus);
+
+ /**
+ * Dispatch event to content only (NOT full processing)
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleDOMEventWithTarget(nsIContent* aTargetContent,
+ dom::Event* aEvent, nsEventStatus* aStatus);
+
+ /**
+ * Return whether or not the event is valid to be dispatched
+ */
+ bool CanDispatchEvent(const WidgetGUIEvent* aEvent = nullptr) const;
+
+ /**
+ * Gets the current target event frame from the PresShell
+ */
+ nsIFrame* GetCurrentEventFrame();
+
+ /**
+ * Gets the current target event frame from the PresShell
+ */
+ already_AddRefed<nsIContent> GetEventTargetContent(WidgetEvent* aEvent);
+
+ /**
+ * Get and set the history state for the current document
+ */
+ nsresult CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState);
+
+ /**
+ * Determine if reflow is currently locked
+ * returns true if reflow is locked, false otherwise
+ */
+ bool IsReflowLocked() const { return mIsReflowing; }
+
+ /**
+ * Called to find out if painting is suppressed for this presshell. If it is
+ * suppressd, we don't allow the painting of any layer but the background, and
+ * we don't recur into our children.
+ */
+ bool IsPaintingSuppressed() const { return mPaintingSuppressed; }
+
+ void TryUnsuppressPaintingSoon();
+
+ void UnsuppressPainting();
+ void InitPaintSuppressionTimer();
+ void CancelPaintSuppressionTimer();
+
+ /**
+ * Reconstruct frames for all elements in the document
+ */
+ MOZ_CAN_RUN_SCRIPT void ReconstructFrames();
+
+ /**
+ * See if reflow verification is enabled. To enable reflow verification add
+ * "verifyreflow:1" to your MOZ_LOG environment variable (any non-zero
+ * debug level will work). Or, call SetVerifyReflowEnable with true.
+ */
+ static bool GetVerifyReflowEnable();
+
+ /**
+ * Set the verify-reflow enable flag.
+ */
+ static void SetVerifyReflowEnable(bool aEnabled);
+
+ nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame);
+
+#ifdef MOZ_REFLOW_PERF
+ void DumpReflows();
+ void CountReflows(const char* aName, nsIFrame* aFrame);
+ void PaintCount(const char* aName, gfxContext* aRenderingContext,
+ nsPresContext* aPresContext, nsIFrame* aFrame,
+ const nsPoint& aOffset, uint32_t aColor);
+ void SetPaintFrameCount(bool aOn);
+ bool IsPaintingFrameCounts();
+#endif // #ifdef MOZ_REFLOW_PERF
+
+ // Debugging hooks
+#ifdef DEBUG
+ void ListComputedStyles(FILE* out, int32_t aIndent = 0);
+#endif
+#if defined(DEBUG) || defined(MOZ_LAYOUT_DEBUGGER)
+ void ListStyleSheets(FILE* out, int32_t aIndent = 0);
+#endif
+
+ /**
+ * Stop all refresh drivers and carets in this presentation and
+ * in the presentations of subdocuments. Resets painting to a suppressed
+ * state.
+ * XXX this should include image animations
+ */
+ void Freeze(bool aIncludeSubDocuments = true);
+ bool IsFrozen() { return mFrozen; }
+
+ /**
+ * Restarts refresh drivers in this presentation and in the
+ * presentations of subdocuments, then do a full invalidate of the content
+ * area.
+ */
+ void Thaw(bool aIncludeSubDocuments = true);
+
+ void FireOrClearDelayedEvents(bool aFireEvents);
+
+ /**
+ * When this shell is disconnected from its containing docshell, we
+ * lose our container pointer. However, we'd still like to be able to target
+ * user events at the docshell's parent. This pointer allows us to do that.
+ * It should not be used for any other purpose.
+ */
+ void SetForwardingContainer(const WeakPtr<nsDocShell>& aContainer);
+
+ /**
+ * Render the document into an arbitrary gfxContext
+ * Designed for getting a picture of a document or a piece of a document
+ * Note that callers will generally want to call FlushPendingNotifications
+ * to get an up-to-date view of the document
+ * @param aRect is the region to capture into the offscreen buffer, in the
+ * root frame's coordinate system (if aIgnoreViewportScrolling is false)
+ * or in the root scrolled frame's coordinate system
+ * (if aIgnoreViewportScrolling is true). The coordinates are in appunits.
+ * @param aFlags see below;
+ * set RenderDocumentFlags::IsUntrusted if the contents may be passed to
+ * malicious agents. E.g. we might choose not to paint the contents of
+ * sensitive widgets such as the file name in a file upload widget, and we
+ * might choose not to paint themes.
+ * set RenderDocumentFlags::IgnoreViewportScrolling to ignore clipping and
+ * scrollbar painting due to scrolling in the viewport
+ * set RenderDocumentFlags::ResetViewportScrolling to temporarily set the
+ * viewport scroll position to 0 so that position:fixed elements are drawn
+ * at their initial position.
+ * set RenderDocumentFlags::DrawCaret to draw the caret if one would be
+ * visible (by default the caret is never drawn)
+ * set RenderDocumentFlags::UseWidgetLayers to force rendering to go
+ * through the layer manager for the window. This may be unexpectedly slow
+ * (if the layer manager must read back data from the GPU) or low-quality
+ * (if the layer manager reads back pixel data and scales it
+ * instead of rendering using the appropriate scaling). It may also
+ * slow everything down if the area rendered does not correspond to the
+ * normal visible area of the window.
+ * set RenderDocumentFlags::AsyncDecodeImages to avoid having images
+ * synchronously decoded during rendering.
+ * (by default images decode synchronously with RenderDocument)
+ * set RenderDocumentFlags::DocumentRelative to render the document as if
+ * there has been no scrolling and interpret |aRect| relative to the document
+ * instead of the CSS viewport. Only considered if
+ * RenderDocumentFlags::IgnoreViewportScrolling is set or the document is in
+ * ignore viewport scrolling mode
+ * (PresShell::SetIgnoreViewportScrolling/IgnoringViewportScrolling).
+ * set RenderDocumentFlags::UseHighQualityScaling to enable downscale on
+ * decode for images.
+ * @param aBackgroundColor a background color to render onto
+ * @param aRenderedContext the gfxContext to render to. We render so that
+ * one CSS pixel in the source document is rendered to one unit in the current
+ * transform.
+ */
+ nsresult RenderDocument(const nsRect& aRect, RenderDocumentFlags aFlags,
+ nscolor aBackgroundColor,
+ gfxContext* aRenderedContext);
+
+ /**
+ * Renders a node aNode to a surface and returns it. The aRegion may be used
+ * to clip the rendering. This region is measured in CSS pixels from the
+ * edge of the presshell area. The aPoint, aScreenRect and aFlags arguments
+ * function in a similar manner as RenderSelection.
+ */
+ already_AddRefed<SourceSurface> RenderNode(nsINode* aNode,
+ const Maybe<CSSIntRegion>& aRegion,
+ const LayoutDeviceIntPoint aPoint,
+ LayoutDeviceIntRect* aScreenRect,
+ RenderImageFlags aFlags);
+
+ /**
+ * Renders a selection to a surface and returns it. This method is primarily
+ * intended to create the drag feedback when dragging a selection.
+ *
+ * aScreenRect will be filled in with the bounding rectangle of the
+ * selection area on screen.
+ *
+ * If the area of the selection is large and the RenderImageFlags::AutoScale
+ * is set, the image will be scaled down. The argument aPoint is used in this
+ * case as a reference point when determining the new screen rectangle after
+ * scaling. Typically, this will be the mouse position, so that the screen
+ * rectangle is positioned such that the mouse is over the same point in the
+ * scaled image as in the original. When scaling does not occur, the mouse
+ * point isn't used because the position can be determined from the displayed
+ * frames.
+ */
+ already_AddRefed<SourceSurface> RenderSelection(
+ dom::Selection* aSelection, const LayoutDeviceIntPoint aPoint,
+ LayoutDeviceIntRect* aScreenRect, RenderImageFlags aFlags);
+
+ void AddAutoWeakFrame(AutoWeakFrame* aWeakFrame);
+ void AddWeakFrame(WeakFrame* aWeakFrame);
+
+ void RemoveAutoWeakFrame(AutoWeakFrame* aWeakFrame);
+ void RemoveWeakFrame(WeakFrame* aWeakFrame);
+
+ /**
+ * Stop or restart non synthetic test mouse event handling on *all*
+ * presShells.
+ *
+ * @param aDisable If true, disable all non synthetic test mouse
+ * events on all presShells. Otherwise, enable them.
+ */
+ void DisableNonTestMouseEvents(bool aDisable);
+
+ /**
+ * Record the background color of the most recently drawn canvas. This color
+ * is composited on top of the user's default background color and then used
+ * to draw the background color of the canvas. See PresShell::Paint,
+ * PresShell::PaintDefaultBackground, and nsDocShell::SetupNewViewer;
+ * bug 488242, bug 476557 and other bugs mentioned there.
+ */
+ void SetCanvasBackground(nscolor aColor) {
+ mCanvasBackground.mViewportColor = aColor;
+ }
+ nscolor GetCanvasBackground() const {
+ return mCanvasBackground.mViewportColor;
+ }
+
+ struct CanvasBackground {
+ // The canvas frame background for the whole viewport.
+ nscolor mViewportColor = 0;
+ // The canvas frame background for a printed page. Note that when
+ // print-previewing / in paged mode we have multiple canvas frames (one for
+ // the viewport, one for each page).
+ nscolor mPageColor = 0;
+ bool mCSSSpecified = false;
+ };
+
+ // Use the current frame tree (if it exists) to update the background color of
+ // the canvas frames.
+ CanvasBackground ComputeCanvasBackground() const;
+ void UpdateCanvasBackground();
+
+ /**
+ * Computes the backstop color for the view: transparent if in a transparent
+ * widget, otherwise the PresContext default background color. This color is
+ * only visible if the contents of the view as a whole are translucent.
+ */
+ nscolor ComputeBackstopColor(nsView* aDisplayRoot);
+
+ void ObserveNativeAnonMutationsForPrint(bool aObserve) {
+ mObservesMutationsForPrint = aObserve;
+ }
+ bool ObservesNativeAnonMutationsForPrint() {
+ return mObservesMutationsForPrint;
+ }
+
+ void ActivenessMaybeChanged();
+ bool IsActive() const { return mIsActive; }
+
+ /**
+ * Keep track of how many times this presshell has been rendered to
+ * a window.
+ */
+ uint64_t GetPaintCount() { return mPaintCount; }
+ void IncrementPaintCount() { ++mPaintCount; }
+
+ /**
+ * Get the root DOM window of this presShell.
+ */
+ already_AddRefed<nsPIDOMWindowOuter> GetRootWindow();
+
+ /**
+ * This returns the focused DOM window under our top level window.
+ * I.e., when we are deactive, this returns the *last* focused DOM window.
+ */
+ already_AddRefed<nsPIDOMWindowOuter> GetFocusedDOMWindowInOurWindow();
+
+ /**
+ * Get the focused content under this window.
+ */
+ already_AddRefed<nsIContent> GetFocusedContentInOurWindow() const;
+
+ /**
+ * Get the window renderer for the widget of the root view, if it has
+ * one.
+ */
+ WindowRenderer* GetWindowRenderer();
+
+ /**
+ * Return true iff there is a widget rendering this presShell and that
+ * widget is APZ-enabled.
+ */
+ bool AsyncPanZoomEnabled();
+
+ /**
+ * Track whether we're ignoring viewport scrolling for the purposes
+ * of painting. If we are ignoring, then layers aren't clipped to
+ * the CSS viewport and scrollbars aren't drawn.
+ */
+ bool IgnoringViewportScrolling() const {
+ return !!(mRenderingStateFlags &
+ RenderingStateFlags::IgnoringViewportScrolling);
+ }
+
+ float GetResolution() const { return mResolution.valueOr(1.0); }
+ float GetCumulativeResolution() const;
+
+ /**
+ * Accessors for a flag that tracks whether the most recent change to
+ * the pres shell's resolution was originated by the main thread.
+ */
+ bool IsResolutionUpdated() const { return mResolutionUpdated; }
+ void SetResolutionUpdated(bool aUpdated) { mResolutionUpdated = aUpdated; }
+
+ /**
+ * Returns true if the resolution has ever been changed by APZ.
+ */
+ bool IsResolutionUpdatedByApz() const { return mResolutionUpdatedByApz; }
+
+ /**
+ * Used by session restore code to restore a resolution before the first
+ * paint.
+ */
+ void SetRestoreResolution(float aResolution,
+ LayoutDeviceIntSize aDisplaySize);
+
+ /**
+ * Returns whether we are in a DrawWindow() call that used the
+ * DRAWWINDOW_DO_NOT_FLUSH flag.
+ */
+ bool InDrawWindowNotFlushing() const {
+ return !!(mRenderingStateFlags &
+ RenderingStateFlags::DrawWindowNotFlushing);
+ }
+
+ /**
+ * Set the isFirstPaint flag.
+ */
+ void SetIsFirstPaint(bool aIsFirstPaint) { mIsFirstPaint = aIsFirstPaint; }
+
+ /**
+ * Get the isFirstPaint flag.
+ */
+ bool GetIsFirstPaint() const { return mIsFirstPaint; }
+
+ uint32_t GetPresShellId() { return mPresShellId; }
+
+ /**
+ * Dispatch a mouse move event based on the most recent mouse position if
+ * this PresShell is visible. This is used when the contents of the page
+ * moved (aFromScroll is false) or scrolled (aFromScroll is true).
+ */
+ void SynthesizeMouseMove(bool aFromScroll);
+
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEvent(nsIFrame* aFrame, WidgetGUIEvent* aEvent,
+ bool aDontRetargetEvents, nsEventStatus* aEventStatus);
+ bool ShouldIgnoreInvalidation();
+ /**
+ * Notify that we called Paint with PaintFlags::PaintComposite.
+ * Fires on the presshell for the painted widget.
+ * This is issued at a time when it's safe to modify widget geometry.
+ */
+ MOZ_CAN_RUN_SCRIPT void DidPaintWindow();
+
+ bool IsVisible() const;
+ bool IsUnderHiddenEmbedderElement() const {
+ return mUnderHiddenEmbedderElement;
+ }
+ void SetIsUnderHiddenEmbedderElement(bool aUnderHiddenEmbedderElement) {
+ mUnderHiddenEmbedderElement = aUnderHiddenEmbedderElement;
+ }
+
+ MOZ_CAN_RUN_SCRIPT
+ void DispatchSynthMouseMove(WidgetGUIEvent* aEvent);
+
+ /* Temporarily ignore the Displayport for better paint performance. We
+ * trigger a repaint once suppression is disabled. Without that
+ * the displayport may get left at the suppressed size for an extended
+ * period of time and result in unnecessary checkerboarding (see bug
+ * 1255054). */
+ void SuppressDisplayport(bool aEnabled);
+
+ /* Whether or not displayport suppression should be turned on. Note that
+ * this only affects the return value of |IsDisplayportSuppressed()|, and
+ * doesn't change the value of the internal counter.
+ */
+ void RespectDisplayportSuppression(bool aEnabled);
+
+ /* Whether or not the displayport is currently suppressed. */
+ bool IsDisplayportSuppressed();
+
+ void AddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const;
+
+ /**
+ * Methods that retrieve the cached font inflation preferences.
+ */
+ uint32_t FontSizeInflationEmPerLine() const {
+ return mFontSizeInflationEmPerLine;
+ }
+
+ uint32_t FontSizeInflationMinTwips() const {
+ return mFontSizeInflationMinTwips;
+ }
+
+ uint32_t FontSizeInflationLineThreshold() const {
+ return mFontSizeInflationLineThreshold;
+ }
+
+ bool FontSizeInflationForceEnabled() const {
+ return mFontSizeInflationForceEnabled;
+ }
+
+ bool FontSizeInflationDisabledInMasterProcess() const {
+ return mFontSizeInflationDisabledInMasterProcess;
+ }
+
+ bool FontSizeInflationEnabled() const { return mFontSizeInflationEnabled; }
+
+ /**
+ * Recomputes whether font-size inflation is enabled.
+ */
+ void RecomputeFontSizeInflationEnabled();
+
+ /**
+ * Return true if the most recent interruptible reflow was interrupted.
+ */
+ bool IsReflowInterrupted() const { return mWasLastReflowInterrupted; }
+
+ /**
+ * Return true if the the interruptible reflows have to be suppressed.
+ * This may happen only if if the most recent reflow was interrupted.
+ */
+ bool SuppressInterruptibleReflows() const {
+ return mWasLastReflowInterrupted;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Approximate frame visibility tracking public API.
+ //////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Schedule an update of the list of approximately visible frames "soon".
+ * This lets the refresh driver know that we want a visibility update in the
+ * near future. The refresh driver applies its own heuristics and throttling
+ * to decide when to actually perform the visibility update.
+ */
+ void ScheduleApproximateFrameVisibilityUpdateSoon();
+
+ /**
+ * Schedule an update of the list of approximately visible frames "now". The
+ * update runs asynchronously, but it will be posted to the event loop
+ * immediately. Prefer the "soon" variation of this method when possible, as
+ * this variation ignores the refresh driver's heuristics.
+ */
+ void ScheduleApproximateFrameVisibilityUpdateNow();
+
+ /**
+ * Clears the current list of approximately visible frames on this pres shell
+ * and replaces it with frames that are in the display list @aList.
+ */
+ void RebuildApproximateFrameVisibilityDisplayList(const nsDisplayList& aList);
+ void RebuildApproximateFrameVisibility(nsRect* aRect = nullptr,
+ bool aRemoveOnly = false);
+
+ /**
+ * Ensures @aFrame is in the list of approximately visible frames.
+ */
+ void EnsureFrameInApproximatelyVisibleList(nsIFrame* aFrame);
+
+ /// Removes @aFrame from the list of approximately visible frames if present.
+ void RemoveFrameFromApproximatelyVisibleList(nsIFrame* aFrame);
+
+ /// Whether we should assume all frames are visible.
+ bool AssumeAllFramesVisible();
+
+ /**
+ * Returns whether the document's style set's rule processor for the
+ * specified level of the cascade is shared by multiple style sets.
+ *
+ * @param aSheetType One of the nsIStyleSheetService.*_SHEET constants.
+ */
+ nsresult HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
+ bool* aRetVal);
+
+ /**
+ * Returns whether or not the document has ever handled user input
+ */
+ bool HasHandledUserInput() const { return mHasHandledUserInput; }
+
+ MOZ_CAN_RUN_SCRIPT void FireResizeEvent();
+ MOZ_CAN_RUN_SCRIPT void FireResizeEventSync();
+
+ void NativeAnonymousContentRemoved(nsIContent* aAnonContent);
+
+ /**
+ * See HTMLDocument.setKeyPressEventModel() in HTMLDocument.webidl for the
+ * detail.
+ */
+ void SetKeyPressEventModel(uint16_t aKeyPressEventModel) {
+ mForceUseLegacyKeyCodeAndCharCodeValues |=
+ aKeyPressEventModel ==
+ dom::Document_Binding::KEYPRESS_EVENT_MODEL_SPLIT;
+ }
+
+ bool AddRefreshObserver(nsARefreshObserver* aObserver, FlushType aFlushType,
+ const char* aObserverDescription);
+ bool RemoveRefreshObserver(nsARefreshObserver* aObserver,
+ FlushType aFlushType);
+
+ bool AddPostRefreshObserver(nsAPostRefreshObserver*);
+ bool AddPostRefreshObserver(mozilla::ManagedPostRefreshObserver*) = delete;
+ bool RemovePostRefreshObserver(nsAPostRefreshObserver*);
+ bool RemovePostRefreshObserver(mozilla::ManagedPostRefreshObserver*) = delete;
+
+ // Represents an update to the visual scroll offset that will be sent to APZ.
+ // The update type is used to determine priority compared to other scroll
+ // updates.
+ struct VisualScrollUpdate {
+ nsPoint mVisualScrollOffset;
+ FrameMetrics::ScrollOffsetUpdateType mUpdateType;
+ bool mAcknowledged = false;
+ };
+
+ // Ask APZ in the next transaction to scroll to the given visual viewport
+ // offset (relative to the document).
+ // This is intended to be used when desired in cases where the browser
+ // internally triggers scrolling; scrolling triggered explicitly by web
+ // content (such as via window.scrollTo() should scroll the layout viewport
+ // only).
+ // If scrolling "far away", i.e. not just within the existing layout
+ // viewport, it's recommended to use both nsIScrollableFrame.ScrollTo*()
+ // (via window.scrollTo if calling from JS) *and* this function; otherwise,
+ // temporary checkerboarding may result. If doing this:
+ // * Be sure to call ScrollTo*() first, as a subsequent layout scroll
+ // in the same transaction will cancel the pending visual scroll.
+ // * Keep in mind that ScrollTo*() can tear down the pres shell and
+ // frame tree. Depending on how the pres shell is obtained for the
+ // subsequent ScrollToVisual() call, AutoWeakFrame or similar may
+ // need to be used.
+ // Please request APZ review if adding a new call site.
+ void ScrollToVisual(const nsPoint& aVisualViewportOffset,
+ FrameMetrics::ScrollOffsetUpdateType aUpdateType,
+ ScrollMode aMode);
+ void AcknowledgePendingVisualScrollUpdate();
+ void ClearPendingVisualScrollUpdate();
+ const Maybe<VisualScrollUpdate>& GetPendingVisualScrollUpdate() const {
+ return mPendingVisualScrollUpdate;
+ }
+
+ nsPoint GetLayoutViewportOffset() const;
+ nsSize GetLayoutViewportSize() const;
+
+ /**
+ * Documents belonging to an invisible DocShell must not be painted ever.
+ */
+ bool IsNeverPainting() { return mIsNeverPainting; }
+
+ void SetNeverPainting(bool aNeverPainting) {
+ mIsNeverPainting = aNeverPainting;
+ }
+
+ /**
+ * True if a reflow event has been scheduled, or is going to be scheduled
+ * to run in the future.
+ */
+ bool HasPendingReflow() const {
+ return mObservingLayoutFlushes || mReflowContinueTimer;
+ }
+
+ void SyncWindowProperties(bool aSync);
+ struct WindowSizeConstraints {
+ nsSize mMinSize;
+ nsSize mMaxSize;
+ };
+ WindowSizeConstraints GetWindowSizeConstraints();
+
+ Document* GetPrimaryContentDocument();
+
+ struct MOZ_RAII AutoAssertNoFlush {
+ explicit AutoAssertNoFlush(PresShell& aPresShell)
+ : mPresShell(aPresShell), mOldForbidden(mPresShell.mForbiddenToFlush) {
+ mPresShell.mForbiddenToFlush = true;
+ }
+
+ ~AutoAssertNoFlush() { mPresShell.mForbiddenToFlush = mOldForbidden; }
+
+ PresShell& mPresShell;
+ const bool mOldForbidden;
+ };
+
+ NS_IMETHOD GetSelectionFromScript(RawSelectionType aRawSelectionType,
+ dom::Selection** aSelection) override;
+ dom::Selection* GetSelection(RawSelectionType aRawSelectionType) override;
+
+ NS_IMETHOD SetDisplaySelection(int16_t aToggle) override;
+ NS_IMETHOD GetDisplaySelection(int16_t* aToggle) override;
+ NS_IMETHOD ScrollSelectionIntoView(RawSelectionType aRawSelectionType,
+ SelectionRegion aRegion,
+ int16_t aFlags) override;
+ NS_IMETHOD RepaintSelection(RawSelectionType aRawSelectionType) override;
+ void SelectionWillTakeFocus() override;
+ void SelectionWillLoseFocus() override;
+
+ // Implements the "focus fix-up rule". Returns true if the focus moved (in
+ // which case we might need to update layout again).
+ // See https://github.com/whatwg/html/issues/8225
+ MOZ_CAN_RUN_SCRIPT bool FixUpFocus();
+
+ /**
+ * Set a "resolution" for the document, which if not 1.0 will
+ * allocate more or fewer pixels for rescalable content by a factor
+ * of |resolution| in both dimensions. Return NS_OK iff the
+ * resolution bounds are sane, and the resolution of this was
+ * actually updated.
+ *
+ * Also increase the scale of the content by the same amount
+ * (that's the "AndScaleTo" part).
+ *
+ * The resolution defaults to 1.0.
+ *
+ * |aOrigin| specifies who originated the resolution change. For changes
+ * sent by APZ, pass ResolutionChangeOrigin::Apz. For changes sent by
+ * the main thread, pass ResolutionChangeOrigin::MainThreadAdjustment (similar
+ * to the |aOrigin| parameter of nsIScrollableFrame::ScrollToCSSPixels()).
+ */
+ nsresult SetResolutionAndScaleTo(float aResolution,
+ ResolutionChangeOrigin aOrigin);
+
+ ResolutionChangeOrigin GetLastResolutionChangeOrigin() {
+ return mLastResolutionChangeOrigin;
+ }
+
+ // Widget notificiations
+ void WindowSizeMoveDone();
+
+ void BackingScaleFactorChanged() { mPresContext->UIResolutionChangedSync(); }
+
+ /**
+ * Does any painting work required to update retained paint state, and pushes
+ * it the compositor (if any). Requests a composite, either by scheduling a
+ * remote composite, or invalidating the widget so that we get a call to
+ * SyncPaintFallback from the widget paint event.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ void PaintAndRequestComposite(nsView* aView, PaintFlags aFlags);
+
+ /**
+ * Does an immediate paint+composite using the FallbackRenderer (which must
+ * be the current WindowRenderer for the root frame's widget).
+ */
+ MOZ_CAN_RUN_SCRIPT
+ void SyncPaintFallback(nsView* aView);
+
+ /**
+ * Notify that we're going to call Paint with PaintFlags::PaintLayers
+ * on the pres shell for a widget (which might not be this one, since
+ * WillPaint is called on all presshells in the same toplevel window as the
+ * painted widget). This is issued at a time when it's safe to modify
+ * widget geometry.
+ */
+ MOZ_CAN_RUN_SCRIPT void WillPaint();
+
+ /**
+ * Ensures that the refresh driver is running, and schedules a view
+ * manager flush on the next tick.
+ */
+ void ScheduleViewManagerFlush();
+
+ // caret handling
+ NS_IMETHOD SetCaretEnabled(bool aInEnable) override;
+ NS_IMETHOD SetCaretReadOnly(bool aReadOnly) override;
+ NS_IMETHOD GetCaretEnabled(bool* aOutEnabled) override;
+ NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility) override;
+ NS_IMETHOD GetCaretVisible(bool* _retval) override;
+
+ /**
+ * Should the images have borders etc. Actual visual effects are determined
+ * by the frames. Visual effects may not effect layout, only display.
+ * Takes effect on next repaint, does not force a repaint itself.
+ *
+ * @param aFlags may be multiple of nsISelectionDisplay::DISPLAY_*.
+ */
+ NS_IMETHOD SetSelectionFlags(int16_t aFlags) override;
+ NS_IMETHOD GetSelectionFlags(int16_t* aFlags) override;
+
+ /**
+ * Gets the current state of non text selection effects
+ * @return current state of non text selection,
+ * as set by SetDisplayNonTextSelection
+ */
+ int16_t GetSelectionFlags() const { return mSelectionFlags; }
+
+ // nsISelectionController
+
+ NS_IMETHOD PhysicalMove(int16_t aDirection, int16_t aAmount,
+ bool aExtend) override;
+ NS_IMETHOD CharacterMove(bool aForward, bool aExtend) override;
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD WordMove(bool aForward,
+ bool aExtend) override;
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD LineMove(bool aForward,
+ bool aExtend) override;
+ NS_IMETHOD IntraLineMove(bool aForward, bool aExtend) override;
+ MOZ_CAN_RUN_SCRIPT
+ NS_IMETHOD PageMove(bool aForward, bool aExtend) override;
+ NS_IMETHOD ScrollPage(bool aForward) override;
+ NS_IMETHOD ScrollLine(bool aForward) override;
+ NS_IMETHOD ScrollCharacter(bool aRight) override;
+ NS_IMETHOD CompleteScroll(bool aForward) override;
+ MOZ_CAN_RUN_SCRIPT NS_IMETHOD CompleteMove(bool aForward,
+ bool aExtend) override;
+
+ // Notifies that the state of the document has changed.
+ void DocumentStatesChanged(dom::DocumentState);
+
+ // nsIDocumentObserver
+ NS_DECL_NSIDOCUMENTOBSERVER_BEGINLOAD
+ NS_DECL_NSIDOCUMENTOBSERVER_ENDLOAD
+ NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATECHANGED
+
+ // nsIMutationObserver
+ NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
+ NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
+ NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+
+ NS_DECL_NSIOBSERVER
+
+ // Inline methods defined in PresShellInlines.h
+ inline void EnsureStyleFlush();
+ inline void SetNeedStyleFlush();
+ inline void SetNeedLayoutFlush();
+ inline void SetNeedThrottledAnimationFlush();
+ inline ServoStyleSet* StyleSet() const;
+
+ /**
+ * Whether we might need a flush for the given flush type. If this
+ * function returns false, we definitely don't need to flush.
+ *
+ * @param aFlushType The flush type to check. This must be
+ * >= FlushType::Style. This also returns true if a throttled
+ * animation flush is required.
+ */
+ bool NeedFlush(FlushType aType) const {
+ // We check mInFlush to handle re-entrant calls to FlushPendingNotifications
+ // by reporting that we always need a flush in that case. Otherwise,
+ // we could end up missing needed flushes, since we clear the mNeedXXXFlush
+ // flags at the top of FlushPendingNotifications.
+ MOZ_ASSERT(aType >= FlushType::Style);
+ return mNeedStyleFlush ||
+ (mNeedLayoutFlush && aType >= FlushType::InterruptibleLayout) ||
+ aType >= FlushType::Display || mNeedThrottledAnimationFlush ||
+ mInFlush;
+ }
+
+ /**
+ * Returns true if we might need to flush layout, even if we haven't scheduled
+ * one yet (as opposed to HasPendingReflow, which returns true if a flush is
+ * scheduled or will soon be scheduled).
+ */
+ bool NeedLayoutFlush() const { return mNeedLayoutFlush; }
+
+ bool NeedStyleFlush() const { return mNeedStyleFlush; }
+
+ /**
+ * Flush pending notifications of the type specified. This method
+ * will not affect the content model; it'll just affect style and
+ * frames. Callers that actually want up-to-date presentation (other
+ * than the document itself) should probably be calling
+ * Document::FlushPendingNotifications.
+ *
+ * This method can execute script, which can destroy this presshell object
+ * unless someone is holding a reference to it on the stack. The presshell
+ * itself will ensure it lives up until the method returns, but callers who
+ * plan to use the presshell after this call should hold a strong ref
+ * themselves!
+ *
+ * @param aType the type of notifications to flush
+ */
+ MOZ_CAN_RUN_SCRIPT
+ void FlushPendingNotifications(FlushType aType) {
+ if (!NeedFlush(aType)) {
+ return;
+ }
+
+ DoFlushPendingNotifications(aType);
+ }
+
+ MOZ_CAN_RUN_SCRIPT
+ void FlushPendingNotifications(ChangesToFlush aType) {
+ if (!NeedFlush(aType.mFlushType)) {
+ return;
+ }
+
+ DoFlushPendingNotifications(aType);
+ }
+
+ /**
+ * Tell the pres shell that a frame needs to be marked dirty and needs
+ * Reflow. It's OK if this is an ancestor of the frame needing reflow as
+ * long as the ancestor chain between them doesn't cross a reflow root.
+ *
+ * The bit to add should be NS_FRAME_IS_DIRTY, NS_FRAME_HAS_DIRTY_CHILDREN
+ * or nsFrameState(0); passing 0 means that dirty bits won't be set on the
+ * frame or its ancestors/descendants, but that intrinsic widths will still
+ * be marked dirty. Passing aIntrinsicDirty = eResize and aBitToAdd = 0
+ * would result in no work being done, so don't do that.
+ */
+ void FrameNeedsReflow(
+ nsIFrame* aFrame, IntrinsicDirty aIntrinsicDirty, nsFrameState aBitToAdd,
+ ReflowRootHandling aRootHandling = ReflowRootHandling::InferFromBitToAdd);
+
+ /**
+ * Calls FrameNeedsReflow on all fixed position children of the root frame.
+ */
+ void MarkFixedFramesForReflow(IntrinsicDirty aIntrinsicDirty);
+
+ void MaybeReflowForInflationScreenSizeChange();
+
+ // This function handles all the work after VisualViewportSize is set
+ // or reset.
+ void CompleteChangeToVisualViewportSize();
+
+ /**
+ * The return value indicates whether the offset actually changed.
+ */
+ bool SetVisualViewportOffset(const nsPoint& aScrollOffset,
+ const nsPoint& aPrevLayoutScrollPos);
+
+ void ResetVisualViewportOffset();
+ nsPoint GetVisualViewportOffset() const {
+ if (mVisualViewportOffset.isSome()) {
+ return *mVisualViewportOffset;
+ }
+ return GetLayoutViewportOffset();
+ }
+ bool IsVisualViewportOffsetSet() const {
+ return mVisualViewportOffset.isSome();
+ }
+
+ void SetVisualViewportSize(nscoord aWidth, nscoord aHeight);
+ void ResetVisualViewportSize();
+ bool IsVisualViewportSizeSet() { return mVisualViewportSizeSet; }
+ nsSize GetVisualViewportSize() {
+ NS_ASSERTION(mVisualViewportSizeSet,
+ "asking for visual viewport size when its not set?");
+ return mVisualViewportSize;
+ }
+
+ nsPoint GetVisualViewportOffsetRelativeToLayoutViewport() const;
+
+ // Returns state of the dynamic toolbar.
+ DynamicToolbarState GetDynamicToolbarState() const {
+ if (!mPresContext) {
+ return DynamicToolbarState::None;
+ }
+
+ return mPresContext->GetDynamicToolbarState();
+ }
+ // Returns the visual viewport size during the dynamic toolbar is being
+ // shown/hidden.
+ nsSize GetVisualViewportSizeUpdatedByDynamicToolbar() const;
+
+ /* Enable/disable author style level. Disabling author style disables the
+ * entire author level of the cascade, including the HTML preshint level.
+ */
+ // XXX these could easily be inlined, but there is a circular #include
+ // problem with nsStyleSet.
+ void SetAuthorStyleDisabled(bool aDisabled);
+ bool GetAuthorStyleDisabled() const;
+
+ // aSheetType is one of the nsIStyleSheetService *_SHEET constants.
+ void NotifyStyleSheetServiceSheetAdded(StyleSheet* aSheet,
+ uint32_t aSheetType);
+ void NotifyStyleSheetServiceSheetRemoved(StyleSheet* aSheet,
+ uint32_t aSheetType);
+
+ // DoReflow returns whether the reflow finished without interruption
+ // If aFrame is not the root frame, the caller must pass a non-null
+ // aOverflowTracker.
+ bool DoReflow(nsIFrame* aFrame, bool aInterruptible,
+ OverflowChangedTracker* aOverflowTracker);
+
+ /**
+ * Add a solid color item to the bottom of aList with frame aFrame and bounds
+ * aBounds. aBackstopColor is composed behind the background color of the
+ * canvas, and it is transparent by default.
+ *
+ * We attempt to make the background color part of the scrolled canvas (to
+ * reduce transparent layers), and if async scrolling is enabled (and the
+ * background is opaque) then we add a second, unscrolled item to handle the
+ * checkerboarding case.
+ */
+ void AddCanvasBackgroundColorItem(
+ nsDisplayListBuilder* aBuilder, nsDisplayList* aList, nsIFrame* aFrame,
+ const nsRect& aBounds, nscolor aBackstopColor = NS_RGBA(0, 0, 0, 0));
+
+ size_t SizeOfTextRuns(MallocSizeOf aMallocSizeOf) const;
+
+ static PresShell* GetShellForEventTarget(nsIFrame* aFrame,
+ nsIContent* aContent);
+ static PresShell* GetShellForTouchEvent(WidgetGUIEvent* aEvent);
+
+ /**
+ * Informs the pres shell that the document is now at the anchor with
+ * the given name. If |aScroll| is true, scrolls the view of the
+ * document so that the anchor with the specified name is displayed at
+ * the top of the window. If |aAnchorName| is empty, then this informs
+ * the pres shell that there is no current target, and |aScroll| must
+ * be false. If |aAdditionalScrollFlags| is ScrollFlags::ScrollSmoothAuto
+ * and |aScroll| is true, the scrolling may be performed with an animation.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult GoToAnchor(const nsAString& aAnchorName, bool aScroll,
+ ScrollFlags aAdditionalScrollFlags = ScrollFlags::None);
+
+ /**
+ * Tells the presshell to scroll again to the last anchor scrolled to by
+ * GoToAnchor, if any. This scroll only happens if the scroll
+ * position has not changed since the last GoToAnchor (modulo scroll anchoring
+ * adjustments). This is called by nsDocumentViewer::LoadComplete. This clears
+ * the last anchor scrolled to by GoToAnchor (we don't want to keep it alive
+ * if it's removed from the DOM), so don't call this more than once.
+ */
+ MOZ_CAN_RUN_SCRIPT nsresult ScrollToAnchor();
+
+ /**
+ * When scroll anchoring adjusts positions in the root frame during page load,
+ * it may move our scroll position in the root frame.
+ *
+ * While that's generally desirable, when scrolling to an anchor via an id-ref
+ * we have a more direct target. If the id-ref points to something that cannot
+ * be selected as a scroll anchor container (like an image or an inline), we
+ * may select a node following it as a scroll anchor, and if then stuff is
+ * inserted on top, we may end up moving the id-ref element offscreen to the
+ * top inadvertently.
+ *
+ * On page load, the document viewer will call ScrollToAnchor(), and will only
+ * scroll to the anchor again if the scroll position is not changed. We don't
+ * want scroll anchoring adjustments to prevent this, so account for them.
+ */
+ void RootScrollFrameAdjusted(nscoord aYAdjustment) {
+ if (mLastAnchorScrolledTo) {
+ mLastAnchorScrollPositionY += aYAdjustment;
+ }
+ }
+
+ /**
+ * Scrolls the view of the document so that the primary frame of the content
+ * is displayed in the window. Layout is flushed before scrolling.
+ *
+ * @param aContent The content object of which primary frame should be
+ * scrolled into view.
+ * @param aVertical How to align the frame vertically and when to do so.
+ * This is a ScrollAxis of Where and When.
+ * @param aHorizontal How to align the frame horizontally and when to do so.
+ * This is a ScrollAxis of Where and When.
+ * @param aScrollFlags If ScrollFlags::ScrollFirstAncestorOnly is set,
+ * only the nearest scrollable ancestor is scrolled,
+ * otherwise all scrollable ancestors may be scrolled
+ * if necessary. If ScrollFlags::ScrollOverflowHidden
+ * is set then we may scroll in a direction even if
+ * overflow:hidden is specified in that direction;
+ * otherwise we will not scroll in that direction when
+ * overflow:hidden is set for that direction. If
+ * ScrollFlags::ScrollNoParentFrames is set then we
+ * only scroll nodes in this document, not in any
+ * parent documents which contain this document in a
+ * iframe or the like. If ScrollFlags::ScrollSmooth
+ * is set and CSSOM-VIEW scroll-behavior is enabled,
+ * we will scroll smoothly using
+ * nsIScrollableFrame::ScrollMode::SMOOTH_MSD;
+ * otherwise, nsIScrollableFrame::ScrollMode::INSTANT
+ * will be used. If ScrollFlags::ScrollSmoothAuto is
+ * set, the CSSOM-View scroll-behavior attribute is
+ * set to 'smooth' on the scroll frame, and CSSOM-VIEW
+ * scroll-behavior is enabled, we will scroll smoothly
+ * using nsIScrollableFrame::ScrollMode::SMOOTH_MSD;
+ * otherwise, nsIScrollableFrame::ScrollMode::INSTANT
+ * will be used.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult ScrollContentIntoView(nsIContent* aContent, ScrollAxis aVertical,
+ ScrollAxis aHorizontal,
+ ScrollFlags aScrollFlags);
+
+ /**
+ * When capturing content is set, it traps all mouse events and retargets
+ * them at this content node. If capturing is not allowed
+ * (gCaptureInfo.mAllowed is false), then capturing is not set. However, if
+ * the CaptureFlags::IgnoreAllowedState is set, the allowed state is ignored
+ * and capturing is set regardless. To disable capture, pass null for the
+ * value of aContent.
+ *
+ * If CaptureFlags::RetargetedToElement is set, all mouse events are
+ * targeted at aContent only. Otherwise, mouse events are targeted at
+ * aContent or its descendants. That is, descendants of aContent receive
+ * mouse events as they normally would, but mouse events outside of aContent
+ * are retargeted to aContent.
+ *
+ * If CaptureFlags::PreventDragStart is set then drags are prevented from
+ * starting while this capture is active.
+ *
+ * If CaptureFlags::PointerLock is set, similar to
+ * CaptureFlags::RetargetToElement, then events are targeted at aContent,
+ * but capturing is held more strongly (i.e., calls to SetCapturingContent()
+ * won't unlock unless CaptureFlags::PointerLock is set again).
+ */
+ static void SetCapturingContent(nsIContent* aContent, CaptureFlags aFlags,
+ WidgetEvent* aEvent = nullptr);
+
+ /**
+ * Alias for SetCapturingContent(nullptr, CaptureFlags::None) for making
+ * callers what they do clearer.
+ */
+ static void ReleaseCapturingContent() {
+ PresShell::SetCapturingContent(nullptr, CaptureFlags::None);
+ }
+
+ static void ReleaseCapturingRemoteTarget(dom::BrowserParent* aBrowserParent) {
+ MOZ_ASSERT(XRE_IsParentProcess());
+ if (sCapturingContentInfo.mRemoteTarget == aBrowserParent) {
+ sCapturingContentInfo.mRemoteTarget = nullptr;
+ }
+ }
+
+ // Called at the end of nsLayoutUtils::PaintFrame() if we were painting to
+ // the widget.
+ // This is used to clear any pending visual scroll updates that have been
+ // acknowledged, to make sure they don't stick around for the next paint.
+ void EndPaint();
+
+ /**
+ * Tell the presshell that the given frame's reflow was interrupted. This
+ * will mark as having dirty children a path from the given frame (inclusive)
+ * to the nearest ancestor with a dirty subtree, or to the reflow root
+ * currently being reflowed if no such ancestor exists (inclusive). This is
+ * to be done immediately after reflow of the current reflow root completes.
+ * This method must only be called during reflow, and the frame it's being
+ * called on must be in the process of being reflowed when it's called. This
+ * method doesn't mark any intrinsic widths dirty and doesn't add any bits
+ * other than NS_FRAME_HAS_DIRTY_CHILDREN.
+ */
+ void FrameNeedsToContinueReflow(nsIFrame* aFrame);
+
+ /**
+ * Notification sent by a frame informing the pres shell that it is about to
+ * be destroyed.
+ * This allows any outstanding references to the frame to be cleaned up
+ */
+ void NotifyDestroyingFrame(nsIFrame* aFrame);
+
+ bool GetZoomableByAPZ() const;
+
+ bool ReflowForHiddenContentIfNeeded();
+ void UpdateHiddenContentInForcedLayout(nsIFrame*);
+ /**
+ * If this frame has content hidden via `content-visibilty` that has a pending
+ * reflow, force the content to reflow immediately.
+ */
+ void EnsureReflowIfFrameHasHiddenContent(nsIFrame*);
+
+ /**
+ * Whether or not this presshell is is forcing a reflow of hidden content in
+ * this frame via EnsureReflowIfFrameHasHiddenContent().
+ */
+ bool IsForcingLayoutForHiddenContent(const nsIFrame*) const;
+
+ void RegisterContentVisibilityAutoFrame(nsIFrame* aFrame) {
+ mContentVisibilityAutoFrames.Insert(aFrame);
+ }
+ void UnregisterContentVisibilityAutoFrame(nsIFrame* aFrame) {
+ mContentVisibilityAutoFrames.Remove(aFrame);
+ }
+ bool HasContentVisibilityAutoFrames() const {
+ return !mContentVisibilityAutoFrames.IsEmpty();
+ }
+
+ void UpdateRelevancyOfContentVisibilityAutoFrames();
+ void ScheduleContentRelevancyUpdate(ContentRelevancyReason aReason);
+ void UpdateContentRelevancyImmediately(ContentRelevancyReason aReason);
+
+ // Determination of proximity to the viewport.
+ // Refer to "update the rendering: step 14", see
+ // https://html.spec.whatwg.org/#update-the-rendering
+ struct ProximityToViewportResult {
+ bool mHadInitialDetermination = false;
+ bool mAnyScrollIntoViewFlag = false;
+ };
+ ProximityToViewportResult DetermineProximityToViewport();
+
+ void ClearTemporarilyVisibleForScrolledIntoViewDescendantFlags() const;
+
+ private:
+ ~PresShell();
+
+ void SetIsActive(bool aIsActive);
+ bool ComputeActiveness() const;
+
+ MOZ_CAN_RUN_SCRIPT
+ void PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags);
+
+ /**
+ * Refresh observer management.
+ */
+ void DoObserveStyleFlushes();
+ void DoObserveLayoutFlushes();
+
+ /**
+ * Does the actual work of figuring out the current state of font size
+ * inflation.
+ */
+ bool DetermineFontSizeInflationState();
+
+ void RecordAlloc(void* aPtr) {
+#ifdef DEBUG
+ if (!mAllocatedPointers) {
+ return; // Hash set was presumably freed to avert OOM.
+ }
+ MOZ_ASSERT(!mAllocatedPointers->Contains(aPtr));
+ if (!mAllocatedPointers->Insert(aPtr, fallible)) {
+ // Yikes! We're nearly out of memory, and this insertion would've pushed
+ // us over the ledge. At this point, we discard & stop using this set,
+ // since we don't have enough memory to keep it accurate from this point
+ // onwards. Hopefully this helps relieve the memory pressure a bit, too.
+ mAllocatedPointers = nullptr;
+ }
+#endif
+ }
+
+ void RecordFree(void* aPtr) {
+#ifdef DEBUG
+ if (!mAllocatedPointers) {
+ return; // Hash set was presumably freed to avert OOM.
+ }
+ MOZ_ASSERT(mAllocatedPointers->Contains(aPtr));
+ mAllocatedPointers->Remove(aPtr);
+#endif
+ }
+
+ void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
+ void PopCurrentEventInfo();
+ nsIContent* GetCurrentEventContent();
+
+ friend class ::nsRefreshDriver;
+ friend class ::nsAutoCauseReflowNotifier;
+
+ void WillCauseReflow();
+ MOZ_CAN_RUN_SCRIPT void DidCauseReflow();
+
+ void CancelPostedReflowCallbacks();
+ void FlushPendingScrollAnchorAdjustments();
+
+ void SetPendingVisualScrollUpdate(
+ const nsPoint& aVisualViewportOffset,
+ FrameMetrics::ScrollOffsetUpdateType aUpdateType);
+
+#ifdef MOZ_REFLOW_PERF
+ UniquePtr<ReflowCountMgr> mReflowCountMgr;
+#endif
+
+ void WillDoReflow();
+
+ // This data is stored as a content property (nsGkAtoms::scrolling) on
+ // mContentToScrollTo when we have a pending ScrollIntoView.
+ struct ScrollIntoViewData {
+ ScrollAxis mContentScrollVAxis;
+ ScrollAxis mContentScrollHAxis;
+ ScrollFlags mContentToScrollToFlags;
+ };
+
+ static LazyLogModule gLog;
+
+ DOMHighResTimeStamp GetPerformanceNowUnclamped();
+
+ // The callback for the mReflowContinueTimer timer.
+ static void sReflowContinueCallback(nsITimer* aTimer, void* aPresShell);
+ bool ScheduleReflowOffTimer();
+ // MaybeScheduleReflow checks if posting a reflow is needed, then checks if
+ // the last reflow was interrupted. In the interrupted case ScheduleReflow is
+ // called off a timer, otherwise it is called directly.
+ void MaybeScheduleReflow();
+ // Actually schedules a reflow. This should only be called by
+ // MaybeScheduleReflow and the reflow timer ScheduleReflowOffTimer
+ // sets up.
+ void ScheduleReflow();
+
+ friend class ::AutoPointerEventTargetUpdater;
+
+ // ProcessReflowCommands returns whether we processed all our dirty roots
+ // without interruptions.
+ MOZ_CAN_RUN_SCRIPT bool ProcessReflowCommands(bool aInterruptible);
+
+ /**
+ * Callback handler for whether reflow happened.
+ *
+ * @param aInterruptible Whether or not reflow interruption is allowed.
+ */
+ MOZ_CAN_RUN_SCRIPT void DidDoReflow(bool aInterruptible);
+
+ MOZ_CAN_RUN_SCRIPT void HandlePostedReflowCallbacks(bool aInterruptible);
+
+ /**
+ * Helper for ScrollContentIntoView()
+ */
+ MOZ_CAN_RUN_SCRIPT void DoScrollContentIntoView();
+
+ /**
+ * Methods to handle changes to user and UA sheet lists that we get
+ * notified about.
+ */
+ void AddUserSheet(StyleSheet*);
+ void AddAgentSheet(StyleSheet*);
+ void AddAuthorSheet(StyleSheet*);
+
+ /**
+ * Initialize cached font inflation preference values and do an initial
+ * computation to determine if font inflation is enabled.
+ *
+ * @see nsLayoutUtils::sFontSizeInflationEmPerLine
+ * @see nsLayoutUtils::sFontSizeInflationMinTwips
+ * @see nsLayoutUtils::sFontSizeInflationLineThreshold
+ */
+ void SetupFontInflation();
+
+ /**
+ * Implementation methods for FlushPendingNotifications.
+ */
+ MOZ_CAN_RUN_SCRIPT void DoFlushPendingNotifications(FlushType aType);
+ MOZ_CAN_RUN_SCRIPT void DoFlushPendingNotifications(ChangesToFlush aType);
+
+ struct RenderingState {
+ explicit RenderingState(PresShell* aPresShell)
+ : mResolution(aPresShell->mResolution),
+ mRenderingStateFlags(aPresShell->mRenderingStateFlags) {}
+ Maybe<float> mResolution;
+ RenderingStateFlags mRenderingStateFlags;
+ };
+
+ struct AutoSaveRestoreRenderingState {
+ explicit AutoSaveRestoreRenderingState(PresShell* aPresShell)
+ : mPresShell(aPresShell), mOldState(aPresShell) {}
+
+ ~AutoSaveRestoreRenderingState() {
+ mPresShell->mRenderingStateFlags = mOldState.mRenderingStateFlags;
+ mPresShell->mResolution = mOldState.mResolution;
+#ifdef ACCESSIBILITY
+ if (nsAccessibilityService* accService = GetAccService()) {
+ accService->NotifyOfResolutionChange(mPresShell,
+ mPresShell->GetResolution());
+ }
+#endif
+ }
+
+ PresShell* mPresShell;
+ RenderingState mOldState;
+ };
+ void SetRenderingState(const RenderingState& aState);
+
+ friend class ::nsPresShellEventCB;
+
+ // methods for painting a range to an offscreen buffer
+
+ // given a display list, clip the items within the list to
+ // the range
+ nsRect ClipListToRange(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
+ nsRange* aRange);
+
+ // create a RangePaintInfo for the range aRange containing the
+ // display list needed to paint the range to a surface
+ UniquePtr<RangePaintInfo> CreateRangePaintInfo(nsRange* aRange,
+ nsRect& aSurfaceRect,
+ bool aForPrimarySelection);
+
+ /*
+ * Paint the items to a new surface and return it.
+ *
+ * aSelection - selection being painted, if any
+ * aRegion - clip region, if any
+ * aArea - area that the surface occupies, relative to the root frame
+ * aPoint - reference point, typically the mouse position
+ * aScreenRect - [out] set to the area of the screen the painted area should
+ * be displayed at
+ * aFlags - set RenderImageFlags::AutoScale to scale down large images, but
+ * it must not be set if a custom image was specified
+ */
+ already_AddRefed<SourceSurface> PaintRangePaintInfo(
+ const nsTArray<UniquePtr<RangePaintInfo>>& aItems,
+ dom::Selection* aSelection, const Maybe<CSSIntRegion>& aRegion,
+ nsRect aArea, const LayoutDeviceIntPoint aPoint,
+ LayoutDeviceIntRect* aScreenRect, RenderImageFlags aFlags);
+
+ // Hide a view if it is a popup
+ void HideViewIfPopup(nsView* aView);
+
+ // Utility method to restore the root scrollframe state
+ void RestoreRootScrollPosition();
+
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void MaybeReleaseCapturingContent();
+
+ class DelayedEvent {
+ public:
+ virtual ~DelayedEvent() = default;
+ virtual void Dispatch() {}
+ virtual bool IsKeyPressEvent() { return false; }
+ };
+
+ class DelayedInputEvent : public DelayedEvent {
+ public:
+ void Dispatch() override;
+
+ protected:
+ DelayedInputEvent();
+ ~DelayedInputEvent() override;
+
+ WidgetInputEvent* mEvent;
+ };
+
+ class DelayedMouseEvent : public DelayedInputEvent {
+ public:
+ explicit DelayedMouseEvent(WidgetMouseEvent* aEvent);
+ };
+
+ class DelayedKeyEvent : public DelayedInputEvent {
+ public:
+ explicit DelayedKeyEvent(WidgetKeyboardEvent* aEvent);
+ bool IsKeyPressEvent() override;
+ };
+
+ /**
+ * return the nsPoint represents the location of the mouse event relative to
+ * the root document in visual coordinates
+ */
+ nsPoint GetEventLocation(const WidgetMouseEvent& aEvent) const;
+
+ // Check if aEvent is a mouse event and record the mouse location for later
+ // synth mouse moves.
+ void RecordPointerLocation(WidgetGUIEvent* aEvent);
+ inline bool MouseLocationWasSetBySynthesizedMouseEventForTests() const;
+ class nsSynthMouseMoveEvent final : public nsARefreshObserver {
+ public:
+ nsSynthMouseMoveEvent(PresShell* aPresShell, bool aFromScroll)
+ : mPresShell(aPresShell), mFromScroll(aFromScroll) {
+ NS_ASSERTION(mPresShell, "null parameter");
+ }
+
+ private:
+ // Private destructor, to discourage deletion outside of Release():
+ ~nsSynthMouseMoveEvent() { Revoke(); }
+
+ public:
+ NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent, override)
+
+ void Revoke();
+
+ MOZ_CAN_RUN_SCRIPT
+ void WillRefresh(TimeStamp aTime) override { Run(); }
+
+ MOZ_CAN_RUN_SCRIPT void Run() {
+ if (mPresShell) {
+ RefPtr<PresShell> shell = mPresShell;
+ shell->ProcessSynthMouseMoveEvent(mFromScroll);
+ }
+ }
+
+ private:
+ PresShell* mPresShell;
+ bool mFromScroll;
+ };
+ MOZ_CAN_RUN_SCRIPT void ProcessSynthMouseMoveEvent(bool aFromScroll);
+
+ void UpdateImageLockingState();
+
+ already_AddRefed<PresShell> GetParentPresShellForEventHandling();
+
+ /**
+ * EventHandler is implementation of PresShell::HandleEvent().
+ */
+ class MOZ_STACK_CLASS EventHandler final {
+ public:
+ EventHandler() = delete;
+ EventHandler(const EventHandler& aOther) = delete;
+ explicit EventHandler(PresShell& aPresShell)
+ : mPresShell(aPresShell), mCurrentEventInfoSetter(nullptr) {}
+ explicit EventHandler(RefPtr<PresShell>&& aPresShell)
+ : mPresShell(std::move(aPresShell)), mCurrentEventInfoSetter(nullptr) {}
+
+ /**
+ * HandleEvent() may dispatch aGUIEvent. This may redirect the event to
+ * another PresShell, or the event may be handled by other classes like
+ * AccessibleCaretEventHub, or discarded. Otherwise, this sets current
+ * event info of mPresShell and calls HandleEventWithCurrentEventInfo()
+ * to dispatch the event into the DOM tree.
+ *
+ * @param aFrameForPresShell The frame for PresShell. If PresShell
+ * has root frame, it should be set.
+ * Otherwise, a frame which contains the
+ * PresShell should be set instead. I.e.,
+ * in the latter case, the frame is in
+ * a parent document.
+ * @param aGUIEvent Event to be handled. Must be a trusted
+ * event.
+ * @param aDontRetargetEvents true if this shouldn't redirect the
+ * event to different PresShell.
+ * false if this can redirect the event to
+ * different PresShell.
+ * @param aEventStatus [in/out] EventStatus of aGUIEvent.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEvent(nsIFrame* aFrameForPresShell,
+ WidgetGUIEvent* aGUIEvent, bool aDontRetargetEvents,
+ nsEventStatus* aEventStatus);
+
+ /**
+ * HandleEventWithTarget() tries to dispatch aEvent on aContent after
+ * setting current event target content to aNewEventContent and current
+ * event frame to aNewEventFrame temporarily. Note that this supports
+ * WidgetEvent, not WidgetGUIEvent. So, you can dispatch a simple event
+ * with this.
+ *
+ * @param aEvent Event to be dispatched. Must be a
+ * trusted event.
+ * @param aNewEventFrame Temporal new event frame.
+ * @param aNewEventContent Temporal new event content.
+ * @param aEventStatus [in/out] EventStuatus of aEvent.
+ * @param aIsHandlingNativeEvent true if aEvent represents a native
+ * event.
+ * @param aTargetContent This is used only when aEvent is a
+ * pointer event. If
+ * PresShell::mPointerEventTarget is
+ * changed during dispatching aEvent,
+ * this is set to the new target.
+ * @param aOverrideClickTarget Override click event target.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEventWithTarget(WidgetEvent* aEvent,
+ nsIFrame* aNewEventFrame,
+ nsIContent* aNewEventContent,
+ nsEventStatus* aEventStatus,
+ bool aIsHandlingNativeEvent,
+ nsIContent** aTargetContent,
+ nsIContent* aOverrideClickTarget);
+
+ /**
+ * OnPresShellDestroy() is called when every PresShell instance is being
+ * destroyed.
+ */
+ static inline void OnPresShellDestroy(Document* aDocument);
+
+ private:
+ static bool InZombieDocument(nsIContent* aContent);
+ static nsIFrame* GetNearestFrameContainingPresShell(PresShell* aPresShell);
+ static nsIPrincipal* GetDocumentPrincipalToCompareWithBlacklist(
+ PresShell& aPresShell);
+
+ /**
+ * HandleEventUsingCoordinates() handles aGUIEvent whose
+ * IsUsingCoordinates() returns true with the following helper methods.
+ *
+ * @param aFrameForPresShell The frame for PresShell. See
+ * explanation of HandleEvent() for the
+ * details.
+ * @param aGUIEvent The handling event. Make sure that
+ * its IsUsingCoordinates() returns true.
+ * @param aEventStatus The status of aGUIEvent.
+ * @param aDontRetargetEvents true if we've already retarget document.
+ * Otherwise, false.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEventUsingCoordinates(nsIFrame* aFrameForPresShell,
+ WidgetGUIEvent* aGUIEvent,
+ nsEventStatus* aEventStatus,
+ bool aDontRetargetEvents);
+
+ /**
+ * EventTargetData struct stores a set of a PresShell (event handler),
+ * a frame (to handle the event) and a content (event target for the frame).
+ */
+ struct MOZ_STACK_CLASS EventTargetData final {
+ EventTargetData() = delete;
+ EventTargetData(const EventTargetData& aOther) = delete;
+ explicit EventTargetData(nsIFrame* aFrameToHandleEvent) {
+ SetFrameAndComputePresShell(aFrameToHandleEvent);
+ }
+
+ void SetFrameAndComputePresShell(nsIFrame* aFrameToHandleEvent);
+ void SetFrameAndComputePresShellAndContent(nsIFrame* aFrameToHandleEvent,
+ WidgetGUIEvent* aGUIEvent);
+ void SetContentForEventFromFrame(WidgetGUIEvent* aGUIEvent);
+
+ nsPresContext* GetPresContext() const {
+ return mPresShell ? mPresShell->GetPresContext() : nullptr;
+ };
+ EventStateManager* GetEventStateManager() const {
+ nsPresContext* presContext = GetPresContext();
+ return presContext ? presContext->EventStateManager() : nullptr;
+ }
+ Document* GetDocument() const {
+ return mPresShell ? mPresShell->GetDocument() : nullptr;
+ }
+
+ /**
+ * Return content of the frame if and only if a frame is set.
+ * I.e., this may return non-element node even when GetContent() returns
+ * an element node.
+ */
+ nsIContent* GetFrameContent() const;
+
+ nsIFrame* GetFrame() const { return mFrame; }
+ nsIContent* GetContent() const { return mContent; }
+
+ /**
+ * Set the event target content and the topmost frame at the event point.
+ * This checks whether the relation is correct if aContent is not nullptr.
+ * If you set aGUIEvent, the check is done with strict way, but otherwise,
+ * it checks whether aContent is a proper inclusive ancestor of
+ * mFrame->GetContent() or not.
+ */
+ void SetFrameAndContent(nsIFrame* aFrame, nsIContent* aContent = nullptr,
+ const WidgetGUIEvent* aGUIEvent = nullptr) {
+ mFrame = aFrame;
+ mContent = aContent ? aContent : GetFrameContent();
+ AssertIfEventTargetContentAndFrameContentMismatch(aGUIEvent);
+ }
+
+ /**
+ * Set the event target content and clear the frame.
+ */
+ void SetContent(nsIContent* aContent) {
+ mContent = aContent;
+ if (mFrame && GetFrameContent() != aContent) {
+ mFrame = nullptr;
+ }
+ }
+
+ /**
+ * MaybeRetargetToActiveDocument() tries retarget aGUIEvent into
+ * active document if there is. Note that this does not support to
+ * retarget mContent. Make sure it is nullptr before calling this.
+ *
+ * @param aGUIEvent The handling event.
+ * @return true if retargetted.
+ */
+ bool MaybeRetargetToActiveDocument(WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * ComputeElementFromFrame() computes mContent for aGUIEvent. If
+ * mContent is set by this method, mContent is always nullptr or an
+ * Element.
+ *
+ * @param aGUIEvent The handling event.
+ * @return true if caller can keep handling the event.
+ * Otherwise, false.
+ * Note that even if this returns true, mContent
+ * may be nullptr.
+ */
+ bool ComputeElementFromFrame(WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * UpdateTouchEventTarget() updates mFrame, mPresShell and mContent if
+ * aGUIEvent is a touch event and there is new proper target.
+ *
+ * @param aGUIEvent The handled event. If it's not a touch event,
+ * this method does nothing.
+ */
+ void UpdateTouchEventTarget(WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * UpdateWheelEventTarget() updates mFrame, mPresShell, and mContent if
+ * aGUIEvent is a wheel event and aGUIEvent should be grouped with prior
+ * wheel events.
+ *
+ * @param aGUIEvent The handled event. If it's not a wheel event,
+ * this method does nothing.
+ */
+ void UpdateWheelEventTarget(WidgetGUIEvent* aGUIEvent);
+
+ private:
+ void AssertIfEventTargetContentAndFrameContentMismatch(
+ const WidgetGUIEvent* aGUIEvent = nullptr) const;
+
+ public:
+ RefPtr<PresShell> mPresShell;
+ nsCOMPtr<nsIContent> mOverrideClickTarget;
+
+ private:
+ nsIFrame* mFrame = nullptr;
+ // mContent is the event target content for mFrame->GetContent().
+ // This may be nullptr even if mFrame is not nullptr.
+ // This may be an ancestor element of mFrame->GetContent() or native
+ // anonymous root content parent.
+ // This may be not an ancestor element of mFrame->GetContent() if
+ // mFrame->GetContentForEvent() returns such element. E.g., clicking in
+ // <area>, mContent is the <area> but mFrame->GetContent() is an <img>.
+ nsCOMPtr<nsIContent> mContent;
+ };
+
+ /**
+ * MaybeFlushPendingNotifications() maybe flush pending notifications if
+ * aGUIEvent should be handled with the latest layout.
+ *
+ * @param aGUIEvent The handling event.
+ * @return true if this actually flushes pending
+ * layout and that has caused changing the
+ * layout.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool MaybeFlushPendingNotifications(WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * GetFrameToHandleNonTouchEvent() returns a frame to handle the event.
+ * This may flush pending layout if the target is in child PresShell.
+ *
+ * @param aRootFrameToHandleEvent The root frame to handle the event.
+ * @param aGUIEvent The handling event.
+ * @return The frame which should handle the
+ * event. nullptr if the caller should
+ * stop handling the event.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsIFrame* GetFrameToHandleNonTouchEvent(nsIFrame* aRootFrameToHandleEvent,
+ WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * ComputeEventTargetFrameAndPresShellAtEventPoint() computes event
+ * target frame at the event point of aGUIEvent and set it to
+ * aEventTargetData.
+ *
+ * @param aRootFrameToHandleEvent The root frame to handle aGUIEvent.
+ * @param aGUIEvent The handling event.
+ * @param aEventTargetData [out] Its frame and PresShell will
+ * be set.
+ * @return true if the caller can handle the
+ * event. Otherwise, false.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool ComputeEventTargetFrameAndPresShellAtEventPoint(
+ nsIFrame* aRootFrameToHandleEvent, WidgetGUIEvent* aGUIEvent,
+ EventTargetData* aEventTargetData);
+
+ /**
+ * DispatchPrecedingPointerEvent() dispatches preceding pointer event for
+ * aGUIEvent if Pointer Events is enabled.
+ *
+ * @param aFrameForPresShell The frame for PresShell. See
+ * explanation of HandleEvent() for the
+ * details.
+ * @param aGUIEvent The handled event.
+ * @param aPointerCapturingContent The content which is capturing pointer
+ * events if there is. Otherwise, nullptr.
+ * @param aDontRetargetEvents Set aDontRetargetEvents of
+ * HandleEvent() which called this method.
+ * @param aEventTargetData [in/out] Event target data of
+ * aGUIEvent. If pointer event listeners
+ * change the DOM tree or reframe the
+ * target, updated by this method.
+ * @param aEventStatus [in/out] The event status of aGUIEvent.
+ * @return true if the caller can handle the
+ * event. Otherwise, false.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool DispatchPrecedingPointerEvent(nsIFrame* aFrameForPresShell,
+ WidgetGUIEvent* aGUIEvent,
+ nsIContent* aPointerCapturingContent,
+ bool aDontRetargetEvents,
+ EventTargetData* aEventTargetData,
+ nsEventStatus* aEventStatus);
+
+ /**
+ * MaybeDiscardEvent() checks whether it's safe to handle aGUIEvent right
+ * now. If it's not safe, this may notify somebody of discarding event if
+ * necessary.
+ *
+ * @param aGUIEvent Handling event.
+ * @return true if it's not safe to handle the event.
+ */
+ bool MaybeDiscardEvent(WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * GetCapturingContentFor() returns capturing content for aGUIEvent.
+ * If aGUIEvent is not related to capturing, this returns nullptr.
+ */
+ static nsIContent* GetCapturingContentFor(WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * GetRetargetEventDocument() returns a document if aGUIEvent should be
+ * handled in another document.
+ *
+ * @param aGUIEvent Handling event.
+ * @param aRetargetEventDocument Document which should handle aGUIEvent.
+ * @return true if caller can keep handling
+ * aGUIEvent.
+ */
+ bool GetRetargetEventDocument(WidgetGUIEvent* aGUIEvent,
+ Document** aRetargetEventDocument);
+
+ /**
+ * GetFrameForHandlingEventWith() returns a frame which should be used as
+ * aFrameForPresShell of HandleEvent(). See @return for the details.
+ *
+ * @param aGUIEvent Handling event.
+ * @param aRetargetDocument Document which aGUIEvent should be
+ * fired on. Typically, should be result
+ * of GetRetargetEventDocument().
+ * @param aFrameForPresShell The frame for PresShell. See
+ * explanation of HandleEvent() for the
+ * details.
+ * @return nullptr if caller should stop handling
+ * the event.
+ * aFrameForPresShell if caller should
+ * keep handling the event by itself.
+ * Otherwise, caller should handle it with
+ * another PresShell which is result of
+ * nsIFrame::PresContext()->GetPresShell().
+ */
+ nsIFrame* GetFrameForHandlingEventWith(WidgetGUIEvent* aGUIEvent,
+ Document* aRetargetDocument,
+ nsIFrame* aFrameForPresShell);
+
+ /**
+ * MaybeHandleEventWithAnotherPresShell() may handle aGUIEvent with another
+ * PresShell.
+ *
+ * @param aFrameForPresShell The frame for PresShell. See
+ * explanation of HandleEvent() for the
+ * details.
+ * @param aGUIEvent Handling event.
+ * @param aEventStatus [in/out] EventStatus of aGUIEvent.
+ * @param aRv [out] Returns error if this gets an
+ * error handling the event.
+ * @return false if caller needs to keep handling
+ * the event by itself.
+ * true if caller shouldn't keep handling
+ * the event. Note that when no PresShell
+ * can handle the event, this returns true.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool MaybeHandleEventWithAnotherPresShell(nsIFrame* aFrameForPresShell,
+ WidgetGUIEvent* aGUIEvent,
+ nsEventStatus* aEventStatus,
+ nsresult* aRv);
+
+ MOZ_CAN_RUN_SCRIPT
+ nsresult RetargetEventToParent(WidgetGUIEvent* aGUIEvent,
+ nsEventStatus* aEventStatus);
+
+ /**
+ * MaybeHandleEventWithAccessibleCaret() may handle aGUIEvent with
+ * AccessibleCaretEventHub if it's necessary.
+ *
+ * @param aFrameForPresShell The frame for PresShell. See explanation of
+ * HandleEvent() for the details.
+ * @param aGUIEvent Event may be handled by AccessibleCaretEventHub.
+ * @param aEventStatus [in/out] EventStatus of aGUIEvent.
+ * @return true if AccessibleCaretEventHub handled the
+ * event and caller shouldn't keep handling it.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool MaybeHandleEventWithAccessibleCaret(nsIFrame* aFrameForPresShell,
+ WidgetGUIEvent* aGUIEvent,
+ nsEventStatus* aEventStatus);
+
+ /**
+ * MaybeDiscardOrDelayKeyboardEvent() may discared or put aGUIEvent into
+ * the delayed event queue if it's a keyboard event and if we should do so.
+ * If aGUIEvent is not a keyboard event, this does nothing.
+ *
+ * @param aGUIEvent The handling event.
+ * @return true if this method discard the event or
+ * put it into the delayed event queue.
+ */
+ bool MaybeDiscardOrDelayKeyboardEvent(WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * MaybeDiscardOrDelayMouseEvent() may discard or put aGUIEvent into the
+ * delayed event queue if it's a mouse event and if we should do so.
+ * If aGUIEvent is not a mouse event, this does nothing.
+ * If there is suppressed event listener like debugger of devtools, this
+ * notifies it of the event after discard or put it into the delayed
+ * event queue.
+ *
+ * @param aFrameToHandleEvent The frame to handle aGUIEvent.
+ * @param aGUIEvent The handling event.
+ * @return true if this method discard the event
+ * or put it into the delayed event queue.
+ */
+ bool MaybeDiscardOrDelayMouseEvent(nsIFrame* aFrameToHandleEvent,
+ WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * MaybeFlushThrottledStyles() tries to flush pending animation. If it's
+ * flushed and then aFrameForPresShell is destroyed, returns new frame
+ * which contains mPresShell.
+ *
+ * @param aFrameForPresShell The frame for PresShell. See
+ * explanation of HandleEvent() for the
+ * details. This can be nullptr.
+ * @return Maybe new frame for mPresShell.
+ * If aFrameForPresShell is not nullptr
+ * and hasn't been destroyed, returns
+ * aFrameForPresShell as-is.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsIFrame* MaybeFlushThrottledStyles(nsIFrame* aFrameForPresShell);
+
+ /**
+ * ComputeRootFrameToHandleEvent() returns root frame to handle the event.
+ * For example, if there is a popup, this returns the popup frame.
+ * If there is capturing content and it's in a scrolled frame, returns
+ * the scrolled frame.
+ *
+ * @param aFrameForPresShell The frame for PresShell. See
+ * explanation of HandleEvent() for
+ * the details.
+ * @param aGUIEvent The handling event.
+ * @param aCapturingContent Capturing content if there is.
+ * nullptr, otherwise.
+ * @param aIsCapturingContentIgnored [out] true if aCapturingContent
+ * is not nullptr but it should be
+ * ignored to handle the event.
+ * @param aIsCaptureRetargeted [out] true if aCapturingContent
+ * is not nullptr but it's
+ * retargeted.
+ * @return Root frame to handle the event.
+ */
+ nsIFrame* ComputeRootFrameToHandleEvent(nsIFrame* aFrameForPresShell,
+ WidgetGUIEvent* aGUIEvent,
+ nsIContent* aCapturingContent,
+ bool* aIsCapturingContentIgnored,
+ bool* aIsCaptureRetargeted);
+
+ /**
+ * ComputeRootFrameToHandleEventWithPopup() returns popup frame if there
+ * is a popup and we should handle the event in it. Otherwise, returns
+ * aRootFrameToHandleEvent.
+ *
+ * @param aRootFrameToHandleEvent Candidate root frame to handle
+ * the event.
+ * @param aGUIEvent The handling event.
+ * @param aCapturingContent Capturing content if there is.
+ * nullptr, otherwise.
+ * @param aIsCapturingContentIgnored [out] true if aCapturingContent
+ * is not nullptr but it should be
+ * ignored to handle the event.
+ * @return A popup frame if there is a
+ * popup and we should handle the
+ * event in it. Otherwise,
+ * aRootFrameToHandleEvent.
+ * I.e., never returns nullptr.
+ */
+ nsIFrame* ComputeRootFrameToHandleEventWithPopup(
+ nsIFrame* aRootFrameToHandleEvent, WidgetGUIEvent* aGUIEvent,
+ nsIContent* aCapturingContent, bool* aIsCapturingContentIgnored);
+
+ /**
+ * ComputeRootFrameToHandleEventWithCapturingContent() returns root frame
+ * to handle event for the capturing content, or aRootFrameToHandleEvent
+ * if it should be ignored.
+ *
+ * @param aRootFrameToHandleEvent Candidate root frame to handle
+ * the event.
+ * @param aCapturingContent Capturing content. nullptr is
+ * not allowed.
+ * @param aIsCapturingContentIgnored [out] true if aCapturingContent
+ * is not nullptr but it should be
+ * ignored to handle the event.
+ * @param aIsCaptureRetargeted [out] true if aCapturingContent
+ * is not nullptr but it's
+ * retargeted.
+ * @return A popup frame if there is a
+ * popup and we should handle the
+ * event in it. Otherwise,
+ * aRootFrameToHandleEvent.
+ * I.e., never returns nullptr.
+ */
+ nsIFrame* ComputeRootFrameToHandleEventWithCapturingContent(
+ nsIFrame* aRootFrameToHandleEvent, nsIContent* aCapturingContent,
+ bool* aIsCapturingContentIgnored, bool* aIsCaptureRetargeted);
+
+ /**
+ * HandleEventWithPointerCapturingContentWithoutItsFrame() handles
+ * aGUIEvent with aPointerCapturingContent when it does not have primary
+ * frame.
+ *
+ * @param aFrameForPresShell The frame for PresShell. See
+ * explanation of HandleEvent() for the
+ * details.
+ * @param aGUIEvent The handling event.
+ * @param aPointerCapturingContent Current pointer capturing content.
+ * Must not be nullptr.
+ * @param aEventStatus [in/out] The event status of aGUIEvent.
+ * @return Basically, result of
+ * HandeEventWithTraget().
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEventWithPointerCapturingContentWithoutItsFrame(
+ nsIFrame* aFrameForPresShell, WidgetGUIEvent* aGUIEvent,
+ nsIContent* aPointerCapturingContent, nsEventStatus* aEventStatus);
+
+ /**
+ * HandleEventAtFocusedContent() handles aGUIEvent at focused content.
+ *
+ * @param aGUIEvent The handling event which should be handled at
+ * focused content.
+ * @param aEventStatus [in/out] The event status of aGUIEvent.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEventAtFocusedContent(WidgetGUIEvent* aGUIEvent,
+ nsEventStatus* aEventStatus);
+
+ /**
+ * ComputeFocusedEventTargetElement() returns event target element for
+ * aGUIEvent which should be handled with focused content.
+ * This may set/unset sLastKeyDownEventTarget if necessary.
+ *
+ * @param aGUIEvent The handling event.
+ * @return The element which should be the event
+ * target of aGUIEvent.
+ */
+ dom::Element* ComputeFocusedEventTargetElement(WidgetGUIEvent* aGUIEvent);
+
+ /**
+ * MaybeHandleEventWithAnotherPresShell() may handle aGUIEvent with another
+ * PresShell.
+ *
+ * @param aEventTargetElement The event target element of aGUIEvent.
+ * @param aGUIEvent Handling event.
+ * @param aEventStatus [in/out] EventStatus of aGUIEvent.
+ * @param aRv [out] Returns error if this gets an
+ * error handling the event.
+ * @return false if caller needs to keep handling
+ * the event by itself.
+ * true if caller shouldn't keep handling
+ * the event. Note that when no PresShell
+ * can handle the event, this returns true.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool MaybeHandleEventWithAnotherPresShell(dom::Element* aEventTargetElement,
+ WidgetGUIEvent* aGUIEvent,
+ nsEventStatus* aEventStatus,
+ nsresult* aRv);
+
+ /**
+ * HandleRetargetedEvent() dispatches aGUIEvent on the PresShell without
+ * retargetting. This should be used only when caller computes final
+ * target of aGUIEvent.
+ *
+ * @param aGUIEvent Event to be dispatched.
+ * @param aEventStatus [in/out] EventStatus of aGUIEvent.
+ * @param aTarget The final target of aGUIEvent.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleRetargetedEvent(WidgetGUIEvent* aGUIEvent,
+ nsEventStatus* aEventStatus,
+ nsIContent* aTarget) {
+ AutoCurrentEventInfoSetter eventInfoSetter(*this, nullptr, aTarget);
+ if (!mPresShell->GetCurrentEventFrame()) {
+ return NS_OK;
+ }
+ nsCOMPtr<nsIContent> overrideClickTarget;
+ return HandleEventWithCurrentEventInfo(aGUIEvent, aEventStatus, true,
+ overrideClickTarget);
+ }
+
+ /**
+ * HandleEventWithFrameForPresShell() handles aGUIEvent with the frame
+ * for mPresShell.
+ *
+ * @param aFrameForPresShell The frame for mPresShell.
+ * @param aGUIEvent The handling event. It shouldn't be
+ * handled with using coordinates nor
+ * handled at focused content.
+ * @param aEventStatus [in/out] The status of aGUIEvent.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEventWithFrameForPresShell(nsIFrame* aFrameForPresShell,
+ WidgetGUIEvent* aGUIEvent,
+ nsEventStatus* aEventStatus);
+
+ /**
+ * HandleEventWithCurrentEventInfo() prepares to dispatch aEvent into the
+ * DOM, dispatches aEvent into the DOM with using current event info of
+ * mPresShell and notifies EventStateManager of that.
+ *
+ * @param aEvent Event to be dispatched.
+ * @param aEventStatus [in/out] EventStatus of aEvent.
+ * @param aIsHandlingNativeEvent true if aGUIEvent represents a native
+ * event.
+ * @param aOverrideClickTarget Override click event target.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ nsresult HandleEventWithCurrentEventInfo(WidgetEvent* aEvent,
+ nsEventStatus* aEventStatus,
+ bool aIsHandlingNativeEvent,
+ nsIContent* aOverrideClickTarget);
+
+ /**
+ * HandlingTimeAccumulator() may accumulate handling time of telemetry
+ * for each type of events.
+ */
+ class MOZ_STACK_CLASS HandlingTimeAccumulator final {
+ public:
+ HandlingTimeAccumulator() = delete;
+ HandlingTimeAccumulator(const HandlingTimeAccumulator& aOther) = delete;
+ HandlingTimeAccumulator(const EventHandler& aEventHandler,
+ const WidgetEvent* aEvent);
+ ~HandlingTimeAccumulator();
+
+ private:
+ const EventHandler& mEventHandler;
+ const WidgetEvent* mEvent;
+ TimeStamp mHandlingStartTime;
+ };
+
+ /**
+ * RecordEventPreparationPerformance() records event preparation performance
+ * with telemetry only when aEvent is a trusted event.
+ *
+ * @param aEvent The handling event which we've finished
+ * preparing something to dispatch.
+ */
+ void RecordEventPreparationPerformance(const WidgetEvent* aEvent);
+
+ /**
+ * RecordEventHandlingResponsePerformance() records event handling response
+ * performance with telemetry.
+ *
+ * @param aEvent The handled event.
+ */
+ void RecordEventHandlingResponsePerformance(const WidgetEvent* aEvent);
+
+ /**
+ * PrepareToDispatchEvent() prepares to dispatch aEvent.
+ *
+ * @param aEvent The handling event.
+ * @param aEventStatus [in/out] The status of aEvent.
+ * @param aTouchIsNew [out] Set to true if the event is an
+ * eTouchMove event and it represents new
+ * touch. Otherwise, set to false.
+ * @return true if the caller can dispatch the
+ * event into the DOM.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool PrepareToDispatchEvent(WidgetEvent* aEvent,
+ nsEventStatus* aEventStatus, bool* aTouchIsNew);
+
+ /**
+ * MaybeHandleKeyboardEventBeforeDispatch() may handle aKeyboardEvent
+ * if it should do something before dispatched into the DOM.
+ *
+ * @param aKeyboardEvent The handling keyboard event.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ void MaybeHandleKeyboardEventBeforeDispatch(
+ WidgetKeyboardEvent* aKeyboardEvent);
+
+ /**
+ * This and the next two helper methods are used to target and position the
+ * context menu when the keyboard shortcut is used to open it.
+ *
+ * If another menu is open, the context menu is opened relative to the
+ * active menuitem within the menu, or the menu itself if no item is active.
+ * Otherwise, if the caret is visible, the menu is opened near the caret.
+ * Otherwise, if a selectable list such as a listbox is focused, the
+ * current item within the menu is opened relative to this item.
+ * Otherwise, the context menu is opened at the topleft corner of the
+ * view.
+ *
+ * Returns true if the context menu event should fire and false if it should
+ * not.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ bool AdjustContextMenuKeyEvent(WidgetMouseEvent* aMouseEvent);
+
+ MOZ_CAN_RUN_SCRIPT
+ bool PrepareToUseCaretPosition(nsIWidget* aEventWidget,
+ LayoutDeviceIntPoint& aTargetPt);
+
+ /**
+ * Get the selected item and coordinates in device pixels relative to root
+ * document's root view for element, first ensuring the element is onscreen.
+ */
+ MOZ_CAN_RUN_SCRIPT
+ void GetCurrentItemAndPositionForElement(dom::Element* aFocusedElement,
+ nsIContent** aTargetToUse,
+ LayoutDeviceIntPoint& aTargetPt,
+ nsIWidget* aRootWidget);
+
+ nsIContent* GetOverrideClickTarget(WidgetGUIEvent* aGUIEvent,
+ nsIFrame* aFrame);
+
+ /**
+ * DispatchEvent() tries to dispatch aEvent and notifies aEventStateManager
+ * of doing it.
+ *
+ * @param aEventStateManager EventStateManager which should handle
+ * the event before/after dispatching
+ * aEvent into the DOM.
+ * @param aEvent The handling event.
+ * @param aTouchIsNew Set this to true when the message is
+ * eTouchMove and it's newly touched.
+ * Then, the "touchmove" event becomes
+ * cancelable.
+ * @param aEventStatus [in/out] The status of aEvent.
+ * @param aOverrideClickTarget Override click event target.
+ */
+ MOZ_CAN_RUN_SCRIPT nsresult
+ DispatchEvent(EventStateManager* aEventStateManager, WidgetEvent* aEvent,
+ bool aTouchIsNew, nsEventStatus* aEventStatus,
+ nsIContent* aOverrideClickTarget);
+
+ /**
+ * DispatchEventToDOM() actually dispatches aEvent into the DOM tree.
+ *
+ * @param aEvent Event to be dispatched into the DOM tree.
+ * @param aEventStatus [in/out] EventStatus of aEvent.
+ * @param aEventCB The callback kicked when the event moves
+ * from the default group to the system group.
+ */
+ MOZ_CAN_RUN_SCRIPT nsresult
+ DispatchEventToDOM(WidgetEvent* aEvent, nsEventStatus* aEventStatus,
+ nsPresShellEventCB* aEventCB);
+
+ /**
+ * DispatchTouchEventToDOM() dispatches touch events into the DOM tree.
+ *
+ * @param aEvent The source of events to be dispatched into the
+ * DOM tree.
+ * @param aEventStatus [in/out] EventStatus of aEvent.
+ * @param aEventCB The callback kicked when the events move
+ * from the default group to the system group.
+ * @param aTouchIsNew Set this to true when the message is eTouchMove
+ * and it's newly touched. Then, the "touchmove"
+ * event becomes cancelable.
+ */
+ MOZ_CAN_RUN_SCRIPT void DispatchTouchEventToDOM(
+ WidgetEvent* aEvent, nsEventStatus* aEventStatus,
+ nsPresShellEventCB* aEventCB, bool aTouchIsNew);
+
+ /**
+ * FinalizeHandlingEvent() should be called after calling DispatchEvent()
+ * and then, this cleans up the state of mPresShell and aEvent.
+ *
+ * @param aEvent The handled event.
+ */
+ MOZ_CAN_RUN_SCRIPT void FinalizeHandlingEvent(WidgetEvent* aEvent);
+
+ /**
+ * AutoCurrentEventInfoSetter() pushes and pops current event info of
+ * aEventHandler.mPresShell.
+ */
+ struct MOZ_STACK_CLASS AutoCurrentEventInfoSetter final {
+ explicit AutoCurrentEventInfoSetter(EventHandler& aEventHandler)
+ : mEventHandler(aEventHandler) {
+ MOZ_DIAGNOSTIC_ASSERT(!mEventHandler.mCurrentEventInfoSetter);
+ mEventHandler.mCurrentEventInfoSetter = this;
+ mEventHandler.mPresShell->PushCurrentEventInfo(nullptr, nullptr);
+ }
+ AutoCurrentEventInfoSetter(EventHandler& aEventHandler, nsIFrame* aFrame,
+ nsIContent* aContent)
+ : mEventHandler(aEventHandler) {
+ MOZ_DIAGNOSTIC_ASSERT(!mEventHandler.mCurrentEventInfoSetter);
+ mEventHandler.mCurrentEventInfoSetter = this;
+ mEventHandler.mPresShell->PushCurrentEventInfo(aFrame, aContent);
+ }
+ AutoCurrentEventInfoSetter(EventHandler& aEventHandler,
+ EventTargetData& aEventTargetData)
+ : mEventHandler(aEventHandler) {
+ MOZ_DIAGNOSTIC_ASSERT(!mEventHandler.mCurrentEventInfoSetter);
+ mEventHandler.mCurrentEventInfoSetter = this;
+ mEventHandler.mPresShell->PushCurrentEventInfo(
+ aEventTargetData.GetFrame(), aEventTargetData.GetContent());
+ }
+ ~AutoCurrentEventInfoSetter() {
+ mEventHandler.mPresShell->PopCurrentEventInfo();
+ mEventHandler.mCurrentEventInfoSetter = nullptr;
+ }
+
+ private:
+ EventHandler& mEventHandler;
+ };
+
+ /**
+ * Wrapper methods to access methods of mPresShell.
+ */
+ nsPresContext* GetPresContext() const {
+ return mPresShell->GetPresContext();
+ }
+ Document* GetDocument() const { return mPresShell->GetDocument(); }
+ nsCSSFrameConstructor* FrameConstructor() const {
+ return mPresShell->FrameConstructor();
+ }
+ already_AddRefed<nsPIDOMWindowOuter> GetFocusedDOMWindowInOurWindow() {
+ return mPresShell->GetFocusedDOMWindowInOurWindow();
+ }
+ already_AddRefed<PresShell> GetParentPresShellForEventHandling() {
+ return mPresShell->GetParentPresShellForEventHandling();
+ }
+ OwningNonNull<PresShell> mPresShell;
+ AutoCurrentEventInfoSetter* mCurrentEventInfoSetter;
+ static TimeStamp sLastInputCreated;
+ static TimeStamp sLastInputProcessed;
+ static StaticRefPtr<dom::Element> sLastKeyDownEventTargetElement;
+ };
+
+ PresShell* GetRootPresShell() const;
+
+ bool IsTransparentContainerElement() const;
+ ColorScheme DefaultBackgroundColorScheme() const;
+ nscolor GetDefaultBackgroundColorToDraw() const;
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Approximate frame visibility tracking implementation.
+ //////////////////////////////////////////////////////////////////////////////
+
+ void UpdateApproximateFrameVisibility();
+ void DoUpdateApproximateFrameVisibility(bool aRemoveOnly);
+
+ void ClearApproximatelyVisibleFramesList(
+ const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
+ static void ClearApproximateFrameVisibilityVisited(nsView* aView,
+ bool aClear);
+ static void MarkFramesInListApproximatelyVisible(const nsDisplayList& aList);
+ void MarkFramesInSubtreeApproximatelyVisible(nsIFrame* aFrame,
+ const nsRect& aRect,
+ bool aRemoveOnly = false);
+
+ void DecApproximateVisibleCount(
+ VisibleFrames& aFrames,
+ const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
+
+ nsRevocableEventPtr<nsRunnableMethod<PresShell>>
+ mUpdateApproximateFrameVisibilityEvent;
+
+ // A set of frames that were visible or could be visible soon at the time
+ // that we last did an approximate frame visibility update.
+ VisibleFrames mApproximatelyVisibleFrames;
+
+#ifdef DEBUG
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY bool VerifyIncrementalReflow();
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void DoVerifyReflow();
+ void VerifyHasDirtyRootAncestor(nsIFrame* aFrame);
+
+ bool mInVerifyReflow = false;
+ // The reflow root under which we're currently reflowing. Null when
+ // not in reflow.
+ nsIFrame* mCurrentReflowRoot = nullptr;
+#endif // #ifdef DEBUG
+
+ // Send, and reset, the current per tick telemetry. This includes:
+ // * non-zero number of style and layout flushes
+ // * non-zero ms duration spent in style and reflow since the last tick.
+ void PingPerTickTelemetry(FlushType aFlushType);
+
+ private:
+ // IMPORTANT: The ownership implicit in the following member variables
+ // has been explicitly checked. If you add any members to this class,
+ // please make the ownership explicit (pinkerton, scc).
+
+ // These are the same Document and PresContext owned by the DocViewer.
+ // we must share ownership.
+ // mDocument and mPresContext should've never been cleared nor swapped with
+ // another instance while PresShell instance is alive so that it's safe to
+ // call their can-run- script methods without local RefPtr variables.
+ MOZ_KNOWN_LIVE RefPtr<Document> const mDocument;
+ MOZ_KNOWN_LIVE RefPtr<nsPresContext> const mPresContext;
+ UniquePtr<nsCSSFrameConstructor> mFrameConstructor;
+ nsViewManager* mViewManager; // [WEAK] docViewer owns it so I don't have to
+ RefPtr<nsFrameSelection> mSelection;
+ // The frame selection that last took focus on this shell, which we need to
+ // hide if we focus another selection. May or may not be the same as
+ // `mSelection`.
+ RefPtr<nsFrameSelection> mFocusedFrameSelection;
+ RefPtr<nsCaret> mCaret;
+ RefPtr<nsCaret> mOriginalCaret;
+ RefPtr<AccessibleCaretEventHub> mAccessibleCaretEventHub;
+ // Pointer into mFrameConstructor - this is purely so that GetRootFrame() can
+ // be inlined:
+ nsFrameManager* mFrameManager;
+ WeakPtr<nsDocShell> mForwardingContainer;
+
+ // The `performance.now()` value when we last started to process reflows.
+ DOMHighResTimeStamp mLastReflowStart{0.0};
+
+ // At least on Win32 and Mac after interupting a reflow we need to post
+ // the resume reflow event off a timer to avoid event starvation because
+ // posted messages are processed before other messages when the modal
+ // moving/sizing loop is running, see bug 491700 for details.
+ nsCOMPtr<nsITimer> mReflowContinueTimer;
+
+#ifdef DEBUG
+ // We track allocated pointers in a diagnostic hash set, to assert against
+ // missing/double frees. This set is allocated infallibly in the PresShell
+ // constructor's initialization list. The set can get quite large, so we use
+ // fallible allocation when inserting into it; and if these operations ever
+ // fail, then we just get rid of the set and stop using this diagnostic from
+ // that point on. (There's not much else we can do, when the set grows
+ // larger than the available memory.)
+ UniquePtr<nsTHashSet<void*>> mAllocatedPointers{
+ MakeUnique<nsTHashSet<void*>>()};
+#endif
+
+ // A list of stack weak frames. This is a pointer to the last item in the
+ // list.
+ AutoWeakFrame* mAutoWeakFrames;
+
+ // A hash table of heap allocated weak frames.
+ nsTHashSet<WeakFrame*> mWeakFrames;
+
+ // Reflow roots that need to be reflowed.
+ DepthOrderedFrameList mDirtyRoots;
+
+ // These two fields capture call stacks of any changes that require a restyle
+ // or a reflow. Only the first change per restyle / reflow is recorded (the
+ // one that caused a call to SetNeedStyleFlush() / SetNeedLayoutFlush()).
+ UniquePtr<ProfileChunkedBuffer> mStyleCause;
+ UniquePtr<ProfileChunkedBuffer> mReflowCause;
+
+ nsTArray<UniquePtr<DelayedEvent>> mDelayedEvents;
+
+ nsRevocableEventPtr<nsSynthMouseMoveEvent> mSynthMouseMoveEvent;
+
+ TouchManager mTouchManager;
+
+ RefPtr<ZoomConstraintsClient> mZoomConstraintsClient;
+ RefPtr<GeckoMVMContext> mMVMContext;
+ RefPtr<MobileViewportManager> mMobileViewportManager;
+
+ // This timer controls painting suppression. Until it fires
+ // or all frames are constructed, we won't paint anything but
+ // our <body> background and scrollbars.
+ nsCOMPtr<nsITimer> mPaintSuppressionTimer;
+
+ // Information about live content (which still stay in DOM tree).
+ // Used in case we need re-dispatch event after sending pointer event,
+ // when target of pointer event was deleted during executing user handlers.
+ nsCOMPtr<nsIContent> mPointerEventTarget;
+
+ nsCOMPtr<nsIContent> mLastAnchorScrolledTo;
+
+ // Information needed to properly handle scrolling content into view if the
+ // pre-scroll reflow flush can be interrupted. mContentToScrollTo is non-null
+ // between the initial scroll attempt and the first time we finish processing
+ // all our dirty roots. mContentToScrollTo has a content property storing the
+ // details for the scroll operation, see ScrollIntoViewData above.
+ nsCOMPtr<nsIContent> mContentToScrollTo;
+
+#ifdef ACCESSIBILITY
+ a11y::DocAccessible* mDocAccessible;
+#endif // #ifdef ACCESSIBILITY
+
+ nsIFrame* mCurrentEventFrame;
+ nsCOMPtr<nsIContent> mCurrentEventContent;
+ nsTArray<nsIFrame*> mCurrentEventFrameStack;
+ nsCOMArray<nsIContent> mCurrentEventContentStack;
+ // Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after
+ // we finish reflowing mCurrentReflowRoot.
+ nsTHashSet<nsIFrame*> mFramesToDirty;
+ nsTHashSet<nsIScrollableFrame*> mPendingScrollAnchorSelection;
+ nsTHashSet<nsIScrollableFrame*> mPendingScrollAnchorAdjustment;
+ nsTHashSet<nsIScrollableFrame*> mPendingScrollResnap;
+
+ nsTHashSet<nsIContent*> mHiddenContentInForcedLayout;
+
+ nsTHashSet<nsIFrame*> mContentVisibilityAutoFrames;
+
+ // The type of content relevancy to update the next time content relevancy
+ // updates are triggered for `content-visibility: auto` frames.
+ ContentRelevancy mContentVisibilityRelevancyToUpdate;
+
+ nsCallbackEventRequest* mFirstCallbackEventRequest = nullptr;
+ nsCallbackEventRequest* mLastCallbackEventRequest = nullptr;
+
+ // This is used for synthetic mouse events that are sent when what is under
+ // the mouse pointer may have changed without the mouse moving (eg scrolling,
+ // change to the document contents).
+ // It is set only on a presshell for a root document, this value represents
+ // the last observed location of the mouse relative to that root document,
+ // in visual coordinates. It is set to (NS_UNCONSTRAINEDSIZE,
+ // NS_UNCONSTRAINEDSIZE) if the mouse isn't over our window or there is no
+ // last observed mouse location for some reason.
+ nsPoint mMouseLocation;
+ // This is used for the synthetic mouse events too. This is set when a mouse
+ // event is dispatched into the DOM.
+ static int16_t sMouseButtons;
+ // The last observed pointer location relative to that root document in visual
+ // coordinates.
+ nsPoint mLastOverWindowPointerLocation;
+ // This is an APZ state variable that tracks the target guid for the last
+ // mouse event that was processed (corresponding to mMouseLocation). This is
+ // needed for the synthetic mouse events.
+ layers::ScrollableLayerGuid mMouseEventTargetGuid;
+
+ // Only populated on root content documents.
+ nsSize mVisualViewportSize;
+
+ // The focus information needed for async keyboard scrolling
+ FocusTarget mAPZFocusTarget;
+
+ using Arena = nsPresArena<8192, ArenaObjectID, eArenaObjectID_COUNT>;
+ Arena mFrameArena;
+
+ Maybe<nsPoint> mVisualViewportOffset;
+
+ // A pending visual scroll offset that we will ask APZ to scroll to
+ // during the next transaction. Cleared when we send the transaction.
+ // Only applicable to the RCD pres shell.
+ Maybe<VisualScrollUpdate> mPendingVisualScrollUpdate;
+
+ // Used to force allocation and rendering of proportionally more or
+ // less pixels in both dimensions.
+ Maybe<float> mResolution;
+ ResolutionChangeOrigin mLastResolutionChangeOrigin;
+
+ TimeStamp mLoadBegin; // used to time loads
+
+ TimeStamp mLastOSWake;
+
+ // Count of the number of times this presshell has been painted to a window.
+ uint64_t mPaintCount;
+
+ // The focus sequence number of the last processed input event
+ uint64_t mAPZFocusSequenceNumber;
+
+ nscoord mLastAnchorScrollPositionY = 0;
+
+ // Most recent canvas background color.
+ CanvasBackground mCanvasBackground;
+
+ int32_t mActiveSuppressDisplayport;
+
+ uint32_t mPresShellId;
+
+ // Cached font inflation values. This is done to prevent changing of font
+ // inflation until a page is reloaded.
+ uint32_t mFontSizeInflationEmPerLine;
+ uint32_t mFontSizeInflationMinTwips;
+ uint32_t mFontSizeInflationLineThreshold;
+
+ // Can be multiple of nsISelectionDisplay::DISPLAY_*.
+ int16_t mSelectionFlags;
+
+ // This is used to protect ourselves from triggering reflow while in the
+ // middle of frame construction and the like... it really shouldn't be
+ // needed, one hopes, but it is for now.
+ uint16_t mChangeNestCount;
+
+ // Flags controlling how our document is rendered. These persist
+ // between paints and so are tied with retained layer pixels.
+ // PresShell flushes retained layers when the rendering state
+ // changes in a way that prevents us from being able to (usefully)
+ // re-use old pixels.
+ RenderingStateFlags mRenderingStateFlags;
+
+ // Whether we're currently under a FlushPendingNotifications.
+ // This is used to handle flush reentry correctly.
+ // NOTE: This can't be a bitfield since AutoRestore has a reference to this
+ // variable.
+ bool mInFlush;
+
+ bool mCaretEnabled : 1;
+
+ // True if a layout flush might not be a no-op
+ bool mNeedLayoutFlush : 1;
+
+ // True if a style flush might not be a no-op
+ bool mNeedStyleFlush : 1;
+
+ // True if there are throttled animations that would be processed when
+ // performing a flush with mFlushAnimations == true.
+ bool mNeedThrottledAnimationFlush : 1;
+
+ bool mVisualViewportSizeSet : 1;
+
+ bool mDidInitialize : 1;
+ bool mIsDestroying : 1;
+ bool mIsReflowing : 1;
+ bool mIsObservingDocument : 1;
+
+ // Whether we shouldn't ever get to FlushPendingNotifications. This flag is
+ // meant only to sanity-check / assert that FlushPendingNotifications doesn't
+ // happen during certain periods of time. It shouldn't be made public nor used
+ // for other purposes.
+ bool mForbiddenToFlush : 1;
+
+ // We've been disconnected from the document. We will refuse to paint the
+ // document until either our timer fires or all frames are constructed.
+ bool mIsDocumentGone : 1;
+ bool mHaveShutDown : 1;
+
+ // For all documents we initially lock down painting.
+ bool mPaintingSuppressed : 1;
+
+ bool mLastRootReflowHadUnconstrainedBSize : 1;
+
+ // Indicates that it is safe to unlock painting once all pending reflows
+ // have been processed.
+ bool mShouldUnsuppressPainting : 1;
+
+ bool mIgnoreFrameDestruction : 1;
+
+ bool mIsActive : 1;
+ bool mFrozen : 1;
+ bool mIsFirstPaint : 1;
+ bool mObservesMutationsForPrint : 1;
+
+ // Whether the most recent interruptible reflow was actually interrupted:
+ bool mWasLastReflowInterrupted : 1;
+
+ // True if we're observing the refresh driver for style flushes.
+ bool mObservingStyleFlushes : 1;
+
+ // True if we're observing the refresh driver for layout flushes, that is, if
+ // we have a reflow scheduled.
+ //
+ // Guaranteed to be false if mReflowContinueTimer is non-null.
+ bool mObservingLayoutFlushes : 1;
+
+ bool mResizeEventPending : 1;
+
+ bool mFontSizeInflationForceEnabled : 1;
+ bool mFontSizeInflationDisabledInMasterProcess : 1;
+ bool mFontSizeInflationEnabled : 1;
+
+ // If a document belongs to an invisible DocShell, this flag must be set
+ // to true, so we can avoid any paint calls for widget related to this
+ // presshell.
+ bool mIsNeverPainting : 1;
+
+ // Whether the most recent change to the pres shell resolution was
+ // originated by the main thread.
+ bool mResolutionUpdated : 1;
+
+ // True if the resolution has been ever changed by APZ.
+ bool mResolutionUpdatedByApz : 1;
+
+ // Whether this presshell is hidden by 'vibility:hidden' on an ancestor
+ // nsSubDocumentFrame.
+ bool mUnderHiddenEmbedderElement : 1;
+
+ bool mDocumentLoading : 1;
+ bool mNoDelayedMouseEvents : 1;
+ bool mNoDelayedKeyEvents : 1;
+
+ bool mApproximateFrameVisibilityVisited : 1;
+
+ // Whether the last chrome-only escape key event is consumed.
+ bool mIsLastChromeOnlyEscapeKeyConsumed : 1;
+
+ // Whether the widget has received a paint message yet.
+ bool mHasReceivedPaintMessage : 1;
+
+ bool mIsLastKeyDownCanceled : 1;
+
+ // Whether we have ever handled a user input event
+ bool mHasHandledUserInput : 1;
+
+ // Whether we should dispatch keypress events even for non-printable keys
+ // for keeping backward compatibility.
+ bool mForceDispatchKeyPressEventsForNonPrintableKeys : 1;
+ // Whether we should set keyCode or charCode value of keypress events whose
+ // value is zero to the other value or not. When this is set to true, we
+ // should keep using legacy keyCode and charCode values (i.e., one of them
+ // is always 0).
+ bool mForceUseLegacyKeyCodeAndCharCodeValues : 1;
+ // Whether mForceDispatchKeyPressEventsForNonPrintableKeys and
+ // mForceUseLegacyKeyCodeAndCharCodeValues are initialized.
+ bool mInitializedWithKeyPressEventDispatchingBlacklist : 1;
+
+ // Set to true if mMouseLocation is set by a mouse event which is synthesized
+ // for tests.
+ bool mMouseLocationWasSetBySynthesizedMouseEventForTests : 1;
+
+ bool mHasTriedFastUnsuppress : 1;
+
+ bool mProcessingReflowCommands : 1;
+ bool mPendingDidDoReflow : 1;
+
+ struct CapturingContentInfo final {
+ CapturingContentInfo()
+ : mRemoteTarget(nullptr),
+ mAllowed(false),
+ mPointerLock(false),
+ mRetargetToElement(false),
+ mPreventDrag(false) {}
+
+ // capture should only be allowed during a mousedown event
+ StaticRefPtr<nsIContent> mContent;
+ dom::BrowserParent* mRemoteTarget;
+ bool mAllowed;
+ bool mPointerLock;
+ bool mRetargetToElement;
+ bool mPreventDrag;
+ };
+ static CapturingContentInfo sCapturingContentInfo;
+
+ static bool sDisableNonTestMouseEvents;
+
+ static bool sProcessInteractable;
+
+ layout_telemetry::Data mLayoutTelemetry;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(PresShell, NS_PRESSHELL_IID)
+
+} // namespace mozilla
+
+#endif // mozilla_PresShell_h