michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: set ts=2 sw=2 et tw=78: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: * michael@0: * This Original Code has been modified by IBM Corporation. michael@0: * Modifications made by IBM described herein are michael@0: * Copyright (c) International Business Machines michael@0: * Corporation, 2000 michael@0: * michael@0: * Modifications to Mozilla code or documentation michael@0: * identified per MPL Section 3.3 michael@0: * michael@0: * Date Modified by Description of modification michael@0: * 05/03/2000 IBM Corp. Observer events for reflow states michael@0: */ michael@0: michael@0: /* a presentation of a document, part 2 */ michael@0: michael@0: #ifndef nsPresShell_h_ michael@0: #define nsPresShell_h_ michael@0: michael@0: #include "nsIPresShell.h" michael@0: #include "nsStubDocumentObserver.h" michael@0: #include "nsISelectionController.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsWeakReference.h" michael@0: #include "nsCRT.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsIWidget.h" michael@0: #include "nsStyleSet.h" michael@0: #include "nsFrameSelection.h" michael@0: #include "nsContentUtils.h" // For AddScriptBlocker(). michael@0: #include "nsRefreshDriver.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/EventForwards.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: michael@0: class nsRange; michael@0: class nsIDragService; michael@0: class nsCSSStyleSheet; michael@0: michael@0: struct RangePaintInfo; michael@0: struct nsCallbackEventRequest; michael@0: #ifdef MOZ_REFLOW_PERF michael@0: class ReflowCountMgr; michael@0: #endif michael@0: michael@0: class nsPresShellEventCB; michael@0: class nsAutoCauseReflowNotifier; michael@0: michael@0: // 250ms. This is actually pref-controlled, but we use this value if we fail michael@0: // to get the pref for any reason. michael@0: #define PAINTLOCK_EVENT_DELAY 250 michael@0: michael@0: class PresShell : public nsIPresShell, michael@0: public nsStubDocumentObserver, michael@0: public nsISelectionController, public nsIObserver, michael@0: public nsSupportsWeakReference michael@0: { michael@0: public: michael@0: PresShell(); michael@0: michael@0: NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW michael@0: michael@0: // nsISupports michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: void Init(nsIDocument* aDocument, nsPresContext* aPresContext, michael@0: nsViewManager* aViewManager, nsStyleSet* aStyleSet, michael@0: nsCompatibility aCompatMode); michael@0: virtual NS_HIDDEN_(void) Destroy() MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) MakeZombie() MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(nsresult) SetPreferenceStyleRules(bool aForceReflow) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection); michael@0: virtual mozilla::dom::Selection* GetCurrentSelection(SelectionType aType) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD SetDisplaySelection(int16_t aToggle) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetDisplaySelection(int16_t *aToggle) MOZ_OVERRIDE; michael@0: NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, michael@0: int16_t aFlags) MOZ_OVERRIDE; michael@0: NS_IMETHOD RepaintSelection(SelectionType aType) MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(void) BeginObservingDocument() MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) EndObservingDocument() MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsresult) Initialize(nscoord aWidth, nscoord aHeight) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsresult) ResizeReflow(nscoord aWidth, nscoord aHeight) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsresult) ResizeReflowOverride(nscoord aWidth, nscoord aHeight) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsIPageSequenceFrame*) GetPageSequenceFrame() const MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsIFrame*) GetRealPrimaryFrameFor(nsIContent* aContent) const MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(nsIFrame*) GetPlaceholderFrameFor(nsIFrame* aFrame) const MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty, michael@0: nsFrameState aBitToAdd) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) FrameNeedsToContinueReflow(nsIFrame *aFrame) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) CancelAllPendingReflows() MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(bool) IsSafeToFlush() const MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) FlushPendingNotifications(mozFlushType aType) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) FlushPendingNotifications(mozilla::ChangesToFlush aType) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * Recreates the frames for a node michael@0: */ michael@0: virtual NS_HIDDEN_(nsresult) RecreateFramesFor(nsIContent* aContent) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * Post a callback that should be handled after reflow has finished. michael@0: */ michael@0: virtual NS_HIDDEN_(nsresult) PostReflowCallback(nsIReflowCallback* aCallback) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) CancelReflowCallback(nsIReflowCallback* aCallback) MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(void) ClearFrameRefs(nsIFrame* aFrame) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(already_AddRefed) CreateReferenceRenderingContext(); michael@0: virtual NS_HIDDEN_(nsresult) GoToAnchor(const nsAString& aAnchorName, bool aScroll) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsresult) ScrollToAnchor() MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent, michael@0: ScrollAxis aVertical, michael@0: ScrollAxis aHorizontal, michael@0: uint32_t aFlags) MOZ_OVERRIDE; michael@0: virtual bool ScrollFrameRectIntoView(nsIFrame* aFrame, michael@0: const nsRect& aRect, michael@0: ScrollAxis aVertical, michael@0: ScrollAxis aHorizontal, michael@0: uint32_t aFlags) MOZ_OVERRIDE; michael@0: virtual nsRectVisibility GetRectVisibility(nsIFrame *aFrame, michael@0: const nsRect &aRect, michael@0: nscoord aMinTwips) const MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(void) SetIgnoreFrameDestruction(bool aIgnore) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) NotifyDestroyingFrame(nsIFrame* aFrame) MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(nsresult) CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState) MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(void) UnsuppressPainting() MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult GetAgentStyleSheets(nsCOMArray& aSheets) MOZ_OVERRIDE; michael@0: virtual nsresult SetAgentStyleSheets(const nsCOMArray& aSheets) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult AddOverrideStyleSheet(nsIStyleSheet *aSheet) MOZ_OVERRIDE; michael@0: virtual nsresult RemoveOverrideStyleSheet(nsIStyleSheet *aSheet) MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(nsresult) HandleEventWithTarget( michael@0: mozilla::WidgetEvent* aEvent, michael@0: nsIFrame* aFrame, michael@0: nsIContent* aContent, michael@0: nsEventStatus* aStatus) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsIFrame*) GetEventTargetFrame() MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(already_AddRefed) GetEventTargetContent( michael@0: mozilla::WidgetEvent* aEvent) MOZ_OVERRIDE; michael@0: michael@0: michael@0: virtual nsresult ReconstructFrames(void) MOZ_OVERRIDE; michael@0: virtual void Freeze() MOZ_OVERRIDE; michael@0: virtual void Thaw() MOZ_OVERRIDE; michael@0: virtual void FireOrClearDelayedEvents(bool aFireEvents) MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(nsresult) RenderDocument(const nsRect& aRect, uint32_t aFlags, michael@0: nscolor aBackgroundColor, michael@0: gfxContext* aThebesContext) MOZ_OVERRIDE; michael@0: michael@0: virtual mozilla::TemporaryRef michael@0: RenderNode(nsIDOMNode* aNode, michael@0: nsIntRegion* aRegion, michael@0: nsIntPoint& aPoint, michael@0: nsIntRect* aScreenRect) MOZ_OVERRIDE; michael@0: michael@0: virtual mozilla::TemporaryRef michael@0: RenderSelection(nsISelection* aSelection, michael@0: nsIntPoint& aPoint, michael@0: nsIntRect* aScreenRect) MOZ_OVERRIDE; michael@0: michael@0: virtual already_AddRefed GetRootWindow() MOZ_OVERRIDE; michael@0: michael@0: virtual LayerManager* GetLayerManager() MOZ_OVERRIDE; michael@0: michael@0: virtual void SetIgnoreViewportScrolling(bool aIgnore) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult SetResolution(float aXResolution, float aYResolution) MOZ_OVERRIDE; michael@0: virtual gfxSize GetCumulativeResolution() MOZ_OVERRIDE; michael@0: michael@0: //nsIViewObserver interface michael@0: michael@0: virtual void Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, michael@0: uint32_t aFlags) MOZ_OVERRIDE; michael@0: virtual nsresult HandleEvent(nsIFrame* aFrame, michael@0: mozilla::WidgetGUIEvent* aEvent, michael@0: bool aDontRetargetEvents, michael@0: nsEventStatus* aEventStatus) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsresult) HandleDOMEventWithTarget( michael@0: nsIContent* aTargetContent, michael@0: mozilla::WidgetEvent* aEvent, michael@0: nsEventStatus* aStatus) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(nsresult) HandleDOMEventWithTarget(nsIContent* aTargetContent, michael@0: nsIDOMEvent* aEvent, michael@0: nsEventStatus* aStatus) MOZ_OVERRIDE; michael@0: virtual bool ShouldIgnoreInvalidation() MOZ_OVERRIDE; michael@0: virtual void WillPaint() MOZ_OVERRIDE; michael@0: virtual void WillPaintWindow() MOZ_OVERRIDE; michael@0: virtual void DidPaintWindow() MOZ_OVERRIDE; michael@0: virtual void ScheduleViewManagerFlush(PaintType aType = PAINT_DEFAULT) MOZ_OVERRIDE; michael@0: virtual void DispatchSynthMouseMove(mozilla::WidgetGUIEvent* aEvent, michael@0: bool aFlushOnHoverChange) MOZ_OVERRIDE; michael@0: virtual void ClearMouseCaptureOnView(nsView* aView) MOZ_OVERRIDE; michael@0: virtual bool IsVisible() MOZ_OVERRIDE; michael@0: michael@0: // caret handling michael@0: virtual NS_HIDDEN_(already_AddRefed) GetCaret() const MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) MaybeInvalidateCaretPosition() MOZ_OVERRIDE; michael@0: NS_IMETHOD SetCaretEnabled(bool aInEnable) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetCaretReadOnly(bool aReadOnly) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetCaretEnabled(bool *aOutEnabled) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetCaretVisible(bool *_retval) MOZ_OVERRIDE; michael@0: virtual void SetCaret(nsCaret *aNewCaret) MOZ_OVERRIDE; michael@0: virtual void RestoreCaret() MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD SetSelectionFlags(int16_t aInEnable) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetSelectionFlags(int16_t *aOutEnable) MOZ_OVERRIDE; michael@0: michael@0: // nsISelectionController michael@0: michael@0: NS_IMETHOD CharacterMove(bool aForward, bool aExtend) MOZ_OVERRIDE; michael@0: NS_IMETHOD CharacterExtendForDelete() MOZ_OVERRIDE; michael@0: NS_IMETHOD CharacterExtendForBackspace() MOZ_OVERRIDE; michael@0: NS_IMETHOD WordMove(bool aForward, bool aExtend) MOZ_OVERRIDE; michael@0: NS_IMETHOD WordExtendForDelete(bool aForward) MOZ_OVERRIDE; michael@0: NS_IMETHOD LineMove(bool aForward, bool aExtend) MOZ_OVERRIDE; michael@0: NS_IMETHOD IntraLineMove(bool aForward, bool aExtend) MOZ_OVERRIDE; michael@0: NS_IMETHOD PageMove(bool aForward, bool aExtend) MOZ_OVERRIDE; michael@0: NS_IMETHOD ScrollPage(bool aForward) MOZ_OVERRIDE; michael@0: NS_IMETHOD ScrollLine(bool aForward) MOZ_OVERRIDE; michael@0: NS_IMETHOD ScrollCharacter(bool aRight) MOZ_OVERRIDE; michael@0: NS_IMETHOD CompleteScroll(bool aForward) MOZ_OVERRIDE; michael@0: NS_IMETHOD CompleteMove(bool aForward, bool aExtend) MOZ_OVERRIDE; michael@0: NS_IMETHOD SelectAll() MOZ_OVERRIDE; michael@0: NS_IMETHOD CheckVisibility(nsIDOMNode *node, int16_t startOffset, int16_t EndOffset, bool *_retval) MOZ_OVERRIDE; michael@0: virtual nsresult CheckVisibilityContent(nsIContent* aNode, int16_t aStartOffset, michael@0: int16_t aEndOffset, bool* aRetval) MOZ_OVERRIDE; michael@0: michael@0: // nsIDocumentObserver michael@0: NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE michael@0: NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE michael@0: NS_DECL_NSIDOCUMENTOBSERVER_BEGINLOAD michael@0: NS_DECL_NSIDOCUMENTOBSERVER_ENDLOAD michael@0: NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATECHANGED michael@0: NS_DECL_NSIDOCUMENTOBSERVER_DOCUMENTSTATESCHANGED michael@0: NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED michael@0: NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED michael@0: NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETAPPLICABLESTATECHANGED michael@0: NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED michael@0: NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED michael@0: NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEREMOVED michael@0: michael@0: // nsIMutationObserver michael@0: NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE michael@0: NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED michael@0: NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE michael@0: NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED michael@0: NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED michael@0: NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED michael@0: NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED michael@0: michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: #ifdef MOZ_REFLOW_PERF michael@0: virtual NS_HIDDEN_(void) DumpReflows() MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) CountReflows(const char * aName, nsIFrame * aFrame) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) PaintCount(const char * aName, michael@0: nsRenderingContext* aRenderingContext, michael@0: nsPresContext* aPresContext, michael@0: nsIFrame * aFrame, michael@0: const nsPoint& aOffset, michael@0: uint32_t aColor) MOZ_OVERRIDE; michael@0: virtual NS_HIDDEN_(void) SetPaintFrameCount(bool aOn) MOZ_OVERRIDE; michael@0: virtual bool IsPaintingFrameCounts() MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: #ifdef DEBUG michael@0: virtual void ListStyleContexts(nsIFrame *aRootFrame, FILE *out, michael@0: int32_t aIndent = 0) MOZ_OVERRIDE; michael@0: michael@0: virtual void ListStyleSheets(FILE *out, int32_t aIndent = 0) MOZ_OVERRIDE; michael@0: virtual void VerifyStyleTree() MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: #ifdef PR_LOGGING michael@0: static PRLogModuleInfo* gLog; michael@0: #endif michael@0: michael@0: virtual NS_HIDDEN_(void) DisableNonTestMouseEvents(bool aDisable) MOZ_OVERRIDE; michael@0: michael@0: virtual void UpdateCanvasBackground() MOZ_OVERRIDE; michael@0: michael@0: virtual void AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder, michael@0: nsDisplayList& aList, michael@0: nsIFrame* aFrame, michael@0: const nsRect& aBounds, michael@0: nscolor aBackstopColor, michael@0: uint32_t aFlags) MOZ_OVERRIDE; michael@0: michael@0: virtual void AddPrintPreviewBackgroundItem(nsDisplayListBuilder& aBuilder, michael@0: nsDisplayList& aList, michael@0: nsIFrame* aFrame, michael@0: const nsRect& aBounds) MOZ_OVERRIDE; michael@0: michael@0: virtual nscolor ComputeBackstopColor(nsView* aDisplayRoot) MOZ_OVERRIDE; michael@0: michael@0: virtual NS_HIDDEN_(nsresult) SetIsActive(bool aIsActive) MOZ_OVERRIDE; michael@0: michael@0: virtual bool GetIsViewportOverridden() MOZ_OVERRIDE { return mViewportOverridden; } michael@0: michael@0: virtual bool IsLayoutFlushObserver() MOZ_OVERRIDE michael@0: { michael@0: return GetPresContext()->RefreshDriver()-> michael@0: IsLayoutFlushObserver(this); michael@0: } michael@0: michael@0: virtual void LoadComplete() MOZ_OVERRIDE; michael@0: michael@0: void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: nsArenaMemoryStats *aArenaObjectsSize, michael@0: size_t *aPresShellSize, michael@0: size_t *aStyleSetsSize, michael@0: size_t *aTextRunsSize, michael@0: size_t *aPresContextSize) MOZ_OVERRIDE; michael@0: size_t SizeOfTextRuns(mozilla::MallocSizeOf aMallocSizeOf) const; michael@0: michael@0: virtual void AddInvalidateHiddenPresShellObserver(nsRefreshDriver *aDriver) MOZ_OVERRIDE; michael@0: michael@0: // This data is stored as a content property (nsGkAtoms::scrolling) on michael@0: // mContentToScrollTo when we have a pending ScrollIntoView. michael@0: struct ScrollIntoViewData { michael@0: ScrollAxis mContentScrollVAxis; michael@0: ScrollAxis mContentScrollHAxis; michael@0: uint32_t mContentToScrollToFlags; michael@0: }; michael@0: michael@0: virtual void ScheduleImageVisibilityUpdate() MOZ_OVERRIDE; michael@0: michael@0: virtual void RebuildImageVisibility(const nsDisplayList& aList) MOZ_OVERRIDE; michael@0: michael@0: virtual void EnsureImageInVisibleList(nsIImageLoadingContent* aImage) MOZ_OVERRIDE; michael@0: michael@0: virtual void RemoveImageFromVisibleList(nsIImageLoadingContent* aImage) MOZ_OVERRIDE; michael@0: michael@0: virtual bool AssumeAllImagesVisible() MOZ_OVERRIDE; michael@0: michael@0: virtual void RestyleShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot); michael@0: michael@0: void SetNextPaintCompressed() { mNextPaintCompressed = true; } michael@0: michael@0: protected: michael@0: virtual ~PresShell(); michael@0: michael@0: void HandlePostedReflowCallbacks(bool aInterruptible); michael@0: void CancelPostedReflowCallbacks(); michael@0: michael@0: void UnsuppressAndInvalidate(); michael@0: michael@0: void WillCauseReflow() { michael@0: nsContentUtils::AddScriptBlocker(); michael@0: ++mChangeNestCount; michael@0: } michael@0: nsresult DidCauseReflow(); michael@0: friend class nsAutoCauseReflowNotifier; michael@0: michael@0: void DispatchTouchEvent(mozilla::WidgetEvent* aEvent, michael@0: nsEventStatus* aStatus, michael@0: nsPresShellEventCB* aEventCB, michael@0: bool aTouchIsNew); michael@0: michael@0: void WillDoReflow(); michael@0: michael@0: /** michael@0: * Callback handler for whether reflow happened. michael@0: * michael@0: * @param aInterruptible Whether or not reflow interruption is allowed. michael@0: * @param aWasInterrupted Whether or not the reflow was interrupted earlier. michael@0: * michael@0: */ michael@0: void DidDoReflow(bool aInterruptible, bool aWasInterrupted); michael@0: // ProcessReflowCommands returns whether we processed all our dirty roots michael@0: // without interruptions. michael@0: bool ProcessReflowCommands(bool aInterruptible); michael@0: // MaybeScheduleReflow checks if posting a reflow is needed, then checks if michael@0: // the last reflow was interrupted. In the interrupted case ScheduleReflow is michael@0: // called off a timer, otherwise it is called directly. michael@0: void MaybeScheduleReflow(); michael@0: // Actually schedules a reflow. This should only be called by michael@0: // MaybeScheduleReflow and the reflow timer ScheduleReflowOffTimer michael@0: // sets up. michael@0: void ScheduleReflow(); michael@0: michael@0: // Reflow regardless of whether the override bit has been set. michael@0: nsresult ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight); michael@0: michael@0: // DoReflow returns whether the reflow finished without interruption michael@0: bool DoReflow(nsIFrame* aFrame, bool aInterruptible); michael@0: #ifdef DEBUG michael@0: void DoVerifyReflow(); michael@0: void VerifyHasDirtyRootAncestor(nsIFrame* aFrame); michael@0: #endif michael@0: michael@0: // Helper for ScrollContentIntoView michael@0: void DoScrollContentIntoView(); michael@0: michael@0: /** michael@0: * Initialize cached font inflation preference values and do an initial michael@0: * computation to determine if font inflation is enabled. michael@0: * michael@0: * @see nsLayoutUtils::sFontSizeInflationEmPerLine michael@0: * @see nsLayoutUtils::sFontSizeInflationMinTwips michael@0: * @see nsLayoutUtils::sFontSizeInflationLineThreshold michael@0: */ michael@0: void SetupFontInflation(); michael@0: michael@0: friend struct AutoRenderingStateSaveRestore; michael@0: friend struct RenderingState; michael@0: michael@0: struct RenderingState { michael@0: RenderingState(PresShell* aPresShell) michael@0: : mXResolution(aPresShell->mXResolution) michael@0: , mYResolution(aPresShell->mYResolution) michael@0: , mRenderFlags(aPresShell->mRenderFlags) michael@0: { } michael@0: float mXResolution; michael@0: float mYResolution; michael@0: RenderFlags mRenderFlags; michael@0: }; michael@0: michael@0: struct AutoSaveRestoreRenderingState { michael@0: AutoSaveRestoreRenderingState(PresShell* aPresShell) michael@0: : mPresShell(aPresShell) michael@0: , mOldState(aPresShell) michael@0: {} michael@0: michael@0: ~AutoSaveRestoreRenderingState() michael@0: { michael@0: mPresShell->mRenderFlags = mOldState.mRenderFlags; michael@0: mPresShell->mXResolution = mOldState.mXResolution; michael@0: mPresShell->mYResolution = mOldState.mYResolution; michael@0: } michael@0: michael@0: PresShell* mPresShell; michael@0: RenderingState mOldState; michael@0: }; michael@0: static RenderFlags ChangeFlag(RenderFlags aFlags, bool aOnOff, michael@0: eRenderFlag aFlag) michael@0: { michael@0: return aOnOff ? (aFlags | aFlag) : (aFlag & ~aFlag); michael@0: } michael@0: michael@0: michael@0: void SetRenderingState(const RenderingState& aState); michael@0: michael@0: friend class nsPresShellEventCB; michael@0: michael@0: bool mCaretEnabled; michael@0: #ifdef DEBUG michael@0: nsStyleSet* CloneStyleSet(nsStyleSet* aSet); michael@0: bool VerifyIncrementalReflow(); michael@0: bool mInVerifyReflow; michael@0: void ShowEventTargetDebug(); michael@0: #endif michael@0: michael@0: void RecordStyleSheetChange(nsIStyleSheet* aStyleSheet); michael@0: michael@0: /** michael@0: * methods that manage rules that are used to implement the associated preferences michael@0: * - initially created for bugs 31816, 20760, 22963 michael@0: */ michael@0: nsresult ClearPreferenceStyleRules(void); michael@0: nsresult CreatePreferenceStyleSheet(void); michael@0: nsresult SetPrefLinkRules(void); michael@0: nsresult SetPrefFocusRules(void); michael@0: nsresult SetPrefNoScriptRule(); michael@0: nsresult SetPrefNoFramesRule(void); michael@0: michael@0: // methods for painting a range to an offscreen buffer michael@0: michael@0: // given a display list, clip the items within the list to michael@0: // the range michael@0: nsRect ClipListToRange(nsDisplayListBuilder *aBuilder, michael@0: nsDisplayList* aList, michael@0: nsRange* aRange); michael@0: michael@0: // create a RangePaintInfo for the range aRange containing the michael@0: // display list needed to paint the range to a surface michael@0: RangePaintInfo* CreateRangePaintInfo(nsIDOMRange* aRange, michael@0: nsRect& aSurfaceRect, michael@0: bool aForPrimarySelection); michael@0: michael@0: /* michael@0: * Paint the items to a new surface and return it. michael@0: * michael@0: * aSelection - selection being painted, if any michael@0: * aRegion - clip region, if any michael@0: * aArea - area that the surface occupies, relative to the root frame michael@0: * aPoint - reference point, typically the mouse position michael@0: * aScreenRect - [out] set to the area of the screen the painted area should michael@0: * be displayed at michael@0: */ michael@0: mozilla::TemporaryRef michael@0: PaintRangePaintInfo(nsTArray >* aItems, michael@0: nsISelection* aSelection, michael@0: nsIntRegion* aRegion, michael@0: nsRect aArea, michael@0: nsIntPoint& aPoint, michael@0: nsIntRect* aScreenRect); michael@0: michael@0: /** michael@0: * Methods to handle changes to user and UA sheet lists that we get michael@0: * notified about. michael@0: */ michael@0: void AddUserSheet(nsISupports* aSheet); michael@0: void AddAgentSheet(nsISupports* aSheet); michael@0: void AddAuthorSheet(nsISupports* aSheet); michael@0: void RemoveSheet(nsStyleSet::sheetType aType, nsISupports* aSheet); michael@0: michael@0: // Hide a view if it is a popup michael@0: void HideViewIfPopup(nsView* aView); michael@0: michael@0: // Utility method to restore the root scrollframe state michael@0: void RestoreRootScrollPosition(); michael@0: michael@0: void MaybeReleaseCapturingContent() michael@0: { michael@0: nsRefPtr frameSelection = FrameSelection(); michael@0: if (frameSelection) { michael@0: frameSelection->SetMouseDownState(false); michael@0: } michael@0: if (gCaptureInfo.mContent && michael@0: gCaptureInfo.mContent->OwnerDoc() == mDocument) { michael@0: SetCapturingContent(nullptr, 0); michael@0: } michael@0: } michael@0: michael@0: nsresult HandleRetargetedEvent(mozilla::WidgetEvent* aEvent, michael@0: nsEventStatus* aStatus, michael@0: nsIContent* aTarget) michael@0: { michael@0: PushCurrentEventInfo(nullptr, nullptr); michael@0: mCurrentEventContent = aTarget; michael@0: nsresult rv = NS_OK; michael@0: if (GetCurrentEventFrame()) { michael@0: rv = HandleEventInternal(aEvent, aStatus); michael@0: } michael@0: PopCurrentEventInfo(); michael@0: return rv; michael@0: } michael@0: michael@0: class DelayedEvent michael@0: { michael@0: public: michael@0: virtual ~DelayedEvent() { } michael@0: virtual void Dispatch() { } michael@0: }; michael@0: michael@0: class DelayedInputEvent : public DelayedEvent michael@0: { michael@0: public: michael@0: virtual void Dispatch() MOZ_OVERRIDE; michael@0: michael@0: protected: michael@0: DelayedInputEvent(); michael@0: virtual ~DelayedInputEvent(); michael@0: michael@0: mozilla::WidgetInputEvent* mEvent; michael@0: }; michael@0: michael@0: class DelayedMouseEvent : public DelayedInputEvent michael@0: { michael@0: public: michael@0: DelayedMouseEvent(mozilla::WidgetMouseEvent* aEvent); michael@0: }; michael@0: michael@0: class DelayedKeyEvent : public DelayedInputEvent michael@0: { michael@0: public: michael@0: DelayedKeyEvent(mozilla::WidgetKeyboardEvent* aEvent); michael@0: }; michael@0: michael@0: // Check if aEvent is a mouse event and record the mouse location for later michael@0: // synth mouse moves. michael@0: void RecordMouseLocation(mozilla::WidgetGUIEvent* aEvent); michael@0: class nsSynthMouseMoveEvent MOZ_FINAL : public nsARefreshObserver { michael@0: public: michael@0: nsSynthMouseMoveEvent(PresShell* aPresShell, bool aFromScroll) michael@0: : mPresShell(aPresShell), mFromScroll(aFromScroll) { michael@0: NS_ASSERTION(mPresShell, "null parameter"); michael@0: } michael@0: michael@0: private: michael@0: // Private destructor, to discourage deletion outside of Release(): michael@0: ~nsSynthMouseMoveEvent() { michael@0: Revoke(); michael@0: } michael@0: michael@0: public: michael@0: NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent) michael@0: michael@0: void Revoke() { michael@0: if (mPresShell) { michael@0: mPresShell->GetPresContext()->RefreshDriver()-> michael@0: RemoveRefreshObserver(this, Flush_Display); michael@0: mPresShell = nullptr; michael@0: } michael@0: } michael@0: virtual void WillRefresh(mozilla::TimeStamp aTime) MOZ_OVERRIDE { michael@0: if (mPresShell) { michael@0: nsRefPtr shell = mPresShell; michael@0: shell->ProcessSynthMouseMoveEvent(mFromScroll); michael@0: } michael@0: } michael@0: private: michael@0: PresShell* mPresShell; michael@0: bool mFromScroll; michael@0: }; michael@0: void ProcessSynthMouseMoveEvent(bool aFromScroll); michael@0: michael@0: void QueryIsActive(); michael@0: nsresult UpdateImageLockingState(); michael@0: michael@0: #ifdef ANDROID michael@0: nsIDocument* GetTouchEventTargetDocument(); michael@0: #endif michael@0: bool InZombieDocument(nsIContent *aContent); michael@0: already_AddRefed GetParentPresShellForEventHandling(); michael@0: nsIContent* GetCurrentEventContent(); michael@0: nsIFrame* GetCurrentEventFrame(); michael@0: nsresult RetargetEventToParent(mozilla::WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus); michael@0: void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent); michael@0: void PopCurrentEventInfo(); michael@0: nsresult HandleEventInternal(mozilla::WidgetEvent* aEvent, michael@0: nsEventStatus* aStatus); michael@0: nsresult HandlePositionedEvent(nsIFrame* aTargetFrame, michael@0: mozilla::WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus); michael@0: // This returns the focused DOM window under our top level window. michael@0: // I.e., when we are deactive, this returns the *last* focused DOM window. michael@0: already_AddRefed GetFocusedDOMWindowInOurWindow(); michael@0: michael@0: /* michael@0: * This and the next two helper methods are used to target and position the michael@0: * context menu when the keyboard shortcut is used to open it. michael@0: * michael@0: * If another menu is open, the context menu is opened relative to the michael@0: * active menuitem within the menu, or the menu itself if no item is active. michael@0: * Otherwise, if the caret is visible, the menu is opened near the caret. michael@0: * Otherwise, if a selectable list such as a listbox is focused, the michael@0: * current item within the menu is opened relative to this item. michael@0: * Otherwise, the context menu is opened at the topleft corner of the michael@0: * view. michael@0: * michael@0: * Returns true if the context menu event should fire and false if it should michael@0: * not. michael@0: */ michael@0: bool AdjustContextMenuKeyEvent(mozilla::WidgetMouseEvent* aEvent); michael@0: michael@0: // michael@0: bool PrepareToUseCaretPosition(nsIWidget* aEventWidget, nsIntPoint& aTargetPt); michael@0: michael@0: // Get the selected item and coordinates in device pixels relative to root michael@0: // document's root view for element, first ensuring the element is onscreen michael@0: void GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl, michael@0: nsIContent **aTargetToUse, michael@0: mozilla::LayoutDeviceIntPoint& aTargetPt, michael@0: nsIWidget *aRootWidget); michael@0: michael@0: void FireResizeEvent(); michael@0: static void AsyncResizeEventCallback(nsITimer* aTimer, void* aPresShell); michael@0: michael@0: virtual void SynthesizeMouseMove(bool aFromScroll) MOZ_OVERRIDE; michael@0: michael@0: PresShell* GetRootPresShell(); michael@0: michael@0: nscolor GetDefaultBackgroundColorToDraw(); michael@0: michael@0: DOMHighResTimeStamp GetPerformanceNow(); michael@0: michael@0: // The callback for the mPaintSuppressionTimer timer. michael@0: static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell); michael@0: michael@0: // The callback for the mReflowContinueTimer timer. michael@0: static void sReflowContinueCallback(nsITimer* aTimer, void* aPresShell); michael@0: bool ScheduleReflowOffTimer(); michael@0: michael@0: // Widget notificiations michael@0: virtual void WindowSizeMoveDone() MOZ_OVERRIDE; michael@0: virtual void SysColorChanged() MOZ_OVERRIDE { mPresContext->SysColorChanged(); } michael@0: virtual void ThemeChanged() MOZ_OVERRIDE { mPresContext->ThemeChanged(); } michael@0: virtual void BackingScaleFactorChanged() MOZ_OVERRIDE { mPresContext->UIResolutionChanged(); } michael@0: michael@0: virtual void PausePainting() MOZ_OVERRIDE; michael@0: virtual void ResumePainting() MOZ_OVERRIDE; michael@0: michael@0: void UpdateImageVisibility(); michael@0: void UpdateActivePointerState(mozilla::WidgetGUIEvent* aEvent); michael@0: michael@0: nsRevocableEventPtr > mUpdateImageVisibilityEvent; michael@0: michael@0: void ClearVisibleImagesList(); michael@0: static void ClearImageVisibilityVisited(nsView* aView, bool aClear); michael@0: static void MarkImagesInListVisible(const nsDisplayList& aList); michael@0: michael@0: void EvictTouches(); michael@0: michael@0: // A list of images that are visible or almost visible. michael@0: nsTHashtable< nsRefPtrHashKey > mVisibleImages; michael@0: michael@0: #ifdef DEBUG michael@0: // The reflow root under which we're currently reflowing. Null when michael@0: // not in reflow. michael@0: nsIFrame* mCurrentReflowRoot; michael@0: uint32_t mUpdateCount; michael@0: #endif michael@0: michael@0: #ifdef MOZ_REFLOW_PERF michael@0: ReflowCountMgr* mReflowCountMgr; michael@0: #endif michael@0: michael@0: // This is used for synthetic mouse events that are sent when what is under michael@0: // the mouse pointer may have changed without the mouse moving (eg scrolling, michael@0: // change to the document contents). michael@0: // It is set only on a presshell for a root document, this value represents michael@0: // the last observed location of the mouse relative to that root document. It michael@0: // is set to (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if the mouse isn't michael@0: // over our window or there is no last observed mouse location for some michael@0: // reason. michael@0: nsPoint mMouseLocation; michael@0: michael@0: // mStyleSet owns it but we maintain a ref, may be null michael@0: nsRefPtr mPrefStyleSheet; michael@0: michael@0: // Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after michael@0: // we finish reflowing mCurrentReflowRoot. michael@0: nsTHashtable > mFramesToDirty; michael@0: michael@0: // Reflow roots that need to be reflowed. michael@0: nsTArray mDirtyRoots; michael@0: michael@0: nsTArray > mDelayedEvents; michael@0: nsRevocableEventPtr > mResizeEvent; michael@0: nsCOMPtr mAsyncResizeEventTimer; michael@0: private: michael@0: nsIFrame* mCurrentEventFrame; michael@0: nsCOMPtr mCurrentEventContent; michael@0: nsTArray mCurrentEventFrameStack; michael@0: nsCOMArray mCurrentEventContentStack; michael@0: protected: michael@0: nsRevocableEventPtr mSynthMouseMoveEvent; michael@0: nsCOMPtr mLastAnchorScrolledTo; michael@0: nsRefPtr mCaret; michael@0: nsRefPtr mOriginalCaret; michael@0: nsCallbackEventRequest* mFirstCallbackEventRequest; michael@0: nsCallbackEventRequest* mLastCallbackEventRequest; michael@0: michael@0: // This timer controls painting suppression. Until it fires michael@0: // or all frames are constructed, we won't paint anything but michael@0: // our background and scrollbars. michael@0: nsCOMPtr mPaintSuppressionTimer; michael@0: michael@0: // At least on Win32 and Mac after interupting a reflow we need to post michael@0: // the resume reflow event off a timer to avoid event starvation because michael@0: // posted messages are processed before other messages when the modal michael@0: // moving/sizing loop is running, see bug 491700 for details. michael@0: nsCOMPtr mReflowContinueTimer; michael@0: michael@0: nsCOMPtr mDelayedPaintTimer; michael@0: michael@0: // The `performance.now()` value when we last started to process reflows. michael@0: DOMHighResTimeStamp mLastReflowStart; michael@0: michael@0: mozilla::TimeStamp mLoadBegin; // used to time loads michael@0: michael@0: // Information needed to properly handle scrolling content into view if the michael@0: // pre-scroll reflow flush can be interrupted. mContentToScrollTo is michael@0: // non-null between the initial scroll attempt and the first time we finish michael@0: // processing all our dirty roots. mContentToScrollTo has a content property michael@0: // storing the details for the scroll operation, see ScrollIntoViewData above. michael@0: nsCOMPtr mContentToScrollTo; michael@0: michael@0: nscoord mLastAnchorScrollPositionY; michael@0: michael@0: // This is used to protect ourselves from triggering reflow while in the michael@0: // middle of frame construction and the like... it really shouldn't be michael@0: // needed, one hopes, but it is for now. michael@0: uint16_t mChangeNestCount; michael@0: michael@0: bool mDocumentLoading : 1; michael@0: bool mIgnoreFrameDestruction : 1; michael@0: bool mHaveShutDown : 1; michael@0: bool mViewportOverridden : 1; michael@0: bool mLastRootReflowHadUnconstrainedHeight : 1; michael@0: bool mNoDelayedMouseEvents : 1; michael@0: bool mNoDelayedKeyEvents : 1; michael@0: michael@0: // We've been disconnected from the document. We will refuse to paint the michael@0: // document until either our timer fires or all frames are constructed. michael@0: bool mIsDocumentGone : 1; michael@0: michael@0: // Indicates that it is safe to unlock painting once all pending reflows michael@0: // have been processed. michael@0: bool mShouldUnsuppressPainting : 1; michael@0: michael@0: bool mAsyncResizeTimerIsActive : 1; michael@0: bool mInResize : 1; michael@0: michael@0: bool mImageVisibilityVisited : 1; michael@0: michael@0: bool mNextPaintCompressed : 1; michael@0: michael@0: static bool sDisableNonTestMouseEvents; michael@0: }; michael@0: michael@0: #endif /* !defined(nsPresShell_h_) */